Index: swarm_client/third_party/requests/cookies.py |
=================================================================== |
--- swarm_client/third_party/requests/cookies.py (revision 235167) |
+++ swarm_client/third_party/requests/cookies.py (working copy) |
@@ -1,406 +0,0 @@ |
-# -*- coding: utf-8 -*- |
- |
-""" |
-Compatibility code to be able to use `cookielib.CookieJar` with requests. |
- |
-requests.utils imports from here, so be careful with imports. |
-""" |
- |
-import time |
-import collections |
-from .compat import cookielib, urlparse, Morsel |
- |
-try: |
- import threading |
- # grr, pyflakes: this fixes "redefinition of unused 'threading'" |
- threading |
-except ImportError: |
- import dummy_threading as threading |
- |
- |
-class MockRequest(object): |
- """Wraps a `requests.Request` to mimic a `urllib2.Request`. |
- |
- The code in `cookielib.CookieJar` expects this interface in order to correctly |
- manage cookie policies, i.e., determine whether a cookie can be set, given the |
- domains of the request and the cookie. |
- |
- The original request object is read-only. The client is responsible for collecting |
- the new headers via `get_new_headers()` and interpreting them appropriately. You |
- probably want `get_cookie_header`, defined below. |
- """ |
- |
- def __init__(self, request): |
- self._r = request |
- self._new_headers = {} |
- self.type = urlparse(self._r.url).scheme |
- |
- def get_type(self): |
- return self.type |
- |
- def get_host(self): |
- return urlparse(self._r.url).netloc |
- |
- def get_origin_req_host(self): |
- return self.get_host() |
- |
- def get_full_url(self): |
- return self._r.url |
- |
- def is_unverifiable(self): |
- return True |
- |
- def has_header(self, name): |
- return name in self._r.headers or name in self._new_headers |
- |
- def get_header(self, name, default=None): |
- return self._r.headers.get(name, self._new_headers.get(name, default)) |
- |
- def add_header(self, key, val): |
- """cookielib has no legitimate use for this method; add it back if you find one.""" |
- raise NotImplementedError("Cookie headers should be added with add_unredirected_header()") |
- |
- def add_unredirected_header(self, name, value): |
- self._new_headers[name] = value |
- |
- def get_new_headers(self): |
- return self._new_headers |
- |
- @property |
- def unverifiable(self): |
- return self.is_unverifiable() |
- |
- @property |
- def origin_req_host(self): |
- return self.get_origin_req_host() |
- |
- @property |
- def host(self): |
- return self.get_host() |
- |
- |
-class MockResponse(object): |
- """Wraps a `httplib.HTTPMessage` to mimic a `urllib.addinfourl`. |
- |
- ...what? Basically, expose the parsed HTTP headers from the server response |
- the way `cookielib` expects to see them. |
- """ |
- |
- def __init__(self, headers): |
- """Make a MockResponse for `cookielib` to read. |
- |
- :param headers: a httplib.HTTPMessage or analogous carrying the headers |
- """ |
- self._headers = headers |
- |
- def info(self): |
- return self._headers |
- |
- def getheaders(self, name): |
- self._headers.getheaders(name) |
- |
- |
-def extract_cookies_to_jar(jar, request, response): |
- """Extract the cookies from the response into a CookieJar. |
- |
- :param jar: cookielib.CookieJar (not necessarily a RequestsCookieJar) |
- :param request: our own requests.Request object |
- :param response: urllib3.HTTPResponse object |
- """ |
- if not (hasattr(response, '_original_response') and |
- response._original_response): |
- return |
- # the _original_response field is the wrapped httplib.HTTPResponse object, |
- req = MockRequest(request) |
- # pull out the HTTPMessage with the headers and put it in the mock: |
- res = MockResponse(response._original_response.msg) |
- jar.extract_cookies(res, req) |
- |
- |
-def get_cookie_header(jar, request): |
- """Produce an appropriate Cookie header string to be sent with `request`, or None.""" |
- r = MockRequest(request) |
- jar.add_cookie_header(r) |
- return r.get_new_headers().get('Cookie') |
- |
- |
-def remove_cookie_by_name(cookiejar, name, domain=None, path=None): |
- """Unsets a cookie by name, by default over all domains and paths. |
- |
- Wraps CookieJar.clear(), is O(n). |
- """ |
- clearables = [] |
- for cookie in cookiejar: |
- if cookie.name == name: |
- if domain is None or domain == cookie.domain: |
- if path is None or path == cookie.path: |
- clearables.append((cookie.domain, cookie.path, cookie.name)) |
- |
- for domain, path, name in clearables: |
- cookiejar.clear(domain, path, name) |
- |
- |
-class CookieConflictError(RuntimeError): |
- """There are two cookies that meet the criteria specified in the cookie jar. |
- Use .get and .set and include domain and path args in order to be more specific.""" |
- |
- |
-class RequestsCookieJar(cookielib.CookieJar, collections.MutableMapping): |
- """Compatibility class; is a cookielib.CookieJar, but exposes a dict interface. |
- |
- This is the CookieJar we create by default for requests and sessions that |
- don't specify one, since some clients may expect response.cookies and |
- session.cookies to support dict operations. |
- |
- Don't use the dict interface internally; it's just for compatibility with |
- with external client code. All `requests` code should work out of the box |
- with externally provided instances of CookieJar, e.g., LWPCookieJar and |
- FileCookieJar. |
- |
- Caution: dictionary operations that are normally O(1) may be O(n). |
- |
- Unlike a regular CookieJar, this class is pickleable. |
- """ |
- |
- def get(self, name, default=None, domain=None, path=None): |
- """Dict-like get() that also supports optional domain and path args in |
- order to resolve naming collisions from using one cookie jar over |
- multiple domains. Caution: operation is O(n), not O(1).""" |
- try: |
- return self._find_no_duplicates(name, domain, path) |
- except KeyError: |
- return default |
- |
- def set(self, name, value, **kwargs): |
- """Dict-like set() that also supports optional domain and path args in |
- order to resolve naming collisions from using one cookie jar over |
- multiple domains.""" |
- # support client code that unsets cookies by assignment of a None value: |
- if value is None: |
- remove_cookie_by_name(self, name, domain=kwargs.get('domain'), path=kwargs.get('path')) |
- return |
- |
- if isinstance(value, Morsel): |
- c = morsel_to_cookie(value) |
- else: |
- c = create_cookie(name, value, **kwargs) |
- self.set_cookie(c) |
- return c |
- |
- def keys(self): |
- """Dict-like keys() that returns a list of names of cookies from the jar. |
- See values() and items().""" |
- keys = [] |
- for cookie in iter(self): |
- keys.append(cookie.name) |
- return keys |
- |
- def values(self): |
- """Dict-like values() that returns a list of values of cookies from the jar. |
- See keys() and items().""" |
- values = [] |
- for cookie in iter(self): |
- values.append(cookie.value) |
- return values |
- |
- def items(self): |
- """Dict-like items() that returns a list of name-value tuples from the jar. |
- See keys() and values(). Allows client-code to call "dict(RequestsCookieJar) |
- and get a vanilla python dict of key value pairs.""" |
- items = [] |
- for cookie in iter(self): |
- items.append((cookie.name, cookie.value)) |
- return items |
- |
- def list_domains(self): |
- """Utility method to list all the domains in the jar.""" |
- domains = [] |
- for cookie in iter(self): |
- if cookie.domain not in domains: |
- domains.append(cookie.domain) |
- return domains |
- |
- def list_paths(self): |
- """Utility method to list all the paths in the jar.""" |
- paths = [] |
- for cookie in iter(self): |
- if cookie.path not in paths: |
- paths.append(cookie.path) |
- return paths |
- |
- def multiple_domains(self): |
- """Returns True if there are multiple domains in the jar. |
- Returns False otherwise.""" |
- domains = [] |
- for cookie in iter(self): |
- if cookie.domain is not None and cookie.domain in domains: |
- return True |
- domains.append(cookie.domain) |
- return False # there is only one domain in jar |
- |
- def get_dict(self, domain=None, path=None): |
- """Takes as an argument an optional domain and path and returns a plain old |
- Python dict of name-value pairs of cookies that meet the requirements.""" |
- dictionary = {} |
- for cookie in iter(self): |
- if (domain is None or cookie.domain == domain) and (path is None |
- or cookie.path == path): |
- dictionary[cookie.name] = cookie.value |
- return dictionary |
- |
- def __getitem__(self, name): |
- """Dict-like __getitem__() for compatibility with client code. Throws exception |
- if there are more than one cookie with name. In that case, use the more |
- explicit get() method instead. Caution: operation is O(n), not O(1).""" |
- |
- return self._find_no_duplicates(name) |
- |
- def __setitem__(self, name, value): |
- """Dict-like __setitem__ for compatibility with client code. Throws exception |
- if there is already a cookie of that name in the jar. In that case, use the more |
- explicit set() method instead.""" |
- |
- self.set(name, value) |
- |
- def __delitem__(self, name): |
- """Deletes a cookie given a name. Wraps cookielib.CookieJar's remove_cookie_by_name().""" |
- remove_cookie_by_name(self, name) |
- |
- def set_cookie(self, cookie, *args, **kwargs): |
- if cookie.value.startswith('"') and cookie.value.endswith('"'): |
- cookie.value = cookie.value.replace('\\"', '') |
- return super(RequestsCookieJar, self).set_cookie(cookie, *args, **kwargs) |
- |
- def update(self, other): |
- """Updates this jar with cookies from another CookieJar or dict-like""" |
- if isinstance(other, cookielib.CookieJar): |
- for cookie in other: |
- self.set_cookie(cookie) |
- else: |
- super(RequestsCookieJar, self).update(other) |
- |
- def _find(self, name, domain=None, path=None): |
- """Requests uses this method internally to get cookie values. Takes as args name |
- and optional domain and path. Returns a cookie.value. If there are conflicting cookies, |
- _find arbitrarily chooses one. See _find_no_duplicates if you want an exception thrown |
- if there are conflicting cookies.""" |
- for cookie in iter(self): |
- if cookie.name == name: |
- if domain is None or cookie.domain == domain: |
- if path is None or cookie.path == path: |
- return cookie.value |
- |
- raise KeyError('name=%r, domain=%r, path=%r' % (name, domain, path)) |
- |
- def _find_no_duplicates(self, name, domain=None, path=None): |
- """__get_item__ and get call _find_no_duplicates -- never used in Requests internally. |
- Takes as args name and optional domain and path. Returns a cookie.value. |
- Throws KeyError if cookie is not found and CookieConflictError if there are |
- multiple cookies that match name and optionally domain and path.""" |
- toReturn = None |
- for cookie in iter(self): |
- if cookie.name == name: |
- if domain is None or cookie.domain == domain: |
- if path is None or cookie.path == path: |
- if toReturn is not None: # if there are multiple cookies that meet passed in criteria |
- raise CookieConflictError('There are multiple cookies with name, %r' % (name)) |
- toReturn = cookie.value # we will eventually return this as long as no cookie conflict |
- |
- if toReturn: |
- return toReturn |
- raise KeyError('name=%r, domain=%r, path=%r' % (name, domain, path)) |
- |
- def __getstate__(self): |
- """Unlike a normal CookieJar, this class is pickleable.""" |
- state = self.__dict__.copy() |
- # remove the unpickleable RLock object |
- state.pop('_cookies_lock') |
- return state |
- |
- def __setstate__(self, state): |
- """Unlike a normal CookieJar, this class is pickleable.""" |
- self.__dict__.update(state) |
- if '_cookies_lock' not in self.__dict__: |
- self._cookies_lock = threading.RLock() |
- |
- def copy(self): |
- """Return a copy of this RequestsCookieJar.""" |
- new_cj = RequestsCookieJar() |
- new_cj.update(self) |
- return new_cj |
- |
- |
-def create_cookie(name, value, **kwargs): |
- """Make a cookie from underspecified parameters. |
- |
- By default, the pair of `name` and `value` will be set for the domain '' |
- and sent on every request (this is sometimes called a "supercookie"). |
- """ |
- result = dict( |
- version=0, |
- name=name, |
- value=value, |
- port=None, |
- domain='', |
- path='/', |
- secure=False, |
- expires=None, |
- discard=True, |
- comment=None, |
- comment_url=None, |
- rest={'HttpOnly': None}, |
- rfc2109=False,) |
- |
- badargs = set(kwargs) - set(result) |
- if badargs: |
- err = 'create_cookie() got unexpected keyword arguments: %s' |
- raise TypeError(err % list(badargs)) |
- |
- result.update(kwargs) |
- result['port_specified'] = bool(result['port']) |
- result['domain_specified'] = bool(result['domain']) |
- result['domain_initial_dot'] = result['domain'].startswith('.') |
- result['path_specified'] = bool(result['path']) |
- |
- return cookielib.Cookie(**result) |
- |
- |
-def morsel_to_cookie(morsel): |
- """Convert a Morsel object into a Cookie containing the one k/v pair.""" |
- expires = None |
- if morsel["max-age"]: |
- expires = time.time() + morsel["max-age"] |
- elif morsel['expires']: |
- expires = morsel['expires'] |
- if type(expires) == type(""): |
- time_template = "%a, %d-%b-%Y %H:%M:%S GMT" |
- expires = time.mktime(time.strptime(expires, time_template)) |
- c = create_cookie( |
- name=morsel.key, |
- value=morsel.value, |
- version=morsel['version'] or 0, |
- port=None, |
- domain=morsel['domain'], |
- path=morsel['path'], |
- secure=bool(morsel['secure']), |
- expires=expires, |
- discard=False, |
- comment=morsel['comment'], |
- comment_url=bool(morsel['comment']), |
- rest={'HttpOnly': morsel['httponly']}, |
- rfc2109=False,) |
- return c |
- |
- |
-def cookiejar_from_dict(cookie_dict, cookiejar=None): |
- """Returns a CookieJar from a key/value dictionary. |
- |
- :param cookie_dict: Dict of key/values to insert into CookieJar. |
- """ |
- if cookiejar is None: |
- cookiejar = RequestsCookieJar() |
- |
- if cookie_dict is not None: |
- for name in cookie_dict: |
- cookiejar.set_cookie(create_cookie(name, cookie_dict[name])) |
- return cookiejar |