Take the 2-minute tour ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

I have written a function to handle post data received from a web page. The Emphasis is on making getting post data easy: using the function allows the coder to specify the required data, type, and default value all in one line.

I'm using django and it provides a nice dict of post data. this will be passed to the function.

All the post data values is str. I want the str values converted to required types, and for default values to be used if the keys were not in the post data.

The required types include int, uuid, long, and str.

here is what I have:

    def handler(post_data, transforms):
    """ Generator function that takes dict of post_data and treats in way specified by transforms

    Arguments:
    post_data  - post data to be transformed to type required - dict
    transforms - tuple of tuples of how to treat the post data.  - tuple

   'schema' of transforms:
   (
       (key in post_data to get, 
        type to convert the vale to e.g, int or uuid, 
        boolean of if value is required or not,
        default value to return if no key not exist ), ... 
   )

    example of transforms: 
    ( ('key1', uuid, True), ('from', str, False, 'UK'), 'user', 'address' ) 

    annotated example :  (    
        ('key1', uuid, True),           # convert val at 'key1' to uuid. required.
        ('from', str, False, 'UK'),     # 'convert' val at 'from' to str. not required. Default value = 'UK'
        'user',                         # get value at 'user'
        'address',                      # get value at 'address'
    )

    """

        def defaults(key, to_type=str, required=True, default_value=None):
            """gives default values to any values not specified in the transform"""
            return key, to_type, required, default_value

        for transform in transforms:
            #if transform is a string then encapsulate
            transform = transform if isinstance(transform, tuple) else [transform]
            #unpack but provide default values for absent keys
            key, to_type, required, fallback = defaults(*transform)
            try:
                #try to convert the value to the format required by transform
                raw = request.POST.get(key)
                yield fallback if not raw else to_type(raw)
            except (ValueError, KeyError):
                #if key not exists or value cannot be converted
                if required:
                    return #bailout
                yield fallback

example usage:

post_data = {'name':'richard', 'age':'23', 'from':'UK', 'key1': '330c48a4-3664-11e2-982e-fda51ac77194'}

[in ] name, age = handler(post_data, transforms=('name', 'age'))
[in ] print name, age
[out] 'richard', '23'#notice 23 as string

[in ] name, age = handler(post_data, transforms=('name', ('age', int)))
[in ] print name, age
[out] 'richard', 23 #notice 23 as int

[in ] key1, brother = handler(post_data, transforms=(('key1', uuid), ('brother', str, False)))
[in ] print key1, brother
[out] UUID('330c48a4-3664-11e2-982e-fda51ac77194') #notice string has been converted to uuid and absense of brother value 

[in ] key1, brother = handler(post_data, transforms=(('key1', uuid), ('brother', str, False, 'Abe')))
[in ] print key1, brother
[out] UUID('330c48a4-3664-11e2-982e-fda51ac77194'), 'Abe' #notice default value for brother used

I'm looking to make the code even more consise.

share|improve this question

1 Answer 1

up vote 2 down vote accepted

I think the code is great.

Some comments:

  1. Transform is a tuple of 4 elements (key, type, is_default, default_value). I think is too many, it is hard to remember which means what.
  2. Since it is a tuple - if you want to provide a "default_value" - you need to provide everything else. But in real life the most common scenario for me is to use request.GET.get('param1', 'default_value')
  3. I'm not sure about the version of python, but in python 2.* it would not cover unicodes isinstance(transform, str)
  4. function name def handler(post_data, transforms) should be a verb probably.
share|improve this answer
    
thanks. I will do the following: 1: combine "is_default" and "default_value" 2: I will do raw = request.POST.get(key) yield fallback if not raw else to_type(raw) 3: I will use not isinstance(transform, list) 4: I will rename accordingly –  rikAtee Jan 17 '13 at 9:43
    
not isinstance(transform, list) will not work, because you are using tuples. If you want to check for unicode + str , you can use isinstance(transform, basestring). if you want to check for collections you need to use collections module it has base classes for collections. –  RomanI Jan 17 '13 at 19:02

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.