[Paste] Re: webob "marshalling"

Top Page
Author: Ian Bicking
Date:  
To: Chris McDonough
CC: paste-users
Subject: [Paste] Re: webob "marshalling"
This is certainly too much of a clash with WebOb -- in part because it's
always been unclear how errors should be handled, and in part because these
aren't really HTTPish. FormEncode's variabledecode has the same basic idea
(though it only does lists and dicts, not types, and so there are no
possible error conditions)... but I wouldn't include that either.
*But*,
subclasses of Request and Response are definitely supported. Ideally
these would actually be descriptors, so it'd be easy to include them
(or not), and then you could have RepozeRequest
that uses these. I'd imagine it looking like:

class RepozeRequest(Request):
    marshalled = Marshaller('params')
    marshalled_GET = Marshaller('GET')
    marshalled_POST = Marshaller('POST')

class Marshaller(object):
    default_converters = {}
    def __init__(self, attr, converters=None):
        self.attr = attr
        self.converters = self.default_converters.copy()
        if converters;
            self.converters.update(converters)
    def __get__(self, obj, type=None):
        if obj is None:
            return self
        return Marshalled(getattr(obj, attr), self.converters)

class Marshalled(object):
    def __init__(self, value, converters):
        self.value = value
        self.converters = converters
    def __getitem__(self, key):
        if key in self.value:
            return self.value[key]
        found = {}
        for name, value in self.value.iteritems():
            if name.startswith(key+':'):
                found[tuple(name[len(key)+1].split(':'))] = value
        and, uh, I'm getting into too much detail here


Anyway, that would allow the addition of a feature like this to the request
object.



On Wed, Jun 17, 2009 at 9:46 PM, Chris McDonough <chrism@???> wrote:

>
> Zope2 has a handy feature that allows you to add "modifiers" to form
> element
> (and query string element) names, e.g. for a form posted with a field named
> "foo:int", Zope will present the field "foo" as an integer value when it's
> retrieved from its request object a certain way. There are other handy
> modifiers, such as grouping fields into records, and marshalling a number
> of
> fields into a single list, and so on (see the below "science fiction" docs
> for
> more).
>
> I've spent a little time working code supporting this feature into WebOb.
> Essentially, when you access:
>
> request.marshalled
>
> It returns a dictionary with the marshalled elements (from both the query
> string
> and the POST file pointer, if any).
>
> similar methods exist:
>
> request.marshalled_GET
>
> and
>
> request.marshalled_POST
>
> Should I bother submitting a patch (or checking in) or is this too much of
> a
> clash of worlds?
>
> Science fiction docs...
>
> Marshalling
> -----------
>
> Marshalling is a feature of webob which will return a dictionary back
> containing "converted" form/query string elements. The form and query
> string elements contained in the request are converted into simple
> Python types when the form element names are decorated with special
> suffixes. For example, in an HTML form that you'd like monty to
> convert a form element for, you might say::
>
> <form action=".">
> Age : <input type="hidden" name="age:int" value="20"/>
> <input type="submit" name="Submit"/>
> </form>
>
> Likewise, in the query string of the URL, you could put::
>
> http://example.com/mypage?age:int=20
>
> In both of these cases, when you use webob marshalling, it might
> return a dictionary like so::
>
> {'age':20}
>
> webob marshalling is a generalized version of the form marshalling
> machinery originated in Zope 2.
>
> Form/Query String Element Marshalling
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>
> webob marshalling provides a way for you to specify form input types
> in the form, rather than needing to unwind these types manually in
> your application code. For example, instead of converting an *age*
> variable to an integer in a controller or view, you can indicate that
> it is an integer in the form itself::
>
> Age <input type="text" name="age:int" />
>
> The ':int' appended to the form input name tells webob to convert the
> form input to an integer when it is invoked. This process is called
> *marshalling*. If the user of your form types something that cannot be
> converted to an integer in the above case (such as "22 going on 23")
> then the field will just not be converted.
>
> Here is a list of webob marshalling's basic parameter converters.
>
> *bool*
>
> Converts a variable to true or false. Variables that are 0, None, an
> empty string, or an empty sequence are false, all others are true.
>
> *int*
>
> Converts a variable to an integer.
>
> *float*
>
> Converts a variable to a floating point number.
>
> *text*
>
> Converts a variable to a string with normalized line breaks.
> Different browsers on various platforms encode line endings
> differently, so this script makes sure the line endings are
> consistent, regardless of how they were encoded by the browser.
>
> *list*
>
> Converts a variable to a Python list.
>
> *tuple*
>
> Converts a variable to a Python tuple.
>
> *tokens*
>
> Converts a string to a tuple by breaking it on white spaces.
>
> *lines*
>
> Converts a string to a list by breaking it on new lines.
>
> *ignore_empty*
>
> Excludes the variable from the returned dictionary if the variable
> is an empty string.
>
> These converters all work in more or less the same way to coerce a
> form variable, which is a string, into another specific type.
>
> The *list* and *tuple* converters can be used in combination with
> other converters. This allows you to apply additional converters to
> each element of the list or tuple. Consider this form::
>
> <form action=".">
>
> <p>I like the following numbers</p>
>
> <input type="checkbox" name="favorite_numbers:list:int"
> value="1" /> One<br />
>
> <input type="checkbox" name="favorite_numbers:list:int"
> value="2" />Two<br />
>
> <input type="checkbox" name="favorite_numbers:list:int"
> value="3" />Three<br />
>
> <input type="checkbox" name="favorite_numbers:list:int"
> value="4" />Four<br />
>
> <input type="checkbox" name="favorite_numbers:list:int"
> value="5" />5<br />
>
> <input type="submit" />
> </form>
>
> A more complex type of form conversion is to convert a series of
> inputs into *records.* Records are structures that have
> attributes. Using records, you can combine a number of form inputs
> into one variable with attributes. The available record converters
> are:
>
> *record*
>
> Converts a variable to a record attribute.
>
> *records*
>
> Converts a variable to a record attribute in a list of records.
>
> *default*
>
> Provides a default value for a record attribute if the variable is
> empty.
>
> *ignore_empty*
>
> Skips a record attribute if the variable is empty.
>
> Here are some examples of how these converters are used::
>
> <form action=".">
>
> First Name <input type="text" name="person.fname:record" /><br />
> Last Name <input type="text" name="person.lname:record" /><br />
> Age <input type="text" name="person.age:record:int" /><br />
>
> <input type="submit" />
> </form>
>
> If the information represented by this form post is present in the
> environment, the result dictionary will container one parameter,
> *person*. The *person* variable will have the attributes *fname*,
> *lname* and *age*.
>
> The *records* converter works like the *record* converter except
> that it produces a list of records, rather than just one. Here is
> an example form::
>
> <form action=".">
>
> <p>Please, enter information about one or more of your next of
> kin.</p>
>
> <p>
> First Name <input type="text" name="people.fname:records" />
> Last Name <input type="text" name="people.lname:records" />
> </p>
>
> <p>
> First Name <input type="text" name="people.fname:records" />
> Last Name <input type="text" name="people.lname:records" />
> </p>
>
> <p>
> First Name <input type="text" name="people.fname:records" />
> Last Name <input type="text" name="people.lname:records" />
> </p>
>
> <input type="submit" />
> </form>
>
> If you access request.marshalled with a form posted from the above
> HTML, a dictionary will be returned from it with a variable called
> *people* that is a list of records. Each record will have *fname* and
> *lname* attributes. Note the difference between the *records*
> converter and the *list:record* converter: the former would create a
> list of records, whereas the latter would produce a single record
> whose attributes *fname* and *lname* would each be a list of values.
>
> The order of combined modifiers does not matter; for example,
> *int:list* is identical to *list:int*.
>


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "Paste Users" group.
To post to this group, send email to paste-users@???
To unsubscribe from this group, send email to paste-users+unsubscribe@???
For more options, visit this group at http://groups.google.com/group/paste-users?hl=en
-~----------~----~----~----~------~----~------~--~---