[Checkins] SVN: Sandbox/shane/republish/zope.publisher/ this version of the publisher uses zope.httpform
Shane Hathaway
shane at hathawaymix.org
Fri Feb 6 02:41:03 EST 2009
Log message for revision 96176:
this version of the publisher uses zope.httpform
Changed:
A Sandbox/shane/republish/zope.publisher/
D Sandbox/shane/republish/zope.publisher/CHANGES.txt
A Sandbox/shane/republish/zope.publisher/CHANGES.txt
D Sandbox/shane/republish/zope.publisher/setup.py
A Sandbox/shane/republish/zope.publisher/setup.py
U Sandbox/shane/republish/zope.publisher/src/zope/publisher/browser.py
-=-
Deleted: Sandbox/shane/republish/zope.publisher/CHANGES.txt
===================================================================
--- zope.publisher/trunk/CHANGES.txt 2009-02-04 21:02:45 UTC (rev 96089)
+++ Sandbox/shane/republish/zope.publisher/CHANGES.txt 2009-02-06 07:41:02 UTC (rev 96176)
@@ -1,130 +0,0 @@
-CHANGES
-=======
-
-3.5.5 (unreleased)
-------------------
-
-* LP #322486: setStatus() now allows any int()-able status value.
-
-
-3.5.4 (2008-09-22)
-------------------
-
-Bugs fixed:
-
-* LP #98440: interfaces lost on retried request
-
-* LP #273296: dealing more nicely with malformed HTTP_ACCEPT_LANGUAGE headers
- within getPreferredLanguages().
-
-* LP #253362: dealing more nicely with malformed HTTP_ACCEPT_CHARSET headers
- within getPreferredCharsets().
-
-* LP #98284: Pass the ``size`` argument to readline, as the version of
- twisted used in zope.app.twisted supports it.
-
-* Fix the LP #98284 fix: do not pass ``size`` argument of None that causes
- cStringIO objects to barf with a TypeError.
-
-
-3.5.3 (2008-06-20)
-------------------
-
-Bugs fixed:
-
-* It turns out that some Web servers (Paste for example) do not send the EOF
- character after the data has been transmitted and the read() of the cached
- stream simply hangs if no expected content length has been specified.
-
-
-3.5.2 (2008-04-06)
-------------------
-
-Bugs fixed:
-
-* A previous fix to handle posting of non-form data broke handling of
- form data with extra information in the content type, as in::
-
- application/x-www-form-urlencoded; charset=UTF-8
-
-3.5.1 (2008-03-23)
-------------------
-
-Bugs fixed:
-
-* When posting non-form (and non-multipart) data, the request body was
- consumed and discarded. This makes it impossible to deal with other
- post types, like xml-rpc or json without resorting to overly complex
- "request factory" contortions.
-
-* https://bugs.launchpad.net/zope2/+bug/143873
-
- The zope.publisher.http.HTTPCharsets was confused by the Zope 2
- publisher, which gives missleading information about which headers
- it has.
-
-3.5.0 (2008-03-02)
-------------------
-
-Features added:
-
-* Added a PasteDeploy app_factory implementation. This should make
- it easier to integrate Zope 3 applications with PasteDeploy. It
- also makes it easier to control the publication used, giving far
- greater control over application policies (e.g. whether or not to
- use the ZODB).
-
-3.4.2 (2007-12-07)
-------------------
-
-* Made segmentation of URLs not strip (trailing) whitespace from path segments
- to allow URLs ending in %20 to be handled correctly. (#172742)
-
-3.4.1 (2007-09-29)
-------------------
-
-No changes since 3.4.1b2.
-
-3.4.1b2 (2007-08-02)
---------------------
-
-* zope.publisher now works on Python 2.5.
-
-* Fix a problem with request.get() when the object that's to be
- retrieved is the request itself.
-
-
-3.4.1b1 (2007-07-13)
---------------------
-
-No changes.
-
-
-3.4.0b2 (2007-07-05)
---------------------
-
-* Fix https://bugs.launchpad.net/zope3/+bug/122054:
- HTTPInputStream understands both the CONTENT_LENGTH and
- HTTP_CONTENT_LENGTH environment variables. It is also now tolerant
- of empty strings and will treat those as if the variable were
- absent.
-
-
-3.4.0b1 (2007-07-05)
---------------------
-
-* Fix caching issue. The input stream never got cached in a temp file
- because of a wrong content-length header lookup. Added CONTENT_LENGTH
- header check in addition to the previous used HTTP_CONTENT_LENGTH. The
- ``HTTP_`` prefix is sometimes added by some CGI proxies, but CONTENT_LENGTH
- is the right header info for the size.
-
-* Fix https://bugs.launchpad.net/zope3/+bug/98413:
- HTTPResponse.handleException should set the content type
-
-
-3.4.0a1 (2007-04-22)
---------------------
-
-Initial release as a separate project, corresponds to zope.publisher
-from Zope 3.4.0a1
Copied: Sandbox/shane/republish/zope.publisher/CHANGES.txt (from rev 96090, zope.publisher/trunk/CHANGES.txt)
===================================================================
--- Sandbox/shane/republish/zope.publisher/CHANGES.txt (rev 0)
+++ Sandbox/shane/republish/zope.publisher/CHANGES.txt 2009-02-06 07:41:02 UTC (rev 96176)
@@ -0,0 +1,136 @@
+CHANGES
+=======
+
+3.5.6 (unreleased)
+------------------
+
+* ...
+
+
+3.5.5 (2009-02-04)
+------------------
+
+* LP #322486: setStatus() now allows any int()-able status value.
+
+
+3.5.4 (2008-09-22)
+------------------
+
+Bugs fixed:
+
+* LP #98440: interfaces lost on retried request
+
+* LP #273296: dealing more nicely with malformed HTTP_ACCEPT_LANGUAGE headers
+ within getPreferredLanguages().
+
+* LP #253362: dealing more nicely with malformed HTTP_ACCEPT_CHARSET headers
+ within getPreferredCharsets().
+
+* LP #98284: Pass the ``size`` argument to readline, as the version of
+ twisted used in zope.app.twisted supports it.
+
+* Fix the LP #98284 fix: do not pass ``size`` argument of None that causes
+ cStringIO objects to barf with a TypeError.
+
+
+3.5.3 (2008-06-20)
+------------------
+
+Bugs fixed:
+
+* It turns out that some Web servers (Paste for example) do not send the EOF
+ character after the data has been transmitted and the read() of the cached
+ stream simply hangs if no expected content length has been specified.
+
+
+3.5.2 (2008-04-06)
+------------------
+
+Bugs fixed:
+
+* A previous fix to handle posting of non-form data broke handling of
+ form data with extra information in the content type, as in::
+
+ application/x-www-form-urlencoded; charset=UTF-8
+
+3.5.1 (2008-03-23)
+------------------
+
+Bugs fixed:
+
+* When posting non-form (and non-multipart) data, the request body was
+ consumed and discarded. This makes it impossible to deal with other
+ post types, like xml-rpc or json without resorting to overly complex
+ "request factory" contortions.
+
+* https://bugs.launchpad.net/zope2/+bug/143873
+
+ The zope.publisher.http.HTTPCharsets was confused by the Zope 2
+ publisher, which gives missleading information about which headers
+ it has.
+
+3.5.0 (2008-03-02)
+------------------
+
+Features added:
+
+* Added a PasteDeploy app_factory implementation. This should make
+ it easier to integrate Zope 3 applications with PasteDeploy. It
+ also makes it easier to control the publication used, giving far
+ greater control over application policies (e.g. whether or not to
+ use the ZODB).
+
+3.4.2 (2007-12-07)
+------------------
+
+* Made segmentation of URLs not strip (trailing) whitespace from path segments
+ to allow URLs ending in %20 to be handled correctly. (#172742)
+
+3.4.1 (2007-09-29)
+------------------
+
+No changes since 3.4.1b2.
+
+3.4.1b2 (2007-08-02)
+--------------------
+
+* zope.publisher now works on Python 2.5.
+
+* Fix a problem with request.get() when the object that's to be
+ retrieved is the request itself.
+
+
+3.4.1b1 (2007-07-13)
+--------------------
+
+No changes.
+
+
+3.4.0b2 (2007-07-05)
+--------------------
+
+* Fix https://bugs.launchpad.net/zope3/+bug/122054:
+ HTTPInputStream understands both the CONTENT_LENGTH and
+ HTTP_CONTENT_LENGTH environment variables. It is also now tolerant
+ of empty strings and will treat those as if the variable were
+ absent.
+
+
+3.4.0b1 (2007-07-05)
+--------------------
+
+* Fix caching issue. The input stream never got cached in a temp file
+ because of a wrong content-length header lookup. Added CONTENT_LENGTH
+ header check in addition to the previous used HTTP_CONTENT_LENGTH. The
+ ``HTTP_`` prefix is sometimes added by some CGI proxies, but CONTENT_LENGTH
+ is the right header info for the size.
+
+* Fix https://bugs.launchpad.net/zope3/+bug/98413:
+ HTTPResponse.handleException should set the content type
+
+
+3.4.0a1 (2007-04-22)
+--------------------
+
+Initial release as a separate project, corresponds to zope.publisher
+from Zope 3.4.0a1
Deleted: Sandbox/shane/republish/zope.publisher/setup.py
===================================================================
--- zope.publisher/trunk/setup.py 2009-02-04 21:02:45 UTC (rev 96089)
+++ Sandbox/shane/republish/zope.publisher/setup.py 2009-02-06 07:41:02 UTC (rev 96176)
@@ -1,61 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2006 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.
-#
-##############################################################################
-
-import os
-from setuptools import setup, find_packages
-
-entry_points = """
-[paste.app_factory]
-main = zope.publisher.paste:Application
-
-[zope.publisher.publication_factory]
-sample = zope.publisher.tests.test_paste:SamplePublication
-"""
-
-setup(name='zope.publisher',
- version = '3.5.5dev',
- url='http://pypi.python.org/pypi/zope.publisher',
- license='ZPL 2.1',
- author='Zope Corporation and Contributors',
- author_email='zope-dev at zope.org',
- description="The Zope publisher publishes Python objects on the web.",
- long_description=(open('README.txt').read()
- + '\n\n'
- + open('CHANGES.txt').read()),
-
- entry_points = entry_points,
-
- packages=find_packages('src'),
- package_dir = {'': 'src'},
-
- namespace_packages=['zope',],
- install_requires=['setuptools',
- 'zope.component',
- 'zope.event',
- 'zope.exceptions',
- 'zope.i18n',
- 'zope.interface',
- 'zope.location',
- 'zope.proxy',
- 'zope.security',
- 'zope.deprecation',
- 'zope.deferredimport'],
- extras_require=dict(
- test = ['zope.testing',
- 'zope.app.testing'],
- ),
- include_package_data = True,
-
- zip_safe = False,
- )
Copied: Sandbox/shane/republish/zope.publisher/setup.py (from rev 96090, zope.publisher/trunk/setup.py)
===================================================================
--- Sandbox/shane/republish/zope.publisher/setup.py (rev 0)
+++ Sandbox/shane/republish/zope.publisher/setup.py 2009-02-06 07:41:02 UTC (rev 96176)
@@ -0,0 +1,63 @@
+##############################################################################
+#
+# Copyright (c) 2006 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.
+#
+##############################################################################
+
+import os
+from setuptools import setup, find_packages
+
+entry_points = """
+[paste.app_factory]
+main = zope.publisher.paste:Application
+
+[zope.publisher.publication_factory]
+sample = zope.publisher.tests.test_paste:SamplePublication
+"""
+
+setup(name='zope.publisher',
+ version = '3.5.6dev',
+ url='http://pypi.python.org/pypi/zope.publisher',
+ license='ZPL 2.1',
+ author='Zope Corporation and Contributors',
+ author_email='zope-dev at zope.org',
+ description="The Zope publisher publishes Python objects on the web.",
+ long_description=(open('README.txt').read()
+ + '\n\n'
+ + open('CHANGES.txt').read()),
+
+ entry_points = entry_points,
+
+ packages=find_packages('src'),
+ package_dir = {'': 'src'},
+
+ namespace_packages=['zope',],
+ install_requires=['setuptools',
+ 'zope.component',
+ 'zope.event',
+ 'zope.exceptions',
+ 'zope.i18n',
+ 'zope.interface',
+ 'zope.location',
+ 'zope.proxy',
+ 'zope.security',
+ 'zope.deprecation',
+ 'zope.deferredimport',
+ 'zope.httpform',
+ ],
+ extras_require=dict(
+ test = ['zope.testing',
+ 'zope.app.testing'],
+ ),
+ include_package_data = True,
+
+ zip_safe = False,
+ )
Modified: Sandbox/shane/republish/zope.publisher/src/zope/publisher/browser.py
===================================================================
--- zope.publisher/trunk/src/zope/publisher/browser.py 2009-02-04 21:02:45 UTC (rev 96089)
+++ Sandbox/shane/republish/zope.publisher/src/zope/publisher/browser.py 2009-02-06 07:41:02 UTC (rev 96176)
@@ -23,9 +23,6 @@
__docformat__ = 'restructuredtext'
import re
-from types import ListType, TupleType, StringType
-from cgi import FieldStorage
-import tempfile
import zope.component
from zope.interface import implements, directlyProvides
@@ -33,6 +30,8 @@
from zope.i18n.interfaces import IUserPreferredLanguages
from zope.i18n.interfaces import IUserPreferredCharsets
from zope.location import Location
+from zope.httpform import FormParser
+from zope.deferredimport import deprecatedFrom
from zope.publisher.interfaces import NotFound
from zope.publisher.interfaces.browser import IBrowserRequest
@@ -46,118 +45,16 @@
from zope.publisher.interfaces.http import IHTTPRequest
from zope.publisher.http import HTTPRequest, HTTPResponse
-__ArrayTypes = (ListType, TupleType)
-
start_of_header_search=re.compile('(<head[^>]*>)', re.I).search
base_re_search=re.compile('(<base.*?>)',re.I).search
isRelative = re.compile("[-_.!~*a-zA-z0-9'()@&=+$,]+(/|$)").match
-newlines = re.compile('\r\n|\n\r|\r')
def is_text_html(content_type):
return content_type.startswith('text/html')
-# Flag Constants
-SEQUENCE = 1
-DEFAULT = 2
-RECORD = 4
-RECORDS = 8
-REC = RECORD | RECORDS
-CONVERTED = 32
DEFAULTABLE_METHODS = 'GET', 'POST', 'HEAD'
-def field2string(v):
- if hasattr(v, 'read'):
- return v.read()
- return str(v)
-
-def field2text(v, nl=newlines):
- return nl.sub("\n", field2string(v))
-
-def field2required(v):
- v = field2string(v)
- if not v.strip():
- raise ValueError('No input for required field<p>')
- return v
-
-def field2int(v):
- if isinstance(v, __ArrayTypes):
- return map(field2int, v)
- v = field2string(v)
- if not v:
- raise ValueError('Empty entry when <strong>integer</strong> expected')
- try:
- return int(v)
- except ValueError:
- raise ValueError("An integer was expected in the value '%s'" % v)
-
-def field2float(v):
- if isinstance(v, __ArrayTypes):
- return map(field2float, v)
- v = field2string(v)
- if not v:
- raise ValueError(
- 'Empty entry when <strong>floating-point number</strong> expected')
- try:
- return float(v)
- except ValueError:
- raise ValueError(
- "A floating-point number was expected in the value '%s'" % v)
-
-def field2long(v):
- if isinstance(v, __ArrayTypes):
- return map(field2long, v)
- v = field2string(v)
-
- # handle trailing 'L' if present.
- if v and v[-1].upper() == 'L':
- v = v[:-1]
- if not v:
- raise ValueError('Empty entry when <strong>integer</strong> expected')
- try:
- return long(v)
- except ValueError:
- raise ValueError("A long integer was expected in the value '%s'" % v)
-
-def field2tokens(v):
- return field2string(v).split()
-
-def field2lines(v):
- if isinstance(v, __ArrayTypes):
- return [str(item) for item in v]
- return field2text(v).splitlines()
-
-def field2boolean(v):
- return bool(v)
-
-type_converters = {
- 'float': field2float,
- 'int': field2int,
- 'long': field2long,
- 'string': field2string,
- 'required': field2required,
- 'tokens': field2tokens,
- 'lines': field2lines,
- 'text': field2text,
- 'boolean': field2boolean,
- }
-
-get_converter = type_converters.get
-
-def registerTypeConverter(field_type, converter, replace=False):
- """Add a custom type converter to the registry.
-
- o If 'replace' is not true, raise a KeyError if a converter is
- already registered for 'field_type'.
- """
- existing = type_converters.get(field_type)
-
- if existing is not None and not replace:
- raise KeyError('Existing converter for field_type: %s' % field_type)
-
- type_converters[field_type] = converter
-
-
isCGI_NAME = {
# These fields are placed in request.environ instead of request.form.
'SERVER_SOFTWARE' : 1,
@@ -185,32 +82,7 @@
'HTTP_CGI_AUTHORIZATION': 1,
}.has_key
-class Record(object):
- _attrs = frozenset(('get', 'keys', 'items', 'values', 'copy',
- 'has_key', '__contains__'))
-
- def __getattr__(self, key, default=None):
- if key in self._attrs:
- return getattr(self.__dict__, key)
- raise AttributeError(key)
-
- def __getitem__(self, key):
- return self.__dict__[key]
-
- def __str__(self):
- items = self.__dict__.items()
- items.sort()
- return "{" + ", ".join(["%s: %s" % item for item in items]) + "}"
-
- def __repr__(self):
- items = self.__dict__.items()
- items.sort()
- return ("{"
- + ", ".join(["%s: %s" % (key, repr(value))
- for key, value in items]) + "}")
-
-_get_or_head = 'GET', 'HEAD'
class BrowserRequest(HTTPRequest):
implements(IBrowserRequest, IBrowserApplicationRequest)
@@ -218,9 +90,6 @@
'__provides__', # Allow request to directly provide interfaces
'form', # Form data
'charsets', # helper attribute
- '__meth',
- '__tuple_items',
- '__defaults',
'__annotations__',
)
@@ -252,273 +121,11 @@
def processInputs(self):
'See IPublisherRequest'
+ parser = FormParser(self._environ, self._body_instream, self._decode)
+ self.form = parser.parse()
+ if parser.action:
+ self.setPathSuffix((parser.action,))
- if self.method not in _get_or_head:
- # Process self.form if not a GET request.
- fp = self._body_instream
- if self.method == 'POST':
- content_type = self._environ.get('CONTENT_TYPE')
- if content_type and not (
- content_type.startswith('application/x-www-form-urlencoded')
- or
- content_type.startswith('multipart/')
- ):
- # for non-multi and non-form content types, FieldStorage
- # consumes the body and we have no good place to put it.
- # So we just won't call FieldStorage. :)
- return
- else:
- fp = None
-
- # If 'QUERY_STRING' is not present in self._environ
- # FieldStorage will try to get it from sys.argv[1]
- # which is not what we need.
- if 'QUERY_STRING' not in self._environ:
- self._environ['QUERY_STRING'] = ''
-
- fs = ZopeFieldStorage(fp=fp, environ=self._environ,
- keep_blank_values=1)
-
- fslist = getattr(fs, 'list', None)
- if fslist is not None:
- self.__meth = None
- self.__tuple_items = {}
- self.__defaults = {}
-
- # process all entries in the field storage (form)
- for item in fslist:
- self.__processItem(item)
-
- if self.__defaults:
- self.__insertDefaults()
-
- if self.__tuple_items:
- self.__convertToTuples()
-
- if self.__meth:
- self.setPathSuffix((self.__meth,))
-
- _typeFormat = re.compile('([a-zA-Z][a-zA-Z0-9_]+|\\.[xy])$')
-
- def __processItem(self, item):
- """Process item in the field storage."""
-
- # Check whether this field is a file upload object
- # Note: A field exists for files, even if no filename was
- # passed in and no data was uploaded. Therefore we can only
- # tell by the empty filename that no upload was made.
- key = item.name
- if (hasattr(item, 'file') and hasattr(item, 'filename')
- and hasattr(item,'headers')):
- if (item.file and
- (item.filename is not None and item.filename != ''
- # RFC 1867 says that all fields get a content-type.
- # or 'content-type' in map(lower, item.headers.keys())
- )):
- item = FileUpload(item)
- else:
- item = item.value
-
- flags = 0
- converter = None
-
- # Loop through the different types and set
- # the appropriate flags
- # Syntax: var_name:type_name
-
- # We'll search from the back to the front.
- # We'll do the search in two steps. First, we'll
- # do a string search, and then we'll check it with
- # a re search.
-
- while key:
- pos = key.rfind(":")
- if pos < 0:
- break
- match = self._typeFormat.match(key, pos + 1)
- if match is None:
- break
-
- key, type_name = key[:pos], key[pos + 1:]
-
- # find the right type converter
- c = get_converter(type_name, None)
-
- if c is not None:
- converter = c
- flags |= CONVERTED
- elif type_name == 'list':
- flags |= SEQUENCE
- elif type_name == 'tuple':
- self.__tuple_items[key] = 1
- flags |= SEQUENCE
- elif (type_name == 'method' or type_name == 'action'):
- if key:
- self.__meth = key
- else:
- self.__meth = item
- elif (type_name == 'default_method'
- or type_name == 'default_action') and not self.__meth:
- if key:
- self.__meth = key
- else:
- self.__meth = item
- elif type_name == 'default':
- flags |= DEFAULT
- elif type_name == 'record':
- flags |= RECORD
- elif type_name == 'records':
- flags |= RECORDS
- elif type_name == 'ignore_empty' and not item:
- # skip over empty fields
- return
-
- # Make it unicode if not None
- if key is not None:
- key = self._decode(key)
-
- if type(item) == StringType:
- item = self._decode(item)
-
- if flags:
- self.__setItemWithType(key, item, flags, converter)
- else:
- self.__setItemWithoutType(key, item)
-
- def __setItemWithoutType(self, key, item):
- """Set item value without explicit type."""
- form = self.form
- if key not in form:
- form[key] = item
- else:
- found = form[key]
- if isinstance(found, list):
- found.append(item)
- else:
- form[key] = [found, item]
-
- def __setItemWithType(self, key, item, flags, converter):
- """Set item value with explicit type."""
- #Split the key and its attribute
- if flags & REC:
- key, attr = self.__splitKey(key)
-
- # defer conversion
- if flags & CONVERTED:
- try:
- item = converter(item)
- except:
- if item or flags & DEFAULT or key not in self.__defaults:
- raise
- item = self.__defaults[key]
- if flags & RECORD:
- item = getattr(item, attr)
- elif flags & RECORDS:
- item = getattr(item[-1], attr)
-
- # Determine which dictionary to use
- if flags & DEFAULT:
- form = self.__defaults
- else:
- form = self.form
-
- # Insert in dictionary
- if key not in form:
- if flags & SEQUENCE:
- item = [item]
- if flags & RECORD:
- r = form[key] = Record()
- setattr(r, attr, item)
- elif flags & RECORDS:
- r = Record()
- setattr(r, attr, item)
- form[key] = [r]
- else:
- form[key] = item
- else:
- r = form[key]
- if flags & RECORD:
- if not flags & SEQUENCE:
- setattr(r, attr, item)
- else:
- if not hasattr(r, attr):
- setattr(r, attr, [item])
- else:
- getattr(r, attr).append(item)
- elif flags & RECORDS:
- last = r[-1]
- if not hasattr(last, attr):
- if flags & SEQUENCE:
- item = [item]
- setattr(last, attr, item)
- else:
- if flags & SEQUENCE:
- getattr(last, attr).append(item)
- else:
- new = Record()
- setattr(new, attr, item)
- r.append(new)
- else:
- if isinstance(r, list):
- r.append(item)
- else:
- form[key] = [r, item]
-
- def __splitKey(self, key):
- """Split the key and its attribute."""
- i = key.rfind(".")
- if i >= 0:
- return key[:i], key[i + 1:]
- return key, ""
-
- def __convertToTuples(self):
- """Convert form values to tuples."""
- form = self.form
-
- for key in self.__tuple_items:
- if key in form:
- form[key] = tuple(form[key])
- else:
- k, attr = self.__splitKey(key)
-
- # remove any type_names in the attr
- i = attr.find(":")
- if i >= 0:
- attr = attr[:i]
-
- if k in form:
- item = form[k]
- if isinstance(item, Record):
- if hasattr(item, attr):
- setattr(item, attr, tuple(getattr(item, attr)))
- else:
- for v in item:
- if hasattr(v, attr):
- setattr(v, attr, tuple(getattr(v, attr)))
-
- def __insertDefaults(self):
- """Insert defaults into form dictionary."""
- form = self.form
-
- for keys, values in self.__defaults.iteritems():
- if not keys in form:
- form[keys] = values
- else:
- item = form[keys]
- if isinstance(values, Record):
- for k, v in values.items():
- if not hasattr(item, k):
- setattr(item, k, v)
- elif isinstance(values, list):
- for val in values:
- if isinstance(val, Record):
- for k, v in val.items():
- for r in item:
- if not hasattr(r, k):
- setattr(r, k, v)
- elif not val in item:
- item.append(val)
-
def traverse(self, obj):
'See IPublisherRequest'
@@ -579,43 +186,7 @@
return super(BrowserRequest, self).get(key, default)
-class ZopeFieldStorage(FieldStorage):
- def make_file(self, binary=None):
- return tempfile.NamedTemporaryFile('w+b')
-
-
-class FileUpload(object):
- '''File upload objects
-
- File upload objects are used to represent file-uploaded data.
-
- File upload objects can be used just like files.
-
- In addition, they have a 'headers' attribute that is a dictionary
- containing the file-upload headers, and a 'filename' attribute
- containing the name of the uploaded file.
- '''
-
- def __init__(self, aFieldStorage):
-
- file = aFieldStorage.file
- if hasattr(file, '__methods__'):
- methods = file.__methods__
- else:
- methods = ['close', 'fileno', 'flush', 'isatty',
- 'read', 'readline', 'readlines', 'seek',
- 'tell', 'truncate', 'write', 'writelines',
- 'name']
-
- d = self.__dict__
- for m in methods:
- if hasattr(file,m):
- d[m] = getattr(file,m)
-
- self.headers = aFieldStorage.headers
- self.filename = unicode(aFieldStorage.filename, 'UTF-8')
-
class RedirectingBrowserRequest(BrowserRequest):
"""Browser requests that redirect when the actual and effective URLs differ
"""
@@ -1030,3 +601,17 @@
def __init__(self, request):
self.request = request
+
+
+deprecatedFrom(
+ 'This name has moved to zope.httpform.typeconv.'
+ 'zope.httpform.typeconv',
+ 'field2string', 'field2text', 'field2required', 'field2int',
+ 'field2float', 'field2long', 'field2tokens', 'field2lines',
+ 'field2boolean', 'type_converters', 'get_converter',
+ 'registerTypeConverter')
+
+deprecatedFrom(
+ 'This name has moved to zope.httpform.parser.'
+ 'zope.httpform.parser',
+ 'Record', 'FileUpload')
More information about the Checkins
mailing list