annotate CSP2/CSP2_env/env-d9b9114564458d9d-741b3de822f2aaca6c6caa4325c4afce/lib/python3.8/site-packages/requests/cookies.py @ 69:33d812a61356

planemo upload commit 2e9511a184a1ca667c7be0c6321a36dc4e3d116d
author jpayne
date Tue, 18 Mar 2025 17:55:14 -0400
parents
children
rev   line source
jpayne@69 1 """
jpayne@69 2 requests.cookies
jpayne@69 3 ~~~~~~~~~~~~~~~~
jpayne@69 4
jpayne@69 5 Compatibility code to be able to use `http.cookiejar.CookieJar` with requests.
jpayne@69 6
jpayne@69 7 requests.utils imports from here, so be careful with imports.
jpayne@69 8 """
jpayne@69 9
jpayne@69 10 import calendar
jpayne@69 11 import copy
jpayne@69 12 import time
jpayne@69 13
jpayne@69 14 from ._internal_utils import to_native_string
jpayne@69 15 from .compat import Morsel, MutableMapping, cookielib, urlparse, urlunparse
jpayne@69 16
jpayne@69 17 try:
jpayne@69 18 import threading
jpayne@69 19 except ImportError:
jpayne@69 20 import dummy_threading as threading
jpayne@69 21
jpayne@69 22
jpayne@69 23 class MockRequest:
jpayne@69 24 """Wraps a `requests.Request` to mimic a `urllib2.Request`.
jpayne@69 25
jpayne@69 26 The code in `http.cookiejar.CookieJar` expects this interface in order to correctly
jpayne@69 27 manage cookie policies, i.e., determine whether a cookie can be set, given the
jpayne@69 28 domains of the request and the cookie.
jpayne@69 29
jpayne@69 30 The original request object is read-only. The client is responsible for collecting
jpayne@69 31 the new headers via `get_new_headers()` and interpreting them appropriately. You
jpayne@69 32 probably want `get_cookie_header`, defined below.
jpayne@69 33 """
jpayne@69 34
jpayne@69 35 def __init__(self, request):
jpayne@69 36 self._r = request
jpayne@69 37 self._new_headers = {}
jpayne@69 38 self.type = urlparse(self._r.url).scheme
jpayne@69 39
jpayne@69 40 def get_type(self):
jpayne@69 41 return self.type
jpayne@69 42
jpayne@69 43 def get_host(self):
jpayne@69 44 return urlparse(self._r.url).netloc
jpayne@69 45
jpayne@69 46 def get_origin_req_host(self):
jpayne@69 47 return self.get_host()
jpayne@69 48
jpayne@69 49 def get_full_url(self):
jpayne@69 50 # Only return the response's URL if the user hadn't set the Host
jpayne@69 51 # header
jpayne@69 52 if not self._r.headers.get("Host"):
jpayne@69 53 return self._r.url
jpayne@69 54 # If they did set it, retrieve it and reconstruct the expected domain
jpayne@69 55 host = to_native_string(self._r.headers["Host"], encoding="utf-8")
jpayne@69 56 parsed = urlparse(self._r.url)
jpayne@69 57 # Reconstruct the URL as we expect it
jpayne@69 58 return urlunparse(
jpayne@69 59 [
jpayne@69 60 parsed.scheme,
jpayne@69 61 host,
jpayne@69 62 parsed.path,
jpayne@69 63 parsed.params,
jpayne@69 64 parsed.query,
jpayne@69 65 parsed.fragment,
jpayne@69 66 ]
jpayne@69 67 )
jpayne@69 68
jpayne@69 69 def is_unverifiable(self):
jpayne@69 70 return True
jpayne@69 71
jpayne@69 72 def has_header(self, name):
jpayne@69 73 return name in self._r.headers or name in self._new_headers
jpayne@69 74
jpayne@69 75 def get_header(self, name, default=None):
jpayne@69 76 return self._r.headers.get(name, self._new_headers.get(name, default))
jpayne@69 77
jpayne@69 78 def add_header(self, key, val):
jpayne@69 79 """cookiejar has no legitimate use for this method; add it back if you find one."""
jpayne@69 80 raise NotImplementedError(
jpayne@69 81 "Cookie headers should be added with add_unredirected_header()"
jpayne@69 82 )
jpayne@69 83
jpayne@69 84 def add_unredirected_header(self, name, value):
jpayne@69 85 self._new_headers[name] = value
jpayne@69 86
jpayne@69 87 def get_new_headers(self):
jpayne@69 88 return self._new_headers
jpayne@69 89
jpayne@69 90 @property
jpayne@69 91 def unverifiable(self):
jpayne@69 92 return self.is_unverifiable()
jpayne@69 93
jpayne@69 94 @property
jpayne@69 95 def origin_req_host(self):
jpayne@69 96 return self.get_origin_req_host()
jpayne@69 97
jpayne@69 98 @property
jpayne@69 99 def host(self):
jpayne@69 100 return self.get_host()
jpayne@69 101
jpayne@69 102
jpayne@69 103 class MockResponse:
jpayne@69 104 """Wraps a `httplib.HTTPMessage` to mimic a `urllib.addinfourl`.
jpayne@69 105
jpayne@69 106 ...what? Basically, expose the parsed HTTP headers from the server response
jpayne@69 107 the way `http.cookiejar` expects to see them.
jpayne@69 108 """
jpayne@69 109
jpayne@69 110 def __init__(self, headers):
jpayne@69 111 """Make a MockResponse for `cookiejar` to read.
jpayne@69 112
jpayne@69 113 :param headers: a httplib.HTTPMessage or analogous carrying the headers
jpayne@69 114 """
jpayne@69 115 self._headers = headers
jpayne@69 116
jpayne@69 117 def info(self):
jpayne@69 118 return self._headers
jpayne@69 119
jpayne@69 120 def getheaders(self, name):
jpayne@69 121 self._headers.getheaders(name)
jpayne@69 122
jpayne@69 123
jpayne@69 124 def extract_cookies_to_jar(jar, request, response):
jpayne@69 125 """Extract the cookies from the response into a CookieJar.
jpayne@69 126
jpayne@69 127 :param jar: http.cookiejar.CookieJar (not necessarily a RequestsCookieJar)
jpayne@69 128 :param request: our own requests.Request object
jpayne@69 129 :param response: urllib3.HTTPResponse object
jpayne@69 130 """
jpayne@69 131 if not (hasattr(response, "_original_response") and response._original_response):
jpayne@69 132 return
jpayne@69 133 # the _original_response field is the wrapped httplib.HTTPResponse object,
jpayne@69 134 req = MockRequest(request)
jpayne@69 135 # pull out the HTTPMessage with the headers and put it in the mock:
jpayne@69 136 res = MockResponse(response._original_response.msg)
jpayne@69 137 jar.extract_cookies(res, req)
jpayne@69 138
jpayne@69 139
jpayne@69 140 def get_cookie_header(jar, request):
jpayne@69 141 """
jpayne@69 142 Produce an appropriate Cookie header string to be sent with `request`, or None.
jpayne@69 143
jpayne@69 144 :rtype: str
jpayne@69 145 """
jpayne@69 146 r = MockRequest(request)
jpayne@69 147 jar.add_cookie_header(r)
jpayne@69 148 return r.get_new_headers().get("Cookie")
jpayne@69 149
jpayne@69 150
jpayne@69 151 def remove_cookie_by_name(cookiejar, name, domain=None, path=None):
jpayne@69 152 """Unsets a cookie by name, by default over all domains and paths.
jpayne@69 153
jpayne@69 154 Wraps CookieJar.clear(), is O(n).
jpayne@69 155 """
jpayne@69 156 clearables = []
jpayne@69 157 for cookie in cookiejar:
jpayne@69 158 if cookie.name != name:
jpayne@69 159 continue
jpayne@69 160 if domain is not None and domain != cookie.domain:
jpayne@69 161 continue
jpayne@69 162 if path is not None and path != cookie.path:
jpayne@69 163 continue
jpayne@69 164 clearables.append((cookie.domain, cookie.path, cookie.name))
jpayne@69 165
jpayne@69 166 for domain, path, name in clearables:
jpayne@69 167 cookiejar.clear(domain, path, name)
jpayne@69 168
jpayne@69 169
jpayne@69 170 class CookieConflictError(RuntimeError):
jpayne@69 171 """There are two cookies that meet the criteria specified in the cookie jar.
jpayne@69 172 Use .get and .set and include domain and path args in order to be more specific.
jpayne@69 173 """
jpayne@69 174
jpayne@69 175
jpayne@69 176 class RequestsCookieJar(cookielib.CookieJar, MutableMapping):
jpayne@69 177 """Compatibility class; is a http.cookiejar.CookieJar, but exposes a dict
jpayne@69 178 interface.
jpayne@69 179
jpayne@69 180 This is the CookieJar we create by default for requests and sessions that
jpayne@69 181 don't specify one, since some clients may expect response.cookies and
jpayne@69 182 session.cookies to support dict operations.
jpayne@69 183
jpayne@69 184 Requests does not use the dict interface internally; it's just for
jpayne@69 185 compatibility with external client code. All requests code should work
jpayne@69 186 out of the box with externally provided instances of ``CookieJar``, e.g.
jpayne@69 187 ``LWPCookieJar`` and ``FileCookieJar``.
jpayne@69 188
jpayne@69 189 Unlike a regular CookieJar, this class is pickleable.
jpayne@69 190
jpayne@69 191 .. warning:: dictionary operations that are normally O(1) may be O(n).
jpayne@69 192 """
jpayne@69 193
jpayne@69 194 def get(self, name, default=None, domain=None, path=None):
jpayne@69 195 """Dict-like get() that also supports optional domain and path args in
jpayne@69 196 order to resolve naming collisions from using one cookie jar over
jpayne@69 197 multiple domains.
jpayne@69 198
jpayne@69 199 .. warning:: operation is O(n), not O(1).
jpayne@69 200 """
jpayne@69 201 try:
jpayne@69 202 return self._find_no_duplicates(name, domain, path)
jpayne@69 203 except KeyError:
jpayne@69 204 return default
jpayne@69 205
jpayne@69 206 def set(self, name, value, **kwargs):
jpayne@69 207 """Dict-like set() that also supports optional domain and path args in
jpayne@69 208 order to resolve naming collisions from using one cookie jar over
jpayne@69 209 multiple domains.
jpayne@69 210 """
jpayne@69 211 # support client code that unsets cookies by assignment of a None value:
jpayne@69 212 if value is None:
jpayne@69 213 remove_cookie_by_name(
jpayne@69 214 self, name, domain=kwargs.get("domain"), path=kwargs.get("path")
jpayne@69 215 )
jpayne@69 216 return
jpayne@69 217
jpayne@69 218 if isinstance(value, Morsel):
jpayne@69 219 c = morsel_to_cookie(value)
jpayne@69 220 else:
jpayne@69 221 c = create_cookie(name, value, **kwargs)
jpayne@69 222 self.set_cookie(c)
jpayne@69 223 return c
jpayne@69 224
jpayne@69 225 def iterkeys(self):
jpayne@69 226 """Dict-like iterkeys() that returns an iterator of names of cookies
jpayne@69 227 from the jar.
jpayne@69 228
jpayne@69 229 .. seealso:: itervalues() and iteritems().
jpayne@69 230 """
jpayne@69 231 for cookie in iter(self):
jpayne@69 232 yield cookie.name
jpayne@69 233
jpayne@69 234 def keys(self):
jpayne@69 235 """Dict-like keys() that returns a list of names of cookies from the
jpayne@69 236 jar.
jpayne@69 237
jpayne@69 238 .. seealso:: values() and items().
jpayne@69 239 """
jpayne@69 240 return list(self.iterkeys())
jpayne@69 241
jpayne@69 242 def itervalues(self):
jpayne@69 243 """Dict-like itervalues() that returns an iterator of values of cookies
jpayne@69 244 from the jar.
jpayne@69 245
jpayne@69 246 .. seealso:: iterkeys() and iteritems().
jpayne@69 247 """
jpayne@69 248 for cookie in iter(self):
jpayne@69 249 yield cookie.value
jpayne@69 250
jpayne@69 251 def values(self):
jpayne@69 252 """Dict-like values() that returns a list of values of cookies from the
jpayne@69 253 jar.
jpayne@69 254
jpayne@69 255 .. seealso:: keys() and items().
jpayne@69 256 """
jpayne@69 257 return list(self.itervalues())
jpayne@69 258
jpayne@69 259 def iteritems(self):
jpayne@69 260 """Dict-like iteritems() that returns an iterator of name-value tuples
jpayne@69 261 from the jar.
jpayne@69 262
jpayne@69 263 .. seealso:: iterkeys() and itervalues().
jpayne@69 264 """
jpayne@69 265 for cookie in iter(self):
jpayne@69 266 yield cookie.name, cookie.value
jpayne@69 267
jpayne@69 268 def items(self):
jpayne@69 269 """Dict-like items() that returns a list of name-value tuples from the
jpayne@69 270 jar. Allows client-code to call ``dict(RequestsCookieJar)`` and get a
jpayne@69 271 vanilla python dict of key value pairs.
jpayne@69 272
jpayne@69 273 .. seealso:: keys() and values().
jpayne@69 274 """
jpayne@69 275 return list(self.iteritems())
jpayne@69 276
jpayne@69 277 def list_domains(self):
jpayne@69 278 """Utility method to list all the domains in the jar."""
jpayne@69 279 domains = []
jpayne@69 280 for cookie in iter(self):
jpayne@69 281 if cookie.domain not in domains:
jpayne@69 282 domains.append(cookie.domain)
jpayne@69 283 return domains
jpayne@69 284
jpayne@69 285 def list_paths(self):
jpayne@69 286 """Utility method to list all the paths in the jar."""
jpayne@69 287 paths = []
jpayne@69 288 for cookie in iter(self):
jpayne@69 289 if cookie.path not in paths:
jpayne@69 290 paths.append(cookie.path)
jpayne@69 291 return paths
jpayne@69 292
jpayne@69 293 def multiple_domains(self):
jpayne@69 294 """Returns True if there are multiple domains in the jar.
jpayne@69 295 Returns False otherwise.
jpayne@69 296
jpayne@69 297 :rtype: bool
jpayne@69 298 """
jpayne@69 299 domains = []
jpayne@69 300 for cookie in iter(self):
jpayne@69 301 if cookie.domain is not None and cookie.domain in domains:
jpayne@69 302 return True
jpayne@69 303 domains.append(cookie.domain)
jpayne@69 304 return False # there is only one domain in jar
jpayne@69 305
jpayne@69 306 def get_dict(self, domain=None, path=None):
jpayne@69 307 """Takes as an argument an optional domain and path and returns a plain
jpayne@69 308 old Python dict of name-value pairs of cookies that meet the
jpayne@69 309 requirements.
jpayne@69 310
jpayne@69 311 :rtype: dict
jpayne@69 312 """
jpayne@69 313 dictionary = {}
jpayne@69 314 for cookie in iter(self):
jpayne@69 315 if (domain is None or cookie.domain == domain) and (
jpayne@69 316 path is None or cookie.path == path
jpayne@69 317 ):
jpayne@69 318 dictionary[cookie.name] = cookie.value
jpayne@69 319 return dictionary
jpayne@69 320
jpayne@69 321 def __contains__(self, name):
jpayne@69 322 try:
jpayne@69 323 return super().__contains__(name)
jpayne@69 324 except CookieConflictError:
jpayne@69 325 return True
jpayne@69 326
jpayne@69 327 def __getitem__(self, name):
jpayne@69 328 """Dict-like __getitem__() for compatibility with client code. Throws
jpayne@69 329 exception if there are more than one cookie with name. In that case,
jpayne@69 330 use the more explicit get() method instead.
jpayne@69 331
jpayne@69 332 .. warning:: operation is O(n), not O(1).
jpayne@69 333 """
jpayne@69 334 return self._find_no_duplicates(name)
jpayne@69 335
jpayne@69 336 def __setitem__(self, name, value):
jpayne@69 337 """Dict-like __setitem__ for compatibility with client code. Throws
jpayne@69 338 exception if there is already a cookie of that name in the jar. In that
jpayne@69 339 case, use the more explicit set() method instead.
jpayne@69 340 """
jpayne@69 341 self.set(name, value)
jpayne@69 342
jpayne@69 343 def __delitem__(self, name):
jpayne@69 344 """Deletes a cookie given a name. Wraps ``http.cookiejar.CookieJar``'s
jpayne@69 345 ``remove_cookie_by_name()``.
jpayne@69 346 """
jpayne@69 347 remove_cookie_by_name(self, name)
jpayne@69 348
jpayne@69 349 def set_cookie(self, cookie, *args, **kwargs):
jpayne@69 350 if (
jpayne@69 351 hasattr(cookie.value, "startswith")
jpayne@69 352 and cookie.value.startswith('"')
jpayne@69 353 and cookie.value.endswith('"')
jpayne@69 354 ):
jpayne@69 355 cookie.value = cookie.value.replace('\\"', "")
jpayne@69 356 return super().set_cookie(cookie, *args, **kwargs)
jpayne@69 357
jpayne@69 358 def update(self, other):
jpayne@69 359 """Updates this jar with cookies from another CookieJar or dict-like"""
jpayne@69 360 if isinstance(other, cookielib.CookieJar):
jpayne@69 361 for cookie in other:
jpayne@69 362 self.set_cookie(copy.copy(cookie))
jpayne@69 363 else:
jpayne@69 364 super().update(other)
jpayne@69 365
jpayne@69 366 def _find(self, name, domain=None, path=None):
jpayne@69 367 """Requests uses this method internally to get cookie values.
jpayne@69 368
jpayne@69 369 If there are conflicting cookies, _find arbitrarily chooses one.
jpayne@69 370 See _find_no_duplicates if you want an exception thrown if there are
jpayne@69 371 conflicting cookies.
jpayne@69 372
jpayne@69 373 :param name: a string containing name of cookie
jpayne@69 374 :param domain: (optional) string containing domain of cookie
jpayne@69 375 :param path: (optional) string containing path of cookie
jpayne@69 376 :return: cookie.value
jpayne@69 377 """
jpayne@69 378 for cookie in iter(self):
jpayne@69 379 if cookie.name == name:
jpayne@69 380 if domain is None or cookie.domain == domain:
jpayne@69 381 if path is None or cookie.path == path:
jpayne@69 382 return cookie.value
jpayne@69 383
jpayne@69 384 raise KeyError(f"name={name!r}, domain={domain!r}, path={path!r}")
jpayne@69 385
jpayne@69 386 def _find_no_duplicates(self, name, domain=None, path=None):
jpayne@69 387 """Both ``__get_item__`` and ``get`` call this function: it's never
jpayne@69 388 used elsewhere in Requests.
jpayne@69 389
jpayne@69 390 :param name: a string containing name of cookie
jpayne@69 391 :param domain: (optional) string containing domain of cookie
jpayne@69 392 :param path: (optional) string containing path of cookie
jpayne@69 393 :raises KeyError: if cookie is not found
jpayne@69 394 :raises CookieConflictError: if there are multiple cookies
jpayne@69 395 that match name and optionally domain and path
jpayne@69 396 :return: cookie.value
jpayne@69 397 """
jpayne@69 398 toReturn = None
jpayne@69 399 for cookie in iter(self):
jpayne@69 400 if cookie.name == name:
jpayne@69 401 if domain is None or cookie.domain == domain:
jpayne@69 402 if path is None or cookie.path == path:
jpayne@69 403 if toReturn is not None:
jpayne@69 404 # if there are multiple cookies that meet passed in criteria
jpayne@69 405 raise CookieConflictError(
jpayne@69 406 f"There are multiple cookies with name, {name!r}"
jpayne@69 407 )
jpayne@69 408 # we will eventually return this as long as no cookie conflict
jpayne@69 409 toReturn = cookie.value
jpayne@69 410
jpayne@69 411 if toReturn:
jpayne@69 412 return toReturn
jpayne@69 413 raise KeyError(f"name={name!r}, domain={domain!r}, path={path!r}")
jpayne@69 414
jpayne@69 415 def __getstate__(self):
jpayne@69 416 """Unlike a normal CookieJar, this class is pickleable."""
jpayne@69 417 state = self.__dict__.copy()
jpayne@69 418 # remove the unpickleable RLock object
jpayne@69 419 state.pop("_cookies_lock")
jpayne@69 420 return state
jpayne@69 421
jpayne@69 422 def __setstate__(self, state):
jpayne@69 423 """Unlike a normal CookieJar, this class is pickleable."""
jpayne@69 424 self.__dict__.update(state)
jpayne@69 425 if "_cookies_lock" not in self.__dict__:
jpayne@69 426 self._cookies_lock = threading.RLock()
jpayne@69 427
jpayne@69 428 def copy(self):
jpayne@69 429 """Return a copy of this RequestsCookieJar."""
jpayne@69 430 new_cj = RequestsCookieJar()
jpayne@69 431 new_cj.set_policy(self.get_policy())
jpayne@69 432 new_cj.update(self)
jpayne@69 433 return new_cj
jpayne@69 434
jpayne@69 435 def get_policy(self):
jpayne@69 436 """Return the CookiePolicy instance used."""
jpayne@69 437 return self._policy
jpayne@69 438
jpayne@69 439
jpayne@69 440 def _copy_cookie_jar(jar):
jpayne@69 441 if jar is None:
jpayne@69 442 return None
jpayne@69 443
jpayne@69 444 if hasattr(jar, "copy"):
jpayne@69 445 # We're dealing with an instance of RequestsCookieJar
jpayne@69 446 return jar.copy()
jpayne@69 447 # We're dealing with a generic CookieJar instance
jpayne@69 448 new_jar = copy.copy(jar)
jpayne@69 449 new_jar.clear()
jpayne@69 450 for cookie in jar:
jpayne@69 451 new_jar.set_cookie(copy.copy(cookie))
jpayne@69 452 return new_jar
jpayne@69 453
jpayne@69 454
jpayne@69 455 def create_cookie(name, value, **kwargs):
jpayne@69 456 """Make a cookie from underspecified parameters.
jpayne@69 457
jpayne@69 458 By default, the pair of `name` and `value` will be set for the domain ''
jpayne@69 459 and sent on every request (this is sometimes called a "supercookie").
jpayne@69 460 """
jpayne@69 461 result = {
jpayne@69 462 "version": 0,
jpayne@69 463 "name": name,
jpayne@69 464 "value": value,
jpayne@69 465 "port": None,
jpayne@69 466 "domain": "",
jpayne@69 467 "path": "/",
jpayne@69 468 "secure": False,
jpayne@69 469 "expires": None,
jpayne@69 470 "discard": True,
jpayne@69 471 "comment": None,
jpayne@69 472 "comment_url": None,
jpayne@69 473 "rest": {"HttpOnly": None},
jpayne@69 474 "rfc2109": False,
jpayne@69 475 }
jpayne@69 476
jpayne@69 477 badargs = set(kwargs) - set(result)
jpayne@69 478 if badargs:
jpayne@69 479 raise TypeError(
jpayne@69 480 f"create_cookie() got unexpected keyword arguments: {list(badargs)}"
jpayne@69 481 )
jpayne@69 482
jpayne@69 483 result.update(kwargs)
jpayne@69 484 result["port_specified"] = bool(result["port"])
jpayne@69 485 result["domain_specified"] = bool(result["domain"])
jpayne@69 486 result["domain_initial_dot"] = result["domain"].startswith(".")
jpayne@69 487 result["path_specified"] = bool(result["path"])
jpayne@69 488
jpayne@69 489 return cookielib.Cookie(**result)
jpayne@69 490
jpayne@69 491
jpayne@69 492 def morsel_to_cookie(morsel):
jpayne@69 493 """Convert a Morsel object into a Cookie containing the one k/v pair."""
jpayne@69 494
jpayne@69 495 expires = None
jpayne@69 496 if morsel["max-age"]:
jpayne@69 497 try:
jpayne@69 498 expires = int(time.time() + int(morsel["max-age"]))
jpayne@69 499 except ValueError:
jpayne@69 500 raise TypeError(f"max-age: {morsel['max-age']} must be integer")
jpayne@69 501 elif morsel["expires"]:
jpayne@69 502 time_template = "%a, %d-%b-%Y %H:%M:%S GMT"
jpayne@69 503 expires = calendar.timegm(time.strptime(morsel["expires"], time_template))
jpayne@69 504 return create_cookie(
jpayne@69 505 comment=morsel["comment"],
jpayne@69 506 comment_url=bool(morsel["comment"]),
jpayne@69 507 discard=False,
jpayne@69 508 domain=morsel["domain"],
jpayne@69 509 expires=expires,
jpayne@69 510 name=morsel.key,
jpayne@69 511 path=morsel["path"],
jpayne@69 512 port=None,
jpayne@69 513 rest={"HttpOnly": morsel["httponly"]},
jpayne@69 514 rfc2109=False,
jpayne@69 515 secure=bool(morsel["secure"]),
jpayne@69 516 value=morsel.value,
jpayne@69 517 version=morsel["version"] or 0,
jpayne@69 518 )
jpayne@69 519
jpayne@69 520
jpayne@69 521 def cookiejar_from_dict(cookie_dict, cookiejar=None, overwrite=True):
jpayne@69 522 """Returns a CookieJar from a key/value dictionary.
jpayne@69 523
jpayne@69 524 :param cookie_dict: Dict of key/values to insert into CookieJar.
jpayne@69 525 :param cookiejar: (optional) A cookiejar to add the cookies to.
jpayne@69 526 :param overwrite: (optional) If False, will not replace cookies
jpayne@69 527 already in the jar with new ones.
jpayne@69 528 :rtype: CookieJar
jpayne@69 529 """
jpayne@69 530 if cookiejar is None:
jpayne@69 531 cookiejar = RequestsCookieJar()
jpayne@69 532
jpayne@69 533 if cookie_dict is not None:
jpayne@69 534 names_from_jar = [cookie.name for cookie in cookiejar]
jpayne@69 535 for name in cookie_dict:
jpayne@69 536 if overwrite or (name not in names_from_jar):
jpayne@69 537 cookiejar.set_cookie(create_cookie(name, cookie_dict[name]))
jpayne@69 538
jpayne@69 539 return cookiejar
jpayne@69 540
jpayne@69 541
jpayne@69 542 def merge_cookies(cookiejar, cookies):
jpayne@69 543 """Add cookies to cookiejar and returns a merged CookieJar.
jpayne@69 544
jpayne@69 545 :param cookiejar: CookieJar object to add the cookies to.
jpayne@69 546 :param cookies: Dictionary or CookieJar object to be added.
jpayne@69 547 :rtype: CookieJar
jpayne@69 548 """
jpayne@69 549 if not isinstance(cookiejar, cookielib.CookieJar):
jpayne@69 550 raise ValueError("You can only merge into CookieJar")
jpayne@69 551
jpayne@69 552 if isinstance(cookies, dict):
jpayne@69 553 cookiejar = cookiejar_from_dict(cookies, cookiejar=cookiejar, overwrite=False)
jpayne@69 554 elif isinstance(cookies, cookielib.CookieJar):
jpayne@69 555 try:
jpayne@69 556 cookiejar.update(cookies)
jpayne@69 557 except AttributeError:
jpayne@69 558 for cookie_in_jar in cookies:
jpayne@69 559 cookiejar.set_cookie(cookie_in_jar)
jpayne@69 560
jpayne@69 561 return cookiejar