PyXR

c:\python24\lib \ test \ test_cookielib.py



0001 # -*- coding: utf-8 -*-
0002 """Tests for cookielib.py."""
0003 
0004 import re, os, time
0005 from unittest import TestCase
0006 
0007 from test import test_support
0008 
0009 class DateTimeTests(TestCase):
0010 
0011     def test_time2isoz(self):
0012         from cookielib import time2isoz
0013 
0014         base = 1019227000
0015         day = 24*3600
0016         self.assertEquals(time2isoz(base), "2002-04-19 14:36:40Z")
0017         self.assertEquals(time2isoz(base+day), "2002-04-20 14:36:40Z")
0018         self.assertEquals(time2isoz(base+2*day), "2002-04-21 14:36:40Z")
0019         self.assertEquals(time2isoz(base+3*day), "2002-04-22 14:36:40Z")
0020 
0021         az = time2isoz()
0022         bz = time2isoz(500000)
0023         for text in (az, bz):
0024             self.assert_(re.search(r"^\d{4}-\d\d-\d\d \d\d:\d\d:\d\dZ$", text),
0025                          "bad time2isoz format: %s %s" % (az, bz))
0026 
0027     def test_http2time(self):
0028         from cookielib import http2time
0029 
0030         def parse_date(text):
0031             return time.gmtime(http2time(text))[:6]
0032 
0033         self.assertEquals(parse_date("01 Jan 2001"), (2001, 1, 1, 0, 0, 0.0))
0034 
0035         # this test will break around year 2070
0036         self.assertEquals(parse_date("03-Feb-20"), (2020, 2, 3, 0, 0, 0.0))
0037 
0038         # this test will break around year 2048
0039         self.assertEquals(parse_date("03-Feb-98"), (1998, 2, 3, 0, 0, 0.0))
0040 
0041     def test_http2time_formats(self):
0042         from cookielib import http2time, time2isoz
0043 
0044         # test http2time for supported dates.  Test cases with 2 digit year
0045         # will probably break in year 2044.
0046         tests = [
0047          'Thu, 03 Feb 1994 00:00:00 GMT',  # proposed new HTTP format
0048          'Thursday, 03-Feb-94 00:00:00 GMT',  # old rfc850 HTTP format
0049          'Thursday, 03-Feb-1994 00:00:00 GMT',  # broken rfc850 HTTP format
0050 
0051          '03 Feb 1994 00:00:00 GMT',  # HTTP format (no weekday)
0052          '03-Feb-94 00:00:00 GMT',  # old rfc850 (no weekday)
0053          '03-Feb-1994 00:00:00 GMT',  # broken rfc850 (no weekday)
0054          '03-Feb-1994 00:00 GMT',  # broken rfc850 (no weekday, no seconds)
0055          '03-Feb-1994 00:00',  # broken rfc850 (no weekday, no seconds, no tz)
0056 
0057          '03-Feb-94',  # old rfc850 HTTP format (no weekday, no time)
0058          '03-Feb-1994',  # broken rfc850 HTTP format (no weekday, no time)
0059          '03 Feb 1994',  # proposed new HTTP format (no weekday, no time)
0060 
0061          # A few tests with extra space at various places
0062          '  03   Feb   1994  0:00  ',
0063          '  03-Feb-1994  ',
0064         ]
0065 
0066         test_t = 760233600  # assume broken POSIX counting of seconds
0067         result = time2isoz(test_t)
0068         expected = "1994-02-03 00:00:00Z"
0069         self.assertEquals(result, expected,
0070                           "%s  =>  '%s' (%s)" % (test_t, result, expected))
0071 
0072         for s in tests:
0073             t = http2time(s)
0074             t2 = http2time(s.lower())
0075             t3 = http2time(s.upper())
0076 
0077             self.assert_(t == t2 == t3 == test_t,
0078                          "'%s'  =>  %s, %s, %s (%s)" % (s, t, t2, t3, test_t))
0079 
0080     def test_http2time_garbage(self):
0081         from cookielib import http2time
0082 
0083         for test in [
0084             '',
0085             'Garbage',
0086             'Mandag 16. September 1996',
0087             '01-00-1980',
0088             '01-13-1980',
0089             '00-01-1980',
0090             '32-01-1980',
0091             '01-01-1980 25:00:00',
0092             '01-01-1980 00:61:00',
0093             '01-01-1980 00:00:62',
0094             ]:
0095             self.assert_(http2time(test) is None,
0096                          "http2time(%s) is not None\n"
0097                          "http2time(test) %s" % (test, http2time(test))
0098                          )
0099 
0100 
0101 class HeaderTests(TestCase):
0102     def test_parse_ns_headers(self):
0103         from cookielib import parse_ns_headers
0104 
0105         # quotes should be stripped
0106         expected = [[('expires', 2209069412L), ('version', '0')]]
0107         for hdr in [
0108             'expires=01 Jan 2040 22:23:32 GMT',
0109             'expires="01 Jan 2040 22:23:32 GMT"',
0110             ]:
0111             self.assertEquals(parse_ns_headers([hdr]), expected)
0112 
0113     def test_join_header_words(self):
0114         from cookielib import join_header_words
0115 
0116         joined = join_header_words([[("foo", None), ("bar", "baz")]])
0117         self.assertEquals(joined, "foo; bar=baz")
0118 
0119         self.assertEquals(join_header_words([[]]), "")
0120 
0121     def test_split_header_words(self):
0122         from cookielib import split_header_words
0123 
0124         tests = [
0125             ("foo", [[("foo", None)]]),
0126             ("foo=bar", [[("foo", "bar")]]),
0127             ("   foo   ", [[("foo", None)]]),
0128             ("   foo=   ", [[("foo", "")]]),
0129             ("   foo=", [[("foo", "")]]),
0130             ("   foo=   ; ", [[("foo", "")]]),
0131             ("   foo=   ; bar= baz ", [[("foo", ""), ("bar", "baz")]]),
0132             ("foo=bar bar=baz", [[("foo", "bar"), ("bar", "baz")]]),
0133             # doesn't really matter if this next fails, but it works ATM
0134             ("foo= bar=baz", [[("foo", "bar=baz")]]),
0135             ("foo=bar;bar=baz", [[("foo", "bar"), ("bar", "baz")]]),
0136             ('foo bar baz', [[("foo", None), ("bar", None), ("baz", None)]]),
0137             ("a, b, c", [[("a", None)], [("b", None)], [("c", None)]]),
0138             (r'foo; bar=baz, spam=, foo="\,\;\"", bar= ',
0139              [[("foo", None), ("bar", "baz")],
0140               [("spam", "")], [("foo", ',;"')], [("bar", "")]]),
0141             ]
0142 
0143         for arg, expect in tests:
0144             try:
0145                 result = split_header_words([arg])
0146             except:
0147                 import traceback, StringIO
0148                 f = StringIO.StringIO()
0149                 traceback.print_exc(None, f)
0150                 result = "(error -- traceback follows)\n\n%s" % f.getvalue()
0151             self.assertEquals(result,  expect, """
0152 When parsing: '%s'
0153 Expected:     '%s'
0154 Got:          '%s'
0155 """ % (arg, expect, result))
0156 
0157     def test_roundtrip(self):
0158         from cookielib import split_header_words, join_header_words
0159 
0160         tests = [
0161             ("foo", "foo"),
0162             ("foo=bar", "foo=bar"),
0163             ("   foo   ", "foo"),
0164             ("foo=", 'foo=""'),
0165             ("foo=bar bar=baz", "foo=bar; bar=baz"),
0166             ("foo=bar;bar=baz", "foo=bar; bar=baz"),
0167             ('foo bar baz', "foo; bar; baz"),
0168             (r'foo="\"" bar="\\"', r'foo="\""; bar="\\"'),
0169             ('foo,,,bar', 'foo, bar'),
0170             ('foo=bar,bar=baz', 'foo=bar, bar=baz'),
0171 
0172             ('text/html; charset=iso-8859-1',
0173              'text/html; charset="iso-8859-1"'),
0174 
0175             ('foo="bar"; port="80,81"; discard, bar=baz',
0176              'foo=bar; port="80,81"; discard, bar=baz'),
0177 
0178             (r'Basic realm="\"foo\\\\bar\""',
0179              r'Basic; realm="\"foo\\\\bar\""')
0180             ]
0181 
0182         for arg, expect in tests:
0183             input = split_header_words([arg])
0184             res = join_header_words(input)
0185             self.assertEquals(res, expect, """
0186 When parsing: '%s'
0187 Expected:     '%s'
0188 Got:          '%s'
0189 Input was:    '%s'
0190 """ % (arg, expect, res, input))
0191 
0192 
0193 class FakeResponse:
0194     def __init__(self, headers=[], url=None):
0195         """
0196         headers: list of RFC822-style 'Key: value' strings
0197         """
0198         import mimetools, StringIO
0199         f = StringIO.StringIO("\n".join(headers))
0200         self._headers = mimetools.Message(f)
0201         self._url = url
0202     def info(self): return self._headers
0203 
0204 def interact_2965(cookiejar, url, *set_cookie_hdrs):
0205     return _interact(cookiejar, url, set_cookie_hdrs, "Set-Cookie2")
0206 
0207 def interact_netscape(cookiejar, url, *set_cookie_hdrs):
0208     return _interact(cookiejar, url, set_cookie_hdrs, "Set-Cookie")
0209 
0210 def _interact(cookiejar, url, set_cookie_hdrs, hdr_name):
0211     """Perform a single request / response cycle, returning Cookie: header."""
0212     from urllib2 import Request
0213     req = Request(url)
0214     cookiejar.add_cookie_header(req)
0215     cookie_hdr = req.get_header("Cookie", "")
0216     headers = []
0217     for hdr in set_cookie_hdrs:
0218         headers.append("%s: %s" % (hdr_name, hdr))
0219     res = FakeResponse(headers, url)
0220     cookiejar.extract_cookies(res, req)
0221     return cookie_hdr
0222 
0223 
0224 class CookieTests(TestCase):
0225     # XXX
0226     # Get rid of string comparisons where not actually testing str / repr.
0227     # .clear() etc.
0228     # IP addresses like 50 (single number, no dot) and domain-matching
0229     #  functions (and is_HDN)?  See draft RFC 2965 errata.
0230     # Strictness switches
0231     # is_third_party()
0232     # unverifiability / third-party blocking
0233     # Netscape cookies work the same as RFC 2965 with regard to port.
0234     # Set-Cookie with negative max age.
0235     # If turn RFC 2965 handling off, Set-Cookie2 cookies should not clobber
0236     #  Set-Cookie cookies.
0237     # Cookie2 should be sent if *any* cookies are not V1 (ie. V0 OR V2 etc.).
0238     # Cookies (V1 and V0) with no expiry date should be set to be discarded.
0239     # RFC 2965 Quoting:
0240     #  Should accept unquoted cookie-attribute values?  check errata draft.
0241     #   Which are required on the way in and out?
0242     #  Should always return quoted cookie-attribute values?
0243     # Proper testing of when RFC 2965 clobbers Netscape (waiting for errata).
0244     # Path-match on return (same for V0 and V1).
0245     # RFC 2965 acceptance and returning rules
0246     #  Set-Cookie2 without version attribute is rejected.
0247 
0248     # Netscape peculiarities list from Ronald Tschalar.
0249     # The first two still need tests, the rest are covered.
0250 ## - Quoting: only quotes around the expires value are recognized as such
0251 ##   (and yes, some folks quote the expires value); quotes around any other
0252 ##   value are treated as part of the value.
0253 ## - White space: white space around names and values is ignored
0254 ## - Default path: if no path parameter is given, the path defaults to the
0255 ##   path in the request-uri up to, but not including, the last '/'. Note
0256 ##   that this is entirely different from what the spec says.
0257 ## - Commas and other delimiters: Netscape just parses until the next ';'.
0258 ##   This means it will allow commas etc inside values (and yes, both
0259 ##   commas and equals are commonly appear in the cookie value). This also
0260 ##   means that if you fold multiple Set-Cookie header fields into one,
0261 ##   comma-separated list, it'll be a headache to parse (at least my head
0262 ##   starts hurting everytime I think of that code).
0263 ## - Expires: You'll get all sorts of date formats in the expires,
0264 ##   including emtpy expires attributes ("expires="). Be as flexible as you
0265 ##   can, and certainly don't expect the weekday to be there; if you can't
0266 ##   parse it, just ignore it and pretend it's a session cookie.
0267 ## - Domain-matching: Netscape uses the 2-dot rule for _all_ domains, not
0268 ##   just the 7 special TLD's listed in their spec. And folks rely on
0269 ##   that...
0270 
0271     def test_domain_return_ok(self):
0272         # test optimization: .domain_return_ok() should filter out most
0273         # domains in the CookieJar before we try to access them (because that
0274         # may require disk access -- in particular, with MSIECookieJar)
0275         # This is only a rough check for performance reasons, so it's not too
0276         # critical as long as it's sufficiently liberal.
0277         import cookielib, urllib2
0278         pol = cookielib.DefaultCookiePolicy()
0279         for url, domain, ok in [
0280             ("http://foo.bar.com/", "blah.com", False),
0281             ("http://foo.bar.com/", "rhubarb.blah.com", False),
0282             ("http://foo.bar.com/", "rhubarb.foo.bar.com", False),
0283             ("http://foo.bar.com/", ".foo.bar.com", True),
0284             ("http://foo.bar.com/", "foo.bar.com", True),
0285             ("http://foo.bar.com/", ".bar.com", True),
0286             ("http://foo.bar.com/", "com", True),
0287             ("http://foo.com/", "rhubarb.foo.com", False),
0288             ("http://foo.com/", ".foo.com", True),
0289             ("http://foo.com/", "foo.com", True),
0290             ("http://foo.com/", "com", True),
0291             ("http://foo/", "rhubarb.foo", False),
0292             ("http://foo/", ".foo", True),
0293             ("http://foo/", "foo", True),
0294             ("http://foo/", "foo.local", True),
0295             ("http://foo/", ".local", True),
0296             ]:
0297             request = urllib2.Request(url)
0298             r = pol.domain_return_ok(domain, request)
0299             if ok: self.assert_(r)
0300             else: self.assert_(not r)
0301 
0302     def test_missing_value(self):
0303         from cookielib import MozillaCookieJar, lwp_cookie_str
0304 
0305         # missing = sign in Cookie: header is regarded by Mozilla as a missing
0306         # name, and by cookielib as a missing value
0307         filename = test_support.TESTFN
0308         c = MozillaCookieJar(filename)
0309         interact_netscape(c, "http://www.acme.com/", 'eggs')
0310         interact_netscape(c, "http://www.acme.com/", '"spam"; path=/foo/')
0311         cookie = c._cookies["www.acme.com"]["/"]["eggs"]
0312         self.assert_(cookie.value is None)
0313         self.assertEquals(cookie.name, "eggs")
0314         cookie = c._cookies["www.acme.com"]['/foo/']['"spam"']
0315         self.assert_(cookie.value is None)
0316         self.assertEquals(cookie.name, '"spam"')
0317         self.assertEquals(lwp_cookie_str(cookie), (
0318             r'"spam"; path="/foo/"; domain="www.acme.com"; '
0319             'path_spec; discard; version=0'))
0320         old_str = repr(c)
0321         c.save(ignore_expires=True, ignore_discard=True)
0322         try:
0323             c = MozillaCookieJar(filename)
0324             c.revert(ignore_expires=True, ignore_discard=True)
0325         finally:
0326             os.unlink(c.filename)
0327         # cookies unchanged apart from lost info re. whether path was specified
0328         self.assertEquals(
0329             repr(c),
0330             re.sub("path_specified=%s" % True, "path_specified=%s" % False,
0331                    old_str)
0332             )
0333         self.assertEquals(interact_netscape(c, "http://www.acme.com/foo/"),
0334                           '"spam"; eggs')
0335 
0336     def test_ns_parser(self):
0337         from cookielib import CookieJar, DEFAULT_HTTP_PORT
0338 
0339         c = CookieJar()
0340         interact_netscape(c, "http://www.acme.com/",
0341                           'spam=eggs; DoMain=.acme.com; port; blArgh="feep"')
0342         interact_netscape(c, "http://www.acme.com/", 'ni=ni; port=80,8080')
0343         interact_netscape(c, "http://www.acme.com:80/", 'nini=ni')
0344         interact_netscape(c, "http://www.acme.com:80/", 'foo=bar; expires=')
0345         interact_netscape(c, "http://www.acme.com:80/", 'spam=eggs; '
0346                           'expires="Foo Bar 25 33:22:11 3022"')
0347 
0348         cookie = c._cookies[".acme.com"]["/"]["spam"]
0349         self.assertEquals(cookie.domain, ".acme.com")
0350         self.assert_(cookie.domain_specified)
0351         self.assertEquals(cookie.port, DEFAULT_HTTP_PORT)
0352         self.assert_(not cookie.port_specified)
0353         # case is preserved
0354         self.assert_(cookie.has_nonstandard_attr("blArgh") and
0355                      not cookie.has_nonstandard_attr("blargh"))
0356 
0357         cookie = c._cookies["www.acme.com"]["/"]["ni"]
0358         self.assertEquals(cookie.domain, "www.acme.com")
0359         self.assert_(not cookie.domain_specified)
0360         self.assertEquals(cookie.port, "80,8080")
0361         self.assert_(cookie.port_specified)
0362 
0363         cookie = c._cookies["www.acme.com"]["/"]["nini"]
0364         self.assert_(cookie.port is None)
0365         self.assert_(not cookie.port_specified)
0366 
0367         # invalid expires should not cause cookie to be dropped
0368         foo = c._cookies["www.acme.com"]["/"]["foo"]
0369         spam = c._cookies["www.acme.com"]["/"]["foo"]
0370         self.assert_(foo.expires is None)
0371         self.assert_(spam.expires is None)
0372 
0373     def test_expires(self):
0374         from cookielib import time2netscape, CookieJar
0375 
0376         # if expires is in future, keep cookie...
0377         c = CookieJar()
0378         future = time2netscape(time.time()+3600)
0379         interact_netscape(c, "http://www.acme.com/", 'spam="bar"; expires=%s' %
0380                           future)
0381         self.assertEquals(len(c), 1)
0382         now = time2netscape(time.time()-1)
0383         # ... and if in past or present, discard it
0384         interact_netscape(c, "http://www.acme.com/", 'foo="eggs"; expires=%s' %
0385                           now)
0386         h = interact_netscape(c, "http://www.acme.com/")
0387         self.assertEquals(len(c), 1)
0388         self.assert_('spam="bar"' in h and "foo" not in h)
0389 
0390         # max-age takes precedence over expires, and zero max-age is request to
0391         # delete both new cookie and any old matching cookie
0392         interact_netscape(c, "http://www.acme.com/", 'eggs="bar"; expires=%s' %
0393                           future)
0394         interact_netscape(c, "http://www.acme.com/", 'bar="bar"; expires=%s' %
0395                           future)
0396         self.assertEquals(len(c), 3)
0397         interact_netscape(c, "http://www.acme.com/", 'eggs="bar"; '
0398                           'expires=%s; max-age=0' % future)
0399         interact_netscape(c, "http://www.acme.com/", 'bar="bar"; '
0400                           'max-age=0; expires=%s' % future)
0401         h = interact_netscape(c, "http://www.acme.com/")
0402         self.assertEquals(len(c), 1)
0403 
0404         # test expiry at end of session for cookies with no expires attribute
0405         interact_netscape(c, "http://www.rhubarb.net/", 'whum="fizz"')
0406         self.assertEquals(len(c), 2)
0407         c.clear_session_cookies()
0408         self.assertEquals(len(c), 1)
0409         self.assert_('spam="bar"' in h)
0410 
0411         # XXX RFC 2965 expiry rules (some apply to V0 too)
0412 
0413     def test_default_path(self):
0414         from cookielib import CookieJar, DefaultCookiePolicy
0415 
0416         # RFC 2965
0417         pol = DefaultCookiePolicy(rfc2965=True)
0418 
0419         c = CookieJar(pol)
0420         interact_2965(c, "http://www.acme.com/", 'spam="bar"; Version="1"')
0421         self.assert_("/" in c._cookies["www.acme.com"])
0422 
0423         c = CookieJar(pol)
0424         interact_2965(c, "http://www.acme.com/blah", 'eggs="bar"; Version="1"')
0425         self.assert_("/" in c._cookies["www.acme.com"])
0426 
0427         c = CookieJar(pol)
0428         interact_2965(c, "http://www.acme.com/blah/rhubarb",
0429                       'eggs="bar"; Version="1"')
0430         self.assert_("/blah/" in c._cookies["www.acme.com"])
0431 
0432         c = CookieJar(pol)
0433         interact_2965(c, "http://www.acme.com/blah/rhubarb/",
0434                       'eggs="bar"; Version="1"')
0435         self.assert_("/blah/rhubarb/" in c._cookies["www.acme.com"])
0436 
0437         # Netscape
0438 
0439         c = CookieJar()
0440         interact_netscape(c, "http://www.acme.com/", 'spam="bar"')
0441         self.assert_("/" in c._cookies["www.acme.com"])
0442 
0443         c = CookieJar()
0444         interact_netscape(c, "http://www.acme.com/blah", 'eggs="bar"')
0445         self.assert_("/" in c._cookies["www.acme.com"])
0446 
0447         c = CookieJar()
0448         interact_netscape(c, "http://www.acme.com/blah/rhubarb", 'eggs="bar"')
0449         self.assert_("/blah" in c._cookies["www.acme.com"])
0450 
0451         c = CookieJar()
0452         interact_netscape(c, "http://www.acme.com/blah/rhubarb/", 'eggs="bar"')
0453         self.assert_("/blah/rhubarb" in c._cookies["www.acme.com"])
0454 
0455     def test_escape_path(self):
0456         from cookielib import escape_path
0457         cases = [
0458             # quoted safe
0459             ("/foo%2f/bar", "/foo%2F/bar"),
0460             ("/foo%2F/bar", "/foo%2F/bar"),
0461             # quoted %
0462             ("/foo%%/bar", "/foo%%/bar"),
0463             # quoted unsafe
0464             ("/fo%19o/bar", "/fo%19o/bar"),
0465             ("/fo%7do/bar", "/fo%7Do/bar"),
0466             # unquoted safe
0467             ("/foo/bar&", "/foo/bar&"),
0468             ("/foo//bar", "/foo//bar"),
0469             ("\176/foo/bar", "\176/foo/bar"),
0470             # unquoted unsafe
0471             ("/foo\031/bar", "/foo%19/bar"),
0472             ("/\175foo/bar", "/%7Dfoo/bar"),
0473             # unicode
0474             (u"/foo/bar\uabcd", "/foo/bar%EA%AF%8D"),  # UTF-8 encoded
0475             ]
0476         for arg, result in cases:
0477             self.assertEquals(escape_path(arg), result)
0478 
0479     def test_request_path(self):
0480         from urllib2 import Request
0481         from cookielib import request_path
0482         # with parameters
0483         req = Request("http://www.example.com/rheum/rhaponicum;"
0484                       "foo=bar;sing=song?apples=pears&spam=eggs#ni")
0485         self.assertEquals(request_path(req), "/rheum/rhaponicum;"
0486                      "foo=bar;sing=song?apples=pears&spam=eggs#ni")
0487         # without parameters
0488         req = Request("http://www.example.com/rheum/rhaponicum?"
0489                       "apples=pears&spam=eggs#ni")
0490         self.assertEquals(request_path(req), "/rheum/rhaponicum?"
0491                      "apples=pears&spam=eggs#ni")
0492         # missing final slash
0493         req = Request("http://www.example.com")
0494         self.assertEquals(request_path(req), "/")
0495 
0496     def test_request_port(self):
0497         from urllib2 import Request
0498         from cookielib import request_port, DEFAULT_HTTP_PORT
0499         req = Request("http://www.acme.com:1234/",
0500                       headers={"Host": "www.acme.com:4321"})
0501         self.assertEquals(request_port(req), "1234")
0502         req = Request("http://www.acme.com/",
0503                       headers={"Host": "www.acme.com:4321"})
0504         self.assertEquals(request_port(req), DEFAULT_HTTP_PORT)
0505 
0506     def test_request_host(self):
0507         from urllib2 import Request
0508         from cookielib import request_host
0509         # this request is illegal (RFC2616, 14.2.3)
0510         req = Request("http://1.1.1.1/",
0511                       headers={"Host": "www.acme.com:80"})
0512         # libwww-perl wants this response, but that seems wrong (RFC 2616,
0513         # section 5.2, point 1., and RFC 2965 section 1, paragraph 3)
0514         #self.assertEquals(request_host(req), "www.acme.com")
0515         self.assertEquals(request_host(req), "1.1.1.1")
0516         req = Request("http://www.acme.com/",
0517                       headers={"Host": "irrelevant.com"})
0518         self.assertEquals(request_host(req), "www.acme.com")
0519         # not actually sure this one is valid Request object, so maybe should
0520         # remove test for no host in url in request_host function?
0521         req = Request("/resource.html",
0522                       headers={"Host": "www.acme.com"})
0523         self.assertEquals(request_host(req), "www.acme.com")
0524         # port shouldn't be in request-host
0525         req = Request("http://www.acme.com:2345/resource.html",
0526                       headers={"Host": "www.acme.com:5432"})
0527         self.assertEquals(request_host(req), "www.acme.com")
0528 
0529     def test_is_HDN(self):
0530         from cookielib import is_HDN
0531         self.assert_(is_HDN("foo.bar.com"))
0532         self.assert_(is_HDN("1foo2.3bar4.5com"))
0533         self.assert_(not is_HDN("192.168.1.1"))
0534         self.assert_(not is_HDN(""))
0535         self.assert_(not is_HDN("."))
0536         self.assert_(not is_HDN(".foo.bar.com"))
0537         self.assert_(not is_HDN("..foo"))
0538         self.assert_(not is_HDN("foo."))
0539 
0540     def test_reach(self):
0541         from cookielib import reach
0542         self.assertEquals(reach("www.acme.com"), ".acme.com")
0543         self.assertEquals(reach("acme.com"), "acme.com")
0544         self.assertEquals(reach("acme.local"), ".local")
0545         self.assertEquals(reach(".local"), ".local")
0546         self.assertEquals(reach(".com"), ".com")
0547         self.assertEquals(reach("."), ".")
0548         self.assertEquals(reach(""), "")
0549         self.assertEquals(reach("192.168.0.1"), "192.168.0.1")
0550 
0551     def test_domain_match(self):
0552         from cookielib import domain_match, user_domain_match
0553         self.assert_(domain_match("192.168.1.1", "192.168.1.1"))
0554         self.assert_(not domain_match("192.168.1.1", ".168.1.1"))
0555         self.assert_(domain_match("x.y.com", "x.Y.com"))
0556         self.assert_(domain_match("x.y.com", ".Y.com"))
0557         self.assert_(not domain_match("x.y.com", "Y.com"))
0558         self.assert_(domain_match("a.b.c.com", ".c.com"))
0559         self.assert_(not domain_match(".c.com", "a.b.c.com"))
0560         self.assert_(domain_match("example.local", ".local"))
0561         self.assert_(not domain_match("blah.blah", ""))
0562         self.assert_(not domain_match("", ".rhubarb.rhubarb"))
0563         self.assert_(domain_match("", ""))
0564 
0565         self.assert_(user_domain_match("acme.com", "acme.com"))
0566         self.assert_(not user_domain_match("acme.com", ".acme.com"))
0567         self.assert_(user_domain_match("rhubarb.acme.com", ".acme.com"))
0568         self.assert_(user_domain_match("www.rhubarb.acme.com", ".acme.com"))
0569         self.assert_(user_domain_match("x.y.com", "x.Y.com"))
0570         self.assert_(user_domain_match("x.y.com", ".Y.com"))
0571         self.assert_(not user_domain_match("x.y.com", "Y.com"))
0572         self.assert_(user_domain_match("y.com", "Y.com"))
0573         self.assert_(not user_domain_match(".y.com", "Y.com"))
0574         self.assert_(user_domain_match(".y.com", ".Y.com"))
0575         self.assert_(user_domain_match("x.y.com", ".com"))
0576         self.assert_(not user_domain_match("x.y.com", "com"))
0577         self.assert_(not user_domain_match("x.y.com", "m"))
0578         self.assert_(not user_domain_match("x.y.com", ".m"))
0579         self.assert_(not user_domain_match("x.y.com", ""))
0580         self.assert_(not user_domain_match("x.y.com", "."))
0581         self.assert_(user_domain_match("192.168.1.1", "192.168.1.1"))
0582         # not both HDNs, so must string-compare equal to match
0583         self.assert_(not user_domain_match("192.168.1.1", ".168.1.1"))
0584         self.assert_(not user_domain_match("192.168.1.1", "."))
0585         # empty string is a special case
0586         self.assert_(not user_domain_match("192.168.1.1", ""))
0587 
0588     def test_wrong_domain(self):
0589         # Cookies whose effective request-host name does not domain-match the
0590         # domain are rejected.
0591 
0592         # XXX far from complete
0593         from cookielib import CookieJar
0594         c = CookieJar()
0595         interact_2965(c, "http://www.nasty.com/",
0596                       'foo=bar; domain=friendly.org; Version="1"')
0597         self.assertEquals(len(c), 0)
0598 
0599     def test_two_component_domain_ns(self):
0600         # Netscape: .www.bar.com, www.bar.com, .bar.com, bar.com, no domain
0601         # should all get accepted, as should .acme.com, acme.com and no domain
0602         # for 2-component domains like acme.com.
0603         from cookielib import CookieJar, DefaultCookiePolicy
0604 
0605         c = CookieJar()
0606 
0607         # two-component V0 domain is OK
0608         interact_netscape(c, "http://foo.net/", 'ns=bar')
0609         self.assertEquals(len(c), 1)
0610         self.assertEquals(c._cookies["foo.net"]["/"]["ns"].value, "bar")
0611         self.assertEquals(interact_netscape(c, "http://foo.net/"), "ns=bar")
0612         # *will* be returned to any other domain (unlike RFC 2965)...
0613         self.assertEquals(interact_netscape(c, "http://www.foo.net/"),
0614                           "ns=bar")
0615         # ...unless requested otherwise
0616         pol = DefaultCookiePolicy(
0617             strict_ns_domain=DefaultCookiePolicy.DomainStrictNonDomain)
0618         c.set_policy(pol)
0619         self.assertEquals(interact_netscape(c, "http://www.foo.net/"), "")
0620 
0621         # unlike RFC 2965, even explicit two-component domain is OK,
0622         # because .foo.net matches foo.net
0623         interact_netscape(c, "http://foo.net/foo/",
0624                           'spam1=eggs; domain=foo.net')
0625         # even if starts with a dot -- in NS rules, .foo.net matches foo.net!
0626         interact_netscape(c, "http://foo.net/foo/bar/",
0627                           'spam2=eggs; domain=.foo.net')
0628         self.assertEquals(len(c), 3)
0629         self.assertEquals(c._cookies[".foo.net"]["/foo"]["spam1"].value,
0630                           "eggs")
0631         self.assertEquals(c._cookies[".foo.net"]["/foo/bar"]["spam2"].value,
0632                           "eggs")
0633         self.assertEquals(interact_netscape(c, "http://foo.net/foo/bar/"),
0634                           "spam2=eggs; spam1=eggs; ns=bar")
0635 
0636         # top-level domain is too general
0637         interact_netscape(c, "http://foo.net/", 'nini="ni"; domain=.net')
0638         self.assertEquals(len(c), 3)
0639 
0640 ##         # Netscape protocol doesn't allow non-special top level domains (such
0641 ##         # as co.uk) in the domain attribute unless there are at least three
0642 ##         # dots in it.
0643         # Oh yes it does!  Real implementations don't check this, and real
0644         # cookies (of course) rely on that behaviour.
0645         interact_netscape(c, "http://foo.co.uk", 'nasty=trick; domain=.co.uk')
0646 ##         self.assertEquals(len(c), 2)
0647         self.assertEquals(len(c), 4)
0648 
0649     def test_two_component_domain_rfc2965(self):
0650         from cookielib import CookieJar, DefaultCookiePolicy
0651 
0652         pol = DefaultCookiePolicy(rfc2965=True)
0653         c = CookieJar(pol)
0654 
0655         # two-component V1 domain is OK
0656         interact_2965(c, "http://foo.net/", 'foo=bar; Version="1"')
0657         self.assertEquals(len(c), 1)
0658         self.assertEquals(c._cookies["foo.net"]["/"]["foo"].value, "bar")
0659         self.assertEquals(interact_2965(c, "http://foo.net/"),
0660                           "$Version=1; foo=bar")
0661         # won't be returned to any other domain (because domain was implied)
0662         self.assertEquals(interact_2965(c, "http://www.foo.net/"), "")
0663 
0664         # unless domain is given explicitly, because then it must be
0665         # rewritten to start with a dot: foo.net --> .foo.net, which does
0666         # not domain-match foo.net
0667         interact_2965(c, "http://foo.net/foo",
0668                       'spam=eggs; domain=foo.net; path=/foo; Version="1"')
0669         self.assertEquals(len(c), 1)
0670         self.assertEquals(interact_2965(c, "http://foo.net/foo"),
0671                           "$Version=1; foo=bar")
0672 
0673         # explicit foo.net from three-component domain www.foo.net *does* get
0674         # set, because .foo.net domain-matches .foo.net
0675         interact_2965(c, "http://www.foo.net/foo/",
0676                       'spam=eggs; domain=foo.net; Version="1"')
0677         self.assertEquals(c._cookies[".foo.net"]["/foo/"]["spam"].value,
0678                           "eggs")
0679         self.assertEquals(len(c), 2)
0680         self.assertEquals(interact_2965(c, "http://foo.net/foo/"),
0681                           "$Version=1; foo=bar")
0682         self.assertEquals(interact_2965(c, "http://www.foo.net/foo/"),
0683                           '$Version=1; spam=eggs; $Domain="foo.net"')
0684 
0685         # top-level domain is too general
0686         interact_2965(c, "http://foo.net/",
0687                       'ni="ni"; domain=".net"; Version="1"')
0688         self.assertEquals(len(c), 2)
0689 
0690         # RFC 2965 doesn't require blocking this
0691         interact_2965(c, "http://foo.co.uk/",
0692                       'nasty=trick; domain=.co.uk; Version="1"')
0693         self.assertEquals(len(c), 3)
0694 
0695     def test_domain_allow(self):
0696         from cookielib import CookieJar, DefaultCookiePolicy
0697         from urllib2 import Request
0698 
0699         c = CookieJar(policy=DefaultCookiePolicy(
0700             blocked_domains=["acme.com"],
0701             allowed_domains=["www.acme.com"]))
0702 
0703         req = Request("http://acme.com/")
0704         headers = ["Set-Cookie: CUSTOMER=WILE_E_COYOTE; path=/"]
0705         res = FakeResponse(headers, "http://acme.com/")
0706         c.extract_cookies(res, req)
0707         self.assertEquals(len(c), 0)
0708 
0709         req = Request("http://www.acme.com/")
0710         res = FakeResponse(headers, "http://www.acme.com/")
0711         c.extract_cookies(res, req)
0712         self.assertEquals(len(c), 1)
0713 
0714         req = Request("http://www.coyote.com/")
0715         res = FakeResponse(headers, "http://www.coyote.com/")
0716         c.extract_cookies(res, req)
0717         self.assertEquals(len(c), 1)
0718 
0719         # set a cookie with non-allowed domain...
0720         req = Request("http://www.coyote.com/")
0721         res = FakeResponse(headers, "http://www.coyote.com/")
0722         cookies = c.make_cookies(res, req)
0723         c.set_cookie(cookies[0])
0724         self.assertEquals(len(c), 2)
0725         # ... and check is doesn't get returned
0726         c.add_cookie_header(req)
0727         self.assert_(not req.has_header("Cookie"))
0728 
0729     def test_domain_block(self):
0730         from cookielib import CookieJar, DefaultCookiePolicy
0731         from urllib2 import Request
0732 
0733         pol = DefaultCookiePolicy(
0734             rfc2965=True, blocked_domains=[".acme.com"])
0735         c = CookieJar(policy=pol)
0736         headers = ["Set-Cookie: CUSTOMER=WILE_E_COYOTE; path=/"]
0737 
0738         req = Request("http://www.acme.com/")
0739         res = FakeResponse(headers, "http://www.acme.com/")
0740         c.extract_cookies(res, req)
0741         self.assertEquals(len(c), 0)
0742 
0743         p = pol.set_blocked_domains(["acme.com"])
0744         c.extract_cookies(res, req)
0745         self.assertEquals(len(c), 1)
0746 
0747         c.clear()
0748         req = Request("http://www.roadrunner.net/")
0749         res = FakeResponse(headers, "http://www.roadrunner.net/")
0750         c.extract_cookies(res, req)
0751         self.assertEquals(len(c), 1)
0752         req = Request("http://www.roadrunner.net/")
0753         c.add_cookie_header(req)
0754         self.assert_((req.has_header("Cookie") and
0755                       req.has_header("Cookie2")))
0756 
0757         c.clear()
0758         pol.set_blocked_domains([".acme.com"])
0759         c.extract_cookies(res, req)
0760         self.assertEquals(len(c), 1)
0761 
0762         # set a cookie with blocked domain...
0763         req = Request("http://www.acme.com/")
0764         res = FakeResponse(headers, "http://www.acme.com/")
0765         cookies = c.make_cookies(res, req)
0766         c.set_cookie(cookies[0])
0767         self.assertEquals(len(c), 2)
0768         # ... and check is doesn't get returned
0769         c.add_cookie_header(req)
0770         self.assert_(not req.has_header("Cookie"))
0771 
0772     def test_secure(self):
0773         from cookielib import CookieJar, DefaultCookiePolicy
0774 
0775         for ns in True, False:
0776             for whitespace in " ", "":
0777                 c = CookieJar()
0778                 if ns:
0779                     pol = DefaultCookiePolicy(rfc2965=False)
0780                     int = interact_netscape
0781                     vs = ""
0782                 else:
0783                     pol = DefaultCookiePolicy(rfc2965=True)
0784                     int = interact_2965
0785                     vs = "; Version=1"
0786                 c.set_policy(pol)
0787                 url = "http://www.acme.com/"
0788                 int(c, url, "foo1=bar%s%s" % (vs, whitespace))
0789                 int(c, url, "foo2=bar%s; secure%s" %  (vs, whitespace))
0790                 self.assert_(
0791                     not c._cookies["www.acme.com"]["/"]["foo1"].secure,
0792                     "non-secure cookie registered secure")
0793                 self.assert_(
0794                     c._cookies["www.acme.com"]["/"]["foo2"].secure,
0795                     "secure cookie registered non-secure")
0796 
0797     def test_quote_cookie_value(self):
0798         from cookielib import CookieJar, DefaultCookiePolicy
0799         c = CookieJar(policy=DefaultCookiePolicy(rfc2965=True))
0800         interact_2965(c, "http://www.acme.com/", r'foo=\b"a"r; Version=1')
0801         h = interact_2965(c, "http://www.acme.com/")
0802         self.assertEquals(h, r'$Version=1; foo=\\b\"a\"r')
0803 
0804     def test_missing_final_slash(self):
0805         # Missing slash from request URL's abs_path should be assumed present.
0806         from cookielib import CookieJar, DefaultCookiePolicy
0807         from urllib2 import Request
0808         url = "http://www.acme.com"
0809         c = CookieJar(DefaultCookiePolicy(rfc2965=True))
0810         interact_2965(c, url, "foo=bar; Version=1")
0811         req = Request(url)
0812         self.assertEquals(len(c), 1)
0813         c.add_cookie_header(req)
0814         self.assert_(req.has_header("Cookie"))
0815 
0816     def test_domain_mirror(self):
0817         from cookielib import CookieJar, DefaultCookiePolicy
0818 
0819         pol = DefaultCookiePolicy(rfc2965=True)
0820 
0821         c = CookieJar(pol)
0822         url = "http://foo.bar.com/"
0823         interact_2965(c, url, "spam=eggs; Version=1")
0824         h = interact_2965(c, url)
0825         self.assert_("Domain" not in h,
0826                      "absent domain returned with domain present")
0827 
0828         c = CookieJar(pol)
0829         url = "http://foo.bar.com/"
0830         interact_2965(c, url, 'spam=eggs; Version=1; Domain=.bar.com')
0831         h = interact_2965(c, url)
0832         self.assert_('$Domain=".bar.com"' in h, "domain not returned")
0833 
0834         c = CookieJar(pol)
0835         url = "http://foo.bar.com/"
0836         # note missing initial dot in Domain
0837         interact_2965(c, url, 'spam=eggs; Version=1; Domain=bar.com')
0838         h = interact_2965(c, url)
0839         self.assert_('$Domain="bar.com"' in h, "domain not returned")
0840 
0841     def test_path_mirror(self):
0842         from cookielib import CookieJar, DefaultCookiePolicy
0843 
0844         pol = DefaultCookiePolicy(rfc2965=True)
0845 
0846         c = CookieJar(pol)
0847         url = "http://foo.bar.com/"
0848         interact_2965(c, url, "spam=eggs; Version=1")
0849         h = interact_2965(c, url)
0850         self.assert_("Path" not in h,
0851                      "absent path returned with path present")
0852 
0853         c = CookieJar(pol)
0854         url = "http://foo.bar.com/"
0855         interact_2965(c, url, 'spam=eggs; Version=1; Path=/')
0856         h = interact_2965(c, url)
0857         self.assert_('$Path="/"' in h, "path not returned")
0858 
0859     def test_port_mirror(self):
0860         from cookielib import CookieJar, DefaultCookiePolicy
0861 
0862         pol = DefaultCookiePolicy(rfc2965=True)
0863 
0864         c = CookieJar(pol)
0865         url = "http://foo.bar.com/"
0866         interact_2965(c, url, "spam=eggs; Version=1")
0867         h = interact_2965(c, url)
0868         self.assert_("Port" not in h,
0869                      "absent port returned with port present")
0870 
0871         c = CookieJar(pol)
0872         url = "http://foo.bar.com/"
0873         interact_2965(c, url, "spam=eggs; Version=1; Port")
0874         h = interact_2965(c, url)
0875         self.assert_(re.search("\$Port([^=]|$)", h),
0876                      "port with no value not returned with no value")
0877 
0878         c = CookieJar(pol)
0879         url = "http://foo.bar.com/"
0880         interact_2965(c, url, 'spam=eggs; Version=1; Port="80"')
0881         h = interact_2965(c, url)
0882         self.assert_('$Port="80"' in h,
0883                      "port with single value not returned with single value")
0884 
0885         c = CookieJar(pol)
0886         url = "http://foo.bar.com/"
0887         interact_2965(c, url, 'spam=eggs; Version=1; Port="80,8080"')
0888         h = interact_2965(c, url)
0889         self.assert_('$Port="80,8080"' in h,
0890                      "port with multiple values not returned with multiple "
0891                      "values")
0892 
0893     def test_no_return_comment(self):
0894         from cookielib import CookieJar, DefaultCookiePolicy
0895 
0896         c = CookieJar(DefaultCookiePolicy(rfc2965=True))
0897         url = "http://foo.bar.com/"
0898         interact_2965(c, url, 'spam=eggs; Version=1; '
0899                       'Comment="does anybody read these?"; '
0900                       'CommentURL="http://foo.bar.net/comment.html"')
0901         h = interact_2965(c, url)
0902         self.assert_(
0903             "Comment" not in h,
0904             "Comment or CommentURL cookie-attributes returned to server")
0905 
0906     def test_Cookie_iterator(self):
0907         from cookielib import CookieJar, Cookie, DefaultCookiePolicy
0908 
0909         cs = CookieJar(DefaultCookiePolicy(rfc2965=True))
0910         # add some random cookies
0911         interact_2965(cs, "http://blah.spam.org/", 'foo=eggs; Version=1; '
0912                       'Comment="does anybody read these?"; '
0913                       'CommentURL="http://foo.bar.net/comment.html"')
0914         interact_netscape(cs, "http://www.acme.com/blah/", "spam=bar; secure")
0915         interact_2965(cs, "http://www.acme.com/blah/",
0916                       "foo=bar; secure; Version=1")
0917         interact_2965(cs, "http://www.acme.com/blah/",
0918                       "foo=bar; path=/; Version=1")
0919         interact_2965(cs, "http://www.sol.no",
0920                       r'bang=wallop; version=1; domain=".sol.no"; '
0921                       r'port="90,100, 80,8080"; '
0922                       r'max-age=100; Comment = "Just kidding! (\"|\\\\) "')
0923 
0924         versions = [1, 1, 1, 0, 1]
0925         names = ["bang", "foo", "foo", "spam", "foo"]
0926         domains = [".sol.no", "blah.spam.org", "www.acme.com",
0927                    "www.acme.com", "www.acme.com"]
0928         paths = ["/", "/", "/", "/blah", "/blah/"]
0929 
0930         for i in range(4):
0931             i = 0
0932             for c in cs:
0933                 self.assert_(isinstance(c, Cookie))
0934                 self.assertEquals(c.version, versions[i])
0935                 self.assertEquals(c.name, names[i])
0936                 self.assertEquals(c.domain, domains[i])
0937                 self.assertEquals(c.path, paths[i])
0938                 i = i + 1
0939 
0940     def test_parse_ns_headers(self):
0941         from cookielib import parse_ns_headers
0942 
0943         # missing domain value (invalid cookie)
0944         self.assertEquals(
0945             parse_ns_headers(["foo=bar; path=/; domain"]),
0946             [[("foo", "bar"),
0947               ("path", "/"), ("domain", None), ("version", "0")]]
0948             )
0949         # invalid expires value
0950         self.assertEquals(
0951             parse_ns_headers(["foo=bar; expires=Foo Bar 12 33:22:11 2000"]),
0952             [[("foo", "bar"), ("expires", None), ("version", "0")]]
0953             )
0954         # missing cookie value (valid cookie)
0955         self.assertEquals(
0956             parse_ns_headers(["foo"]),
0957             [[("foo", None), ("version", "0")]]
0958             )
0959         # shouldn't add version if header is empty
0960         self.assertEquals(parse_ns_headers([""]), [])
0961 
0962     def test_bad_cookie_header(self):
0963 
0964         def cookiejar_from_cookie_headers(headers):
0965             from cookielib import CookieJar
0966             from urllib2 import Request
0967             c = CookieJar()
0968             req = Request("http://www.example.com/")
0969             r = FakeResponse(headers, "http://www.example.com/")
0970             c.extract_cookies(r, req)
0971             return c
0972 
0973         # none of these bad headers should cause an exception to be raised
0974         for headers in [
0975             ["Set-Cookie: "],  # actually, nothing wrong with this
0976             ["Set-Cookie2: "],  # ditto
0977             # missing domain value
0978             ["Set-Cookie2: a=foo; path=/; Version=1; domain"],
0979             # bad max-age
0980             ["Set-Cookie: b=foo; max-age=oops"],
0981             ]:
0982             c = cookiejar_from_cookie_headers(headers)
0983             # these bad cookies shouldn't be set
0984             self.assertEquals(len(c), 0)
0985 
0986         # cookie with invalid expires is treated as session cookie
0987         headers = ["Set-Cookie: c=foo; expires=Foo Bar 12 33:22:11 2000"]
0988         c = cookiejar_from_cookie_headers(headers)
0989         cookie = c._cookies["www.example.com"]["/"]["c"]
0990         self.assert_(cookie.expires is None)
0991 
0992 
0993 class LWPCookieTests(TestCase):
0994     # Tests taken from libwww-perl, with a few modifications and additions.
0995 
0996     def test_netscape_example_1(self):
0997         from cookielib import CookieJar, DefaultCookiePolicy
0998         from urllib2 import Request
0999 
1000         #-------------------------------------------------------------------
1001         # First we check that it works for the original example at
1002         # http://www.netscape.com/newsref/std/cookie_spec.html
1003 
1004         # Client requests a document, and receives in the response:
1005         #
1006         #       Set-Cookie: CUSTOMER=WILE_E_COYOTE; path=/; expires=Wednesday, 09-Nov-99 23:12:40 GMT
1007         #
1008         # When client requests a URL in path "/" on this server, it sends:
1009         #
1010         #       Cookie: CUSTOMER=WILE_E_COYOTE
1011         #
1012         # Client requests a document, and receives in the response:
1013         #
1014         #       Set-Cookie: PART_NUMBER=ROCKET_LAUNCHER_0001; path=/
1015         #
1016         # When client requests a URL in path "/" on this server, it sends:
1017         #
1018         #       Cookie: CUSTOMER=WILE_E_COYOTE; PART_NUMBER=ROCKET_LAUNCHER_0001
1019         #
1020         # Client receives:
1021         #
1022         #       Set-Cookie: SHIPPING=FEDEX; path=/fo
1023         #
1024         # When client requests a URL in path "/" on this server, it sends:
1025         #
1026         #       Cookie: CUSTOMER=WILE_E_COYOTE; PART_NUMBER=ROCKET_LAUNCHER_0001
1027         #
1028         # When client requests a URL in path "/foo" on this server, it sends:
1029         #
1030         #       Cookie: CUSTOMER=WILE_E_COYOTE; PART_NUMBER=ROCKET_LAUNCHER_0001; SHIPPING=FEDEX
1031         #
1032         # The last Cookie is buggy, because both specifications say that the
1033         # most specific cookie must be sent first.  SHIPPING=FEDEX is the
1034         # most specific and should thus be first.
1035 
1036         year_plus_one = time.localtime()[0] + 1
1037 
1038         headers = []
1039 
1040         c = CookieJar(DefaultCookiePolicy(rfc2965 = True))
1041 
1042         #req = Request("http://1.1.1.1/",
1043         #              headers={"Host": "www.acme.com:80"})
1044         req = Request("http://www.acme.com:80/",
1045                       headers={"Host": "www.acme.com:80"})
1046 
1047         headers.append(
1048             "Set-Cookie: CUSTOMER=WILE_E_COYOTE; path=/ ; "
1049             "expires=Wednesday, 09-Nov-%d 23:12:40 GMT" % year_plus_one)
1050         res = FakeResponse(headers, "http://www.acme.com/")
1051         c.extract_cookies(res, req)
1052 
1053         req = Request("http://www.acme.com/")
1054         c.add_cookie_header(req)
1055 
1056         self.assertEqual(req.get_header("Cookie"), "CUSTOMER=WILE_E_COYOTE")
1057         self.assertEqual(req.get_header("Cookie2"), '$Version="1"')
1058 
1059         headers.append("Set-Cookie: PART_NUMBER=ROCKET_LAUNCHER_0001; path=/")
1060         res = FakeResponse(headers, "http://www.acme.com/")
1061         c.extract_cookies(res, req)
1062 
1063         req = Request("http://www.acme.com/foo/bar")
1064         c.add_cookie_header(req)
1065 
1066         h = req.get_header("Cookie")
1067         self.assert_("PART_NUMBER=ROCKET_LAUNCHER_0001" in h and
1068                      "CUSTOMER=WILE_E_COYOTE" in h)
1069 
1070         headers.append('Set-Cookie: SHIPPING=FEDEX; path=/foo')
1071         res = FakeResponse(headers, "http://www.acme.com")
1072         c.extract_cookies(res, req)
1073 
1074         req = Request("http://www.acme.com/")
1075         c.add_cookie_header(req)
1076 
1077         h = req.get_header("Cookie")
1078         self.assert_("PART_NUMBER=ROCKET_LAUNCHER_0001" in h and
1079                      "CUSTOMER=WILE_E_COYOTE" in h and
1080                      "SHIPPING=FEDEX" not in h)
1081 
1082         req = Request("http://www.acme.com/foo/")
1083         c.add_cookie_header(req)
1084 
1085         h = req.get_header("Cookie")
1086         self.assert_(("PART_NUMBER=ROCKET_LAUNCHER_0001" in h and
1087                       "CUSTOMER=WILE_E_COYOTE" in h and
1088                       h.startswith("SHIPPING=FEDEX;")))
1089 
1090     def test_netscape_example_2(self):
1091         from cookielib import CookieJar
1092         from urllib2 import Request
1093 
1094         # Second Example transaction sequence:
1095         #
1096         # Assume all mappings from above have been cleared.
1097         #
1098         # Client receives:
1099         #
1100         #       Set-Cookie: PART_NUMBER=ROCKET_LAUNCHER_0001; path=/
1101         #
1102         # When client requests a URL in path "/" on this server, it sends:
1103         #
1104         #       Cookie: PART_NUMBER=ROCKET_LAUNCHER_0001
1105         #
1106         # Client receives:
1107         #
1108         #       Set-Cookie: PART_NUMBER=RIDING_ROCKET_0023; path=/ammo
1109         #
1110         # When client requests a URL in path "/ammo" on this server, it sends:
1111         #
1112         #       Cookie: PART_NUMBER=RIDING_ROCKET_0023; PART_NUMBER=ROCKET_LAUNCHER_0001
1113         #
1114         #       NOTE: There are two name/value pairs named "PART_NUMBER" due to
1115         #       the inheritance of the "/" mapping in addition to the "/ammo" mapping.
1116 
1117         c = CookieJar()
1118         headers = []
1119 
1120         req = Request("http://www.acme.com/")
1121         headers.append("Set-Cookie: PART_NUMBER=ROCKET_LAUNCHER_0001; path=/")
1122         res = FakeResponse(headers, "http://www.acme.com/")
1123 
1124         c.extract_cookies(res, req)
1125 
1126         req = Request("http://www.acme.com/")
1127         c.add_cookie_header(req)
1128 
1129         self.assertEquals(req.get_header("Cookie"),
1130                           "PART_NUMBER=ROCKET_LAUNCHER_0001")
1131 
1132         headers.append(
1133             "Set-Cookie: PART_NUMBER=RIDING_ROCKET_0023; path=/ammo")
1134         res = FakeResponse(headers, "http://www.acme.com/")
1135         c.extract_cookies(res, req)
1136 
1137         req = Request("http://www.acme.com/ammo")
1138         c.add_cookie_header(req)
1139 
1140         self.assert_(re.search(r"PART_NUMBER=RIDING_ROCKET_0023;\s*"
1141                                "PART_NUMBER=ROCKET_LAUNCHER_0001",
1142                                req.get_header("Cookie")))
1143 
1144     def test_ietf_example_1(self):
1145         from cookielib import CookieJar, DefaultCookiePolicy
1146         #-------------------------------------------------------------------
1147         # Then we test with the examples from draft-ietf-http-state-man-mec-03.txt
1148         #
1149         # 5.  EXAMPLES
1150 
1151         c = CookieJar(DefaultCookiePolicy(rfc2965=True))
1152 
1153         #
1154         # 5.1  Example 1
1155         #
1156         # Most detail of request and response headers has been omitted.  Assume
1157         # the user agent has no stored cookies.
1158         #
1159         #   1.  User Agent -> Server
1160         #
1161         #       POST /acme/login HTTP/1.1
1162         #       [form data]
1163         #
1164         #       User identifies self via a form.
1165         #
1166         #   2.  Server -> User Agent
1167         #
1168         #       HTTP/1.1 200 OK
1169         #       Set-Cookie2: Customer="WILE_E_COYOTE"; Version="1"; Path="/acme"
1170         #
1171         #       Cookie reflects user's identity.
1172 
1173         cookie = interact_2965(
1174             c, 'http://www.acme.com/acme/login',
1175             'Customer="WILE_E_COYOTE"; Version="1"; Path="/acme"')
1176         self.assert_(not cookie)
1177 
1178         #
1179         #   3.  User Agent -> Server
1180         #
1181         #       POST /acme/pickitem HTTP/1.1
1182         #       Cookie: $Version="1"; Customer="WILE_E_COYOTE"; $Path="/acme"
1183         #       [form data]
1184         #
1185         #       User selects an item for ``shopping basket.''
1186         #
1187         #   4.  Server -> User Agent
1188         #
1189         #       HTTP/1.1 200 OK
1190         #       Set-Cookie2: Part_Number="Rocket_Launcher_0001"; Version="1";
1191         #               Path="/acme"
1192         #
1193         #       Shopping basket contains an item.
1194 
1195         cookie = interact_2965(c, 'http://www.acme.com/acme/pickitem',
1196                                'Part_Number="Rocket_Launcher_0001"; '
1197                                'Version="1"; Path="/acme"');
1198         self.assert_(re.search(
1199             r'^\$Version="?1"?; Customer="?WILE_E_COYOTE"?; \$Path="/acme"$',
1200             cookie))
1201 
1202         #
1203         #   5.  User Agent -> Server
1204         #
1205         #       POST /acme/shipping HTTP/1.1
1206         #       Cookie: $Version="1";
1207         #               Customer="WILE_E_COYOTE"; $Path="/acme";
1208         #               Part_Number="Rocket_Launcher_0001"; $Path="/acme"
1209         #       [form data]
1210         #
1211         #       User selects shipping method from form.
1212         #
1213         #   6.  Server -> User Agent
1214         #
1215         #       HTTP/1.1 200 OK
1216         #       Set-Cookie2: Shipping="FedEx"; Version="1"; Path="/acme"
1217         #
1218         #       New cookie reflects shipping method.
1219 
1220         cookie = interact_2965(c, "http://www.acme.com/acme/shipping",
1221                                'Shipping="FedEx"; Version="1"; Path="/acme"')
1222 
1223         self.assert_(re.search(r'^\$Version="?1"?;', cookie))
1224         self.assert_(re.search(r'Part_Number="?Rocket_Launcher_0001"?;'
1225                                '\s*\$Path="\/acme"', cookie))
1226         self.assert_(re.search(r'Customer="?WILE_E_COYOTE"?;\s*\$Path="\/acme"',
1227                                cookie))
1228 
1229         #
1230         #   7.  User Agent -> Server
1231         #
1232         #       POST /acme/process HTTP/1.1
1233         #       Cookie: $Version="1";
1234         #               Customer="WILE_E_COYOTE"; $Path="/acme";
1235         #               Part_Number="Rocket_Launcher_0001"; $Path="/acme";
1236         #               Shipping="FedEx"; $Path="/acme"
1237         #       [form data]
1238         #
1239         #       User chooses to process order.
1240         #
1241         #   8.  Server -> User Agent
1242         #
1243         #       HTTP/1.1 200 OK
1244         #
1245         #       Transaction is complete.
1246 
1247         cookie = interact_2965(c, "http://www.acme.com/acme/process")
1248         self.assert_(
1249             re.search(r'Shipping="?FedEx"?;\s*\$Path="\/acme"', cookie) and
1250             "WILE_E_COYOTE" in cookie)
1251 
1252         #
1253         # The user agent makes a series of requests on the origin server, after
1254         # each of which it receives a new cookie.  All the cookies have the same
1255         # Path attribute and (default) domain.  Because the request URLs all have
1256         # /acme as a prefix, and that matches the Path attribute, each request
1257         # contains all the cookies received so far.
1258 
1259     def test_ietf_example_2(self):
1260         from cookielib import CookieJar, DefaultCookiePolicy
1261 
1262         # 5.2  Example 2
1263         #
1264         # This example illustrates the effect of the Path attribute.  All detail
1265         # of request and response headers has been omitted.  Assume the user agent
1266         # has no stored cookies.
1267 
1268         c = CookieJar(DefaultCookiePolicy(rfc2965=True))
1269 
1270         # Imagine the user agent has received, in response to earlier requests,
1271         # the response headers
1272         #
1273         # Set-Cookie2: Part_Number="Rocket_Launcher_0001"; Version="1";
1274         #         Path="/acme"
1275         #
1276         # and
1277         #
1278         # Set-Cookie2: Part_Number="Riding_Rocket_0023"; Version="1";
1279         #         Path="/acme/ammo"
1280 
1281         interact_2965(
1282             c, "http://www.acme.com/acme/ammo/specific",
1283             'Part_Number="Rocket_Launcher_0001"; Version="1"; Path="/acme"',
1284             'Part_Number="Riding_Rocket_0023"; Version="1"; Path="/acme/ammo"')
1285 
1286         # A subsequent request by the user agent to the (same) server for URLs of
1287         # the form /acme/ammo/...  would include the following request header:
1288         #
1289         # Cookie: $Version="1";
1290         #         Part_Number="Riding_Rocket_0023"; $Path="/acme/ammo";
1291         #         Part_Number="Rocket_Launcher_0001"; $Path="/acme"
1292         #
1293         # Note that the NAME=VALUE pair for the cookie with the more specific Path
1294         # attribute, /acme/ammo, comes before the one with the less specific Path
1295         # attribute, /acme.  Further note that the same cookie name appears more
1296         # than once.
1297 
1298         cookie = interact_2965(c, "http://www.acme.com/acme/ammo/...")
1299         self.assert_(
1300             re.search(r"Riding_Rocket_0023.*Rocket_Launcher_0001", cookie))
1301 
1302         # A subsequent request by the user agent to the (same) server for a URL of
1303         # the form /acme/parts/ would include the following request header:
1304         #
1305         # Cookie: $Version="1"; Part_Number="Rocket_Launcher_0001"; $Path="/acme"
1306         #
1307         # Here, the second cookie's Path attribute /acme/ammo is not a prefix of
1308         # the request URL, /acme/parts/, so the cookie does not get forwarded to
1309         # the server.
1310 
1311         cookie = interact_2965(c, "http://www.acme.com/acme/parts/")
1312         self.assert_("Rocket_Launcher_0001" in cookie and
1313                      "Riding_Rocket_0023" not in cookie)
1314 
1315     def test_rejection(self):
1316         # Test rejection of Set-Cookie2 responses based on domain, path, port.
1317         from cookielib import DefaultCookiePolicy, LWPCookieJar
1318 
1319         pol = DefaultCookiePolicy(rfc2965=True)
1320 
1321         c = LWPCookieJar(policy=pol)
1322 
1323         max_age = "max-age=3600"
1324 
1325         # illegal domain (no embedded dots)
1326         cookie = interact_2965(c, "http://www.acme.com",
1327                                'foo=bar; domain=".com"; version=1')
1328         self.assert_(not c)
1329 
1330         # legal domain
1331         cookie = interact_2965(c, "http://www.acme.com",
1332                                'ping=pong; domain="acme.com"; version=1')
1333         self.assertEquals(len(c), 1)
1334 
1335         # illegal domain (host prefix "www.a" contains a dot)
1336         cookie = interact_2965(c, "http://www.a.acme.com",
1337                                'whiz=bang; domain="acme.com"; version=1')
1338         self.assertEquals(len(c), 1)
1339 
1340         # legal domain
1341         cookie = interact_2965(c, "http://www.a.acme.com",
1342                                'wow=flutter; domain=".a.acme.com"; version=1')
1343         self.assertEquals(len(c), 2)
1344 
1345         # can't partially match an IP-address
1346         cookie = interact_2965(c, "http://125.125.125.125",
1347                                'zzzz=ping; domain="125.125.125"; version=1')
1348         self.assertEquals(len(c), 2)
1349 
1350         # illegal path (must be prefix of request path)
1351         cookie = interact_2965(c, "http://www.sol.no",
1352                                'blah=rhubarb; domain=".sol.no"; path="/foo"; '
1353                                'version=1')
1354         self.assertEquals(len(c), 2)
1355 
1356         # legal path
1357         cookie = interact_2965(c, "http://www.sol.no/foo/bar",
1358                                'bing=bong; domain=".sol.no"; path="/foo"; '
1359                                'version=1')
1360         self.assertEquals(len(c), 3)
1361 
1362         # illegal port (request-port not in list)
1363         cookie = interact_2965(c, "http://www.sol.no",
1364                                'whiz=ffft; domain=".sol.no"; port="90,100"; '
1365                                'version=1')
1366         self.assertEquals(len(c), 3)
1367 
1368         # legal port
1369         cookie = interact_2965(
1370             c, "http://www.sol.no",
1371             r'bang=wallop; version=1; domain=".sol.no"; '
1372             r'port="90,100, 80,8080"; '
1373             r'max-age=100; Comment = "Just kidding! (\"|\\\\) "')
1374         self.assertEquals(len(c), 4)
1375 
1376         # port attribute without any value (current port)
1377         cookie = interact_2965(c, "http://www.sol.no",
1378                                'foo9=bar; version=1; domain=".sol.no"; port; '
1379                                'max-age=100;')
1380         self.assertEquals(len(c), 5)
1381 
1382         # encoded path
1383         # LWP has this test, but unescaping allowed path characters seems
1384         # like a bad idea, so I think this should fail:
1385 ##         cookie = interact_2965(c, "http://www.sol.no/foo/",
1386 ##                           r'foo8=bar; version=1; path="/%66oo"')
1387         # but this is OK, because '<' is not an allowed HTTP URL path
1388         # character:
1389         cookie = interact_2965(c, "http://www.sol.no/<oo/",
1390                                r'foo8=bar; version=1; path="/%3coo"')
1391         self.assertEquals(len(c), 6)
1392 
1393         # save and restore
1394         filename = test_support.TESTFN
1395 
1396         try:
1397             c.save(filename, ignore_discard=True)
1398             old = repr(c)
1399 
1400             c = LWPCookieJar(policy=pol)
1401             c.load(filename, ignore_discard=True)
1402         finally:
1403             try: os.unlink(filename)
1404             except OSError: pass
1405 
1406         self.assertEquals(old, repr(c))
1407 
1408     def test_url_encoding(self):
1409         # Try some URL encodings of the PATHs.
1410         # (the behaviour here has changed from libwww-perl)
1411         from cookielib import CookieJar, DefaultCookiePolicy
1412 
1413         c = CookieJar(DefaultCookiePolicy(rfc2965=True))
1414         interact_2965(c, "http://www.acme.com/foo%2f%25/%3c%3c%0Anew%E5/%E5",
1415                       "foo  =   bar; version    =   1")
1416 
1417         cookie = interact_2965(
1418             c, "http://www.acme.com/foo%2f%25/<<%0anewå/æøå",
1419             'bar=baz; path="/foo/"; version=1');
1420         version_re = re.compile(r'^\$version=\"?1\"?', re.I)
1421         self.assert_("foo=bar" in cookie and version_re.search(cookie))
1422 
1423         cookie = interact_2965(
1424             c, "http://www.acme.com/foo/%25/<<%0anewå/æøå")
1425         self.assert_(not cookie)
1426 
1427         # unicode URL doesn't raise exception
1428         cookie = interact_2965(c, u"http://www.acme.com/\xfc")
1429 
1430     def test_mozilla(self):
1431         # Save / load Mozilla/Netscape cookie file format.
1432         from cookielib import MozillaCookieJar, DefaultCookiePolicy
1433 
1434         year_plus_one = time.localtime()[0] + 1
1435 
1436         filename = test_support.TESTFN
1437 
1438         c = MozillaCookieJar(filename,
1439                              policy=DefaultCookiePolicy(rfc2965=True))
1440         interact_2965(c, "http://www.acme.com/",
1441                       "foo1=bar; max-age=100; Version=1")
1442         interact_2965(c, "http://www.acme.com/",
1443                       'foo2=bar; port="80"; max-age=100; Discard; Version=1')
1444         interact_2965(c, "http://www.acme.com/", "foo3=bar; secure; Version=1")
1445 
1446         expires = "expires=09-Nov-%d 23:12:40 GMT" % (year_plus_one,)
1447         interact_netscape(c, "http://www.foo.com/",
1448                           "fooa=bar; %s" % expires)
1449         interact_netscape(c, "http://www.foo.com/",
1450                           "foob=bar; Domain=.foo.com; %s" % expires)
1451         interact_netscape(c, "http://www.foo.com/",
1452                           "fooc=bar; Domain=www.foo.com; %s" % expires)
1453 
1454         def save_and_restore(cj, ignore_discard):
1455             try:
1456                 cj.save(ignore_discard=ignore_discard)
1457                 new_c = MozillaCookieJar(filename,
1458                                          DefaultCookiePolicy(rfc2965=True))
1459                 new_c.load(ignore_discard=ignore_discard)
1460             finally:
1461                 try: os.unlink(filename)
1462                 except OSError: pass
1463             return new_c
1464 
1465         new_c = save_and_restore(c, True)
1466         self.assertEquals(len(new_c), 6)  # none discarded
1467         self.assert_("name='foo1', value='bar'" in repr(new_c))
1468 
1469         new_c = save_and_restore(c, False)
1470         self.assertEquals(len(new_c), 4)  # 2 of them discarded on save
1471         self.assert_("name='foo1', value='bar'" in repr(new_c))
1472 
1473     def test_netscape_misc(self):
1474         # Some additional Netscape cookies tests.
1475         from cookielib import CookieJar
1476         from urllib2 import Request
1477 
1478         c = CookieJar()
1479         headers = []
1480         req = Request("http://foo.bar.acme.com/foo")
1481 
1482         # Netscape allows a host part that contains dots
1483         headers.append("Set-Cookie: Customer=WILE_E_COYOTE; domain=.acme.com")
1484         res = FakeResponse(headers, "http://www.acme.com/foo")
1485         c.extract_cookies(res, req)
1486 
1487         # and that the domain is the same as the host without adding a leading
1488         # dot to the domain.  Should not quote even if strange chars are used
1489         # in the cookie value.
1490         headers.append("Set-Cookie: PART_NUMBER=3,4; domain=foo.bar.acme.com")
1491         res = FakeResponse(headers, "http://www.acme.com/foo")
1492         c.extract_cookies(res, req)
1493 
1494         req = Request("http://foo.bar.acme.com/foo")
1495         c.add_cookie_header(req)
1496         self.assert_(
1497             "PART_NUMBER=3,4" in req.get_header("Cookie") and
1498             "Customer=WILE_E_COYOTE" in req.get_header("Cookie"))
1499 
1500     def test_intranet_domains_2965(self):
1501         # Test handling of local intranet hostnames without a dot.
1502         from cookielib import CookieJar, DefaultCookiePolicy
1503 
1504         c = CookieJar(DefaultCookiePolicy(rfc2965=True))
1505         interact_2965(c, "http://example/",
1506                       "foo1=bar; PORT; Discard; Version=1;")
1507         cookie = interact_2965(c, "http://example/",
1508                                'foo2=bar; domain=".local"; Version=1')
1509         self.assert_("foo1=bar" in cookie)
1510 
1511         interact_2965(c, "http://example/", 'foo3=bar; Version=1')
1512         cookie = interact_2965(c, "http://example/")
1513         self.assert_("foo2=bar" in cookie and len(c) == 3)
1514 
1515     def test_intranet_domains_ns(self):
1516         from cookielib import CookieJar, DefaultCookiePolicy
1517 
1518         c = CookieJar(DefaultCookiePolicy(rfc2965 = False))
1519         interact_netscape(c, "http://example/", "foo1=bar")
1520         cookie = interact_netscape(c, "http://example/",
1521                                    'foo2=bar; domain=.local')
1522         self.assertEquals(len(c), 2)
1523         self.assert_("foo1=bar" in cookie)
1524 
1525         cookie = interact_netscape(c, "http://example/")
1526         self.assert_("foo2=bar" in cookie)
1527         self.assertEquals(len(c), 2)
1528 
1529     def test_empty_path(self):
1530         from cookielib import CookieJar, DefaultCookiePolicy
1531         from urllib2 import Request
1532 
1533         # Test for empty path
1534         # Broken web-server ORION/1.3.38 returns to the client response like
1535         #
1536         #       Set-Cookie: JSESSIONID=ABCDERANDOM123; Path=
1537         #
1538         # ie. with Path set to nothing.
1539         # In this case, extract_cookies() must set cookie to / (root)
1540         c = CookieJar(DefaultCookiePolicy(rfc2965 = True))
1541         headers = []
1542 
1543         req = Request("http://www.ants.com/")
1544         headers.append("Set-Cookie: JSESSIONID=ABCDERANDOM123; Path=")
1545         res = FakeResponse(headers, "http://www.ants.com/")
1546         c.extract_cookies(res, req)
1547 
1548         req = Request("http://www.ants.com/")
1549         c.add_cookie_header(req)
1550 
1551         self.assertEquals(req.get_header("Cookie"),
1552                           "JSESSIONID=ABCDERANDOM123")
1553         self.assertEquals(req.get_header("Cookie2"), '$Version="1"')
1554 
1555         # missing path in the request URI
1556         req = Request("http://www.ants.com:8080")
1557         c.add_cookie_header(req)
1558 
1559         self.assertEquals(req.get_header("Cookie"),
1560                           "JSESSIONID=ABCDERANDOM123")
1561         self.assertEquals(req.get_header("Cookie2"), '$Version="1"')
1562 
1563     def test_session_cookies(self):
1564         from cookielib import CookieJar
1565         from urllib2 import Request
1566 
1567         year_plus_one = time.localtime()[0] + 1
1568 
1569         # Check session cookies are deleted properly by
1570         # CookieJar.clear_session_cookies method
1571 
1572         req = Request('http://www.perlmeister.com/scripts')
1573         headers = []
1574         headers.append("Set-Cookie: s1=session;Path=/scripts")
1575         headers.append("Set-Cookie: p1=perm; Domain=.perlmeister.com;"
1576                        "Path=/;expires=Fri, 02-Feb-%d 23:24:20 GMT" %
1577                        year_plus_one)
1578         headers.append("Set-Cookie: p2=perm;Path=/;expires=Fri, "
1579                        "02-Feb-%d 23:24:20 GMT" % year_plus_one)
1580         headers.append("Set-Cookie: s2=session;Path=/scripts;"
1581                        "Domain=.perlmeister.com")
1582         headers.append('Set-Cookie2: s3=session;Version=1;Discard;Path="/"')
1583         res = FakeResponse(headers, 'http://www.perlmeister.com/scripts')
1584 
1585         c = CookieJar()
1586         c.extract_cookies(res, req)
1587         # How many session/permanent cookies do we have?
1588         counter = {"session_after": 0,
1589                    "perm_after": 0,
1590                    "session_before": 0,
1591                    "perm_before": 0}
1592         for cookie in c:
1593             key = "%s_before" % cookie.value
1594             counter[key] = counter[key] + 1
1595         c.clear_session_cookies()
1596         # How many now?
1597         for cookie in c:
1598             key = "%s_after" % cookie.value
1599             counter[key] = counter[key] + 1
1600 
1601         self.assert_(not (
1602             # a permanent cookie got lost accidently
1603             counter["perm_after"] != counter["perm_before"] or
1604             # a session cookie hasn't been cleared
1605             counter["session_after"] != 0 or
1606             # we didn't have session cookies in the first place
1607             counter["session_before"] == 0))
1608 
1609 
1610 def test_main(verbose=None):
1611     from test import test_sets
1612     test_support.run_unittest(
1613         DateTimeTests,
1614         HeaderTests,
1615         CookieTests,
1616         LWPCookieTests,
1617         )
1618 
1619 if __name__ == "__main__":
1620     test_main(verbose=True)
1621 

Generated by PyXR 0.9.4
SourceForge.net Logo