FormDict.py :  » Web-Frameworks » Aquarium » aquarium-2.3 » aquarium » util » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Web Frameworks » Aquarium 
Aquarium » aquarium 2.3 » aquarium » util » FormDict.py
"""Translate a ``cgi.FieldStorage`` into a (possibly recursive) dict."""

__docformat__ = "restructuredtext"

# Created: Wed May  5 13:45:45 PDT 2004
# Author: Shannon -jj Behrens
# Email: jjinux@users.sourceforge.net
#
# Copyright (c) Shannon -jj Behrens.  All rights reserved.

import re
import types

from aquarium.util.InternalLibrary import FormValueError


class FormDict(dict):

    """Translate a ``cgi.FieldStorage`` into a (possibly recursive) dict.

    If you've used ``cgi.FieldStorage`` from the Python standard library,
    you've probably translated it into a dict, which has a more friendly API.
    Then, at some point (either before or after you wrote the translation), you
    probably realized why ``cgi.FieldStorage`` is the way it is--because the
    same field can have multiple values.

    This code works around this requirement in a more friendly way that is
    inspired by PHP.  Specifically:

    * A field named ``foo`` cannot have multiple values.  If multiple values
      are encountered, a aquarium.util.InternalLibrary.FormValueError_ is
      raised (in the constructor).

    * If you actually wish for ``foo`` to have multiple values, name the
      HTML fields ``foo[]``.  The key ``foo`` within this dict will
      automatically have a list for its value.

    * If your form had the elements ``field[1][1]=="bob"`` and
      ``field[1][2]=="junk"`` the resultant dict would be what you expect:
      ``{'field': {'1': {'1': 'bob'}, {'2': 'junk'}}``.

    * Something of the form ``field[][0]`` is unsupported.

    XXX Below here doesn't actually work and is more of a TODO:

    * If you name an HTML field something like ``foo[bar]``, then the
      key ``foo`` within this dict will automatically have a dict (actually a
      FormDict) containing the key ``bar`` for its value.

    * You can perform the above recursively.  I.e. the following is
      valid: ``foo[bar][][bat]``.

    * In the same way that a simple field like ``foo`` cannot have multiple
      values without raising a ``FormValueError``, if you mix field types, such
      as naming one field ``foo[]`` and another ``foo[bar]``, you'll get a
      ``FormValueError``.  It is expected that you should only get this error
      if:

      1) you as the programmer mess up.

      2) the user is maliciously adding fields to your perfect form.  Hence, an
         exception is indeed appropriate.

    The following attributes are used:

    fieldStorage
      This is the original ``cgi.FieldStorage`` object, just in case
      you actually need it.  I won't even use it outside of the constructor.

    .. _aquarium.util.InternalLibrary.FormValueError:
       aquarium.util.InternalLibrary.FormValueError-class.html

    """

    def __init__(self, fieldStorage):
        """Accept a ``cgi.FieldStorage`` as an initializer."""
        dict.__init__(self)
        self.fieldStorage = fieldStorage

        self.reIndex = re.compile(r"\[([\w\s]+)\]")
        for key in fieldStorage.keys():
            if key.endswith("[]"):
                try:
                    self[key[:-len("[]")]] = [x.value
                                              for x in fieldStorage[key]]
                except TypeError:
                    self[key[:-len("[]")]] = [fieldStorage[key].value]

            elif self.reIndex.search(key):

                (idxs, baseKey) = self.extractIndexes(key)
                if not self.has_key(baseKey):
                    self[baseKey] = {}

                self[baseKey].update(
                    self.buildDict(idxs, fieldStorage[key].value,
                    self[baseKey]) )

            else:
                if isinstance(fieldStorage[key], types.ListType):
                    raise FormValueError("""\
There is more than one field named '%s'.  Use '%s[]' instead.""" % (key, key))
                self[key] = fieldStorage[key].value


    def extractIndexes(self, key):
        idxs = []
        m = self.reIndex.search(key)
        baseKey = key[:m.start(1)-1]
        while m:
            idxs.append(m.group(1))
            key = key[m.end():]
            m = self.reIndex.search(key)

        return (idxs, baseKey)


    def buildDict(self, idxs, val, thardict):
        """Takes a list of idxs to follow down the nested dicts contained
           in thardict where it will insert val.

           idxs
             The list of indexes to follow through the dict

           val
             The value to insert at the end of the indexes

           thardict
             The dict to use. Keys will be created.

        """

        if idxs:
            if thardict.has_key(idxs[0]):
                thardict[idxs[0]].update(self.buildDict(
                    idxs[1:], val, thardict[idxs[0]]))
            else:
                thardict[idxs[0]] = self.buildDict(
                    idxs[1:], val, {})
            return thardict
        else:
            return val
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.