Esempio n. 1
0
    def __init__(self, *args, **kwargs):
        args_len = len(args)
        meta = getmeta(self)
        if args_len > len(meta.init_fields):
            raise TypeError('This resource takes %s positional arguments but %s where given.' % (
                len(meta.init_fields), args_len))

        # The ordering of the zip calls matter - zip throws StopIteration
        # when an iter throws it. So if the first iter throws it, the second
        # is *not* consumed. We rely on this, so don't change the order
        # without changing the logic.
        fields_iter = iter(meta.init_fields)
        if args_len:
            if not kwargs:
                for val, field in zip(args, fields_iter):
                    setattr(self, field.attname, val)
            else:
                for val, field in zip(args, fields_iter):
                    setattr(self, field.attname, val)
                    kwargs.pop(field.name, None)

        # Now we're left with the unprocessed fields that *must* come from
        # keywords, or default.
        for field in fields_iter:
            try:
                val = kwargs.pop(field.attname)
            except KeyError:
                val = field.get_default()
            setattr(self, field.attname, val)

        if kwargs:
            raise TypeError("'%s' is an invalid keyword argument for this function" % list(kwargs)[0])
Esempio n. 2
0
 def on_resource_ready(self):
     # Extract reference to fields
     meta = getmeta(self.resource)
     try:
         self._fields = tuple(meta.field_map[name] for name in self.field_names)
     except KeyError as ex:
         raise AttributeError("Attribute {0} not found on {1!r}".format(ex, self.resource))
Esempio n. 3
0
    def clean_fields(self, exclude=None, ignore_not_provided=False):
        errors = {}
        meta = getmeta(self)

        for f in meta.fields:
            if exclude and f.name in exclude:
                continue

            raw_value = f.value_from_object(self)

            if (f.null and raw_value is None) or (ignore_not_provided and raw_value is NotProvided):
                continue

            try:
                raw_value = f.clean(raw_value)
            except ValidationError as e:
                errors[f.name] = e.messages

            # Check for resource level clean methods.
            clean_method = getattr(self, "clean_%s" % f.attname, None)
            if callable(clean_method):
                try:
                    raw_value = clean_method(raw_value)
                except ValidationError as e:
                    errors.setdefault(f.name, []).extend(e.messages)

            if f not in meta.readonly_fields:
                setattr(self, f.attname, raw_value)

        if errors:
            raise ValidationError(errors)
Esempio n. 4
0
def generate_definition(resource):
    """
    Generate a `Swagger Definitions Object <http://swagger.io/specification/#definitionsObject>`_
    from a resource.

    """
    meta = getmeta(resource)

    definition = {
        'type': "object",
        'properties': {}
    }

    for field in meta.all_fields:
        field_definition = {
            'type': SWAGGER_SPEC_TYPE_MAPPING.get(field, 'string')
        }

        if field in SWAGGER_SPEC_FORMAT_MAPPING:
            field_definition['format'] = SWAGGER_SPEC_FORMAT_MAPPING[field]

        if field.doc_text:
            field_definition['description'] = field.doc_text

        definition['properties'][field.name] = field_definition

    return {meta.name: definition}
Esempio n. 5
0
    def clean_fields(self, exclude=None):
        errors = {}

        for f in getmeta(self).fields:
            if exclude and f.name in exclude:
                continue

            raw_value = f.value_from_object(self)

            if f.null and raw_value is None:
                continue

            try:
                raw_value = f.clean(raw_value)
            except ValidationError as e:
                errors[f.name] = e.messages

            # Check for resource level clean methods.
            clean_method = getattr(self, "clean_%s" % f.attname, None)
            if callable(clean_method):
                try:
                    raw_value = clean_method(raw_value)
                except ValidationError as e:
                    errors.setdefault(f.name, []).extend(e.messages)

            setattr(self, f.attname, raw_value)

        if errors:
            raise ValidationError(errors)
Esempio n. 6
0
    def test_field_sorting(self):
        class SampleProxy(proxy.ResourceProxy):
            class Meta:
                field_sorting = True
                resource = Book

        assert [f.attname for f in getmeta(SampleProxy).fields] == [
            'title', 'isbn', 'num_pages', 'rrp', 'fiction', 'genre', 'published', 'authors', 'publisher']
Esempio n. 7
0
 def field_names(self):
     """
     Field names from resource.
     """
     fields = getmeta(self.resource_type).fields
     if self.ignore_header_case:
         return CaseLessStringList(field.name for field in fields)
     else:
         return tuple(field.name for field in fields)
Esempio n. 8
0
    def test_field_sorting__custom(self):
        class SampleProxy(proxy.ResourceProxy):
            class Meta:
                def field_sorting(fields):
                    return sorted(fields, key=lambda f: f.attname)
                resource = Book

        assert [f.attname for f in getmeta(SampleProxy).fields] == [
            'authors', 'fiction', 'genre', 'isbn', 'num_pages', 'published', 'publisher', 'rrp', 'title']
Esempio n. 9
0
    def apply_to(cls, sources, include=None, exclude=None, **kwargs):
        """
        Convenience method that applies include/exclude lists to all items in an
        iterable collection of resources.

        :param sources: Source resources being wrapped.
        :param include: Fields that should be explicitly included on the adapter.
        :param exclude: Fields to explicitly exclude on the adapter.

        """
        meta_objects = {}
        for resource in sources:
            try:
                meta = meta_objects[getmeta(resource).resource_name]
            except KeyError:
                meta = cls._create_options_adapter(getmeta(resource), include, exclude)
                meta_objects[getmeta(resource).resource_name] = meta
            yield cls(resource, meta=meta, **kwargs)
Esempio n. 10
0
 def to_python(self, value):
     if value is None:
         return None
     if isinstance(value, self.of):
         return value
     if isinstance(value, dict):
         return create_resource_from_dict(value, getmeta(self.of).resource_name)
     msg = self.error_messages['invalid'] % self.of
     raise exceptions.ValidationError(msg)
Esempio n. 11
0
 def default(self, o):
     if isinstance(o, (resources.ResourceBase, ResourceAdapter)):
         meta = getmeta(o)
         obj = o.to_dict(self.include_virtual_fields)
         obj[meta.type_field] = meta.resource_name
         return obj
     elif isinstance(o, bases.ResourceIterable):
         return list(o)
     elif o.__class__ in TYPE_SERIALIZERS:
         return TYPE_SERIALIZERS[o.__class__](o)
Esempio n. 12
0
    def __init__(self, *args, **kwargs):
        meta = getmeta(self)

        # Get shadowed resource if supplied
        shadow = kwargs.pop('__resource', None)
        if shadow is None:
            # Create a new instance
            self._shadow = meta.resource()
            super(ResourceProxyBase, self).__init__(*args, **kwargs)
        else:
            self._shadow = shadow
Esempio n. 13
0
    def contribute_to_class(self, cls, _):
        cls._meta = self
        cls_name = cls.__name__
        self.name = cls_name
        self.class_name = "{}.{}".format(cls.__module__, cls_name)

        # Get and filter meta attributes
        meta_attrs = self.meta.__dict__.copy()
        for name in self.meta.__dict__:
            if name.startswith('_'):
                del meta_attrs[name]

        # Get the required resource object
        self.resource = meta_attrs.pop('resource', None)
        if not self.resource:
            raise AttributeError('`resource` has not been defined.')
        self.shadow = shadow = getmeta(self.resource)

        # Extract all meta options and fetch from shadow if not defined
        proxy_attrs = {
            'name': cls_name,
            'verbose_name': cls_name.replace('_', ' ').strip('_ '),
        }
        for attr_name in self.META_OPTION_NAMES:
            if attr_name in meta_attrs:
                value = meta_attrs.pop(attr_name)

                if attr_name == 'verbose_name':
                    # If defined generate pluralised form base on this name.
                    if 'verbose_name_plural' not in proxy_attrs:
                        proxy_attrs['verbose_name_plural'] = value + 's'

                elif attr_name == 'namespace':
                    # Allow meta to be defined as namespace
                    attr_name = 'name_space'

                elif attr_name == 'key_field_name':
                    # Remap to key_field names
                    attr_name = 'key_field_names'
                    value = [value]

                proxy_attrs[attr_name] = value

            elif hasattr(shadow, attr_name):
                proxy_attrs.setdefault(attr_name, getattr(shadow, attr_name))

        # Any leftover attributes must be invalid.
        if meta_attrs != {}:
            raise TypeError("'class Meta' got invalid attribute(s): %s" % ','.join(meta_attrs.keys()))
        del self.meta

        # Apply to self
        for attr_name, value in proxy_attrs.items():
            setattr(self, attr_name, value)
Esempio n. 14
0
 def default(self, o):
     if isinstance(o, (resources.ResourceBase, ResourceAdapter)):
         meta = getmeta(o)
         obj = o.to_dict(self.include_virtual_fields)
         if self.include_type_field:
             obj[meta.type_field] = meta.resource_name
         return obj
     elif isinstance(o, LIST_TYPES):
         return list(o)
     elif o.__class__ in JSON_TYPES:
         return JSON_TYPES[o.__class__](o)
     return super(OdinEncoder, self).default(o)
Esempio n. 15
0
    def __next__(self):
        if self._resource_iters:
            if self._field_iters:
                # Check if the last entry in the field stack has any unprocessed fields.
                if self._field_iters[-1]:
                    # Select the very last field in the field stack.
                    field = self._field_iters[-1][0]
                    # Request a list of resources along with keys from the composite field.
                    self._resource_iters.append(field.item_iter_from_object(self.current_resource))
                    # Update the path
                    self._path.append((NotSupplied, NotSupplied, field.name))
                    self._resource_stack.append(None)
                    # Remove the field from the list (and remove this field entry if it has been emptied)
                    self._field_iters[-1].pop(0)
                else:
                    self._field_iters.pop()

            if self.current_resource:
                if hasattr(self, 'on_exit'):
                    self.on_exit()

            try:
                key, next_resource = next(self._resource_iters[-1])
            except StopIteration:
                # End of the current list of resources pop this list off and get the next list.
                self._path.pop()
                self._resource_iters.pop()
                self._resource_stack.pop()

                return next(self)
            else:
                next_meta = getmeta(next_resource)
                # If we have a key (ie DictOf, ListOf composite fields) update the path key field.
                if key is not None:
                    _, name, field = self._path[-1]
                    if next_meta.key_field:
                        key = next_meta.key_field.value_from_object(next_resource)
                        name = next_meta.key_field.name
                    self._path[-1] = (key, name, field)

                # Get list of any composite fields for this resource (this is a cached field).
                self._field_iters.append(list(next_meta.composite_fields))

                # self.current_resource = next_resource
                self._resource_stack[-1] = next_resource

                if hasattr(self, 'on_enter'):
                    self.on_enter()
                return next_resource
        else:
            raise StopIteration()
Esempio n. 16
0
    def register_resources(self, *resources):
        """
        Register a resource (or resources).

        :param resources: Argument list of resources to register.

        """
        for resource in resources:
            meta = getmeta(resource)
            resource_name = meta.resource_name.lower()
            self.resources[resource_name] = resource
            class_name = meta.class_name.lower()
            if resource_name != class_name:
                self.resources[class_name] = resource
Esempio n. 17
0
def create_resource_from_iter(i, resource, full_clean=True, default_to_not_provided=False):
    """
    Create a resource from an iterable sequence

    :param i: Iterable of values (it is assumed the values are in field order)
    :param resource: A resource type, resource name or list of resources and names to use as the base for creating a
        resource.
    :param full_clean: Perform a full clean as part of the creation, this is useful for parsing data with known
        columns (eg CSV data).
    :param default_to_not_provided: If an value is not supplied keep the value as NotProvided. This is used
        to support merging an updated value.
    :return: New instance of resource type specified in the *resource* param.

    """
    i = list(i)
    resource_type = resource
    fields = getmeta(resource_type).fields

    # Optimisation to allow the assumption that len(fields) == len(i)
    len_fields = len(fields)
    len_i = len(i)
    extra = None
    if len_i < len_fields:
        i += [NotProvided] * (len_fields - len_i)
    elif len_i > len_fields:
        extra = i[len_fields:]
        i = i[:len_fields]

    attrs = []
    errors = {}
    for f, value in zip(fields, i):
        if value is NotProvided:
            if not default_to_not_provided:
                value = f.get_default() if f.use_default_if_not_provided else None
        else:
            try:
                value = f.to_python(value)
            except ValidationError as ve:
                errors[f.name] = ve.error_messages
        attrs.append(value)

    if errors:
        raise ValidationError(errors)

    new_resource = resource_type(*attrs)
    if extra:
        new_resource.extra_attrs(extra)
    if full_clean:
        new_resource.full_clean()
    return new_resource
Esempio n. 18
0
    def __init__(self, source, include=None, exclude=None, meta=None):
        """
        Initialise the adapter.

        :param source: Source resource being wrapped.
        :param include: Fields that should be explicitly included on the adapter.
        :param exclude: Fields to explicitly exclude on the adapter.

        """
        self.__dict__['_source'] = source

        if not meta:
            meta = self._create_options_adapter(getmeta(source), include, exclude)
        self._meta = meta
Esempio n. 19
0
    def to_dict(self, include_virtual=True):
        """
        Convert this resource into a `dict` of field_name/value pairs.

        .. note::
            This method is not recursive, it only operates on this single resource, any sub resources are returned as
            is. The use case that prompted the creation of this method is within codecs when a resource must be
            converted into a type that can be serialised, these codecs then operate recursively on the returned `dict`.

        :param include_virtual: Include virtual fields when generating `dict`.

        """
        meta = getmeta(self)
        fields = meta.all_fields if include_virtual else meta.fields
        return {f.name: v for f, v in field_iter_items(self, fields)}
Esempio n. 20
0
    def add_directive_header(self, _):
        domain = getattr(self, 'domain', 'py')
        directive = getattr(self, 'directivetype', self.objtype)
        source_name = self.get_sourcename()

        if self.options.get('api_documentation'):
            meta = getmeta(self.object)
            name = meta.resource_name
        else:
            name = self.format_name()

        self.add_line(u'.. %s:%s:: %s' % (domain, directive, name), source_name)

        if self.options.noindex:
            self.add_line(u'   :noindex:', source_name)
Esempio n. 21
0
def reader(f, resource, includes_header=False, csv_module=csv, full_clean=True, *args, **kwargs):
    """
    CSV reader that returns resource objects

    :param f: file like object
    :param resource:
    :param includes_header: File includes a header that should be used to map columns
    :param csv_module: Specify an alternate csv module (eg unicodecsv); defaults to the builtin csv as this module
        is implemented in C.
    :param full_clean: Perform a full clean on each object
    :return: Iterable reader object

    """
    csv_reader = csv_module.reader(f, *args, **kwargs)
    if includes_header:
        fields = getmeta(resource).fields

        # Pre-generate field mapping
        header = csv_reader.next()
        mapping = []
        for field in fields:
            if field.name in header:
                mapping.append(header.index(field.name))
            else:
                mapping.append(None)

        # Iterate CSV and process input
        for row in csv_reader:
            yield create_resource_from_iter(
                (NOT_PROVIDED if s is None else row[s] for s in mapping), resource, full_clean
            )

    else:
        # Iterate CSV and process input
        for row in csv_reader:
            yield create_resource_from_iter(
                (NOT_PROVIDED if col is None else col for col in row), resource, full_clean
            )
Esempio n. 22
0
def dumps(fmt=FORMAT_TEMPLATE_RST, exclude=None, template_path=None):
    """
    Dump resource documentation to a string.

    :param fmt: Format template, default is restructured text (can be used with Sphinx).
    :param exclude: List of resources to exclude from generation.
    :param template_path: An additional template_path for customisation of generated documentation.
    :returns: string representation of documentation.

    If an additional template path is supplied it will be made the first path in the template search paths and will
    override any built in templates.
    """
    exclude = exclude or []

    # Get template
    search_path = (template_path, _TEMPLATE_ROOT) if template_path else _TEMPLATE_ROOT
    env = Environment(loader=FileSystemLoader(search_path), autoescape=_auto_escape, )
    template = env.get_template(fmt)

    # Build resources list
    resources = [ResourceDocumentation(r) for r in registration.cache if getmeta(r).resource_name not in exclude]

    return template.render(resources=resources)
Esempio n. 23
0
    def get_value(self, root_resource):
        """
        Get a value from a resource structure.
        """
        result = root_resource
        for value, key, attr in self:
            meta = getmeta(result)
            try:
                field = meta.field_map[attr]
            except KeyError:
                raise InvalidPathError(self, "Unknown field `{0}`".format(attr))

            result = field.value_from_object(result)
            if value is NotSupplied:
                # Nothing is required
                continue
            elif key is NotSupplied:
                # Index or key into element
                value = field.key_to_python(value)
                try:
                    result = result[value]
                except (KeyError, IndexError):
                    raise NoMatchError(self, "Could not find index `{0}` in {1}.".format(value, field))
            else:
                # Filter elements
                if isinstance(result, dict):
                    result = result.values()
                results = tuple(r for r in result if getattr(r, key) == value)
                if len(results) == 0:
                    raise NoMatchError(
                        self, "Filter matched no values; `{0}` == `{1}` in {2}.".format(key, value, field))
                elif len(results) > 1:
                    raise MultipleMatchesError(
                        self, "Filter matched multiple values; `{0}` == `{1}`.".format(key, value))
                else:
                    result = results[0]
        return result
Esempio n. 24
0
 def __repr__(self):
     return '<Proxy of {!r}>'.format(getmeta(self.resource))
Esempio n. 25
0
 def test_options(self, attr, actual):
     target = getmeta(BookProxy)
     assert actual == getattr(target, attr)
Esempio n. 26
0
 def contribute_to_class(self, cls, name):
     self.set_attributes_from_name(name)
     self.resource = cls
     getmeta(cls).add_field(self)
Esempio n. 27
0
def reference_to(obj):
    if hasattr(obj, '_meta'):
        return ":py:class:`%s`" % getmeta(obj).name
    return obj
Esempio n. 28
0
 def __init__(self, resource):
     self.resource = resource
     self._meta = getmeta(resource)
     self._fields = None
Esempio n. 29
0
 def represent_resource(self, data):
     obj = data.to_dict(self.include_virtual_fields)
     if self.include_type_field:
         meta = getmeta(data)
         obj[meta.type_field] = meta.resource_name
     return self.represent_dict(obj)
Esempio n. 30
0
def resolve_resource_type(resource):
    if isinstance(resource, type) and issubclass(resource, ResourceBase):
        meta = getmeta(resource)
        return meta.resource_name, meta.type_field
    else:
        return resource, DEFAULT_TYPE_FIELD
Esempio n. 31
0
 def get_field_dict(self):
     """Return a dictionary of fields along with their names."""
     return getmeta(self.obj).field_map
Esempio n. 32
0
 def field_map(self):
     return getmeta(Book).field_map
Esempio n. 33
0
 def field_map(self):
     return getmeta(Book).field_map
Esempio n. 34
0
 def test_options_type(self):
     actual = getmeta(BookProxy)
     assert isinstance(actual, proxy.ResourceProxyOptions)
Esempio n. 35
0
 def parent_resource_names(self):
     """
     List of parent resource names.
     """
     return tuple(getmeta(p).resource_name for p in self.parents)
Esempio n. 36
0
 def __repr__(self):
     return '<Proxy of {!r}>'.format(getmeta(self.resource))
Esempio n. 37
0
 def represent_resource(self, data):
     obj = data.to_dict(self.include_virtual_fields)
     if self.include_type_field:
         meta = getmeta(data)
         obj[meta.type_field] = meta.resource_name
     return self.represent_dict(obj)
Esempio n. 38
0
def value_fields(resource):
    """
    Iterator to get non-composite (eg value) fields for export
    """
    meta = getmeta(resource)
    return [f for f in meta.all_fields if f not in meta.composite_fields]
Esempio n. 39
0
def reference_to(obj):
    if hasattr(obj, '_meta'):
        return ":py:class:`%s`" % getmeta(obj).name
    return obj
Esempio n. 40
0
def create_resource_from_dict(d,
                              resource=None,
                              full_clean=True,
                              copy_dict=True,
                              default_to_not_provided=False):
    # type: (Dict[str, Any], R, bool, bool, bool) -> Instance[R]
    """
    Create a resource from a dict.

    :param d: dictionary of data.
    :param resource: A resource type, resource name or list of resources and names to use as the base for creating a
        resource. If a list is supplied the first item will be used if a resource type is not supplied; this could also
        be a parent(s) of any resource defined by the dict.
    :param full_clean: Perform a full clean as part of the creation.
    :param copy_dict: Use a copy of the input dictionary rather than destructively processing the input dict.
    :param default_to_not_provided: If an value is not supplied keep the value as NOT_PROVIDED. This is used
        to support merging an updated value.

    """
    if not isinstance(d, dict):
        raise TypeError('`d` must be a dict instance.')

    if copy_dict:
        d = d.copy()

    if resource:
        resource_type = None

        # Convert to single resource then resolve document type
        if isinstance(resource, (tuple, list)):
            resources = (resolve_resource_type(r) for r in resource)
        else:
            resources = [resolve_resource_type(resource)]

        for resource_name, type_field in resources:
            # See if the input includes a type field  and check it's registered
            document_resource_name = d.get(type_field, None)
            if document_resource_name:
                resource_type = registration.get_resource(
                    document_resource_name)
            else:
                resource_type = registration.get_resource(resource_name)

            if not resource_type:
                raise exceptions.ResourceException(
                    "Resource `%s` is not registered." %
                    document_resource_name)

            if document_resource_name:
                # Check resource types match or are inherited types
                if (resource_name == document_resource_name or resource_name
                        in getmeta(resource_type).parent_resource_names):
                    break  # We are done
            else:
                break

        if not resource_type:
            raise exceptions.ResourceException(
                "Incoming resource does not match [%s]" %
                ', '.join(r for r, t in resources))
    else:
        # No resource specified, relay on type field
        document_resource_name = d.pop(DEFAULT_TYPE_FIELD, None)
        if not document_resource_name:
            raise exceptions.ResourceException("Resource not defined.")

        # Get an instance of a resource type
        resource_type = registration.get_resource(document_resource_name)
        if not resource_type:
            raise exceptions.ResourceException(
                "Resource `%s` is not registered." % document_resource_name)

    attrs = []
    errors = {}
    meta = getmeta(resource_type)
    for f in meta.init_fields:
        value = d.pop(f.name, NotProvided)
        if value is NotProvided:
            if not default_to_not_provided:
                value = f.get_default(
                ) if f.use_default_if_not_provided else None
        else:
            try:
                value = f.to_python(value)
            except ValidationError as ve:
                errors[f.name] = ve.error_messages
        attrs.append(value)

    if errors:
        raise ValidationError(errors)

    new_resource = resource_type(*attrs)
    if d:
        new_resource.extra_attrs(d)
    if full_clean:
        new_resource.full_clean()
    return new_resource
Esempio n. 41
0
 def __str__(self):
     return '%s resource' % getmeta(self).resource_name
Esempio n. 42
0
 def get_field_dict(self):
     """Return a dictionary of fields along with their names."""
     return getmeta(self.obj).field_map
Esempio n. 43
0
def create_resource_from_dict(d, resource=None, full_clean=True, copy_dict=True, default_to_not_provided=False):
    # type: (Dict[str, Any], R, bool, bool, bool) -> Instance[R]
    """
    Create a resource from a dict.

    :param d: dictionary of data.
    :param resource: A resource type, resource name or list of resources and names to use as the base for creating a
        resource. If a list is supplied the first item will be used if a resource type is not supplied; this could also
        be a parent(s) of any resource defined by the dict.
    :param full_clean: Perform a full clean as part of the creation.
    :param copy_dict: Use a copy of the input dictionary rather than destructively processing the input dict.
    :param default_to_not_provided: If an value is not supplied keep the value as NOT_PROVIDED. This is used
        to support merging an updated value.

    """
    if not isinstance(d, dict):
        raise TypeError('`d` must be a dict instance.')

    if copy_dict:
        d = d.copy()

    if resource:
        resource_type = None

        # Convert to single resource then resolve document type
        if isinstance(resource, (tuple, list)):
            resources = (resolve_resource_type(r) for r in resource)
        else:
            resources = [resolve_resource_type(resource)]

        for resource_name, type_field in resources:
            # See if the input includes a type field  and check it's registered
            document_resource_name = d.get(type_field, None)
            if document_resource_name:
                resource_type = registration.get_resource(document_resource_name)
            else:
                resource_type = registration.get_resource(resource_name)

            if not resource_type:
                raise exceptions.ResourceException("Resource `%s` is not registered." % document_resource_name)

            if document_resource_name:
                # Check resource types match or are inherited types
                if (resource_name == document_resource_name or
                        resource_name in getmeta(resource_type).parent_resource_names):
                    break  # We are done
            else:
                break

        if not resource_type:
            raise exceptions.ResourceException(
                "Incoming resource does not match [%s]" % ', '.join(r for r, t in resources))
    else:
        # No resource specified, relay on type field
        document_resource_name = d.pop(DEFAULT_TYPE_FIELD, None)
        if not document_resource_name:
            raise exceptions.ResourceException("Resource not defined.")

        # Get an instance of a resource type
        resource_type = registration.get_resource(document_resource_name)
        if not resource_type:
            raise exceptions.ResourceException("Resource `%s` is not registered." % document_resource_name)

    attrs = []
    errors = {}
    meta = getmeta(resource_type)
    for f in meta.init_fields:
        value = d.pop(f.name, NotProvided)
        if value is NotProvided:
            if not default_to_not_provided:
                value = f.get_default() if f.use_default_if_not_provided else None
        else:
            try:
                value = f.to_python(value)
            except ValidationError as ve:
                errors[f.name] = ve.error_messages
        attrs.append(value)

    if errors:
        raise ValidationError(errors)

    new_resource = resource_type(*attrs)
    if d:
        new_resource.extra_attrs(d)
    if full_clean:
        new_resource.full_clean()
    return new_resource
Esempio n. 44
0
def resource_reference(resource):
    return "{} <{}.{}>".format(getmeta(resource).resource_name, resource.__module__, resource.__name__)