def _transform(self, original_data, handlers):
        output = {}
        for key, values in original_data.items():
            try:
                result = self.index.query(key)
                if not result:
                    raise MissingRule(key)

                name, creator = result
                extra = self._get_extra_arguments(creator, key, original_data)
                data = creator(output, key, values, **extra)
                if getattr(creator, '__output_reduce__', False):
                    reduce_func = getattr(creator, '__output_reduce__', False)
                    reduce_func(output=output, name=name, key=key, data=data, original_value=values)
                else:
                    output[name] = data
            except Exception as exc:
                if exc.__class__ in handlers:
                    handler = handlers[exc.__class__]
                    if handler is not None:
                        handler(exc, output, key, values)
                else:
                    raise
        return output
Example #2
0
    def do(self, blob, ignore_missing=True, exception_handlers=None):
        """Translate blob values and instantiate new model instance.

        Takes out the indicators, if any, from the returned dictionary and puts
        them into the key.

        :param blob: ``dict``-like object on which the matching rules are
                     going to be applied.
        :param ignore_missing: Set to ``False`` if you prefer to raise
                               an exception ``MissingRule`` for the first
                               key that it is not matching any rule.
        :param exception_handlers: Give custom exception handlers to take care
                                   of non-standard names that are installation
                                   specific.

        .. versionadded:: 1.0.0

           ``ignore_missing`` allows to specify if the function should raise
           an exception.

        .. versionadded:: 1.1.0

           ``exception_handlers`` allows unknown keys to treated in a custom
           fashion.
        """
        handlers = {IgnoreKey: None}
        handlers.update(exception_handlers or {})

        if ignore_missing:
            handlers.setdefault(MissingRule, None)

        output = []

        if self.index is None:
            self.build()

        if '__order__' in blob and not isinstance(blob, GroupableOrderedDict):
            blob = GroupableOrderedDict(blob)

        if '__order__' in blob:
            items = blob.iteritems(repeated=True)
        else:
            items = iteritems(blob)

        for key, value in items:
            try:
                result = self.index.query(key)
                if not result:
                    raise MissingRule(key)

                name, creator = result
                item = creator(output, key, value)
                if isinstance(item, MutableMapping):
                    field = '{0}{1}{2}'.format(name, item.pop('$ind1', '_'),
                                               item.pop('$ind2', '_'))
                    if '__order__' in item:
                        item = GroupableOrderedDict(item)
                    output.append((field, item))
                elif isinstance(item, MutableSequence):
                    for v in item:
                        try:
                            field = '{0}{1}{2}'.format(name,
                                                       v.pop('$ind1', '_'),
                                                       v.pop('$ind2', '_'))
                        except AttributeError:
                            field = name
                        output.append((field, v))
                else:
                    output.append((name, item))
            except Exception as exc:
                if exc.__class__ in handlers:
                    handler = handlers[exc.__class__]
                    if handler is not None:
                        handler(exc, output, key, value)
                else:
                    raise

        return GroupableOrderedDict(sorted(output, key=lambda i: i[0][:3]))
Example #3
0
    def do(
        self,
        blob,
        ignore_missing=True,
        exception_handlers=None,
        init_fields=None,
    ):
        """Translate blob values and instantiate new model instance.

        Raises ``MissingRule`` when no rule matched and ``ignore_missing``
        is ``False``.

        :param blob: ``dict``-like object on which the matching rules are
                     going to be applied.
        :param ignore_missing: Set to ``False`` if you prefer to raise
                               an exception ``MissingRule`` for the first
                               key that it is not matching any rule.
        :param exception_handlers: Give custom exception handlers to take care
                                   of non-standard codes that are installation
                                   specific.
        """
        handlers = {IgnoreKey: None}
        handlers.update(exception_handlers or {})

        def clean_missing(exc, output, key, value, rectype=None):
            order = output.get("__order__")
            if order:
                order.remove(key)

        if ignore_missing:
            handlers.setdefault(MissingRule, clean_missing)

        output = {}

        if init_fields:
            output.update(**init_fields)

        if self.index is None:
            self.build()

        if isinstance(blob, GroupableOrderedDict):
            items = blob.iteritems(repeated=True, with_order=False)
        else:
            items = iteritems(blob)

        for key, value in items:
            try:
                result = self.index.query(key)
                if not result:
                    raise MissingRule(key)

                name, creator = result
                data = creator(output, key, value)
                if getattr(creator, "__extend__", False):
                    existing = output.get(name, [])
                    existing.extend(data)
                    output[name] = existing
                else:
                    output[name] = data
            except Exception as exc:
                if exc.__class__ in handlers:
                    handler = handlers[exc.__class__]
                    if handler is not None:
                        handler(exc, output, key, value, rectype=self.rectype)
                else:
                    raise
        return output