[Checkins] SVN: zope.contenttype/trunk/src/zope/contenttype/parse.py moved the implementation of zope.publisher.contenttype to zope.contenttype.parse

Thomas Lotze tl at gocept.com
Thu Oct 8 10:57:19 EDT 2009


Log message for revision 104932:
  moved the implementation of zope.publisher.contenttype to zope.contenttype.parse
  

Changed:
  A   zope.contenttype/trunk/src/zope/contenttype/parse.py

-=-
Copied: zope.contenttype/trunk/src/zope/contenttype/parse.py (from rev 104931, zope.publisher/trunk/src/zope/publisher/contenttype.py)
===================================================================
--- zope.contenttype/trunk/src/zope/contenttype/parse.py	                        (rev 0)
+++ zope.contenttype/trunk/src/zope/contenttype/parse.py	2009-10-08 14:57:19 UTC (rev 104932)
@@ -0,0 +1,136 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""MIME Content-Type parsing helper functions.
+
+This supports parsing RFC 1341 Content-Type values, including
+quoted-string values as defined in RFC 822.
+
+"""
+__docformat__ = "reStructuredText"
+
+import re
+
+
+# TODO: This still needs to support comments in structured fields as
+# specified in RFC 2822.
+
+
+def parse(string):
+    major, minor, params = parseOrdered(string)
+    d = {}
+    for (name, value) in params:
+        d[name] = value
+    return major, minor, d
+
+def parseOrdered(string):
+    if ";" in string:
+        type, params = string.split(";", 1)
+        params = _parse_params(params)
+    else:
+        type = string
+        params = []
+    if "/" not in type:
+        raise ValueError("content type missing major/minor parts: %r" % type)
+    type = type.strip()
+
+    major, minor = type.lower().split("/", 1)
+    return _check_token(major.strip()), _check_token(minor.strip()), params
+
+def _parse_params(string):
+    result = []
+    string = string.strip()
+    while string:
+        if not "=" in string:
+            raise ValueError("parameter values are not optional")
+        name, rest = string.split("=", 1)
+        name = _check_token(name.strip().lower())
+        rest = rest.strip()
+
+        # rest is: value *[";" parameter]
+
+        if rest[:1] == '"':
+            # quoted-string, defined in RFC 822.
+            m = _quoted_string_match(rest)
+            if m is None:
+                raise ValueError("invalid quoted-string in %r" % rest)
+            value = m.group()
+            rest = rest[m.end():].strip()
+            #import pdb; pdb.set_trace()
+            if rest[:1] not in ("", ";"):
+                raise ValueError(
+                    "invalid token following quoted-string: %r" % rest)
+            rest = rest[1:]
+            value = _unescape(value)
+
+        elif ";" in rest:
+            value, rest = rest.split(";")
+            value = _check_token(value.strip())
+
+        else:
+            value = _check_token(rest.strip())
+            rest = ""
+
+        result.append((name, value))
+        string = rest.strip()
+    return result
+
+
+def _quoted_string_match(string):
+    # This support RFC 822 quoted-string values.
+    global _quoted_string_match
+    _quoted_string_match = re.compile(
+        '"(?:\\\\.|[^"\n\r\\\\])*"', re.DOTALL).match
+    return _quoted_string_match(string)
+
+def _check_token(string):
+    if _token_match(string) is None:
+        raise ValueError('"%s" is not a valid token' % string)
+    return string
+
+def _token_match(string):
+    global _token_match
+    _token_match = re.compile("[^][ \t\n\r()<>@,;:\"/?=\\\\]+$").match
+    return _token_match(string)
+
+def _unescape(string):
+    assert string[0] == '"'
+    assert string[-1] == '"'
+    string = string[1:-1]
+    if "\\" in string:
+        string = re.sub(r"\\(.)", r"\1", string)
+    return string
+
+
+def join((major, minor, params)):
+    pstr = ""
+    try:
+        params.items
+    except AttributeError:
+        pass
+    else:
+        params = params.items()
+        # ensure a predictable order:
+        params.sort()
+    for name, value in params:
+        pstr += ";%s=%s" % (name, _escape(value))
+    return "%s/%s%s" % (major, minor, pstr)
+
+def _escape(string):
+    try:
+        return _check_token(string)
+    except ValueError:
+        # '\\' must be first
+        for c in '\\"\n\r':
+            string = string.replace(c, "\\" + c)
+        return '"%s"' % string



More information about the checkins mailing list