Compare commits

...

16 Commits

Author SHA1 Message Date
Kenneth Reitz
c60b72e2d0 v1.0.3 2012-12-18 04:50:41 -05:00
Kenneth Reitz
b2d03ac9a2 Merge pull request #1026 from TorKlingberg/master
Added requirements.txt to MANIFEST.in
2012-12-17 21:49:45 -08:00
Kenneth Reitz
027fbd3d51 Merge pull request #1030 from bboe/cookie_fix
Fix issue 1027. Always persist cookies.
2012-12-17 21:45:49 -08:00
Kenneth Reitz
a2f773a9fc Merge pull request #1031 from sigmavirus24/master
Just a bit of linting
2012-12-17 21:44:56 -08:00
Ian Cordasco
68d394952a A bit of linting.
Mostly removed a whole bunch of unused imports.
2012-12-17 20:19:11 -05:00
Bryce Boe
e355d6ac6c Fix issue 1027. Always persist cookies. 2012-12-17 17:13:18 -08:00
Apoc2400
dc74223461 MANIFEST.in contained test_requests.py but was missing requirements.txt that it depends on.
Added requirements.txt.
Now both files will be included in the .tar.gz file that can be downloaded from http://pypi.python.org/pypi/requests
2012-12-18 00:16:29 +01:00
Kenneth Reitz
5c4aa0bcb7 Merge pull request #1024 from etscrivner/master
Fix HTTP method encoding problem with attached files
2012-12-17 12:53:22 -08:00
Eric Scrivner
8c01865d62 Remove unicode encoding for HTTP method. 2012-12-17 12:39:15 -08:00
Eric Scrivner
916e6fcd64 Add unit-test to reproduce encoding error. 2012-12-17 12:28:08 -08:00
Kenneth Reitz
4701243199 Merge pull request #1009 from Lukasa/master
Auth documentation.
2012-12-17 11:27:36 -08:00
Cory Benfield
a7c5d5e8ac Split authentication out into a separate file. 2012-12-17 19:25:21 +00:00
Kenneth Reitz
d0f23820b5 Merge pull request #1022 from kisielk/master
JSON-related doc fixes
2012-12-17 11:03:40 -08:00
Kamil Kisiel
fe0b0a989f Fixed a few spots in the docs that were still using json as a property. 2012-12-17 11:02:06 -08:00
Cory Benfield
54b77afbb5 Uh, typo broke the link. Yeah. That happened. 2012-12-17 18:31:56 +00:00
Cory Benfield
be364e13d3 Update auth documentation with org info. 2012-12-17 18:31:56 +00:00
12 changed files with 124 additions and 112 deletions

View File

@@ -3,6 +3,12 @@
History
-------
1.0.3 (2012-12-18)
++++++++++++++++++
- Fix file upload encoding bug
- Fix cookie behavior
1.0.2 (2012-12-17)
++++++++++++++++++

View File

@@ -1 +1 @@
include README.rst LICENSE NOTICE HISTORY.rst test_requests.py requests/cacert.pem
include README.rst LICENSE NOTICE HISTORY.rst test_requests.py requirements.txt requests/cacert.pem

View File

@@ -27,7 +27,7 @@ Things shouldnt be this way. Not in Python.
'utf-8'
>>> r.text
u'{"type":"User"...'
>>> r.json
>>> r.json()
{u'private_gists': 419, u'total_private_repos': 77, ...}
See `similar code, without Requests <https://gist.github.com/973705>`_.
@@ -90,6 +90,7 @@ instructions for getting the most out of Requests.
user/install
user/quickstart
user/advanced
user/authentication
Community Guide

View File

@@ -0,0 +1,84 @@
.. _authentication:
Authentication
==============
This document discusses using various kinds of authentication with Requests.
Many web services require authentication, and there are many different types.
Below, we outline various forms of authentication available in Requests, from
the simple to the complex.
Basic Authentication
--------------------
Many web services that require authentication accept HTTP Basic Auth. This is
the simplest kind, and Requests supports it straight out of the box.
Making requests with HTTP Basic Auth is very simple::
>>> from requests.auth import HTTPBasicAuth
>>> requests.get('https://api.github.com/user', auth=HTTPBasicAuth('user', 'pass'))
<Response [200]>
In fact, HTTP Basic Auth is so common that Requests provides a handy shorthand
for using it::
>>> requests.get('https://api.github.com/user', auth=('user', 'pass'))
<Response [200]>
Providing the credentials in a tuple like this is exactly the same as the
``HTTPBasicAuth`` example above.
Digest Authentication
---------------------
Another very popular form of HTTP Authentication is Digest Authentication,
and Requests supports this out of the box as well::
>>> from requests.auth import HTTPDigestAuth
>>> url = 'http://httpbin.org/digest-auth/auth/user/pass'
>>> requests.get(url, auth=HTTPDigestAuth('user', 'pass'))
<Response [200]>
Other Authentication
--------------------
Requests is designed to allow other forms of authentication to be easily and
quickly plugged in. Members of the open-source community frequently write
authentication handlers for more complicated or less commonly-used forms of
authentication. Some of the best have been brought together under the
`Requests organization`_, including:
- OAuth_
- Kerberos_
- NTLM_
If you want to use any of these forms of authentication, go straight to their
Github page and follow the instructions.
New Forms of Authentication
---------------------------
If you can't find a good implementation of the form of authentication you
want, you can implement it yourself. Requests makes it easy to add your own
forms of authentication.
To do so, subclass :class:`requests.auth.AuthBase` and implement the
``__call__()`` method. When an authentication handler is attached to a request,
it is called during request setup. The ``__call__`` method must therefore do
whatever is required to make the authentication work. Some forms of
authentication will additionally add hooks to provide further functionality.
Examples can be found under the `Requests organization`_ and in the
``auth.py`` file.
.. _OAuth: https://github.com/requests/requests-oauthlib
.. _Kerberos: https://github.com/requests/requests-kerberos
.. _NTLM: https://github.com/requests/requests-ntlm
.. _Requests organization: https://github.com/requests

View File

@@ -128,10 +128,10 @@ There's also a builtin JSON decoder, in case you're dealing with JSON data::
>>> import requests
>>> r = requests.get('https://github.com/timeline.json')
>>> r.json
>>> r.json()
[{u'repository': {u'open_issues': 0, u'url': 'https://github.com/...
In case the JSON decoding fails, ``r.json`` simply returns ``None``.
In case the JSON decoding fails, ``r.json`` raises an exception.
Raw Response Content
@@ -337,80 +337,6 @@ parameter::
'{"cookies": {"cookies_are": "working"}}'
Basic Authentication
--------------------
Many web services require authentication. There are many different types of
authentication, but the most common is HTTP Basic Auth.
Making requests with Basic Auth is extremely simple::
>>> from requests.auth import HTTPBasicAuth
>>> requests.get('https://api.github.com/user', auth=HTTPBasicAuth('user', 'pass'))
<Response [200]>
Due to the prevalence of HTTP Basic Auth, requests provides a shorthand for
this authentication method::
>>> requests.get('https://api.github.com/user', auth=('user', 'pass'))
<Response [200]>
Providing the credentials as a tuple in this fashion is functionally equivalent
to the ``HTTPBasicAuth`` example above.
Digest Authentication
---------------------
Another popular form of web service protection is Digest Authentication::
>>> from requests.auth import HTTPDigestAuth
>>> url = 'http://httpbin.org/digest-auth/auth/user/pass'
>>> requests.get(url, auth=HTTPDigestAuth('user', 'pass'))
<Response [200]>
OAuth Authentication
--------------------
Requests features robust, built-in OAuth support!
OAuth takes many forms, so let's take a look at a few different forms::
import requests
from requests.auth import OAuth1
url = u'https://api.twitter.com/1/account/settings.json'
client_key = u'...'
client_secret = u'...'
resource_owner_key = u'...'
resource_owner_secret = u'...'
Query signing::
queryoauth = OAuth1(client_key, client_secret,
resource_owner_key, resource_owner_secret,
signature_type='query')
r = requests.get(url, auth=queryoauth)
Header signing::
headeroauth = OAuth1(client_key, client_secret,
resource_owner_key, resource_owner_secret,
signature_type='auth_header')
r = requests.get(url, auth=headeroauth)
Body signing::
bodyoauth = OAuth1(client_key, client_secret,
resource_owner_key, resource_owner_secret,
signature_type='body')
r = requests.post(url, auth=bodyoauth)
Redirection and History
-----------------------

View File

@@ -42,8 +42,8 @@ is at <http://python-requests.org>.
"""
__title__ = 'requests'
__version__ = '1.0.2'
__build__ = 0x01002
__version__ = '1.0.3'
__build__ = 0x01003
__author__ = 'Kenneth Reitz'
__license__ = 'Apache 2.0'
__copyright__ = 'Copyright 2012 Kenneth Reitz'

View File

@@ -8,11 +8,9 @@ This module contains the transport adapters that Requests uses to define
and maintain connections.
"""
import os
import socket
from .models import Response
from .auth import HTTPProxyAuth
from .packages.urllib3.poolmanager import PoolManager, proxy_from_url
from .hooks import dispatch_hook
from .compat import urlparse
@@ -83,7 +81,6 @@ class HTTPAdapter(BaseAdapter):
else:
conn.cert_file = cert
def build_response(self, req, resp):
response = Response()
@@ -125,7 +122,6 @@ class HTTPAdapter(BaseAdapter):
return conn
def close(self):
"""Dispose of any internal state.

View File

@@ -165,4 +165,4 @@ class HTTPDigestAuth(AuthBase):
if self.last_nonce:
r.headers['Authorization'] = self.build_digest_header(r.method, r.url)
r.register_hook('response', self.handle_401)
return r
return r

View File

@@ -11,24 +11,21 @@ import collections
import logging
from io import BytesIO
from .hooks import dispatch_hook, default_hooks
from .hooks import default_hooks
from .structures import CaseInsensitiveDict
from .status_codes import codes
from .auth import HTTPBasicAuth, HTTPProxyAuth
from .cookies import cookiejar_from_dict, extract_cookies_to_jar, get_cookie_header
from .auth import HTTPBasicAuth
from .cookies import cookiejar_from_dict, get_cookie_header
from .packages.urllib3.filepost import encode_multipart_formdata
from .exceptions import (
ConnectionError, HTTPError, RequestException, Timeout, TooManyRedirects,
URLRequired, SSLError, MissingSchema, InvalidSchema, InvalidURL)
from .exceptions import HTTPError, RequestException, MissingSchema, InvalidURL
from .utils import (
get_encoding_from_headers, stream_untransfer, guess_filename, requote_uri,
stream_decode_response_unicode, get_netrc_auth, get_environ_proxies,
to_key_val_list, DEFAULT_CA_BUNDLE_PATH, parse_header_links, iter_slices,
guess_json_utf)
stream_untransfer, guess_filename, requote_uri,
stream_decode_response_unicode, to_key_val_list, parse_header_links,
iter_slices, guess_json_utf)
from .compat import (
cookielib, urlparse, urlunparse, urljoin, urlsplit, urlencode, str, bytes,
StringIO, is_py2, chardet, json, builtin_str, urldefrag, basestring)
cookielib, urlparse, urlunparse, urlsplit, urlencode, str, bytes, StringIO,
is_py2, chardet, json, builtin_str, basestring)
REDIRECT_STATI = (codes.moved, codes.found, codes.other, codes.temporary_moved)
CONTENT_CHUNK_SIZE = 10 * 1024
@@ -222,13 +219,9 @@ class PreparedRequest(RequestEncodingMixin, RequestHooksMixin):
def prepare_method(self, method):
"""Prepares the given HTTP method."""
try:
method = unicode(method)
except NameError:
# We're on Python 3.
method = str(method)
self.method = method.upper()
self.method = method
if self.method is not None:
self.method = self.method.upper()
def prepare_url(self, url, params):
"""Prepares the given HTTP URL."""
@@ -389,7 +382,6 @@ class Response(object):
#: up here. The list is sorted from the oldest to the most recent request.
self.history = []
self.reason = None
#: A CookieJar of Cookies the server sent back.

View File

@@ -71,10 +71,6 @@ class SessionRedirectMixin(object):
# ((resp.status_code is codes.see_other))
while (('location' in resp.headers and resp.status_code in REDIRECT_STATI)):
# Persist cookies.
for cookie in resp.cookies:
self.cookies.set_cookie(cookie)
resp.content # Consume socket so it can be released
if i >= self.max_redirects:
@@ -265,6 +261,10 @@ class Session(SessionRedirectMixin):
# Send the request.
resp = self.send(prep, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies)
# Persist cookies.
for cookie in resp.cookies:
self.cookies.set_cookie(cookie)
# Redirect resolving generator.
gen = self.resolve_redirects(resp, req, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies)

View File

@@ -20,7 +20,7 @@ from netrc import netrc, NetrcParseError
from . import __version__
from .compat import parse_http_list as _parse_list_header
from .compat import quote, quote_plus, urlparse, basestring, bytes, str, OrderedDict
from .compat import quote, urlparse, bytes, str, OrderedDict
from .cookies import RequestsCookieJar, cookiejar_from_dict
_hush_pyflakes = (RequestsCookieJar,)
@@ -254,7 +254,6 @@ def unquote_header_value(value, is_filename=False):
return value
def dict_from_cookiejar(cj):
"""Returns a key/value dictionary from a CookieJar.

View File

@@ -3,6 +3,7 @@
"""Tests for Requests."""
import json
import os
import unittest
@@ -243,7 +244,14 @@ class RequestsTestCase(unittest.TestCase):
self.assertEqual(r.status_code, 200)
self.assertEqual(r.url, httpbin('get?test=foo&test=baz'))
def test_different_encodings_dont_break_post(self):
r = requests.post(httpbin('post'),
data={'stuff': json.dumps({'a': 123})},
params={'blah': 'asdf1234'},
files={'file': ('test_requests.py', open(__file__, 'rb'))})
self.assertEqual(r.status_code, 200)
if __name__ == '__main__':
unittest.main()
unittest.main()