From 430e87d0fd738adde494ccfe7d3fb3882fd8ca02 Mon Sep 17 00:00:00 2001 From: Mike Waldner Date: Mon, 15 Aug 2011 00:12:14 -0400 Subject: [PATCH 01/20] First commit of curl command from request --- requests/models.py | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/requests/models.py b/requests/models.py index 08f3e321..9e0b0ddb 100644 --- a/requests/models.py +++ b/requests/models.py @@ -328,6 +328,37 @@ class Request(object): return self.sent + @property + def curl(self): + """Creates a curl command from the request""" + + #TODO - Auth. User names and accounts + #TODO - Query string... + #TODO - Files...How do I do files??? + + #: --location - if there is a redirect, redo request on the new place + curl_cmd = 'curl --location ' + + if self.method.upper() == 'HEAD': + #: --head - fetch headers only + method_opt = '--head ' + else: + #: --request - specify request method + method_opt = '--request %s ' % self.method.upper() + + data = '' + if self.method in ('PUT', 'POST', 'PATCH'): + #: --data - send specified data in post request. + #: '-data name=John -data skill=Doe' generates the + #: post chunk 'name=daniel&skill=lousy' + + #if data is file: + if isinstance(self.data, (list, tuple)): + data = data.join(['--data ' + key + '=' + value + ' ' for key, value in self.data]) + + curl_cmd = curl_cmd + method_opt + data + self.url + + return curl_cmd class Response(object): From aad27218d58e82637c43f92c85237fa90f0178c6 Mon Sep 17 00:00:00 2001 From: Mike Waldner Date: Tue, 16 Aug 2011 01:39:02 -0400 Subject: [PATCH 02/20] Using build_url and also including headers --- requests/models.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/requests/models.py b/requests/models.py index 9e0b0ddb..5e1474d5 100644 --- a/requests/models.py +++ b/requests/models.py @@ -333,12 +333,16 @@ class Request(object): """Creates a curl command from the request""" #TODO - Auth. User names and accounts - #TODO - Query string... #TODO - Files...How do I do files??? #: --location - if there is a redirect, redo request on the new place curl_cmd = 'curl --location ' + #: --header - Extra header to use when getting a web page + header = '' + if self.headers: + header = header.join(['--header "' + key + ':' + value + '" ' for key, value in self.headers.iteritems()]) + if self.method.upper() == 'HEAD': #: --head - fetch headers only method_opt = '--head ' @@ -355,8 +359,11 @@ class Request(object): #if data is file: if isinstance(self.data, (list, tuple)): data = data.join(['--data ' + key + '=' + value + ' ' for key, value in self.data]) + else: + data = '--data ' + self._enc_data + ' ' - curl_cmd = curl_cmd + method_opt + data + self.url + #: Params handled in _build_url + curl_cmd = curl_cmd + method_opt + data + header + '"' + self._build_url() + '"' return curl_cmd From 2a17e5237c90a537c96b486ef30cddf8b544a966 Mon Sep 17 00:00:00 2001 From: Mike Waldner Date: Tue, 23 Aug 2011 22:03:42 -0400 Subject: [PATCH 03/20] Ive never seen anyone use the --'s unix command options --- requests/models.py | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/requests/models.py b/requests/models.py index 5e1474d5..9c51bb8a 100644 --- a/requests/models.py +++ b/requests/models.py @@ -332,23 +332,24 @@ class Request(object): def curl(self): """Creates a curl command from the request""" - #TODO - Auth. User names and accounts - #TODO - Files...How do I do files??? + #TODO - Auth with User names and accounts + #TODO - Files + #TODO - OAuth - #: --location - if there is a redirect, redo request on the new place - curl_cmd = 'curl --location ' + #: -L/--location - if there is a redirect, redo request on the new place + curl_cmd = 'curl -L ' - #: --header - Extra header to use when getting a web page + #: -H/--header - Extra header to use when getting a web page header = '' if self.headers: - header = header.join(['--header "' + key + ':' + value + '" ' for key, value in self.headers.iteritems()]) + header = header.join(['-H "' + key + ':' + value + '" ' for key, value in self.headers.iteritems()]) if self.method.upper() == 'HEAD': - #: --head - fetch headers only - method_opt = '--head ' + #: -I/--head - fetch headers only + method_opt = '-I ' else: - #: --request - specify request method - method_opt = '--request %s ' % self.method.upper() + #: -X/--request - specify request method + method_opt = '-X %s ' % self.method.upper() data = '' if self.method in ('PUT', 'POST', 'PATCH'): @@ -358,9 +359,9 @@ class Request(object): #if data is file: if isinstance(self.data, (list, tuple)): - data = data.join(['--data ' + key + '=' + value + ' ' for key, value in self.data]) + data = data.join(['-d ' + key + '=' + value + ' ' for key, value in self.data]) else: - data = '--data ' + self._enc_data + ' ' + data = '-d ' + self._enc_data + ' ' #: Params handled in _build_url curl_cmd = curl_cmd + method_opt + data + header + '"' + self._build_url() + '"' From c56acf0e321d7a2ae1c0726352d9d7698091d05c Mon Sep 17 00:00:00 2001 From: Mike Waldner Date: Tue, 23 Aug 2011 22:17:36 -0400 Subject: [PATCH 04/20] Small Cleanup --- requests/models.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/requests/models.py b/requests/models.py index 9c51bb8a..ec18b08c 100644 --- a/requests/models.py +++ b/requests/models.py @@ -353,20 +353,17 @@ class Request(object): data = '' if self.method in ('PUT', 'POST', 'PATCH'): - #: --data - send specified data in post request. - #: '-data name=John -data skill=Doe' generates the - #: post chunk 'name=daniel&skill=lousy' + #: -d/--data - send specified data in post request. + #: '-d name=John -d last=Doe' generates the + #: post chunk 'name=John&last=Doe' - #if data is file: if isinstance(self.data, (list, tuple)): data = data.join(['-d ' + key + '=' + value + ' ' for key, value in self.data]) else: data = '-d ' + self._enc_data + ' ' #: Params handled in _build_url - curl_cmd = curl_cmd + method_opt + data + header + '"' + self._build_url() + '"' - - return curl_cmd + return curl_cmd + method_opt + data + header + '"' + self._build_url() + '"' class Response(object): From 84d9ff0c5c63ec22dd10670e373b4a46d8770ff4 Mon Sep 17 00:00:00 2001 From: Mike Waldner Date: Tue, 23 Aug 2011 22:34:05 -0400 Subject: [PATCH 05/20] More Small Cleanup --- requests/models.py | 1 + 1 file changed, 1 insertion(+) diff --git a/requests/models.py b/requests/models.py index 7a9ba098..3cd8def1 100644 --- a/requests/models.py +++ b/requests/models.py @@ -421,6 +421,7 @@ class Request(object): #: Params handled in _build_url return curl_cmd + method_opt + data + header + '"' + self._build_url() + '"' + class Response(object): """The core :class:`Response ` object. All :class:`Request ` objects contain a From 0bf60c8876cddb5b203c652834ab8c6da55e4ce5 Mon Sep 17 00:00:00 2001 From: Mike Waldner Date: Tue, 23 Aug 2011 23:08:26 -0400 Subject: [PATCH 06/20] Adding check when _enc_data in None --- requests/models.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/requests/models.py b/requests/models.py index 3cd8def1..fc828e13 100644 --- a/requests/models.py +++ b/requests/models.py @@ -391,6 +391,7 @@ class Request(object): #TODO - Auth with User names and accounts #TODO - Files #TODO - OAuth + #TODO - Cookies? #: -L/--location - if there is a redirect, redo request on the new place curl_cmd = 'curl -L ' @@ -410,12 +411,9 @@ class Request(object): data = '' if self.method in ('PUT', 'POST', 'PATCH'): #: -d/--data - send specified data in post request. - #: '-d name=John -d last=Doe' generates the - #: post chunk 'name=John&last=Doe' - if isinstance(self.data, (list, tuple)): data = data.join(['-d ' + key + '=' + value + ' ' for key, value in self.data]) - else: + elif self._enc_data is not None: data = '-d ' + self._enc_data + ' ' #: Params handled in _build_url From 256c86f8f7deb5375c38b6cc55c3d54d0366d283 Mon Sep 17 00:00:00 2001 From: Kenneth Reitz Date: Tue, 23 Aug 2011 23:52:43 -0400 Subject: [PATCH 07/20] moving curl into utils #139 --- requests/models.py | 35 ----------------------------------- requests/utils.py | 37 ++++++++++++++++++++++++++++++++++++- 2 files changed, 36 insertions(+), 36 deletions(-) diff --git a/requests/models.py b/requests/models.py index 0d90ea92..5ff9eb48 100644 --- a/requests/models.py +++ b/requests/models.py @@ -383,41 +383,6 @@ class Request(object): return self.sent - @property - def curl(self): - """Creates a curl command from the request""" - - #TODO - Auth with User names and accounts - #TODO - Files - #TODO - OAuth - #TODO - Cookies? - - #: -L/--location - if there is a redirect, redo request on the new place - curl_cmd = 'curl -L ' - - #: -H/--header - Extra header to use when getting a web page - header = '' - if self.headers: - header = header.join(['-H "' + key + ':' + value + '" ' for key, value in self.headers.iteritems()]) - - if self.method.upper() == 'HEAD': - #: -I/--head - fetch headers only - method_opt = '-I ' - else: - #: -X/--request - specify request method - method_opt = '-X %s ' % self.method.upper() - - data = '' - if self.method in ('PUT', 'POST', 'PATCH'): - #: -d/--data - send specified data in post request. - if isinstance(self.data, (list, tuple)): - data = data.join(['-d ' + key + '=' + value + ' ' for key, value in self.data]) - elif self._enc_data is not None: - data = '-d ' + self._enc_data + ' ' - - #: Params handled in _build_url - return curl_cmd + method_opt + data + header + '"' + self._build_url() + '"' - class Response(object): """The core :class:`Response ` object. All diff --git a/requests/utils.py b/requests/utils.py index 2b55a164..51ec4bfe 100644 --- a/requests/utils.py +++ b/requests/utils.py @@ -165,4 +165,39 @@ def decode_gzip(content): :param content: bytestring to gzip-decode. """ - return zlib.decompress(content, 16+zlib.MAX_WBITS) \ No newline at end of file + return zlib.decompress(content, 16+zlib.MAX_WBITS) + + +def curl_from_request(request): + """Creates a curl command from the request.""" + + #TODO - Auth with User names and accounts + #TODO - Files + #TODO - OAuth + #TODO - Cookies? + + #: -L/--location - if there is a redirect, redo request on the new place + curl_cmd = 'curl -L ' + + #: -H/--header - Extra header to use when getting a web page + header = '' + if request.headers: + header = header.join(['-H "' + key + ':' + value + '" ' for key, value in request.headers.iteritems()]) + + if request.method.upper() == 'HEAD': + #: -I/--head - fetch headers only + method_opt = '-I ' + else: + #: -X/--request - specify request method + method_opt = '-X %s ' % request.method.upper() + + data = '' + if request.method in ('PUT', 'POST', 'PATCH'): + #: -d/--data - send specified data in post request. + if isinstance(request.data, (list, tuple)): + data = data.join(['-d ' + key + '=' + value + ' ' for key, value in request.data]) + elif request._enc_data is not None: + data = '-d ' + request._enc_data + ' ' + + #: Params handled in _build_url + return curl_cmd + method_opt + data + header + '"' + request._build_url() + '"' \ No newline at end of file From 2dfcc0bb7b7eb9060e523f785845919d277ab412 Mon Sep 17 00:00:00 2001 From: Kenneth Reitz Date: Wed, 24 Aug 2011 00:04:18 -0400 Subject: [PATCH 08/20] string formatting #139 --- requests/utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/requests/utils.py b/requests/utils.py index 51ec4bfe..58e7850e 100644 --- a/requests/utils.py +++ b/requests/utils.py @@ -195,9 +195,9 @@ def curl_from_request(request): if request.method in ('PUT', 'POST', 'PATCH'): #: -d/--data - send specified data in post request. if isinstance(request.data, (list, tuple)): - data = data.join(['-d ' + key + '=' + value + ' ' for key, value in request.data]) + data = data.join(['-d %s=%s ' % (k, v) for (k, v) in request.data]) elif request._enc_data is not None: - data = '-d ' + request._enc_data + ' ' + data = '-d %s ' % (request._enc_data) #: Params handled in _build_url return curl_cmd + method_opt + data + header + '"' + request._build_url() + '"' \ No newline at end of file From cc2c54093e97965b38d0ae1611bb19cd503d6888 Mon Sep 17 00:00:00 2001 From: Mike Waldner Date: Wed, 24 Aug 2011 01:21:44 -0400 Subject: [PATCH 09/20] Adding basic authentication. Also string formatting --- requests/utils.py | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/requests/utils.py b/requests/utils.py index 58e7850e..8bda43d1 100644 --- a/requests/utils.py +++ b/requests/utils.py @@ -171,33 +171,37 @@ def decode_gzip(content): def curl_from_request(request): """Creates a curl command from the request.""" - #TODO - Auth with User names and accounts #TODO - Files - #TODO - OAuth - #TODO - Cookies? + #TODO - OAuth/Other Auths + #TODO - Cookies #: -L/--location - if there is a redirect, redo request on the new place - curl_cmd = 'curl -L ' + curl = 'curl -L ' + + #: -u/--user - Specify the user name and password to use for server auth. + auth = '' + if request.auth is not None: + auth = '-u "%s:%s" ' % (request.auth.username, request.auth.password) + + if request.method.upper() == 'HEAD': + #: -I/--head - fetch headers only + method = '-I ' + else: + #: -X/--request - specify request method + method = '-X %s ' % request.method.upper() #: -H/--header - Extra header to use when getting a web page header = '' if request.headers: - header = header.join(['-H "' + key + ':' + value + '" ' for key, value in request.headers.iteritems()]) - - if request.method.upper() == 'HEAD': - #: -I/--head - fetch headers only - method_opt = '-I ' - else: - #: -X/--request - specify request method - method_opt = '-X %s ' % request.method.upper() + header = header.join(['-H "%s:%s" ' % (k, v) for k, v in request.headers.iteritems()]) data = '' if request.method in ('PUT', 'POST', 'PATCH'): #: -d/--data - send specified data in post request. if isinstance(request.data, (list, tuple)): - data = data.join(['-d %s=%s ' % (k, v) for (k, v) in request.data]) + data = data.join(['-d "%s=%s" ' % (k, v) for (k, v) in request.data]) elif request._enc_data is not None: data = '-d %s ' % (request._enc_data) #: Params handled in _build_url - return curl_cmd + method_opt + data + header + '"' + request._build_url() + '"' \ No newline at end of file + return curl + auth + method + header + data + '"' + request._build_url() + '"' From 3dd2235ac5343ce0c4d4a4b7937f8ce2127f0612 Mon Sep 17 00:00:00 2001 From: Mike Waldner Date: Wed, 24 Aug 2011 01:30:38 -0400 Subject: [PATCH 10/20] Adding basic authentication. Also string formatting #139 --- requests/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requests/utils.py b/requests/utils.py index 8bda43d1..461582cf 100644 --- a/requests/utils.py +++ b/requests/utils.py @@ -172,7 +172,7 @@ def curl_from_request(request): """Creates a curl command from the request.""" #TODO - Files - #TODO - OAuth/Other Auths + #TODO - OAuth #TODO - Cookies #: -L/--location - if there is a redirect, redo request on the new place From cfee8308772a3c931539688f9928ca6ff81d36cf Mon Sep 17 00:00:00 2001 From: Mike Waldner Date: Wed, 24 Aug 2011 01:39:43 -0400 Subject: [PATCH 11/20] Renaming vars. String formatting #139 --- requests/utils.py | 57 ++++++++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/requests/utils.py b/requests/utils.py index 461582cf..65ce4f72 100644 --- a/requests/utils.py +++ b/requests/utils.py @@ -168,40 +168,41 @@ def decode_gzip(content): return zlib.decompress(content, 16+zlib.MAX_WBITS) -def curl_from_request(request): - """Creates a curl command from the request.""" +def curl_from_request(request): + """Creates a curl command from the request.""" - #TODO - Files - #TODO - OAuth - #TODO - Cookies + #TODO - Files + #TODO - OAuth + #TODO - Cookies - #: -L/--location - if there is a redirect, redo request on the new place - curl = 'curl -L ' + #: -L/--location - if there is a redirect, redo request on the new place + curl = 'curl -L ' #: -u/--user - Specify the user name and password to use for server auth. - auth = '' - if request.auth is not None: + auth = '' + if request.auth is not None: auth = '-u "%s:%s" ' % (request.auth.username, request.auth.password) - if request.method.upper() == 'HEAD': - #: -I/--head - fetch headers only - method = '-I ' - else: - #: -X/--request - specify request method - method = '-X %s ' % request.method.upper() + if request.method.upper() == 'HEAD': + #: -I/--head - fetch headers only + method = '-I ' + else: + #: -X/--request - specify request method + method = '-X %s ' % request.method.upper() - #: -H/--header - Extra header to use when getting a web page - header = '' - if request.headers: - header = header.join(['-H "%s:%s" ' % (k, v) for k, v in request.headers.iteritems()]) + #: -H/--header - Extra header to use when getting a web page + header = '' + if request.headers: + header = header.join(['-H "%s:%s" ' % (k, v) for k, v in request.headers.iteritems()]) - data = '' - if request.method in ('PUT', 'POST', 'PATCH'): - #: -d/--data - send specified data in post request. - if isinstance(request.data, (list, tuple)): - data = data.join(['-d "%s=%s" ' % (k, v) for (k, v) in request.data]) - elif request._enc_data is not None: - data = '-d %s ' % (request._enc_data) + data = '' + if request.method in ('PUT', 'POST', 'PATCH'): + #: -d/--data - send specified data in post request. + if isinstance(request.data, (list, tuple)): + data = data.join(['-d "%s=%s" ' % (k, v) for (k, v) in request.data]) + elif request._enc_data is not None: + data = '-d %s ' % (request._enc_data) - #: Params handled in _build_url - return curl + auth + method + header + data + '"' + request._build_url() + '"' + + #: Params handled in _build_url + return curl + auth + method + header + data + '"' + request._build_url() + '"' From ec0b708b1856be4803ab10eeb50824f739baf0ce Mon Sep 17 00:00:00 2001 From: Mike Waldner Date: Wed, 24 Aug 2011 01:40:44 -0400 Subject: [PATCH 12/20] Removing trailing whitespace #139 --- requests/utils.py | 60 +++++++++++++++++++++++------------------------ 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/requests/utils.py b/requests/utils.py index 65ce4f72..3f4d9a44 100644 --- a/requests/utils.py +++ b/requests/utils.py @@ -168,41 +168,41 @@ def decode_gzip(content): return zlib.decompress(content, 16+zlib.MAX_WBITS) -def curl_from_request(request): - """Creates a curl command from the request.""" +def curl_from_request(request): + """Creates a curl command from the request.""" - #TODO - Files - #TODO - OAuth - #TODO - Cookies + #TODO - Files + #TODO - OAuth + #TODO - Cookies - #: -L/--location - if there is a redirect, redo request on the new place - curl = 'curl -L ' + #: -L/--location - if there is a redirect, redo request on the new place + curl = 'curl -L ' - #: -u/--user - Specify the user name and password to use for server auth. - auth = '' - if request.auth is not None: - auth = '-u "%s:%s" ' % (request.auth.username, request.auth.password) + #: -u/--user - Specify the user name and password to use for server auth. + auth = '' + if request.auth is not None: + auth = '-u "%s:%s" ' % (request.auth.username, request.auth.password) - if request.method.upper() == 'HEAD': - #: -I/--head - fetch headers only - method = '-I ' - else: - #: -X/--request - specify request method - method = '-X %s ' % request.method.upper() + if request.method.upper() == 'HEAD': + #: -I/--head - fetch headers only + method = '-I ' + else: + #: -X/--request - specify request method + method = '-X %s ' % request.method.upper() - #: -H/--header - Extra header to use when getting a web page - header = '' - if request.headers: - header = header.join(['-H "%s:%s" ' % (k, v) for k, v in request.headers.iteritems()]) + #: -H/--header - Extra header to use when getting a web page + header = '' + if request.headers: + header = header.join(['-H "%s:%s" ' % (k, v) for k, v in request.headers.iteritems()]) - data = '' - if request.method in ('PUT', 'POST', 'PATCH'): - #: -d/--data - send specified data in post request. - if isinstance(request.data, (list, tuple)): - data = data.join(['-d "%s=%s" ' % (k, v) for (k, v) in request.data]) - elif request._enc_data is not None: - data = '-d %s ' % (request._enc_data) + data = '' + if request.method in ('PUT', 'POST', 'PATCH'): + #: -d/--data - send specified data in post request. + if isinstance(request.data, (list, tuple)): + data = data.join(['-d "%s=%s" ' % (k, v) for (k, v) in request.data]) + elif request._enc_data is not None: + data = '-d %s ' % (request._enc_data) - #: Params handled in _build_url - return curl + auth + method + header + data + '"' + request._build_url() + '"' + #: Params handled in _build_url + return curl + auth + method + header + data + '"' + request._build_url() + '"' From 71195bb219ed24717961a3f968a00be7f3d8a4a7 Mon Sep 17 00:00:00 2001 From: Mike Waldner Date: Wed, 24 Aug 2011 01:50:06 -0400 Subject: [PATCH 13/20] Adding myself to Authors. Small cleanup #139 --- AUTHORS | 1 + requests/utils.py | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/AUTHORS b/AUTHORS index 1eabf651..5a80c622 100644 --- a/AUTHORS +++ b/AUTHORS @@ -42,3 +42,4 @@ Patches and Suggestions - Alejandro Giacometti - Rick Mak - Johan Bergström +- Mike Waldner diff --git a/requests/utils.py b/requests/utils.py index 3f4d9a44..b4e760a9 100644 --- a/requests/utils.py +++ b/requests/utils.py @@ -203,6 +203,5 @@ def curl_from_request(request): elif request._enc_data is not None: data = '-d %s ' % (request._enc_data) - #: Params handled in _build_url return curl + auth + method + header + data + '"' + request._build_url() + '"' From 7fa4fdacc9d3e0a418bf2dee1a897bfa799748e9 Mon Sep 17 00:00:00 2001 From: Mike Waldner Date: Wed, 24 Aug 2011 22:01:06 -0400 Subject: [PATCH 14/20] Adding in file support #139 --- requests/utils.py | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/requests/utils.py b/requests/utils.py index b4e760a9..03e5fac4 100644 --- a/requests/utils.py +++ b/requests/utils.py @@ -171,7 +171,6 @@ def decode_gzip(content): def curl_from_request(request): """Creates a curl command from the request.""" - #TODO - Files #TODO - OAuth #TODO - Cookies @@ -179,6 +178,7 @@ def curl_from_request(request): curl = 'curl -L ' #: -u/--user - Specify the user name and password to use for server auth. + #: Basic Auth only for now auth = '' if request.auth is not None: auth = '-u "%s:%s" ' % (request.auth.username, request.auth.password) @@ -195,13 +195,26 @@ def curl_from_request(request): if request.headers: header = header.join(['-H "%s:%s" ' % (k, v) for k, v in request.headers.iteritems()]) - data = '' + form = '' if request.method in ('PUT', 'POST', 'PATCH'): - #: -d/--data - send specified data in post request. - if isinstance(request.data, (list, tuple)): - data = data.join(['-d "%s=%s" ' % (k, v) for (k, v) in request.data]) - elif request._enc_data is not None: - data = '-d %s ' % (request._enc_data) + #: request.files is updated with request.data if both exist. + #: ContentType multipart/form-data is used + if request.files: + #: -F/--form - Emulate form data. To force 'content' to a file, prefix file name @. + for k, v in request.files.iteritems(): + if isinstance(v, file): + form = form + '-F "%s=@%s" ' % (k, v.name) + elif v not in (None, ''): + form = form + '-F "%s=%s" ' % (k, v) + + #: content-type application/x-www-form-urlencoded is used here + else: + #: -d/--data - send specified data in post request. + if isinstance(request.data, (list, tuple)): + form = form.join(['-d "%s=%s" ' % (k, v) for k, v in request.data]) + elif request._enc_data not in (None, ''): + form = "-d '%s' " % (request._enc_data) #: Params handled in _build_url - return curl + auth + method + header + data + '"' + request._build_url() + '"' + return curl + auth + method + header + form + '"' + request._build_url() + '"' + From 3d448f843e82f8c35613ea3d5657e8215d068163 Mon Sep 17 00:00:00 2001 From: Mike Waldner Date: Thu, 25 Aug 2011 23:55:24 -0400 Subject: [PATCH 15/20] Adding cookies #139 --- requests/utils.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/requests/utils.py b/requests/utils.py index 03e5fac4..8a0967b9 100644 --- a/requests/utils.py +++ b/requests/utils.py @@ -172,7 +172,6 @@ def curl_from_request(request): """Creates a curl command from the request.""" #TODO - OAuth - #TODO - Cookies #: -L/--location - if there is a redirect, redo request on the new place curl = 'curl -L ' @@ -183,6 +182,7 @@ def curl_from_request(request): if request.auth is not None: auth = '-u "%s:%s" ' % (request.auth.username, request.auth.password) + method = '' if request.method.upper() == 'HEAD': #: -I/--head - fetch headers only method = '-I ' @@ -190,6 +190,13 @@ def curl_from_request(request): #: -X/--request - specify request method method = '-X %s ' % request.method.upper() + #: -b/--cookie + #: (HTTP) Pass the data to the HTTP server as a cookie. It is supposedly the + #: data previously received from the server in a "Set-Cookie:" line. + cookies = '' + if request.cookiejar: + cookies = cookies.join(['-b "%s=%s" ' % (k.name, k.value) for k in request.cookiejar]) + #: -H/--header - Extra header to use when getting a web page header = '' if request.headers: @@ -216,5 +223,5 @@ def curl_from_request(request): form = "-d '%s' " % (request._enc_data) #: Params handled in _build_url - return curl + auth + method + header + form + '"' + request._build_url() + '"' + return curl + auth + method + header + cookies + form + '"' + request._build_url() + '"' From 3f98034c2aa5d04e45670ef968c0c7026c188ed9 Mon Sep 17 00:00:00 2001 From: Mike Waldner Date: Thu, 25 Aug 2011 23:57:56 -0400 Subject: [PATCH 16/20] Trailing whitespace #139 --- requests/utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/requests/utils.py b/requests/utils.py index 8a0967b9..8fa9d659 100644 --- a/requests/utils.py +++ b/requests/utils.py @@ -192,10 +192,10 @@ def curl_from_request(request): #: -b/--cookie #: (HTTP) Pass the data to the HTTP server as a cookie. It is supposedly the - #: data previously received from the server in a "Set-Cookie:" line. + #: data previously received from the server in a "Set-Cookie:" line. cookies = '' if request.cookiejar: - cookies = cookies.join(['-b "%s=%s" ' % (k.name, k.value) for k in request.cookiejar]) + cookies = cookies.join(['-b "%s=%s" ' % (k.name, k.value) for k in request.cookiejar]) #: -H/--header - Extra header to use when getting a web page header = '' From 58d63d55bc0cbbb1d543a4165f2e80a808c5577e Mon Sep 17 00:00:00 2001 From: Mike Waldner Date: Sun, 28 Aug 2011 21:19:51 -0400 Subject: [PATCH 17/20] Sphinx Documentation #139 --- docs/api.rst | 4 ++++ requests/utils.py | 26 ++++++++++++++++++-------- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/docs/api.rst b/docs/api.rst index e3338b66..328e9e8b 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -48,6 +48,10 @@ Cookies .. autofunction:: cookiejar_from_dict .. autofunction:: add_dict_to_cookiejar +Curl +~~~~ +.. autofunction:: curl_from_request + Encodings ~~~~~~~~~ diff --git a/requests/utils.py b/requests/utils.py index 8fa9d659..d4f05b5e 100644 --- a/requests/utils.py +++ b/requests/utils.py @@ -169,11 +169,21 @@ def decode_gzip(content): def curl_from_request(request): - """Creates a curl command from the request.""" + """Returns a curl command from the request. + + :param request: The :class:`Request ` object + + Example: + | import requests + | from requests.utils import curl_from_request + | r = requests.get('http://httpbin.org/get') + | curl_from_request(r.request) + + """ #TODO - OAuth - #: -L/--location - if there is a redirect, redo request on the new place + #: -L/--location - if there is a redirect, redo request on the new place. curl = 'curl -L ' #: -u/--user - Specify the user name and password to use for server auth. @@ -184,10 +194,10 @@ def curl_from_request(request): method = '' if request.method.upper() == 'HEAD': - #: -I/--head - fetch headers only + #: -I/--head - fetch headers only. method = '-I ' else: - #: -X/--request - specify request method + #: -X/--request - specify request method. method = '-X %s ' % request.method.upper() #: -b/--cookie @@ -197,15 +207,15 @@ def curl_from_request(request): if request.cookiejar: cookies = cookies.join(['-b "%s=%s" ' % (k.name, k.value) for k in request.cookiejar]) - #: -H/--header - Extra header to use when getting a web page + #: -H/--header - Extra header to use when getting a web page. header = '' if request.headers: header = header.join(['-H "%s:%s" ' % (k, v) for k, v in request.headers.iteritems()]) form = '' if request.method in ('PUT', 'POST', 'PATCH'): - #: request.files is updated with request.data if both exist. - #: ContentType multipart/form-data is used + #: request.files is updated with request.data if both exist, so only iterate request.files. + #: ContentType multipart/form-data is used. if request.files: #: -F/--form - Emulate form data. To force 'content' to a file, prefix file name @. for k, v in request.files.iteritems(): @@ -214,7 +224,7 @@ def curl_from_request(request): elif v not in (None, ''): form = form + '-F "%s=%s" ' % (k, v) - #: content-type application/x-www-form-urlencoded is used here + #: content-type application/x-www-form-urlencoded is used here. else: #: -d/--data - send specified data in post request. if isinstance(request.data, (list, tuple)): From e46351cfbd1ee908fecdd54c52bd928c370b4c05 Mon Sep 17 00:00:00 2001 From: Mike Waldner Date: Sun, 28 Aug 2011 23:31:43 -0400 Subject: [PATCH 18/20] Unit Tests for curl_from_request #139 --- test_requests.py | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/test_requests.py b/test_requests.py index dd923471..b3f590cd 100755 --- a/test_requests.py +++ b/test_requests.py @@ -14,6 +14,7 @@ except ImportError: import requests from requests.sessions import Session +from requests.utils import curl_from_request HTTPBIN_URL = 'http://httpbin.org/' @@ -470,6 +471,53 @@ class RequestsTestSuite(unittest.TestCase): self.assertEqual(r2.status_code, 200) + def test_curl_HTTP_OK_GET(self): + curl_str = 'curl -L -X GET -H "Accept-Encoding:gzip" -H "User-Agent:python-requests.org" "http://httpbin.org//"' + r = requests.get(httpbin('/')) + self.assertEqual(curl_from_request(r.request), curl_str) + + + def test_curl_HTTP_OK_GET_WITH_PARAMS(self): + curl_str = 'curl -L -X GET -H "Accept-Encoding:gzip" -H "User-agent:Mozilla/5.0" "http://httpbin.org/user-agent"' + + heads = {'User-agent': 'Mozilla/5.0'} + r = requests.get(httpbin('user-agent'), headers=heads) + self.assertEqual(curl_from_request(r.request), curl_str) + + + def test_curl_HTTP_OK_HEAD(self): + curl_str ='curl -L -I -H "Accept-Encoding:gzip" -H "User-Agent:python-requests.org" "http://httpbin.org//"' + r = requests.head(httpbin('/')) + self.assertEqual(curl_from_request(r.request), curl_str) + + + def test_curl_HTTP_OK_PATCH(self): + curl_str = 'curl -L -X PATCH -H "Accept-Encoding:gzip" -H "User-Agent:python-requests.org" "http://httpbin.org/patch"' + r = requests.patch(httpbin('patch')) + self.assertEqual(curl_from_request(r.request), curl_str) + + + def test_curl_AUTH_HTTPS_OK_GET(self): + curl_str = 'curl -L -u "user:pass" -X GET -H "Accept-Encoding:gzip" -H "User-Agent:python-requests.org" "https://httpbin.ep.io/basic-auth/user/pass"' + auth = ('user', 'pass') + r = requests.get(httpsbin('basic-auth', 'user', 'pass'), auth=auth) + self.assertEqual(curl_from_request(r.request), curl_str) + + + def test_curl_POSTBIN_GET_POST_FILES(self): + curl_str = 'curl -L -X POST -H "Accept-Encoding:gzip" -H "User-Agent:python-requests.org" -d "some=data" "http://httpbin.org/post"' + post = requests.post(httpbin('post'), data={'some': 'data'}) + self.assertEqual(curl_from_request(post.request), curl_str) + + curl_str = 'curl -L -X POST -H "Accept-Encoding:gzip" -H "User-Agent:python-requests.org" -F "some=@test_requests.py" "https://httpbin.ep.io/post"' + post2 = requests.post(httpsbin('post'), files={'some': open('test_requests.py')}) + self.assertEqual(curl_from_request(post2.request), curl_str) + + #TODO - This doesn't seem right with \ \ + #curl_str = 'curl -L -X POST -H "Accept-Encoding:gzip" -H "User-Agent:python-requests.org" -d \'[{"some": "json"}]\' "http://httpbin.org/post"' + #post3 = requests.post(httpbin('post'), data='[{"some": "json"}]') + #self.assertEqual(curl_from_request(post3.request), curl_str) + if __name__ == '__main__': unittest.main() From 2aa32c16dcb905e303b2bc19ea95d616fba28adf Mon Sep 17 00:00:00 2001 From: Mike Waldner Date: Sat, 3 Sep 2011 20:54:55 -0400 Subject: [PATCH 19/20] Updated unit tests #139 --- test_requests.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/test_requests.py b/test_requests.py index b3f590cd..a4484c41 100755 --- a/test_requests.py +++ b/test_requests.py @@ -513,10 +513,9 @@ class RequestsTestSuite(unittest.TestCase): post2 = requests.post(httpsbin('post'), files={'some': open('test_requests.py')}) self.assertEqual(curl_from_request(post2.request), curl_str) - #TODO - This doesn't seem right with \ \ - #curl_str = 'curl -L -X POST -H "Accept-Encoding:gzip" -H "User-Agent:python-requests.org" -d \'[{"some": "json"}]\' "http://httpbin.org/post"' - #post3 = requests.post(httpbin('post'), data='[{"some": "json"}]') - #self.assertEqual(curl_from_request(post3.request), curl_str) + curl_str = 'curl -L -X POST -H "Accept-Encoding:gzip" -H "User-Agent:python-requests.org" -d \'[{"some": "json"}]\' "http://httpbin.org/post"' + post3 = requests.post(httpbin('post'), data='[{"some": "json"}]') + self.assertEqual(curl_from_request(post3.request), curl_str) if __name__ == '__main__': From 724ff7e4fa3af4d18b948c84fec48833006fea0b Mon Sep 17 00:00:00 2001 From: Kenneth Reitz Date: Mon, 5 Sep 2011 16:25:09 -0400 Subject: [PATCH 20/20] yep --- HISTORY.rst | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/HISTORY.rst b/HISTORY.rst index 33d56b93..0b129066 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -1,11 +1,12 @@ History ------- -* Automatic decoding of unicode, when available. +* Automatic decoding of unicode, based on HTTP Headers. * New ``decode_unicode`` setting * Removal of ``r.read/close`` methods -* New ``r.fo`` interface for advanced response usage. - +* New ``r.fo`` interface for advanced response usage.* +* Automatic expansion of parameterized headers +* Turn off Redirects for GET/HEAD requests 0.6.1 (2011-08-20) ++++++++++++++++++