Permalink
Browse files

Merge branch 'release/0.5.1'

  • Loading branch information...
2 parents 2d98ca7 + 1cdd1d0 commit 95ba6fcab2564a0e13f7fec99e4470a851b19c99 @kennethreitz kennethreitz committed Jul 24, 2011
View
@@ -5,4 +5,5 @@ nosetests.xml
pylint.txt
*.pyc
docs/_build
-toy.py
+toy.py
+.gitignore
View
@@ -25,4 +25,8 @@ Patches and Suggestions
- Daniele Tricoli 'Eriol'
- Richard Boulton
- Miguel Olivares <miguel@moliware.com>
-- Alberto Paro
+- Alberto Paro
+- Jérémy Bethmont
+- 潘旭 (Xu Pan)
+- Tamás Gulácsi
+- Rubén Abad
View
@@ -1,6 +1,19 @@
History
-------
+0.5.1 (2011-07-23)
+++++++++++++++++++
+
+* International Domain Name Support!
+* Access headers without fetching entire body (``read()``)
+* Use lists as dicts for parameters
+* Add Forced Basic Authentication
+* Forced Basic is default authentication type
+* ``python-requests.org`` default User-Agent header
+* CaseInsensitiveDict lower-case caching
+* Response.history bugfix
+
+
0.5.0 (2011-06-21)
++++++++++++++++++
View
@@ -36,14 +36,14 @@ It couldn't be simpler. ::
HTTPS? Basic Authentication? ::
- >>> r = requests.get('https://httpbin.ep.ip/basic-auth/user/pass')
+ >>> r = requests.get('https://httpbin.ep.io/basic-auth/user/pass')
>>> r.status_code
401
Uh oh, we're not authorized! Let's add authentication. ::
- >>> r = requests.get(https://httpbin.ep.ip/basic-auth/user/pass', auth=('user', 'pass'))
+ >>> r = requests.get(https://httpbin.ep.io/basic-auth/user/pass', auth=('user', 'pass'))
>>> r.status_code
200
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
@@ -1,4 +1,9 @@
-<h3>About Requests</h3>
+<p class="logo">
+ <a href="{{ pathto(master_doc) }}">
+ <img class="logo" src="{{ pathto('_static/requests-sidebar.png', 1) }}" alt="Logo"/>
+ </a>
+</p>
+
<p>
Requests is an elegant and simple HTTP library for Python, built for
human beings. You are currently looking at the documentation of the
@@ -1,4 +1,9 @@
-<h3><a href="http://python-requests.org">About Requests</a></h3>
+<p class="logo">
+ <a href="{{ pathto(master_doc) }}">
+ <img class="logo" src="{{ pathto('_static/requests-sidebar.png', 1) }}" alt="Logo"/>
+ </a>
+</p>
+
<p>
Requests is an elegant and simple HTTP library for Python, built for
human beings. You are currently looking at the documentation of the
@@ -91,8 +91,8 @@ div.sphinxsidebarwrapper {
}
div.sphinxsidebarwrapper p.logo {
- padding: 0 0 20px 0;
- margin: 0;
+ padding: 0;
+ margin: -10px 0 0 -20px;
text-align: center;
}
@@ -461,3 +461,9 @@ a:hover tt {
background-color: #ccc;
-webkit-border-radius: 3px;
}
+
+/* misc. */
+
+.revsys-inline {
+ display: none!important;
+}
View
@@ -13,7 +13,7 @@ important right here and provide links to the canonical documentation.
Main Interface
--------------
-All of Request's functionality can be accessed by these 5 methods. They
+All of Request's functionality can be accessed by these 6 methods. They
all return a :class:`Response <models.Response>` object.
.. autofunction:: head
View
@@ -0,0 +1,15 @@
+How to Help
+===========
+
+Requests is under active development, and contributions are more than welcome!
+
+
+What Needs to be Done
+---------------------
+
+- OAuth Support (`#65 <https://github.com/kennethreitz/requests/issues/65>`_)
+- HTTP Cert Checking (`#30 <https://github.com/kennethreitz/requests/issues/30>`_)
+- Removal of Poster (`#68 <https://github.com/kennethreitz/requests/issues/68>`_)
+- Python 3.x Support (`#70 <https://github.com/kennethreitz/requests/issues/70>`_)
+- Kerberos Support (`#47 <https://github.com/kennethreitz/requests/issues/47>`_)
+- More Flexible Context Manager (`#69 <https://github.com/kennethreitz/requests/issues/69>`_)
View
@@ -87,3 +87,4 @@ you.
:maxdepth: 2
dev/internals
+ dev/todo
View

Large diffs are not rendered by default.

Oops, something went wrong.
View
@@ -53,4 +53,6 @@ def __getattribute__(self, key):
return None
return object.__getattribute__(self, key)
-settings = Settings()
+settings = Settings()
+settings.base_headers = {'User-Agent': 'python-requests.org'}
+settings.accept_gzip = True
View
@@ -12,8 +12,8 @@
"""
__title__ = 'requests'
-__version__ = '0.5.0'
-__build__ = 0x000500
+__version__ = '0.5.1'
+__build__ = 0x000501
__author__ = 'Kenneth Reitz'
__license__ = 'ISC'
__copyright__ = 'Copyright 2011 Kenneth Reitz'
View
@@ -12,11 +12,11 @@
import zlib
from urllib2 import HTTPError
-from urlparse import urlparse
+from urlparse import urlparse, urlunparse
from datetime import datetime
from .config import settings
-from .monkeys import Request as _Request, HTTPBasicAuthHandler, HTTPDigestAuthHandler, HTTPRedirectHandler
+from .monkeys import Request as _Request, HTTPBasicAuthHandler, HTTPForcedBasicAuthHandler, HTTPDigestAuthHandler, HTTPRedirectHandler
from .structures import CaseInsensitiveDict
from .packages.poster.encode import multipart_encode
from .packages.poster.streaminghttp import register_openers, get_handlers
@@ -81,6 +81,23 @@ def __init__(self,
self.sent = False
+ # Header manipulation and defaults.
+
+ if settings.accept_gzip:
+ settings.base_headers.update({'Accept-Encoding': 'gzip'})
+
+ if headers:
+ headers = CaseInsensitiveDict(self.headers)
+ else:
+ headers = CaseInsensitiveDict()
+
+ for (k, v) in settings.base_headers.items():
+ if k not in headers:
+ headers[k] = v
+
+ self.headers = headers
+
+
def __repr__(self):
return '<Request [%s]>' % (self.method)
@@ -151,18 +168,11 @@ def build(resp):
try:
response.headers = CaseInsensitiveDict(getattr(resp.info(), 'dict', None))
- response.content = resp.read()
+ response.read = resp.read
+ response.close = resp.close
except AttributeError:
pass
- if response.headers['content-encoding'] == 'gzip':
- try:
- response.content = zlib.decompress(response.content, 16+zlib.MAX_WBITS)
- except zlib.error:
- pass
-
- # TODO: Support deflate
-
response.url = getattr(resp, 'url', None)
return response
@@ -172,10 +182,7 @@ def build(resp):
r = build(resp)
- if r.status_code in REDIRECT_STATI:
- self.redirect = True
-
- if self.redirect:
+ if r.status_code in REDIRECT_STATI and not self.redirect:
while (
('location' in r.headers) and
@@ -218,26 +225,32 @@ def _encode_params(data):
"""Encode parameters in a piece of data.
If the data supplied is a dictionary, encodes each parameter in it, and
- returns the dictionary of encoded parameters, and a urlencoded version
- of that.
+ returns a list of tuples containing the encoded parameters, and a urlencoded
+ version of that.
Otherwise, assumes the data is already encoded appropriately, and
returns it twice.
"""
if hasattr(data, 'items'):
- result = {}
- for (k, v) in data.items():
- result[k.encode('utf-8') if isinstance(k, unicode) else k] \
- = v.encode('utf-8') if isinstance(v, unicode) else v
- return result, urllib.urlencode(result)
+ result = []
+ for k, vs in data.items():
+ for v in isinstance(vs, list) and vs or [vs]:
+ result.append((k.encode('utf-8') if isinstance(k, unicode) else k,
+ v.encode('utf-8') if isinstance(v, unicode) else v))
+ return result, urllib.urlencode(result, doseq=True)
else:
return data, data
def _build_url(self):
"""Build the actual URL to use"""
+ # Support for unicode domain names.
+ parsed_url = list(urlparse(self.url))
+ parsed_url[1] = parsed_url[1].encode('idna')
+ self.url = urlunparse(parsed_url)
+
if self._enc_params:
if urlparse(self.url).query:
return '%s&%s' % (self.url, self._enc_params)
@@ -319,10 +332,6 @@ def send(self, anyway=False):
return self.sent
- def read(self, *args):
- return self.response.read()
-
-
class Response(object):
"""The core :class:`Response <models.Response>` object. All
@@ -335,7 +344,7 @@ def __init__(self):
#: Raw content of the response, in bytes.
#: If ``content-encoding`` of response was set to ``gzip``, the
#: response data will be automatically deflated.
- self.content = None
+ self._content = None
#: Integer Code of responded HTTP Status.
self.status_code = None
#: Case-insensitive Dictionary of Response Headers.
@@ -365,17 +374,25 @@ def __nonzero__(self):
return not self.error
+ def __getattr__(self, name):
+ """Read and returns the full stream when accessing to :attr: `content`"""
+ if name == 'content':
+ if self._content is not None:
+ return self._content
+ self._content = self.read()
+ if self.headers.get('content-encoding', '') == 'gzip':
+ try:
+ self._content = zlib.decompress(self._content, 16+zlib.MAX_WBITS)
+ except zlib.error:
+ pass
+ return self._content
+
+
def raise_for_status(self):
- """Raises stored :class:`HTTPError`, if one occured."""
+ """Raises stored :class:`HTTPError` or :class:`URLError`, if one occured."""
if self.error:
raise self.error
- def read(self, *args):
- """Returns :attr:`content`. Used for file-like object compatiblity."""
-
- return self.content
-
-
class AuthManager(object):
"""Requests Authentication Manager."""
@@ -532,17 +549,18 @@ class AuthObject(object):
_handlers = {
'basic': HTTPBasicAuthHandler,
+ 'forced_basic': HTTPForcedBasicAuthHandler,
'digest': HTTPDigestAuthHandler,
'proxy_basic': urllib2.ProxyBasicAuthHandler,
'proxy_digest': urllib2.ProxyDigestAuthHandler
}
- def __init__(self, username, password, handler='basic', realm=None):
+ def __init__(self, username, password, handler='forced_basic', realm=None):
self.username = username
self.password = password
self.realm = realm
if isinstance(handler, basestring):
- self.handler = self._handlers.get(handler.lower(), urllib2.HTTPBasicAuthHandler)
+ self.handler = self._handlers.get(handler.lower(), HTTPForcedBasicAuthHandler)
else:
self.handler = handler
Oops, something went wrong.

0 comments on commit 95ba6fc

Please sign in to comment.