Staging
v0.5.1
https://github.com/python/cpython
Revision 3feef61742facb3cbf53f9df1cb89062452597f2 authored by Christian Heimes on 11 February 2008, 06:19:17 UTC, committed by Christian Heimes on 11 February 2008, 06:19:17 UTC
svn+ssh://pythondev@svn.python.org/python/trunk

........
  r60701 | georg.brandl | 2008-02-09 22:36:15 +0100 (Sat, 09 Feb 2008) | 2 lines

  Needs only 2.4 now.
........
  r60702 | georg.brandl | 2008-02-09 22:38:54 +0100 (Sat, 09 Feb 2008) | 2 lines

  Docs are rst now.
........
  r60703 | georg.brandl | 2008-02-09 23:00:00 +0100 (Sat, 09 Feb 2008) | 2 lines

  Fix link.
........
  r60704 | georg.brandl | 2008-02-10 00:09:25 +0100 (Sun, 10 Feb 2008) | 2 lines

  Fix for newest doctools.
........
  r60709 | raymond.hettinger | 2008-02-10 08:21:09 +0100 (Sun, 10 Feb 2008) | 1 line

  Clarify that decimal also supports fixed-point arithmetic.
........
  r60710 | nick.coghlan | 2008-02-10 08:32:52 +0100 (Sun, 10 Feb 2008) | 1 line

  Add missing NEWS entry for r60695
........
  r60712 | mark.dickinson | 2008-02-10 15:58:38 +0100 (Sun, 10 Feb 2008) | 3 lines

  Turn classmethods into staticmethods, and avoid calling the constructor
  of subclasses of Rational.  (See discussion in issue #1682.)
........
  r60715 | mark.dickinson | 2008-02-10 16:19:58 +0100 (Sun, 10 Feb 2008) | 2 lines

  Typos in decimal comment and documentation
........
  r60716 | skip.montanaro | 2008-02-10 16:31:54 +0100 (Sun, 10 Feb 2008) | 2 lines

  Get the saying right. ;-)
........
  r60717 | skip.montanaro | 2008-02-10 16:32:16 +0100 (Sun, 10 Feb 2008) | 2 lines

  whoops - revert
........
  r60718 | mark.dickinson | 2008-02-10 20:23:36 +0100 (Sun, 10 Feb 2008) | 2 lines

  Remove reference to Rational
........
  r60719 | raymond.hettinger | 2008-02-10 21:35:16 +0100 (Sun, 10 Feb 2008) | 1 line

  Complete an open todo on pickletools -- add a pickle optimizer.
........
  r60721 | mark.dickinson | 2008-02-10 22:29:51 +0100 (Sun, 10 Feb 2008) | 3 lines

  Rename rational.Rational to fractions.Fraction, to avoid name clash
  with numbers.Rational.  See issue #1682 for related discussion.
........
  r60722 | christian.heimes | 2008-02-11 03:26:22 +0100 (Mon, 11 Feb 2008) | 1 line

  The test requires the network resource
........
  r60723 | mark.dickinson | 2008-02-11 04:11:55 +0100 (Mon, 11 Feb 2008) | 3 lines

  Put an extra space into the repr of a Fraction:
  Fraction(1, 2) instead of Fraction(1,2).
........
1 parent ba99c58
Raw File
Tip revision: 3feef61742facb3cbf53f9df1cb89062452597f2 authored by Christian Heimes on 11 February 2008, 06:19:17 UTC
Merged revisions 60481,60485,60489-60492,60494-60496,60498-60499,60501-60503,60505-60506,60508-60509,60523-60524,60532,60543,60545,60547-60548,60552,60554,60556-60559,60561-60562,60569,60571-60572,60574,60576-60583,60585-60586,60589,60591,60594-60595,60597-60598,60600-60601,60606-60612,60615,60617,60619-60621,60623-60625,60627-60629,60631,60633,60635,60647,60650,60652,60654,60656,60658-60659,60664-60666,60668-60670,60672,60676,60678,60680-60683,60685-60686,60688,60690,60692-60694,60697-60706,60708-60712,60714-60724 via svnmerge from
Tip revision: 3feef61
_LWPCookieJar.py
"""Load / save to libwww-perl (LWP) format files.

Actually, the format is slightly extended from that used by LWP's
(libwww-perl's) HTTP::Cookies, to avoid losing some RFC 2965 information
not recorded by LWP.

It uses the version string "2.0", though really there isn't an LWP Cookies
2.0 format.  This indicates that there is extra information in here
(domain_dot and # port_spec) while still being compatible with
libwww-perl, I hope.

"""

import time, re
from cookielib import (_warn_unhandled_exception, FileCookieJar, LoadError,
                       Cookie, MISSING_FILENAME_TEXT,
                       join_header_words, split_header_words,
                       iso2time, time2isoz)

def lwp_cookie_str(cookie):
    """Return string representation of Cookie in an the LWP cookie file format.

    Actually, the format is extended a bit -- see module docstring.

    """
    h = [(cookie.name, cookie.value),
         ("path", cookie.path),
         ("domain", cookie.domain)]
    if cookie.port is not None: h.append(("port", cookie.port))
    if cookie.path_specified: h.append(("path_spec", None))
    if cookie.port_specified: h.append(("port_spec", None))
    if cookie.domain_initial_dot: h.append(("domain_dot", None))
    if cookie.secure: h.append(("secure", None))
    if cookie.expires: h.append(("expires",
                               time2isoz(float(cookie.expires))))
    if cookie.discard: h.append(("discard", None))
    if cookie.comment: h.append(("comment", cookie.comment))
    if cookie.comment_url: h.append(("commenturl", cookie.comment_url))

    keys = sorted(cookie._rest.keys())
    for k in keys:
        h.append((k, str(cookie._rest[k])))

    h.append(("version", str(cookie.version)))

    return join_header_words([h])

class LWPCookieJar(FileCookieJar):
    """
    The LWPCookieJar saves a sequence of"Set-Cookie3" lines.
    "Set-Cookie3" is the format used by the libwww-perl libary, not known
    to be compatible with any browser, but which is easy to read and
    doesn't lose information about RFC 2965 cookies.

    Additional methods

    as_lwp_str(ignore_discard=True, ignore_expired=True)

    """

    def as_lwp_str(self, ignore_discard=True, ignore_expires=True):
        """Return cookies as a string of "\n"-separated "Set-Cookie3" headers.

        ignore_discard and ignore_expires: see docstring for FileCookieJar.save

        """
        now = time.time()
        r = []
        for cookie in self:
            if not ignore_discard and cookie.discard:
                continue
            if not ignore_expires and cookie.is_expired(now):
                continue
            r.append("Set-Cookie3: %s" % lwp_cookie_str(cookie))
        return "\n".join(r+[""])

    def save(self, filename=None, ignore_discard=False, ignore_expires=False):
        if filename is None:
            if self.filename is not None: filename = self.filename
            else: raise ValueError(MISSING_FILENAME_TEXT)

        f = open(filename, "w")
        try:
            # There really isn't an LWP Cookies 2.0 format, but this indicates
            # that there is extra information in here (domain_dot and
            # port_spec) while still being compatible with libwww-perl, I hope.
            f.write("#LWP-Cookies-2.0\n")
            f.write(self.as_lwp_str(ignore_discard, ignore_expires))
        finally:
            f.close()

    def _really_load(self, f, filename, ignore_discard, ignore_expires):
        magic = f.readline()
        if not re.search(self.magic_re, magic):
            msg = ("%r does not look like a Set-Cookie3 (LWP) format "
                   "file" % filename)
            raise LoadError(msg)

        now = time.time()

        header = "Set-Cookie3:"
        boolean_attrs = ("port_spec", "path_spec", "domain_dot",
                         "secure", "discard")
        value_attrs = ("version",
                       "port", "path", "domain",
                       "expires",
                       "comment", "commenturl")

        try:
            while 1:
                line = f.readline()
                if line == "": break
                if not line.startswith(header):
                    continue
                line = line[len(header):].strip()

                for data in split_header_words([line]):
                    name, value = data[0]
                    standard = {}
                    rest = {}
                    for k in boolean_attrs:
                        standard[k] = False
                    for k, v in data[1:]:
                        if k is not None:
                            lc = k.lower()
                        else:
                            lc = None
                        # don't lose case distinction for unknown fields
                        if (lc in value_attrs) or (lc in boolean_attrs):
                            k = lc
                        if k in boolean_attrs:
                            if v is None: v = True
                            standard[k] = v
                        elif k in value_attrs:
                            standard[k] = v
                        else:
                            rest[k] = v

                    h = standard.get
                    expires = h("expires")
                    discard = h("discard")
                    if expires is not None:
                        expires = iso2time(expires)
                    if expires is None:
                        discard = True
                    domain = h("domain")
                    domain_specified = domain.startswith(".")
                    c = Cookie(h("version"), name, value,
                               h("port"), h("port_spec"),
                               domain, domain_specified, h("domain_dot"),
                               h("path"), h("path_spec"),
                               h("secure"),
                               expires,
                               discard,
                               h("comment"),
                               h("commenturl"),
                               rest)
                    if not ignore_discard and c.discard:
                        continue
                    if not ignore_expires and c.is_expired(now):
                        continue
                    self.set_cookie(c)

        except IOError:
            raise
        except Exception:
            _warn_unhandled_exception()
            raise LoadError("invalid Set-Cookie3 format file %r: %r" %
                            (filename, line))
back to top