[Zope3-checkins] CVS: Zope3/src/zope/publisher - browser.py:1.29
Dmitry Vasiliev
dima at hlabs.spb.ru
Thu Apr 8 04:32:02 EDT 2004
Update of /cvs-repository/Zope3/src/zope/publisher
In directory cvs.zope.org:/tmp/cvs-serv24500/src/zope/publisher
Modified Files:
browser.py
Log Message:
'BrowserRequest.processInputs' long method was splitted into small parts.
=== Zope3/src/zope/publisher/browser.py 1.28 => 1.29 ===
--- Zope3/src/zope/publisher/browser.py:1.28 Sat Mar 20 11:27:17 2004
+++ Zope3/src/zope/publisher/browser.py Thu Apr 8 04:31:30 2004
@@ -37,8 +37,7 @@
__ArrayTypes = (ListType, TupleType)
-search_type = re.compile('(:[a-zA-Z][a-zA-Z0-9_]+|\\.[xy])$').search
-start_of_header_search=re.compile('(<head[^>]*>)', re.IGNORECASE).search
+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
newline_search = re.compile('\r\n|\n\r').search
@@ -47,13 +46,12 @@
def is_text_html(content_type):
return content_type.startswith('text/html')
-# Flas Constants
+# Flag Constants
SEQUENCE = 1
DEFAULT = 2
RECORD = 4
RECORDS = 8
-REC = 12 # RECORD|RECORDS
-EMPTY = 16
+REC = RECORD | RECORDS
CONVERTED = 32
DEFAULTABLE_METHODS = 'GET', 'POST', 'HEAD'
@@ -204,7 +202,7 @@
}.has_key
-class record:
+class Record:
def __getattr__(self, key, default=None):
if key in ('get', 'keys', 'items', 'values', 'copy',
@@ -233,6 +231,9 @@
__slots__ = (
'form', # Form data
'charsets', # helper attribute
+ '__meth',
+ '__tuple_items',
+ '__defaults',
)
use_redirect = 0 # Set this to 1 in a subclass to redirect GET
@@ -266,344 +267,253 @@
def processInputs(self):
'See IPublisherRequest'
- environ = self._environ
- form = self.form
-
if self.method != 'GET':
- # Process form if not a GET request.
+ # Process self.form if not a GET request.
fp = self._body_instream
else:
fp = None
- fs = FieldStorage(fp = fp,
- environ = environ,
- keep_blank_values = 1)
+ fs = FieldStorage(fp=fp, environ=self._environ, keep_blank_values=1)
- meth = None
fslist = getattr(fs, 'list', None)
if fslist is not None:
- tuple_items = {}
- CGI_name = isCGI_NAME
- defaults = {}
- converter = None
+ self.__meth = None
+ self.__tuple_items = {}
+ self.__defaults = {}
# process all entries in the field storage (form)
for item in fslist:
+ self.__processItem(item)
- # 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
+ if self.__defaults:
+ self.__insertDefaults()
- flags = 0
+ if self.__tuple_items:
+ self.__convertToTuples()
- # 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.
-
- # Get the location of the name type splitter
- loc = key.rfind(':')
- if loc >= 0:
- mo = search_type(key,loc)
- if mo: loc = mo.start(0)
- else: loc = -1
-
- while loc >= 0:
- type_name = key[loc+1:]
- key = key[:loc]
- # find the right type converter
- c = get_converter(type_name, None)
-
- if c is not None:
- converter = c
- flags=flags|CONVERTED
- elif type_name == 'list':
- seqf=list
- flags=flags|SEQUENCE
- elif type_name == 'tuple':
- seqf=tuple
- tuple_items[key]=1
- flags=flags|SEQUENCE
- elif (type_name == 'method' or type_name == 'action'):
- if loc: meth=key
- else: meth=item
- elif (type_name == 'default_method' or type_name == \
- 'default_action'):
- if not meth:
- if loc: meth=key
- else: meth=item
- elif type_name == 'default':
- flags=flags|DEFAULT
- elif type_name == 'record':
- flags=flags|RECORD
- elif type_name == 'records':
- flags=flags|RECORDS
- elif type_name == 'ignore_empty':
- if not item: flags=flags|EMPTY
-
- loc = key.rfind(':')
- if loc < 0:
- break
- mo = search_type(key, loc)
- if mo:
- loc = mo.start(0)
- else:
- loc = -1
-
-
- # Filter out special names from form:
- if CGI_name(key) or key.startswith('HTTP_'):
- continue
-
- # Make it unicode
- key = self._decode(key)
- if type(item) == StringType:
- item = self._decode(item)
-
- if flags:
-
- # skip over empty fields
- if flags & EMPTY: continue
-
- #Split the key and its attribute
- if flags & REC:
- key = key.split(".")
- key, attr = ".".join(key[:-1]), key[-1]
-
- # defer conversion
- if flags & CONVERTED:
- try:
- item=converter(item)
- except:
- if (not item and not (flags&DEFAULT) and
- (key in defaults)):
- item = defaults[key]
- if flags&RECORD:
- item=getattr(item,attr)
- if flags&RECORDS:
- item.reverse()
- item = item[0]
- item=getattr(item,attr)
- else:
- raise
-
- # Determine which dictionary to use
- if flags & DEFAULT:
- mapping_object = defaults
- else:
- mapping_object = form
+ 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
- # Insert in dictionary
- if key in mapping_object:
- if flags & RECORDS:
- #Get the list and the last record
- #in the list
- reclist = mapping_object[key]
- reclist.reverse()
- x=reclist[0]
- reclist.reverse()
- if not hasattr(x,attr):
- #If the attribute does not
- #exist, setit
- if flags&SEQUENCE: item=[item]
- reclist.remove(x)
- setattr(x,attr,item)
- reclist.append(x)
- mapping_object[key] = reclist
- else:
- if flags&SEQUENCE:
- # If the attribute is a
- # sequence, append the item
- # to the existing attribute
- reclist.remove(x)
- y = getattr(x, attr)
- y.append(item)
- setattr(x, attr, y)
- reclist.append(x)
- mapping_object[key] = reclist
- else:
- # Create a new record and add
- # it to the list
- n=record()
- setattr(n,attr,item)
- reclist.append(n)
- mapping_object[key]=reclist
- elif flags&RECORD:
- b=mapping_object[key]
- if flags&SEQUENCE:
- item=[item]
- if not hasattr(b,attr):
- # if it does not have the
- # attribute, set it
- setattr(b,attr,item)
- else:
- # it has the attribute so
- # append the item to it
- setattr(b,attr,getattr(b,attr)+item)
- else:
- # it is not a sequence so
- # set the attribute
- setattr(b,attr,item)
- else:
- # it is not a record or list of records
- found=mapping_object[key]
- if isinstance(found, list):
- found.append(item)
- else:
- found=[found,item]
- mapping_object[key]=found
- else:
- # The dictionary does not have the key
- if flags&RECORDS:
- # Create a new record, set its attribute
- # and put it in the dictionary as a list
- a = record()
- if flags&SEQUENCE: item=[item]
- setattr(a,attr,item)
- mapping_object[key]=[a]
- elif flags&RECORD:
- # Create a new record, set its attribute
- # and put it in the dictionary
- if flags&SEQUENCE: item=[item]
- r = mapping_object[key]=record()
- setattr(r,attr,item)
- else:
- # it is not a record or list of records
- if flags&SEQUENCE: item=[item]
- mapping_object[key]=item
+ 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:
- # This branch is for case when no type was specified.
- mapping_object = form
+ 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
+
+ # Filter out special names from form:
+ if not (isCGI_NAME(key) or key.startswith('HTTP_')):
+ # Make it unicode
+ 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)
- #Insert in dictionary
- if key in mapping_object:
- # it is not a record or list of records
- found=mapping_object[key]
- if isinstance(found, list):
- found.append(item)
- else:
- found=[found,item]
- mapping_object[key]=found
- else:
- mapping_object[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 defaults into form dictionary
- if defaults:
- for keys, values in defaults.items():
- if not (keys in form):
- # if the form does not have the key,
- # set the default
- form[keys]=values
+ # 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:
- #The form has the key
- if isinstance(values, record):
- # if the key is mapped to a record, get the
- # record
- r = form[keys]
- for k, v in values.__dict__.items():
- # loop through the attributes and values
- # in the default dictionary
- if not hasattr(r, k):
- # if the form dictionary doesn't have
- # the attribute, set it to the default
- setattr(r,k,v)
- form[keys] = r
-
- elif isinstance(values, list):
- # the key is mapped to a list
- lst = form[keys]
- for val in values:
- # for each val in the list
- if isinstance(val, record):
- # if the val is a record
- for k, v in val.__dict__.items():
-
- # loop through each
- # attribute and value in
- # the record
-
- for y in lst:
-
- # loop through each
- # record in the form
- # list if it doesn't
- # have the attributes
- # in the default
- # dictionary, set them
-
- if not hasattr(y, k):
- setattr(y, k, v)
- else:
- # val is not a record
- if not a in lst:
- lst.append(a)
- form[keys] = lst
- else:
- # The form has the key, the key is not mapped
- # to a record or sequence so do nothing
- pass
-
- # Convert to tuples
- if tuple_items:
- for key in tuple_items.keys():
- # Split the key and get the attr
- k=key.split(".")
- k, attr=".".join(k[:-1]), k[-1]
-
- # remove any type_names in the attr
- while not attr == '':
- attr = attr.split(":")
- attr, new = ":".join(attr[:-1]), attr[-1]
- attr = new
-
- if k in form:
- # If the form has the split key get its value
- item = form[k]
- if isinstance(item, record):
- # if the value is mapped to a record, check if it
- # has the attribute, if it has it, convert it to
- # a tuple and set it
- if hasattr(item, attr):
- value = tuple(getattr(item, attr))
- setattr(item, attr, value)
- else:
- # It is mapped to a list of records
- for x in item:
- # loop through the records
- if hasattr(x, attr):
- # If the record has the attribute
- # convert it to a tuple and set it
- value = tuple(getattr(x, attr))
- setattr(x, attr, value)
+ 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:
- # the form does not have the split key
- if key in form:
- # if it has the original key, get the item
- # convert it to a tuple
- item = form[key]
- item = tuple(form[key])
- form[key] = item
+ new = Record()
+ setattr(new, attr, item)
+ r.append(new)
+ else:
+ if isinstance(r, list):
+ r.append(item)
+ else:
+ form[key] = [r, item]
- if meth:
- self.setPathSuffix((meth,))
+ 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, object):
'See IPublisherRequest'
@@ -685,18 +595,21 @@
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']
+ file = aFieldStorage.file
+ if hasattr(file, '__methods__'):
+ methods = file.__methods__
+ else:
+ methods = ['close', 'fileno', 'flush', 'isatty',
+ 'read', 'readline', 'readlines', 'seek',
+ 'tell', 'truncate', 'write', 'writelines']
- d=self.__dict__
+ d = self.__dict__
for m in methods:
- if hasattr(file,m): d[m]=getattr(file,m)
+ if hasattr(file,m):
+ d[m] = getattr(file,m)
- self.headers=aFieldStorage.headers
- self.filename=aFieldStorage.filename
+ self.headers = aFieldStorage.headers
+ self.filename = aFieldStorage.filename
class RedirectingBrowserRequest(BrowserRequest):
"""Browser requests that redirect when the actual and effective URLs differ
More information about the Zope3-Checkins
mailing list