Exemple #1
0
 def test_data_and_request_conversion(self):
     """
     Test convert request to data and convert data to request
     """
     schema_nested = schemaish.Structure([
         ("one", schemaish.Structure([
             ("a", schemaish.String()),
             ("b", schemaish.String()),
             ("c", schemaish.Structure([("x", schemaish.String()),("y", schemaish.String())])),
             ])
          ),
         ])
     r = {'one.a':'','one.b': '','one.c.x': '','one.c.y': ''}
     reqr = {'one.a':None,'one.b': None,'one.c.x': None,'one.c.y': None}
     reqrdata = {'one.a':[''],'one.b': [''],'one.c.x': [''],'one.c.y': ['']}
     data = {'one.a': '', 'one.b': '', 'one.c.x': '', 'one.c.y': ''}
     
     name = "Nested Form Two"
     request =  Request(name, r)
     form = formish.Form(schema_nested, name)
     # request to data
     rdtd = validation.convert_request_data_to_data(form.structure, dottedDict(copy.deepcopy(request.POST)))
     assert rdtd == dottedDict(reqr)
     # data to request
     dtrd = validation.convert_data_to_request_data(form.structure, dottedDict(data))
     assert dtrd == reqrdata
Exemple #2
0
def convert_data_to_request_data(form_structure, data,
                      request_data=None, errors=None):
    """
    Take a form structure and use it's widgets to convert schema data (dict) to
    request data
    
    :arg form_structure: a formish form
    :arg data: a dictionary structure to be converted using the form
    :arg request_data: used to accumulate request
        data (internal - used while recursing)
    :arg errors: used to accumulate conversion 
        failures (internal - used while recursing)
    
    """
    if request_data is None:
        request_data = dottedDict()
    if errors is None:
        errors = dottedDict()
    for field in form_structure.fields:
        try:
            if field.type is 'group' or \
              (field.type is 'sequence' and \
                (field.widget is None or \
                  field.widget.converttostring is False)):
                convert_data_to_request_data(field, data,
                        request_data=request_data, errors=errors)
            else:
                item_data = getNestedProperty(data, field.name)
                request_data[field.name] = \
                        field.widget.pre_render(field.attr, item_data)
        except Invalid, e:
            errors[field.name] = e
            raise
Exemple #3
0
 def test_references(self):
     """Does it refer to the same data if you convert an existing dottedDict or plain dict """
     a = DummyObject()
     d = {'a.a.a':1, 'a.b.a':3, 'b':a}
     # Check dict single level keys don't lose reference
     self.assertEqual( dottedDict(d).data['b'], d['b'] )
     self.assertEqual( dottedDict(d).data, dottedDict(dottedDict(d)).data )
Exemple #4
0
    def test_get(self):
        tests = [
        ( {'a':1, 'b':2}, ( ('a',1),('b',2) ) ),
        ( {'a':{'a':1}, 'b':2}, ( ('a.a',1),('b',2) ) ),
        ( {'a':{'a':1, 'b':3}, 'b':2}, ( ('a.a',1),('a.b',3),('b',2) ) ),
        ( {'a':{'a':[1,3], 'b':2}}, ( ('a.a.0',1),('a.a.1',3) ) ),
        ( {'a':{'a':[1, {'a':7}], 'b':2}}, ( ('a.a.0',1),('a.a.1.a',7) ) ),
        ( {'list': [{'a': 1, 'b': 2}, {'a': 3, 'b': 4}]}, ( ('list.0.a',1), ) ),
        
        ]
        for d, checkers  in tests:
            dd = dottedDict(d)
            for k, v in checkers:
                self.assertEquals(dd.get(k), v)

        error_tests = [
        ( {'list': {}}, ( ('list.0.a',None), ) ),
        ( {'list': {}}, ( ('list.0.a', 'foo'), ) ),
        
        ]
        # Check None's come out
        for d, checkers  in error_tests:
            dd = dottedDict(d)
            for k, v in checkers:
                self.assertEquals(dd.get(k), None)
        # Check the default comes out
        for d, checkers  in error_tests:
            dd = dottedDict(d)
            for k, v in checkers:
                self.assertEquals(dd.get(k, v), v)
Exemple #5
0
def convert_sequences(data):
    """
    Converts numeric keyed dictionaries into sequences

    Converts ``{'0': 'foo', '1': 'bar'}`` into ``['foo','bar']``. leaves anything else alone
    """
    # must be a dict
    if not hasattr(data,'keys'):
        return data
    # if the first key cannot be converted to an int then we don't have a
    # sequence
    try:
        int(data.keys()[0])
    except ValueError:
        return dottedDict(data)
    # collect the keys as sorted integers
    intkeys = []
    for key in data.keys():
        intkeys.append(int(key))
    intkeys.sort()
    # construct the sequence
    out = []
    for key in intkeys:
        out.append(data[str(key)])
    return out
Exemple #6
0
    def test_integer_type(self):
        schema_flat = schemaish.Structure([("a", schemaish.Integer()), ("b", schemaish.String())])
        name = "Integer Form"
        form = formish.Form(schema_flat, name)
        r = {'a': '3', 'b': '4'}
        request = Request(name, r)
        R = copy.deepcopy(r)

        reqr = {'a': ['3'], 'b': ['4']}
        # check scmea matches
        self.assert_(form.structure.attr is schema_flat)
        # Does the form produce an int and a string
        self.assertEquals(form.validate(request), {'a': 3, 'b': '4'})
        # Does the convert request to data work
        self.assertEqual( validation.convert_request_data_to_data(form.structure, dottedDict(request.POST)) , {'a': 3, 'b': '4'})
        # Does the convert data to request work
        self.assert_( validation.convert_data_to_request_data(form.structure, dottedDict( {'a': 3, 'b': '4'} )) == reqr)
Exemple #7
0
 def _set_request_data(self, request_data):
     """ 
     Assign raw request data to the form
     
     :arg request_data: raw request data (e.g. request.POST)
     :type request_data: Dictionary (dotted or nested or dottedDict or MultiDict)
     """
     self._request_data = dottedDict(request_data)
Exemple #8
0
 def get_item_data_values(self, name):
     """
     get all of the item data values
     """
     data = dottedDict({})
     for key, value in self.item_data:
         if value.has_key(name):
             data[key] = value[name]
     return data
Exemple #9
0
    def test_datetuple_type(self):
        schema_flat = schemaish.Structure([("a", schemaish.Date()), ("b", schemaish.String())])
        name = "Date Form"
        form = formish.Form(schema_flat, name)
        form['a'].widget = formish.DateParts()

        r = {'a.day': '1','a.month': '3','a.year': '1966', 'b': '4'}
        R = copy.deepcopy(r)
        request = Request(name, r)

        from datetime import date
        d = date(1966,3,1)

        # Check the data is converted correctly
        self.assertEquals(form.validate(request), {'a': d, 'b': '4'})
        # Check req to data
        self.assertEqual( validation.convert_request_data_to_data(form.structure, dottedDict(request.POST)) , dottedDict({'a': d, 'b': '4'}))
        # Check data to req
        self.assert_( validation.convert_data_to_request_data(form.structure, dottedDict( {'a': d, 'b': '4'} )) == dottedDict({'a': {'month': [3], 'day': [1], 'year': [1966]}, 'b': ['4']}))
Exemple #10
0
 def _get_request_data(self):
     """
     Retrieve previously set request_data or return the defaults in
     request_data format.
     """
     if self._request_data is not None:
         return self._request_data
     self._request_data = validation.convert_data_to_request_data(self.structure, \
                             dottedDict(self.defaults))
     return self._request_data
Exemple #11
0
 def test_set(self):
     tests = [
     ( {'list': {}}, ( ('list.0.a',7, {'list':[{'a':7}]}), ) ),
     ( {'list': {'x':{}}}, ( ('list.x.0.a',7, {'list':{'x':[{'a':7}]}}), ) ),
     
     ]
     for d, checkers  in tests:
         dd = dottedDict(d)
         for k, v, result in checkers:
             dd[k] = v
             self.assertEquals(dd, result)
Exemple #12
0
def build_request(formname, data):
    d = dottedDict(data)
    e = {'REQUEST_METHOD': 'POST'}
    request = webob.Request.blank('/',environ=e)
    fields = []
    fields.append( ('_charset)','UTF-8') )
    fields.append( ('__formish_form__','form') )
    for k, v in d.dotteditems():
        fields.append( (k,v) )
    fields.append( ('submit','Submit') )
    request.body = urlencode( fields )
    
    return request
Exemple #13
0
 def validate(self, request, failure_callable=None, success_callable=None):
     """ 
     Get the data without raising exceptions and then validate the data. If
     there are errors, raise them; otherwise return the data
     """
     # If we pass in explicit failure and success callables then do this
     # first
     if failure_callable is not None and success_callable is not None:
         return self._validate_and_call(request, \
                       failure_callable=None, success_callable=None)
     self.errors = {}
     # Check this request was POSTed by this form.
     if not request.method =='POST' and \
        request.POST.get('__formish_form__',None) == self.name:
         raise Exception("request does not match form name")
     
     request_post = UnicodeMultiDict(request.POST, \
                     encoding=util.get_post_charset(request))
     # Remove the sequence factory data from the request
     for k in request_post.keys():
         if '*' in k:
             request_post.pop(k)
     # We need the _request_data to be populated so sequences know how many
     # items they have (i.e. .fields method on a sequence uses the number of
     # values on the _request_data)
     self._request_data = dottedDict(request_post)
     self.request_data = validation.pre_parse_request_data( \
                 self.structure,dottedDict(request_post))
     data = self.get_unvalidated_data( \
                 self.request_data, raise_exceptions=False)
     #self._request_data = dottedDict(request_post)
     try:
         self.structure.attr.validate(data)
     except schemaish.attr.Invalid, e:
         for key, value in e.error_dict.items():
             if key not in self.errors:
                 self.errors[key] = value
Exemple #14
0
def pre_parse_request_data(form_structure, request_data, data=None):
    """
    Some widgets (at the moment only files) need to have their data massaged in
    order to make sure that data->request and request->data is symmetric

    This pre parsing is a null operation for most widgets
    """
    if data is None:
        data = {}
    for field in form_structure.fields:
        if field.type is 'group' or \
          (field.type == 'sequence' and \
             field.widget._template is 'SequenceDefault'):
            pre_parse_request_data(field, request_data, data=data)
        else: 
            # This needs to be cleverer...
            item_data = request_data.get(field.name, [])
            data[field.name] = field.widget.pre_parse_request(field.attr, item_data, full_request_data=request_data)

    return dottedDict(data)
Exemple #15
0
    def __init__(self, structure, name=None, defaults=None, errors=None,
            action_url=None, renderer=None):
        """
        Create a new form instance

        :arg structure: Schema Structure attribute to bind to the the form
        :type structure: schemaish.Structure

        :arg name: Optional form name used to identify multiple forms on the same page
        :type name: str "valid html id"
            
        :arg defaults: Default values for the form
        :type defaults: dict

        :arg errors: Errors to store on the form for redisplay
        :type errors: dict

        :arg action_url: Use if you don't want the form to post to itself
        :type action_url: string "url or path"

        :arg renderer: Something that returns a form serialization when called
        :type renderer: callable
        """
        # allow a single schema items to be used on a form
        if not isinstance(structure, schemaish.Structure):
            structure = schemaish.Structure([structure])
        self.structure = Group(None, structure, self)
        self.item_data = {}
        self.name = name
        if defaults is None:
            defaults = {}
        if errors is None:
            errors = {}
        self.defaults = defaults
        self.errors = dottedDict(errors)
        self.error = None
        self._actions = []
        self.action_url = action_url
        if renderer is not None:
            self.renderer = renderer
Exemple #16
0
                (field.widget._template is 'SequenceDefault' \
                 or field.widget.converttostring is False)):
                if field.type == 'sequence':
                    # Make sure we have an empty field at least. If we don't do
                    # this and there are no items in the list then this key
                    # wouldn't appear.
                    data[field.name] = []
                convert_request_data_to_data(field, request_data,
                                          data=data, errors=errors)
            else: 
                data[field.name] = field.widget.convert(field.attr, \
                                                request_data.get(field.name,[]))
        except convert.ConvertError, e:
            errors[field.name] = e.message
    
    data = recursive_convert_sequences(dottedDict(data))
    return data

def pre_parse_request_data(form_structure, request_data, data=None):
    """
    Some widgets (at the moment only files) need to have their data massaged in
    order to make sure that data->request and request->data is symmetric

    This pre parsing is a null operation for most widgets
    """
    if data is None:
        data = {}
    for field in form_structure.fields:
        if field.type is 'group' or \
          (field.type == 'sequence' and \
             field.widget._template is 'SequenceDefault'):
Exemple #17
0
 def _get_defaults(self):
     """ Get the raw default data """
     return dottedDict(self._defaults)
Exemple #18
0
 def test_comparing(self):
     """Using the special method __eq__ to compare a dotted dict with a normal dict """
     for test in self.test_dict_data:
         self.assertEqual(dottedDict(test[0]), test[1])
Exemple #19
0
 def test_convert_dictlist(self):
     for test in self.test_dictlist_data:
         self.assertEqual(dottedDict(test[0]).data, test[1])
Exemple #20
0
 def test_convert(self):
     """Just checking that converting results in assigning the right dict """
     for test in self.test_dict_data:
         self.assertEqual(dottedDict(test[0]).data, test[1])