{"action":"created","comment":{"url":"https://api.github.com/repos/boto/botocore/pulls/comments/27747194","id":27747194,"diff_hunk":"@@ -130,3 +134,275 @@ def get_auth(self, signing_name, region_name, signature_version=None):\n             auth = cls(**kwargs)\n             self._cache[key] = auth\n             return auth\n+\n+    def generate_url(self, request_dict, expires_in=3600, region_name=None):\n+        \"\"\"Generates a presigned url\n+\n+        :type request_dict: dict\n+        :param request_dict: The prepared request dictionary returned by\n+            ``botocore.awsrequest.prepare_request_dict()``\n+\n+        :type expires_in: int\n+        :param expires_in: The number of seconds the presigned url is valid\n+            for. By default it expires in an hour (3600 seconds)\n+\n+        :type region_name: string\n+        :param region_name: The region name to sign the presigned url.\n+\n+        returns: The presigned url\n+        \"\"\"\n+        if region_name is None:\n+            region_name = self._region_name\n+        query_prefix = '-query'\n+        signature_version = self._signature_version\n+        if not signature_version.endswith(query_prefix):\n+            signature_version += query_prefix\n+\n+        kwargs = {'signing_name': self._signing_name,\n+                  'region_name': region_name,\n+                  'signature_version': signature_version,\n+                  'expires': expires_in}\n+\n+        auth = self.get_auth(**kwargs)\n+        request = create_request_object(request_dict)\n+\n+        # Fix s3 host for s3 sigv2 bucket names\n+        signature_type = signature_version.split('-', 1)[0]\n+        fix_s3_host(request, signature_type, region_name)\n+\n+        auth.add_auth(request)\n+        request.prepare()\n+\n+        return request.url\n+\n+    def build_post_form_args(self, request_dict, fields=None, conditions=None,","path":"botocore/signers.py","position":80,"original_position":80,"commit_id":"f29355148998b3f4295d7b1119d0b27acabb1a41","original_commit_id":"f29355148998b3f4295d7b1119d0b27acabb1a41","user":{"login":"jamesls","id":368057,"avatar_url":"https://avatars.githubusercontent.com/u/368057?v=3","gravatar_id":"","url":"https://api.github.com/users/jamesls","html_url":"https://github.com/jamesls","followers_url":"https://api.github.com/users/jamesls/followers","following_url":"https://api.github.com/users/jamesls/following{/other_user}","gists_url":"https://api.github.com/users/jamesls/gists{/gist_id}","starred_url":"https://api.github.com/users/jamesls/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jamesls/subscriptions","organizations_url":"https://api.github.com/users/jamesls/orgs","repos_url":"https://api.github.com/users/jamesls/repos","events_url":"https://api.github.com/users/jamesls/events{/privacy}","received_events_url":"https://api.github.com/users/jamesls/received_events","type":"User","site_admin":false},"body":"I get that these are the names from boto, but I think we should be consistent in our naming, in one case we're using generate, in another we're using build.  I prefer generate.","created_at":"2015-04-03T18:42:04Z","updated_at":"2015-04-03T18:42:04Z","html_url":"https://github.com/boto/botocore/pull/504#discussion_r27747194","pull_request_url":"https://api.github.com/repos/boto/botocore/pulls/504","_links":{"self":{"href":"https://api.github.com/repos/boto/botocore/pulls/comments/27747194"},"html":{"href":"https://github.com/boto/botocore/pull/504#discussion_r27747194"},"pull_request":{"href":"https://api.github.com/repos/boto/botocore/pulls/504"}}},"pull_request":{"url":"https://api.github.com/repos/boto/botocore/pulls/504","id":32268449,"html_url":"https://github.com/boto/botocore/pull/504","diff_url":"https://github.com/boto/botocore/pull/504.diff","patch_url":"https://github.com/boto/botocore/pull/504.patch","issue_url":"https://api.github.com/repos/boto/botocore/issues/504","number":504,"state":"open","locked":false,"title":"Generate url","user":{"login":"kyleknap","id":4605355,"avatar_url":"https://avatars.githubusercontent.com/u/4605355?v=3","gravatar_id":"","url":"https://api.github.com/users/kyleknap","html_url":"https://github.com/kyleknap","followers_url":"https://api.github.com/users/kyleknap/followers","following_url":"https://api.github.com/users/kyleknap/following{/other_user}","gists_url":"https://api.github.com/users/kyleknap/gists{/gist_id}","starred_url":"https://api.github.com/users/kyleknap/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kyleknap/subscriptions","organizations_url":"https://api.github.com/users/kyleknap/orgs","repos_url":"https://api.github.com/users/kyleknap/repos","events_url":"https://api.github.com/users/kyleknap/events{/privacy}","received_events_url":"https://api.github.com/users/kyleknap/received_events","type":"User","site_admin":false},"body":"So this pull request is to expose an interface for supporting presigned url. Note that this PR does not include support for s3's presigned POST's. With this interface, in order to generate a presigned url. All you need is a ``RequestSigner``. With the ``RequestSigner`` you can call ``generate_url()`` method that takes in a request dictionary (from the serializer and prepare_request_dict) and will return a url that is presigned. Note that I considered calling the method ``presign_url()``, but I decided to name it how boto does. You also have the option to specify how many seconds till the url expires and if you want to sign with a different region name.\r\n\r\nAlso, this PR removes the last of the skips in the integration test for the clients-only branch.\r\n\r\ncc @jamesls @danielgtaylor ","created_at":"2015-03-30T21:16:55Z","updated_at":"2015-04-03T18:42:04Z","closed_at":null,"merged_at":null,"merge_commit_sha":"49dd2666f66debd3ef65e53bb7a805a5b26de8d6","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/boto/botocore/pulls/504/commits","review_comments_url":"https://api.github.com/repos/boto/botocore/pulls/504/comments","review_comment_url":"https://api.github.com/repos/boto/botocore/pulls/comments{/number}","comments_url":"https://api.github.com/repos/boto/botocore/issues/504/comments","statuses_url":"https://api.github.com/repos/boto/botocore/statuses/f29355148998b3f4295d7b1119d0b27acabb1a41","head":{"label":"kyleknap:generate-url","ref":"generate-url","sha":"f29355148998b3f4295d7b1119d0b27acabb1a41","user":{"login":"kyleknap","id":4605355,"avatar_url":"https://avatars.githubusercontent.com/u/4605355?v=3","gravatar_id":"","url":"https://api.github.com/users/kyleknap","html_url":"https://github.com/kyleknap","followers_url":"https://api.github.com/users/kyleknap/followers","following_url":"https://api.github.com/users/kyleknap/following{/other_user}","gists_url":"https://api.github.com/users/kyleknap/gists{/gist_id}","starred_url":"https://api.github.com/users/kyleknap/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kyleknap/subscriptions","organizations_url":"https://api.github.com/users/kyleknap/orgs","repos_url":"https://api.github.com/users/kyleknap/repos","events_url":"https://api.github.com/users/kyleknap/events{/privacy}","received_events_url":"https://api.github.com/users/kyleknap/received_events","type":"User","site_admin":false},"repo":{"id":12170049,"name":"botocore","full_name":"kyleknap/botocore","owner":{"login":"kyleknap","id":4605355,"avatar_url":"https://avatars.githubusercontent.com/u/4605355?v=3","gravatar_id":"","url":"https://api.github.com/users/kyleknap","html_url":"https://github.com/kyleknap","followers_url":"https://api.github.com/users/kyleknap/followers","following_url":"https://api.github.com/users/kyleknap/following{/other_user}","gists_url":"https://api.github.com/users/kyleknap/gists{/gist_id}","starred_url":"https://api.github.com/users/kyleknap/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kyleknap/subscriptions","organizations_url":"https://api.github.com/users/kyleknap/orgs","repos_url":"https://api.github.com/users/kyleknap/repos","events_url":"https://api.github.com/users/kyleknap/events{/privacy}","received_events_url":"https://api.github.com/users/kyleknap/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/kyleknap/botocore","description":"The low-level, core functionality of boto 3.","fork":true,"url":"https://api.github.com/repos/kyleknap/botocore","forks_url":"https://api.github.com/repos/kyleknap/botocore/forks","keys_url":"https://api.github.com/repos/kyleknap/botocore/keys{/key_id}","collaborators_url":"https://api.github.com/repos/kyleknap/botocore/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/kyleknap/botocore/teams","hooks_url":"https://api.github.com/repos/kyleknap/botocore/hooks","issue_events_url":"https://api.github.com/repos/kyleknap/botocore/issues/events{/number}","events_url":"https://api.github.com/repos/kyleknap/botocore/events","assignees_url":"https://api.github.com/repos/kyleknap/botocore/assignees{/user}","branches_url":"https://api.github.com/repos/kyleknap/botocore/branches{/branch}","tags_url":"https://api.github.com/repos/kyleknap/botocore/tags","blobs_url":"https://api.github.com/repos/kyleknap/botocore/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/kyleknap/botocore/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/kyleknap/botocore/git/refs{/sha}","trees_url":"https://api.github.com/repos/kyleknap/botocore/git/trees{/sha}","statuses_url":"https://api.github.com/repos/kyleknap/botocore/statuses/{sha}","languages_url":"https://api.github.com/repos/kyleknap/botocore/languages","stargazers_url":"https://api.github.com/repos/kyleknap/botocore/stargazers","contributors_url":"https://api.github.com/repos/kyleknap/botocore/contributors","subscribers_url":"https://api.github.com/repos/kyleknap/botocore/subscribers","subscription_url":"https://api.github.com/repos/kyleknap/botocore/subscription","commits_url":"https://api.github.com/repos/kyleknap/botocore/commits{/sha}","git_commits_url":"https://api.github.com/repos/kyleknap/botocore/git/commits{/sha}","comments_url":"https://api.github.com/repos/kyleknap/botocore/comments{/number}","issue_comment_url":"https://api.github.com/repos/kyleknap/botocore/issues/comments{/number}","contents_url":"https://api.github.com/repos/kyleknap/botocore/contents/{+path}","compare_url":"https://api.github.com/repos/kyleknap/botocore/compare/{base}...{head}","merges_url":"https://api.github.com/repos/kyleknap/botocore/merges","archive_url":"https://api.github.com/repos/kyleknap/botocore/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/kyleknap/botocore/downloads","issues_url":"https://api.github.com/repos/kyleknap/botocore/issues{/number}","pulls_url":"https://api.github.com/repos/kyleknap/botocore/pulls{/number}","milestones_url":"https://api.github.com/repos/kyleknap/botocore/milestones{/number}","notifications_url":"https://api.github.com/repos/kyleknap/botocore/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/kyleknap/botocore/labels{/name}","releases_url":"https://api.github.com/repos/kyleknap/botocore/releases{/id}","created_at":"2013-08-16T22:59:40Z","updated_at":"2013-08-21T17:14:36Z","pushed_at":"2015-04-02T21:21:39Z","git_url":"git://github.com/kyleknap/botocore.git","ssh_url":"git@github.com:kyleknap/botocore.git","clone_url":"https://github.com/kyleknap/botocore.git","svn_url":"https://github.com/kyleknap/botocore","homepage":null,"size":16070,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"develop"}},"base":{"label":"boto:clients-only","ref":"clients-only","sha":"e318dd64eff88be9a2ee7e2c922cc7eba04f93d9","user":{"login":"boto","id":327752,"avatar_url":"https://avatars.githubusercontent.com/u/327752?v=3","gravatar_id":"","url":"https://api.github.com/users/boto","html_url":"https://github.com/boto","followers_url":"https://api.github.com/users/boto/followers","following_url":"https://api.github.com/users/boto/following{/other_user}","gists_url":"https://api.github.com/users/boto/gists{/gist_id}","starred_url":"https://api.github.com/users/boto/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/boto/subscriptions","organizations_url":"https://api.github.com/users/boto/orgs","repos_url":"https://api.github.com/users/boto/repos","events_url":"https://api.github.com/users/boto/events{/privacy}","received_events_url":"https://api.github.com/users/boto/received_events","type":"Organization","site_admin":false},"repo":{"id":6670942,"name":"botocore","full_name":"boto/botocore","owner":{"login":"boto","id":327752,"avatar_url":"https://avatars.githubusercontent.com/u/327752?v=3","gravatar_id":"","url":"https://api.github.com/users/boto","html_url":"https://github.com/boto","followers_url":"https://api.github.com/users/boto/followers","following_url":"https://api.github.com/users/boto/following{/other_user}","gists_url":"https://api.github.com/users/boto/gists{/gist_id}","starred_url":"https://api.github.com/users/boto/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/boto/subscriptions","organizations_url":"https://api.github.com/users/boto/orgs","repos_url":"https://api.github.com/users/boto/repos","events_url":"https://api.github.com/users/boto/events{/privacy}","received_events_url":"https://api.github.com/users/boto/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/boto/botocore","description":"The low-level, core functionality of boto 3.","fork":false,"url":"https://api.github.com/repos/boto/botocore","forks_url":"https://api.github.com/repos/boto/botocore/forks","keys_url":"https://api.github.com/repos/boto/botocore/keys{/key_id}","collaborators_url":"https://api.github.com/repos/boto/botocore/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/boto/botocore/teams","hooks_url":"https://api.github.com/repos/boto/botocore/hooks","issue_events_url":"https://api.github.com/repos/boto/botocore/issues/events{/number}","events_url":"https://api.github.com/repos/boto/botocore/events","assignees_url":"https://api.github.com/repos/boto/botocore/assignees{/user}","branches_url":"https://api.github.com/repos/boto/botocore/branches{/branch}","tags_url":"https://api.github.com/repos/boto/botocore/tags","blobs_url":"https://api.github.com/repos/boto/botocore/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/boto/botocore/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/boto/botocore/git/refs{/sha}","trees_url":"https://api.github.com/repos/boto/botocore/git/trees{/sha}","statuses_url":"https://api.github.com/repos/boto/botocore/statuses/{sha}","languages_url":"https://api.github.com/repos/boto/botocore/languages","stargazers_url":"https://api.github.com/repos/boto/botocore/stargazers","contributors_url":"https://api.github.com/repos/boto/botocore/contributors","subscribers_url":"https://api.github.com/repos/boto/botocore/subscribers","subscription_url":"https://api.github.com/repos/boto/botocore/subscription","commits_url":"https://api.github.com/repos/boto/botocore/commits{/sha}","git_commits_url":"https://api.github.com/repos/boto/botocore/git/commits{/sha}","comments_url":"https://api.github.com/repos/boto/botocore/comments{/number}","issue_comment_url":"https://api.github.com/repos/boto/botocore/issues/comments{/number}","contents_url":"https://api.github.com/repos/boto/botocore/contents/{+path}","compare_url":"https://api.github.com/repos/boto/botocore/compare/{base}...{head}","merges_url":"https://api.github.com/repos/boto/botocore/merges","archive_url":"https://api.github.com/repos/boto/botocore/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/boto/botocore/downloads","issues_url":"https://api.github.com/repos/boto/botocore/issues{/number}","pulls_url":"https://api.github.com/repos/boto/botocore/pulls{/number}","milestones_url":"https://api.github.com/repos/boto/botocore/milestones{/number}","notifications_url":"https://api.github.com/repos/boto/botocore/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/boto/botocore/labels{/name}","releases_url":"https://api.github.com/repos/boto/botocore/releases{/id}","created_at":"2012-11-13T13:25:36Z","updated_at":"2015-04-02T21:57:37Z","pushed_at":"2015-04-02T21:57:37Z","git_url":"git://github.com/boto/botocore.git","ssh_url":"git@github.com:boto/botocore.git","clone_url":"https://github.com/boto/botocore.git","svn_url":"https://github.com/boto/botocore","homepage":null,"size":22350,"stargazers_count":149,"watchers_count":149,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":80,"mirror_url":null,"open_issues_count":23,"forks":80,"open_issues":23,"watchers":149,"default_branch":"develop"}},"_links":{"self":{"href":"https://api.github.com/repos/boto/botocore/pulls/504"},"html":{"href":"https://github.com/boto/botocore/pull/504"},"issue":{"href":"https://api.github.com/repos/boto/botocore/issues/504"},"comments":{"href":"https://api.github.com/repos/boto/botocore/issues/504/comments"},"review_comments":{"href":"https://api.github.com/repos/boto/botocore/pulls/504/comments"},"review_comment":{"href":"https://api.github.com/repos/boto/botocore/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/boto/botocore/pulls/504/commits"},"statuses":{"href":"https://api.github.com/repos/boto/botocore/statuses/f29355148998b3f4295d7b1119d0b27acabb1a41"}}}}