Example #1
0
def validate_colander_schema(schema, request):
    """Validates that the request is conform to the given schema"""
    from colander import Invalid, Sequence, drop

    def _validate_fields(location, data):
        for attr in schema.get_attributes(location=location,
                                          request=request):
            if attr.required and not attr.name in data:
                # missing
                request.errors.add(location, attr.name,
                                   "%s is missing" % attr.name)
            else:
                try:
                    if not attr.name in data:
                        deserialized = attr.deserialize()
                    else:
                        if (location == 'querystring' and
                                isinstance(attr.typ, Sequence)):
                            serialized = data.getall(attr.name)
                        else:
                            serialized = data[attr.name]
                        deserialized = attr.deserialize(serialized)
                except Invalid as e:
                    # the struct is invalid
                    try:
                        request.errors.add(location, attr.name,
                                           e.asdict()[attr.name])
                    except KeyError:
                        for k, v in e.asdict().items():
                            if k.startswith(attr.name):
                                request.errors.add(location, k, v)
                else:
                    if deserialized is not drop:
                        request.validated[attr.name] = deserialized

    qs, headers, body, path = extract_request_data(request)

    _validate_fields('path', path)
    _validate_fields('header', headers)
    _validate_fields('body', body)
    _validate_fields('querystring', qs)

    # These taken from colander's _SchemaNode::deserialize
    # to apply preparer/validator on the root node
    from colander.compat import is_nonstr_iter
    c_schema = schema._schema_inst
    if c_schema.preparer is not None:
        # if the preparer is a function, call a single preparer
        if hasattr(c_schema.preparer, '__call__'):
            request.validated = c_schema.preparer(request.validated)
            # if the preparer is a list, call each separate preparer
        elif is_nonstr_iter(c_schema.preparer):
            for preparer in c_schema.preparer:
                request.validated = preparer(request.validated)

    from colander import deferred
    if c_schema.validator is not None:
        if not isinstance(c_schema.validator, deferred): # unbound
            c_schema.validator(c_schema, request.validated)
Example #2
0
    def deserialize(self, node, cstruct):

        if cstruct is colander.null:
            return colander.null

        if not is_nonstr_iter(cstruct):
            raise colander.Invalid(node, '{} is not iterable'.format(cstruct))

        return self.deserialize_set_to_models(node, cstruct)
Example #3
0
def add_sequence_nodes(schema, *sequence_nodes, **kwargs):
    for sequence_node in sequence_nodes:
        if isinstance(sequence_node, dict):
            sequence_node.update(kwargs)
            add_sequence_node(schema, **sequence_node)
        elif is_nonstr_iter(sequence_node):
            add_sequence_node(schema, *sequence_node, **kwargs)
        else:
            add_sequence_node(schema, sequence_node, sequence_node.name, **kwargs)
Example #4
0
def add_sequence_nodes(schema, *sequence_nodes, **kwargs):
    for sequence_node in sequence_nodes:
        if isinstance(sequence_node, dict):
            sequence_node.update(kwargs)
            add_sequence_node(schema, **sequence_node)
        elif is_nonstr_iter(sequence_node):
            add_sequence_node(schema, *sequence_node, **kwargs)
        else:
            add_sequence_node(schema, sequence_node, sequence_node.name, **kwargs)
Example #5
0
    def create_filter_by(self, node, json_value, filter_type=None):
        if isinstance(json_value, dict):
            queries = []
            for value_filter_type, value in json_value.items():
                if not filter_type and value_filter_type.lower() in ('and', 'or'):
                    filter_type = value_filter_type

                if isinstance(value, dict):
                    query = self.create_filter_by(node, value, value_filter_type)
                    if isinstance(query, FilterBy):
                        queries.append(query)

                elif not is_nonstr_iter(value):
                    query = self.create_filter_by(node, value, value_filter_type)
                    if isinstance(query, FilterBy):
                        queries.append(query)

                else:
                    for deep_value in value:
                        query = self.create_filter_by(node, deep_value, value_filter_type)
                        if isinstance(query, FilterBy):
                            queries.append(query)

            filter_type = (filter_type or 'and').lower()
            if filter_type not in ('and', 'or'):
                message = 'Invalid filter type %s for %s' % (filter_type, json_value)
                raise Invalid('filter_type', message)
            else:
                return FilterBy(filter_type, queries)

        elif is_nonstr_iter(json_value):
            filter_type = filter_type or 'or'
            return self.create_filter_by(node, {filter_type: json_value}, filter_type)

        else:
            value = super(FilterByType, self).deserialize(node, json_value)
            if value is not null:
                return FilterBy(filter_type, value)
            else:
                return null
Example #6
0
    def create_filter_by(self, node, json_value, filter_type=None):
        if isinstance(json_value, dict):
            queries = []
            for value_filter_type, value in json_value.items():
                if not filter_type and value_filter_type.lower() in ('and', 'or'):
                    filter_type = value_filter_type

                if isinstance(value, dict):
                    query = self.create_filter_by(node, value, value_filter_type)
                    if isinstance(query, FilterBy):
                        queries.append(query)

                elif not is_nonstr_iter(value):
                    query = self.create_filter_by(node, value, value_filter_type)
                    if isinstance(query, FilterBy):
                        queries.append(query)

                else:
                    for deep_value in value:
                        query = self.create_filter_by(node, deep_value, value_filter_type)
                        if isinstance(query, FilterBy):
                            queries.append(query)

            filter_type = (filter_type or 'and').lower()
            if filter_type not in ('and', 'or'):
                message = u'Invalid filter type %s for %s' % (value_filter_type, json_value)
                raise Invalid('filter_type', message)
            else:
                return FilterBy(filter_type, queries)

        elif is_nonstr_iter(json_value):
            filter_type = filter_type or 'or'
            return self.create_filter_by(node, {filter_type: json_value}, filter_type)

        else:
            value = super(FilterByType, self).deserialize(node, json_value)
            if value is not null:
                return FilterBy(filter_type or '==', value)
            else:
                return value
Example #7
0
def OrderFinisher(node, appstruct):
    if appstruct and appstruct.get('order_by'):
        order_by = appstruct['order_by']
        if not is_nonstr_iter(order_by):
            order_by = [order_by]

        appstruct['order_by'] = []
        for ob in order_by:
            ob = ob.split(' ', 1)
            descendant = bool(len(ob) == 2 and ob[1].lower() in ('desc', 'd'))
            appstruct['order_by'].append(OrderBy(ob[0], descendant))

    return appstruct
Example #8
0
def PaginationOrderFinisher(node, appstruct):
    if appstruct and appstruct.get('order_by'):
        order_by = appstruct['order_by']
        if not is_nonstr_iter(order_by):
            order_by = [order_by]

        appstruct['order_by'] = []
        output_node = getattr(node, '__output_node__')
        for ob in order_by:
            ob = ob.split(' ', 1)
            if output_node:
                breadcrumbs = ob[0].split('.')
                if len(breadcrumbs) == 2:
                    table_name, column_name = breadcrumbs
                    table_name = uncamelcase(table_name)
                elif len(breadcrumbs) == 1:
                    column_name = breadcrumbs[0]
                    table_name = None
                else:
                    continue

                column_name = uncamelcase(column_name)
                for schema in output_node.__class_schema_nodes__:
                    if not table_name or schema.name == table_name:
                        if isinstance(schema, SequenceSchema):
                            schema = schema.__class_schema_nodes__[0]

                        nodes = schema.__class_schema_nodes__
                        nodes.extend(schema.__all_schema_nodes__)
                        for schema_node in nodes:
                            if isinstance(schema_node, SchemaNode) and schema_node.name == column_name:
                                break
                        else:
                            # Nothing found! dont add order by
                            continue
                        # Break this FOR to add order by
                        break
                else:
                    # Nothing found! dont add order by
                    continue

            descendant = bool(len(ob) == 2 and ob[1].lower() in ('desc', 'd'))
            appstruct['order_by'].append(OrderBy(ob[0], descendant))

    return appstruct
Example #9
0
def my_deserialize(self, cstruct=null):
    # Return None, only if request and cstruct is empty
    if self.return_none_if_defined and cstruct == '':
        return None

    appstruct = super(SchemaNode, self).deserialize(cstruct)

    # Propose this!
    if hasattr(self, 'finisher'):
        # if the finisher is a function, call a single preparer
        if callable(self.finisher):
            appstruct = self.finisher(appstruct)
        # if the finisher is a list, call each separate preparer
        elif is_nonstr_iter(self.finisher):
            for preparer in self.finisher:
                appstruct = preparer(self, appstruct)

    return appstruct
Example #10
0
def add_sequence_node(schema, sequence_node, single_key, plural_key=None, with_filter_by=False):
    if not sequence_node.name:
        sequence_node = sequence_node.clone(name=single_key)

    if with_filter_by:
        sequence_node = set_node_with_filter_by(sequence_node)

    single_node = SequenceSchema(Sequence(), sequence_node, missing=drop, name=single_key)
    schema.__class_schema_nodes__.append(single_node)
    schema.__all_schema_nodes__.append(single_node)

    if plural_key:
        if not sequence_node.name:
            sequence_node = sequence_node.clone(name=plural_key)

        plural_node = SequenceSchema(
            Sequence(),
            sequence_node,
            missing=drop,
            preparer=split_values,
            name=plural_key)
        schema.__class_schema_nodes__.append(plural_node)
        schema.__all_schema_nodes__.append(plural_node)

        sequence_finisher = SequenceFinisher(single_key, plural_key)
        if hasattr(schema, 'finisher'):
            if not is_nonstr_iter(schema.finisher):
                previous_finisher = schema.finisher

                def decorator(cls, appstruct):
                    appstruct = sequence_finisher(cls, appstruct)
                    return previous_finisher(cls, appstruct)
                schema.finisher = decorator
            else:
                schema.finisher.append(sequence_finisher)
        else:
            schema.finisher = [sequence_finisher]
Example #11
0
def add_sequence_node(schema, sequence_node, single_key, plural_key=None, with_filter_by=False):
    if not sequence_node.name:
        sequence_node = sequence_node.clone(name=single_key)

    if with_filter_by:
        sequence_node = set_node_with_filter_by(sequence_node)

    single_node = SequenceSchema(Sequence(), sequence_node, missing=drop, name=single_key)
    schema.__class_schema_nodes__.append(single_node)
    schema.__all_schema_nodes__.append(single_node)

    if plural_key:
        if not sequence_node.name:
            sequence_node = sequence_node.clone(name=plural_key)

        plural_node = SequenceSchema(
            Sequence(),
            sequence_node,
            missing=drop,
            preparer=split_values,
            name=plural_key)
        schema.__class_schema_nodes__.append(plural_node)
        schema.__all_schema_nodes__.append(plural_node)

        sequence_finisher = SequenceFinisher(single_key, plural_key)
        if hasattr(schema, 'finisher'):
            if not is_nonstr_iter(schema.finisher):
                previous_finisher = schema.finisher
                def decorator(cls, appstruct):
                    appstruct = sequence_finisher(cls, appstruct)
                    return previous_finisher(cls, appstruct)
                schema.finisher = decorator
            else:
                schema.finisher.append(sequence_finisher)
        else:
            schema.finisher = [sequence_finisher]
Example #12
0
 def __unicode__(self):
     if not is_nonstr_iter(self.value):
         return force_unicode(self.value)
     else:
         return self.value
Example #13
0
 def __str__(self):
     if not is_nonstr_iter(self.value):
         return force_string(self.value)
     else:
         return self.value