Example #1
0
 def __check_parent(self, new_mb_rc):
     parent_mb_cls = get_member_class(self.context.__parent__)
     for attr_name, attr in type(new_mb_rc).get_attributes().iteritems():
         if attr.kind == ResourceAttributeKinds.MEMBER \
            and get_member_class(attr.value_type) is parent_mb_cls \
            and getattr(new_mb_rc, attr_name) is None:
             setattr(new_mb_rc, attr_name, self.context.__parent__)
Example #2
0
 def after(self):
     # Register resources eagerly so the various adapters and utilities are
     # available for other directives.
     discriminator = ('resource', self.interface)
     reg = get_current_registry()
     config = Configurator(reg, package=self.context.package)
     config.add_resource(self.interface, self.member, self.entity,
                         collection=self.collection,
                         collection_root_name=self.collection_root_name,
                         collection_title=self.collection_title,
                         repository=self.repository,
                         expose=self.expose,
                         _info=self.context.info)
     for key, value in iteritems_(self.representers):
         cnt_type, rc_kind = key
         opts, mp_opts = value
         if rc_kind == RESOURCE_KINDS.MEMBER:
             rc = get_member_class(self.interface)
         elif rc_kind == RESOURCE_KINDS.COLLECTION:
             rc = get_collection_class(self.interface)
         else: # None
             rc = self.interface
         discriminator = ('resource_representer', rc, cnt_type, rc_kind)
         self.action(discriminator=discriminator, # pylint: disable=E1101
                     callable=config.add_resource_representer,
                     args=(rc, cnt_type),
                     kw=dict(options=opts,
                             attribute_options=mp_opts,
                             _info=self.context.info),
                     )
Example #3
0
 def visit(self, key, attribute_options):
     # We only collect load options for attributes which are explicitly not
     # ignored or member attributes unless they are explicitly ignored.
     ignore_opt = attribute_options.get(IGNORE_OPTION)
     if not ignore_opt is True:
         rc = get_member_class(self._context)
         entity_attr_names = []
         store_key = True
         for idx, attr_name in enumerate(key):
             attr = get_resource_class_attribute(rc, attr_name)
             if attr is None:
                 # Referencing non-existing attribute; ignore.
                 store_key = False
                 break
             elif idx == 0 \
                  and is_collection_attribute(attr) \
                  and not ignore_opt is False:
                 # Referencing collection attribute which was not
                 # explicitly enabled.
                 store_key = False
                 break
             entity_attr_name = attr.entity_attr
             if is_terminal_attribute(attr):
                 if '.' in entity_attr_name:
                     entity_attr_name = \
                         entity_attr_name[:entity_attr_name.rfind('.')]
                 else:
                     store_key = False
                     break
             entity_attr_names.append(entity_attr_name)
             rc = attr.attr_type
         if store_key:
             self.__attr_map[key] = entity_attr_names
Example #4
0
 def __process_row(self, row_data, mapped_class, attribute_key):
     is_repeating_row = len(attribute_key) == 0 \
                        and not self.__coll_data is None \
                        and self.__coll_data.has(self.__row_data_key)
     if is_repeating_row:
         self.__process_row(row_data,
                            self.__coll_data.collection_class,
                            self.__coll_data.attribute_key)
         new_data_el = None
     else:
         mb_cls = get_member_class(mapped_class)
         new_data_el = \
                 self._mapping.create_data_element(mapped_class=mb_cls)
         for attr in self._mapping.terminal_attribute_iterator(
                                             mapped_class, attribute_key):
             self.__process_attr(attr, attribute_key, new_data_el,
                                 row_data)
         for attr in self._mapping.nonterminal_attribute_iterator(
                                             mapped_class, attribute_key):
             self.__process_attr(attr, attribute_key, new_data_el,
                                 row_data)
         if not self.__coll_data is None \
            and mapped_class == self.__coll_data.collection_class:
             if not self.__coll_data.has(self.__row_data_key):
                 coll_data_el = \
                     self._mapping.create_data_element(mapped_class=
                                                             mapped_class)
                 self.__coll_data.set(self.__row_data_key, coll_data_el)
             else:
                 coll_data_el = self.__coll_data.get(self.__row_data_key)
             coll_data_el.add_member(new_data_el)
             new_data_el = coll_data_el
     return new_data_el
Example #5
0
 def after(self):
     # Register resources eagerly so the various adapters and utilities are
     # available for other directives.
     discriminator = ('resource', self.interface)
     reg = get_current_registry()
     config = Configurator(reg, package=self.context.package)
     config.add_resource(self.interface,
                         self.member,
                         self.entity,
                         collection=self.collection,
                         collection_root_name=self.collection_root_name,
                         collection_title=self.collection_title,
                         repository=self.repository,
                         expose=self.expose,
                         _info=self.context.info)
     for key, value in self.representers.iteritems():
         cnt_type, rc_kind = key
         opts, mp_opts = value
         if rc_kind == RESOURCE_KINDS.member:
             rc = get_member_class(self.interface)
         elif rc_kind == RESOURCE_KINDS.collection:
             rc = get_collection_class(self.interface)
         else:  # None
             rc = self.interface
         discriminator = ('resource_representer', rc, cnt_type, rc_kind)
         self.action(
             discriminator=discriminator,  # pylint: disable=E1101
             callable=config.add_resource_representer,
             args=(rc, cnt_type),
             kw=dict(options=opts,
                     attribute_options=mp_opts,
                     _info=self.context.info),
         )
Example #6
0
File: xml.py Project: b8va/everest
 def __get_q_tag(self, attr):
     # FIXME: We should cache the namespace for each attribute.
     if not attr.namespace is None:
         q_tag = '{%s}%s' % (attr.namespace, attr.repr_name)
     else:
         if attr.kind == RESOURCE_ATTRIBUTE_KINDS.TERMINAL:
             xml_ns = \
               self.mapping.configuration.get_option(XML_NAMESPACE_OPTION)
         else:
             if attr.kind == RESOURCE_ATTRIBUTE_KINDS.MEMBER:
                 attr_type = get_member_class(attr.value_type)
             elif attr.kind == RESOURCE_ATTRIBUTE_KINDS.COLLECTION:
                 attr_type = get_collection_class(attr.value_type)
             mp = self.mapping.mapping_registry.find_mapping(attr_type)
             if not mp is None:
                 xml_ns = mp.configuration.get_option(XML_NAMESPACE_OPTION)
             else: # pragma: no cover
                 # Not mapped.
                 # FIXME This case is neither tested nor documented.
                 xml_ns = None
         if not xml_ns is None:
             q_tag = '{%s}%s' % (xml_ns, attr.repr_name)
         else:
             q_tag = attr.repr_name
     return q_tag
Example #7
0
 def __process_row(self, row_data, mapped_class, attribute_key):
     is_repeating_row = len(attribute_key) == 0 \
                        and not self.__coll_data is None \
                        and self.__coll_data.has(self.__row_data_key)
     if is_repeating_row:
         self.__process_row(row_data, self.__coll_data.collection_class,
                            self.__coll_data.attribute_key)
         new_data_el = None
     else:
         mb_cls = get_member_class(mapped_class)
         new_data_el = \
                 self._mapping.create_data_element(mapped_class=mb_cls)
         for attr in self._mapping.terminal_attribute_iterator(
                 mapped_class, attribute_key):
             self.__process_attr(attr, attribute_key, new_data_el, row_data)
         for attr in self._mapping.nonterminal_attribute_iterator(
                 mapped_class, attribute_key):
             self.__process_attr(attr, attribute_key, new_data_el, row_data)
         if not self.__coll_data is None \
            and mapped_class == self.__coll_data.collection_class:
             if not self.__coll_data.has(self.__row_data_key):
                 coll_data_el = \
                     self._mapping.create_data_element(mapped_class=
                                                             mapped_class)
                 self.__coll_data.set(self.__row_data_key, coll_data_el)
             else:
                 coll_data_el = self.__coll_data.get(self.__row_data_key)
             coll_data_el.add_member(new_data_el)
             new_data_el = coll_data_el
     return new_data_el
Example #8
0
 def test_dependency_graph(self):
     grph = build_resource_dependency_graph(self._interfaces)
     self.assert_equal(len(grph.nodes()), 4)
     entity_mb_cls = get_member_class(IMyEntity)
     entity_parent_mb_cls = get_member_class(IMyEntityParent)
     entity_child_mb_cls = get_member_class(IMyEntityChild)
     entity_grandchild_mb_cls = get_member_class(IMyEntityGrandchild)
     # Entity Parent resource deps should be empty.
     self.assert_equal(grph.neighbors(entity_parent_mb_cls), [])
     # Entity Child has Grandchild.
     self.assert_equal(grph.neighbors(entity_child_mb_cls),
                       [entity_grandchild_mb_cls])
     # Entity Grandchild has Child, but backrefs are excluded by default.
     self.assert_equal(grph.neighbors(entity_grandchild_mb_cls), [])
     # Entity has Parent and Child.
     self.assert_equal(set(grph.neighbors(entity_mb_cls)),
                       set([entity_parent_mb_cls, entity_child_mb_cls]))
Example #9
0
 def __get__(self, dummy, entity_class):
     mb_cls = get_member_class(entity_class)
     attr_map = OrderedDict()
     for rc_attr in itervalues_(mb_cls.__everest_attributes__):
         attr_map[rc_attr.entity_attr] = rc_attr
     # This replaces the injector.
     entity_class.__everest_attributes__ = attr_map
     return attr_map
Example #10
0
 def _create_link_data_element(self, attribute, member_node):
     if attribute.kind == RESOURCE_ATTRIBUTE_KINDS.MEMBER:
         kind = RESOURCE_KINDS.MEMBER
         rc_cls = get_member_class(attribute.value_type)
     else:
         kind = RESOURCE_KINDS.COLLECTION
         rc_cls = get_collection_class(attribute.value_type)
     return self._mapping.create_linked_data_element(
         member_node, kind, relation=rc_cls.relation, title=rc_cls.title)
Example #11
0
 def test_dependency_graph(self):
     grph = build_resource_dependency_graph(self._interfaces)
     self.assert_equal(len(grph.nodes()), 4)
     entity_mb_cls = get_member_class(IMyEntity)
     entity_parent_mb_cls = get_member_class(IMyEntityParent)
     entity_child_mb_cls = get_member_class(IMyEntityChild)
     entity_grandchild_mb_cls = get_member_class(IMyEntityGrandchild)
     # Entity Parent resource deps should be empty.
     self.assert_equal(grph.neighbors(entity_parent_mb_cls), [])
     # Entity Child has Grandchild.
     self.assert_equal(grph.neighbors(entity_child_mb_cls),
                       [entity_grandchild_mb_cls])
     # Entity Grandchild has Child, but backrefs are excluded by default.
     self.assert_equal(grph.neighbors(entity_grandchild_mb_cls),
                       [])
     # Entity has Parent and Child.
     self.assert_equal(set(grph.neighbors(entity_mb_cls)),
                       set([entity_parent_mb_cls, entity_child_mb_cls]))
Example #12
0
 def _get_node_nested(self, node, attr):
     nested_data = node.get(attr.repr_name)
     if isinstance(nested_data, dict): # Can also be None or a URL.
         json_class = nested_data.pop('__jsonclass__', None)
         if not json_class is None:
             rel = get_member_class(attr.value_type).relation
             if json_class != rel:
                 raise ValueError('Expected data for %s, got %s.'
                                  % (rel, json_class))
     return nested_data
Example #13
0
 def __collect(self, resource):
     ent_cls = get_entity_class(resource)
     coll_cls = get_collection_class(resource)
     cache = EntityCacheMap()
     agg = StagingAggregate(ent_cls, cache)
     coll = coll_cls.create_from_aggregate(agg)
     coll.add(resource)
     return dict([(get_member_class(ent_cls),
                   coll.get_root_collection(ent_cls))
                  for ent_cls in cache.keys()])
Example #14
0
 def __collect(self, resource):
     ent_cls = get_entity_class(resource)
     coll_cls = get_collection_class(resource)
     cache = EntityCacheMap()
     agg = StagingAggregate(ent_cls, cache)
     coll = coll_cls.create_from_aggregate(agg)
     coll.add(resource)
     return dict([(get_member_class(ent_cls),
                   coll.get_root_collection(ent_cls))
                  for ent_cls in cache.keys()])
Example #15
0
 def _get_node_nested(self, node, attr):
     nested_data = node.get(attr.repr_name)
     if isinstance(nested_data, dict):  # Can also be None or a URL.
         json_class = nested_data.pop('__jsonclass__', None)
         if not json_class is None:
             rel = get_member_class(attr.value_type).relation
             if json_class != rel:
                 raise ValueError('Expected data for %s, got %s.' %
                                  (rel, json_class))
     return nested_data
Example #16
0
 def _traverse_member(self,
                      attr_key,
                      attr,
                      member_node,
                      parent_data,
                      visitor,
                      index=None):
     member_data = OrderedDict()
     is_link_node = \
         self._is_link_node(member_node, attr) \
         or (not index is None and not attr is None and
             attr.options.get(WRITE_MEMBERS_AS_LINK_OPTION) is True)
     # Ignore links for traversal.
     if not is_link_node:
         if not attr is None:
             node_type = get_member_class(attr.value_type)
         else:
             node_type = self._get_node_type(member_node)
         for mb_attr in self._mapping.attribute_iterator(
                 node_type, attr_key):
             ignore_opt = self.__check_attribute_ignore \
                          and mb_attr.should_ignore(attr_key)
             if ignore_opt:
                 continue
             if mb_attr.kind == RESOURCE_ATTRIBUTE_KINDS.TERMINAL:
                 # Terminal attribute - extract.
                 value = self._get_node_terminal(member_node, mb_attr)
                 if value is None and self.__ignore_none_values:
                     # We ignore None attribute values when reading
                     # representations.
                     continue
                 member_data[mb_attr] = value
             else:
                 # Nested attribute - traverse.
                 nested_node = self._get_node_nested(member_node, mb_attr)
                 if nested_node is None:
                     # Stop condition - the given data element does not
                     # contain a nested attribute of the given mapped
                     # name.
                     continue
                 nested_attr_key = attr_key + (mb_attr, )
                 if ignore_opt is False:
                     # The offset in the attribute key ensures that
                     # the defaults for ignoring attributes of the
                     # nested attribute can be retrieved correctly.
                     nested_attr_key.offset = len(nested_attr_key)
                 self._dispatch(nested_attr_key, mb_attr, nested_node,
                                member_data, visitor)
     visitor.visit_member(attr_key,
                          attr,
                          member_node,
                          member_data,
                          is_link_node,
                          parent_data,
                          index=index)
Example #17
0
    def update_from_data(self, data_element):
        """
        Updates this collection from the given data element.

        This iterates over the members of this collection and checks if
        a member with the same ID exists in the given update data. If yes, 
        the existing member is updated with the update member; if no,
        the member is removed. All data elements in the update data that
        have no ID are added as new members. Data elements with an ID that
        can not be found in this collection trigger an error.

        :param data_element: data element (hierarchical) to create a resource
            from
        :type data_element: object implementing
         `:class:everest.resources.interfaces.IExplicitDataElement`
        :raises ValueError: when a data element with an ID that is not present
          in this collection is encountered.
        """
        attrs = data_element.mapping.get_attribute_map()
        id_attr = attrs['id']
        update_ids = set()
        new_mb_els = []
        self_id_map = dict([(self_mb.id, self_mb) for self_mb in iter(self)])
        for member_el in data_element.get_members():
#            if ILinkedDataElement in provided_by(member_el):
#                # Found a link - do not do anything.
#                mb_id = member_el.get_id()
#            else:
            mb_id = member_el.get_terminal(id_attr)
            if mb_id is None:
                # New data element without an ID - queue for adding.
                new_mb_els.append(member_el)
                continue
            else:
                self_mb = self_id_map.get(mb_id)
                if not self_mb is None:
                    # Found an existing member - update.
                    self_mb.update_from_data(member_el)
                else:
                    # New data element with a new ID. This is suspicious.
                    raise ValueError('New member data should not provide '
                                     'an ID attribute.')
            update_ids.add(mb_id)
        # Before adding any new members, check for delete operations.
        for self_mb in iter(self):
            if not self_mb.id in update_ids:
                # Found an existing member ID that was not supplied with
                # the update data- remove.
                self.remove(self_mb)
        # Now, add new members.
        mb_cls = get_member_class(self.__class__)
        for new_member_el in new_mb_els:
            new_member = mb_cls.create_from_data(new_member_el)
            self.add(new_member)
Example #18
0
 def _create_link_data_element(self, attribute, member_node):
     if attribute.kind == RESOURCE_ATTRIBUTE_KINDS.MEMBER:
         kind = RESOURCE_KINDS.MEMBER
         rc_cls = get_member_class(attribute.value_type)
     else:
         kind = RESOURCE_KINDS.COLLECTION
         rc_cls = get_collection_class(attribute.value_type)
     return self._mapping.create_linked_data_element(
                                             member_node, kind,
                                             relation=rc_cls.relation,
                                             title=rc_cls.title)
Example #19
0
 def _set_order(self, order_spec):
     if not order_spec is None:
         # Translate to entity order expression before passing on to the
         # aggregate.
         visitor = ResourceToEntityOrderSpecificationVisitor(
                                                 get_member_class(self))
         order_spec.accept(visitor)
         self.__aggregate.order = visitor.expression
     else:
         self.__aggregate.order = None
     self._order_spec = order_spec
Example #20
0
 def _set_order(self, order_spec):
     if not order_spec is None:
         # Translate to entity order expression before passing on to the
         # aggregate.
         visitor = ResourceToEntityOrderSpecificationVisitor(
                                                     get_member_class(self))
         order_spec.accept(visitor)
         self.__aggregate.order = visitor.expression
     else:
         self.__aggregate.order = None
     self._order_spec = order_spec
Example #21
0
 def _get_node_type(self, node):
     relation = node.get('__jsonclass__')
     if not relation is None:
         tpe = get_resource_class_for_relation(relation)
     else:
         # In the absence of class hinting, the best we can do is to
         # look up the member class for the mapped class. For polymorphic
         # types, this will only work if a representer was initialized
         # for every derived class separately.
         tpe = get_member_class(self._mapping.mapped_class)
     return tpe
Example #22
0
 def _get_node_type(self, node):
     relation = node.get('__jsonclass__')
     if not relation is None:
         tpe = get_resource_class_for_relation(relation)
     else:
         # In the absence of class hinting, the best we can do is to
         # look up the member class for the mapped class. For polymorphic
         # types, this will only work if a representer was initialized
         # for every derived class separately.
         tpe = get_member_class(self._mapping.mapped_class)
     return tpe
Example #23
0
 def __get__(self, resource, resource_class):
     if not resource is None:
         ent = get_nested_attribute(resource.get_entity(), self.entity_attr)
         if not ent is None:
             fac = get_member_class(self.attr_type).as_related_member
             member = fac(ent, self.make_relationship(resource))
         else:
             member = None
     else:
         # class level access
         member = self
     return member
Example #24
0
 def __process_link(self, link, attr):
     if not self.__is_link(link):
         raise ValueError('Value for nested attribute "%s" '
                          'is not a link.' % attr.repr_name)
     if attr.kind == RESOURCE_ATTRIBUTE_KINDS.MEMBER:
         kind = RESOURCE_KINDS.MEMBER
         rc_cls = get_member_class(attr.value_type)
     else:
         kind = RESOURCE_KINDS.COLLECTION
         rc_cls = get_collection_class(attr.value_type)
     return self._mapping.create_linked_data_element(
         link, kind, relation=rc_cls.relation, title=rc_cls.title)
Example #25
0
 def __get__(self, resource, resource_class):
     if not resource is None:
         ent = get_nested_attribute(resource.get_entity(), self.entity_attr)
         if not ent is None:
             fac = get_member_class(self.attr_type).as_related_member
             member = fac(ent, self.make_relationship(resource))
         else:
             member = None
     else:
         # class level access
         member = self
     return member
Example #26
0
def build_resource_graph(resource, dependency_graph=None):
    """
    Traverses the graph of resources that is reachable from the given
    resource.

    If a resource dependency graph is given, links to other resources are
    only followed if the dependency graph has an edge connecting the two
    corresponding resource classes; otherwise, a default graph is built
    which ignores all direct cyclic resource references.

    :resource: a :class:`everest.resources.MemberResource` instance.
    :returns: a :class:`ResourceGraph` instance representing the graph of
        resources reachable from the given resource.
    """
    def visit(rc, grph, dep_grph):
        mb_cls = type(rc)
        attr_map = get_resource_class_attributes(mb_cls)
        for attr_name, attr in iteritems_(attr_map):
            if is_resource_class_terminal_attribute(mb_cls, attr_name):
                continue
            # Only follow the resource attribute if the dependency graph
            # has an edge here.
            child_mb_cls = get_member_class(attr.attr_type)
            if not dep_grph.has_edge((mb_cls, child_mb_cls)):
                continue
            child_rc = getattr(rc, attr_name)
            if is_resource_class_collection_attribute(mb_cls, attr_name):
                for child_mb in child_rc:
                    if not grph.has_node(
                            child_mb):  # Ignore cyclic references.
                        grph.add_node(child_mb)
                        grph.add_edge((rc, child_mb))
                        visit(child_mb, grph, dep_grph)
            else:  # Member.
                if not grph.has_node(child_rc):  # Ignore cyclic references.
                    grph.add_node(child_rc)
                    grph.add_edge((rc, child_rc))
                    visit(child_rc, grph, dep_grph)

    if dependency_graph is None:
        dependency_graph = build_resource_dependency_graph(
            [get_member_class(resource)])
    graph = ResourceGraph()
    if provides_member_resource(resource):
        rcs = [resource]
    else:
        rcs = resource
    for rc in rcs:
        graph.add_node(rc)
        visit(rc, graph, dependency_graph)
    return graph
Example #27
0
 def test_filter_specification_visitor(self):
     coll = get_root_collection(IMyEntity)
     mb_cls = get_member_class(coll)
     my_entity = create_entity()
     member = coll.create_member(my_entity)
     spec_fac = FilterSpecificationFactory()
     specs = [
             # Terminal access.
             spec_fac.create_equal_to('text', self.TEST_TEXT),
             # Terminal access with different name in entity.
             spec_fac.create_equal_to('text_rc', self.TEST_TEXT),
             # Nested member access with different name in entity.
             spec_fac.create_equal_to('parent.text_rc', self.TEST_TEXT),
             # Nested collection access with different name in entity.
             spec_fac.create_equal_to('children.text_rc', self.TEST_TEXT),
             # Access with dotted entity name in rc attr declaration.
             spec_fac.create_equal_to('parent_text', self.TEST_TEXT),
             # Access to member.
             spec_fac.create_equal_to('parent',
                                      member.parent.get_entity()),
             ]
     expecteds = [('text', MyEntity.text.__eq__(self.TEST_TEXT)),
                  ('text_ent', MyEntity.text_ent.__eq__(self.TEST_TEXT)),
                  ('parent.text_ent',
                   MyEntity.parent.has(
                                 MyEntityParent.text_ent.__eq__(
                                                     self.TEST_TEXT))),
                  ('children.text_ent',
                   MyEntity.children.any(
                                 MyEntityChild.text_ent.__eq__(
                                                     self.TEST_TEXT))),
                  ('parent.text_ent',
                   MyEntity.parent.has(
                                 MyEntityParent.text_ent.__eq__(
                                                     self.TEST_TEXT))),
                  ('parent',
                   MyEntity.parent.__eq__(member.parent.get_entity())),
                  ]
     for spec, expected in zip(specs, expecteds):
         new_attr_name, expr = expected
         visitor = ResourceToEntityFilterSpecificationVisitor(mb_cls)
         spec.accept(visitor)
         new_spec = visitor.expression
         self.assert_equal(new_spec.attr_name, new_attr_name)
         visitor = SqlFilterSpecificationVisitor(MyEntity)
         new_spec.accept(visitor)
         self.assert_equal(str(visitor.expression), str(expr))
     invalid_spec = spec_fac.create_equal_to('foo', self.TEST_TEXT)
     vst = ResourceToEntityFilterSpecificationVisitor(mb_cls)
     self.assert_raises(AttributeError, invalid_spec.accept, vst)
Example #28
0
def build_resource_graph(resource, dependency_graph=None):
    """
    Traverses the graph of resources that is reachable from the given 
    resource.
    
    If a resource dependency graph is given, links to other resources are 
    only followed if the dependency graph has an edge connecting the two 
    corresponding resource classes; otherwise, a default graph is built
    which ignores all direct cyclic resource references. 

    :resource: a :class:`everest.resources.MemberResource` instance.
    :returns: a :class:`ResourceGraph` instance representing the graph of 
        resources reachable from the given resource.
    """
    def visit(rc, grph, dep_grph):
        mb_cls = type(rc)
        attr_map = mb_cls.get_attributes()
        for attr_name, attr in attr_map.iteritems():
            if mb_cls.is_terminal(attr_name):
                continue
            # Only follow the resource attribute if the dependency graph
            # has an edge here.
            child_mb_cls = get_member_class(attr.value_type)
            if not dep_grph.has_edge((mb_cls, child_mb_cls)):
                continue
            child_rc = getattr(rc, attr_name)
            if mb_cls.is_collection(attr_name):
                for child_mb in child_rc:
                    if not grph.has_node(child_mb): # Ignore cyclic references.
                        grph.add_node(child_mb)
                        grph.add_edge((rc, child_mb))
                        visit(child_mb, grph, dep_grph)
            else: # Member.
                if not grph.has_node(child_rc): # Ignore cyclic references.
                    grph.add_node(child_rc)
                    grph.add_edge((rc, child_rc))
                    visit(child_rc, grph, dep_grph)
    if  dependency_graph is None:
        dependency_graph = build_resource_dependency_graph(
                                            [get_member_class(resource)])
    graph = ResourceGraph()
    if provides_member_resource(resource):
        rcs = [resource]
    else:
        rcs = resource
    for rc in rcs:
        graph.add_node(rc)
        visit(rc, graph, dependency_graph)
    return graph
Example #29
0
 def __process_link(self, link, attr):
     if not self.__is_link(link):
         raise ValueError('Value for nested attribute "%s" '
                          'is not a link.' % attr.repr_name)
     if attr.kind == RESOURCE_ATTRIBUTE_KINDS.MEMBER:
         kind = RESOURCE_KINDS.MEMBER
         rc_cls = get_member_class(attr.value_type)
     else:
         kind = RESOURCE_KINDS.COLLECTION
         rc_cls = get_collection_class(attr.value_type)
     return self._mapping.create_linked_data_element(link,
                                                     kind,
                                                     relation=
                                                         rc_cls.relation,
                                                     title=rc_cls.title)
Example #30
0
 def __dump_entities(self, entity_class):
     cache = self._get_cache(entity_class)
     coll_cls = get_collection_class(entity_class)
     mb_cls = get_member_class(entity_class)
     fn = get_write_collection_path(coll_cls,
                                    self._config['content_type'],
                                    directory=self._config['directory'])
     # Wrap the entities in a temporary collection.
     coll = create_staging_collection(coll_cls)
     for ent in cache.iterator():
         coll.add(mb_cls.create_from_entity(ent))
     # Open stream for writing and dump the collection.
     stream = file(fn, 'w')
     with stream:
         dump_resource(coll, stream,
                       content_type=self._config['content_type'])
Example #31
0
 def __convert_to_entity_attr(self, rc_attr_name):
     entity_attr_tokens = []
     rc_class = self.__rc_class
     for rc_attr_token in rc_attr_name.split('.'):
         rc_attr = get_resource_class_attributes(rc_class)[rc_attr_token]
         ent_attr_name = rc_attr.entity_name
         if ent_attr_name is None:
             raise ValueError('Resource attribute "%s" does not have a '
                              'corresponding entity attribute.'
                              % rc_attr.name)
         if rc_attr.kind != ResourceAttributeKinds.TERMINAL:
             # Look up the member class for the specified member or
             # collection resource interface.
             rc_class = get_member_class(rc_attr.value_type)
         entity_attr_tokens.append(ent_attr_name)
     return '.'.join(entity_attr_tokens)
Example #32
0
    def __setup_backref(self):
        if not self.backref is None:
            # We require the backref to be a resource attribute of the target.
            attr_mb_class = get_member_class(self.attr_type)
            backref_rc_descr = getattr(attr_mb_class, self.backref, None)
#            if backref_rc_descr is None:
#                raise ValueError('The "backref" attribute must be a '
#                                 'resource attribute declared on the '
#                                 'target of the descriptor.')
            if not backref_rc_descr is None:
                self.__resource_backref = self.backref
                self.__entity_backref = backref_rc_descr.entity_attr
            else:
                # FIXME: Falling back on the entity attribute here is fishy.
                self.__entity_backref = self.backref # pragma: no cover
        self.__need_backref_setup = False
Example #33
0
 def _traverse_member(self, attr_key, attr, member_node, parent_data,
                      visitor, index=None):
     member_data = OrderedDict()
     is_link_node = \
         self._is_link_node(member_node, attr) \
         or (not index is None and not attr is None and
             attr.options.get(WRITE_MEMBERS_AS_LINK_OPTION) is True)
     # Ignore links for traversal.
     if not is_link_node:
         if not attr is None:
             node_type = get_member_class(attr.value_type)
         else:
             node_type = self._get_node_type(member_node)
         for mb_attr in self._mapping.attribute_iterator(node_type,
                                                         attr_key):
             ignore_opt = self.__check_attribute_ignore \
                          and mb_attr.should_ignore(attr_key)
             if ignore_opt:
                 continue
             if mb_attr.kind == RESOURCE_ATTRIBUTE_KINDS.TERMINAL:
                 # Terminal attribute - extract.
                 value = self._get_node_terminal(member_node, mb_attr)
                 if value is None and self.__ignore_none_values:
                     # We ignore None attribute values when reading
                     # representations.
                     continue
                 member_data[mb_attr] = value
             else:
                 # Nested attribute - traverse.
                 nested_node = self._get_node_nested(member_node,
                                                     mb_attr)
                 if nested_node is None:
                     # Stop condition - the given data element does not
                     # contain a nested attribute of the given mapped
                     # name.
                     continue
                 nested_attr_key = attr_key + (mb_attr,)
                 if ignore_opt is False:
                     # The offset in the attribute key ensures that
                     # the defaults for ignoring attributes of the
                     # nested attribute can be retrieved correctly.
                     nested_attr_key.offset = len(nested_attr_key)
                 self._dispatch(nested_attr_key, mb_attr, nested_node,
                                member_data, visitor)
     visitor.visit_member(attr_key, attr, member_node, member_data,
                          is_link_node, parent_data, index=index)
Example #34
0
 def test_filter_specification_visitor(self):
     coll = get_root_collection(IMyEntity)
     mb_cls = get_member_class(coll)
     my_entity = create_entity()
     member = coll.create_member(my_entity)
     spec_fac = FilterSpecificationFactory()
     specs = [
         # Terminal access.
         spec_fac.create_equal_to('text', self.TEST_TEXT),
         # Terminal access with different name in entity.
         spec_fac.create_equal_to('text_rc', self.TEST_TEXT),
         # Nested member access with different name in entity.
         spec_fac.create_equal_to('parent.text_rc', self.TEST_TEXT),
         # Nested collection access with different name in entity.
         spec_fac.create_equal_to('children.text_rc', self.TEST_TEXT),
         # Access with dotted entity name in rc attr declaration.
         spec_fac.create_equal_to('parent_text', self.TEST_TEXT),
         # Access to member.
         spec_fac.create_equal_to('parent', member.parent.get_entity()),
     ]
     expecteds = [
         ('text', MyEntity.text.__eq__(self.TEST_TEXT)),
         ('text_ent', MyEntity.text_ent.__eq__(self.TEST_TEXT)),
         ('parent.text_ent',
          MyEntity.parent.has(MyEntityParent.text_ent.__eq__(
              self.TEST_TEXT))),
         ('children.text_ent',
          MyEntity.children.any(
              MyEntityChild.text_ent.__eq__(self.TEST_TEXT))),
         ('parent.text_ent',
          MyEntity.parent.has(MyEntityParent.text_ent.__eq__(
              self.TEST_TEXT))),
         ('parent', MyEntity.parent.__eq__(member.parent.get_entity())),
     ]
     for spec, expected in zip(specs, expecteds):
         new_attr_name, expr = expected
         visitor = ResourceToEntityFilterSpecificationVisitor(mb_cls)
         spec.accept(visitor)
         new_spec = visitor.expression
         self.assert_equal(new_spec.attr_name, new_attr_name)
         visitor = SqlFilterSpecificationVisitor(MyEntity)
         new_spec.accept(visitor)
         self.assert_equal(str(visitor.expression), str(expr))
     invalid_spec = spec_fac.create_equal_to('foo', self.TEST_TEXT)
     vst = ResourceToEntityFilterSpecificationVisitor(mb_cls)
     self.assert_raises(AttributeError, invalid_spec.accept, vst)
Example #35
0
 def __dump_entities(self, entity_class):
     cache = self._get_cache(entity_class)
     coll_cls = get_collection_class(entity_class)
     mb_cls = get_member_class(entity_class)
     fn = get_write_collection_path(coll_cls,
                                    self._config['content_type'],
                                    directory=self._config['directory'])
     # Wrap the entities in a temporary collection.
     coll = create_staging_collection(coll_cls)
     for ent in cache.iterator():
         coll.add(mb_cls.create_from_entity(ent))
     # Open stream for writing and dump the collection.
     stream = file(fn, 'w')
     with stream:
         dump_resource(coll,
                       stream,
                       content_type=self._config['content_type'])
Example #36
0
 def visit(mb_cls, grph, path, incl_backrefs):
     for attr_name in get_resource_class_attribute_names(mb_cls):
         if is_resource_class_terminal_attribute(mb_cls, attr_name):
             continue
         child_descr = getattr(mb_cls, attr_name)
         child_mb_cls = get_member_class(child_descr.attr_type)
         # We do not follow cyclic references back to a resource class
         # that is last in the path.
         if len(path) > 0 and child_mb_cls is path[-1] \
            and not incl_backrefs:
             continue
         if not grph.has_node(child_mb_cls):
             grph.add_node(child_mb_cls)
             path.append(mb_cls)
             visit(child_mb_cls, grph, path, incl_backrefs)
             path.pop()
         if not grph.has_edge((mb_cls, child_mb_cls)):
             grph.add_edge((mb_cls, child_mb_cls))
Example #37
0
 def visit(mb_cls, grph, path, incl_backrefs):
     for attr_name in mb_cls.get_attribute_names():
         if mb_cls.is_terminal(attr_name):
             continue
         child_descr = getattr(mb_cls, attr_name)
         child_mb_cls = get_member_class(child_descr.attr_type)
         # We do not follow cyclic references back to a resource class
         # that is last in the path.
         if len(path) > 0 and child_mb_cls is path[-1] \
            and not incl_backrefs:
             continue
         if not grph.has_node(child_mb_cls):
             grph.add_node(child_mb_cls)
             path.append(mb_cls)
             visit(child_mb_cls, grph, path, incl_backrefs)
             path.pop()
         if not grph.has_edge((mb_cls, child_mb_cls)):
             grph.add_edge((mb_cls, child_mb_cls))
Example #38
0
 def entity_backref(self):
     if self.__entity_backref is None:
         if self.resource_backref is None:
             self.__entity_backref = None
         else:
             attr_mb_class = get_member_class(self.attr_type)
             backref_rc_descr = getattr(attr_mb_class, self.resource_backref, None)
             #                # We require the backref to be a resource attribute of the
             #                # target.
             #                if backref_rc_descr is None:
             #                    raise ValueError('The "backref" attribute must be a '
             #                                     'resource attribute declared on the '
             #                                     'target of the descriptor.')
             if not backref_rc_descr is None:
                 self.__entity_backref = backref_rc_descr.entity_attr
             else:
                 self.__entity_backref = self.resource_backref
     return self.__entity_backref
Example #39
0
def find_connected_resources(resource, dependency_graph=None):
    """
    Collects all resources connected to the given resource and returns a
    dictionary mapping member resource classes to new collections containing
    the members found.
    """
    # Build a resource_graph.
    resource_graph = \
                build_resource_graph(resource,
                                     dependency_graph=dependency_graph)
    entity_map = OrderedDict()
    for mb in topological_sorting(resource_graph):
        mb_cls = get_member_class(mb)
        ents = entity_map.get(mb_cls)
        if ents is None:
            ents = []
            entity_map[mb_cls] = ents
        ents.append(mb.get_entity())
    return entity_map
Example #40
0
File: base.py Project: b8va/everest
 def __convert_to_entity_attr(self, rc_attr_name):
     entity_attr_tokens = []
     rc_class = self.__rc_class
     for rc_attr_token in rc_attr_name.split('.'):
         rc_attr = get_resource_class_attribute(rc_class, rc_attr_token)
         if rc_attr is None:
             raise ValueError('%s resource does not have an attribute '
                              '"%s".' % (rc_class.__name__, rc_attr_name))
         ent_attr_name = rc_attr.entity_attr
         if ent_attr_name is None:
             raise ValueError('Resource attribute "%s" does not have a '
                              'corresponding entity attribute.'
                              % rc_attr.resource_attr)
         if rc_attr.kind != RESOURCE_ATTRIBUTE_KINDS.TERMINAL:
             # Look up the member class for the specified member or
             # collection resource interface.
             rc_class = get_member_class(rc_attr.attr_type)
         entity_attr_tokens.append(ent_attr_name)
     return '.'.join(entity_attr_tokens)
Example #41
0
 def entity_backref(self):
     if self.__entity_backref is None:
         if self.resource_backref is None:
             self.__entity_backref = None
         else:
             attr_mb_class = get_member_class(self.attr_type)
             backref_rc_descr = getattr(attr_mb_class,
                                        self.resource_backref, None)
             #                # We require the backref to be a resource attribute of the
             #                # target.
             #                if backref_rc_descr is None:
             #                    raise ValueError('The "backref" attribute must be a '
             #                                     'resource attribute declared on the '
             #                                     'target of the descriptor.')
             if not backref_rc_descr is None:
                 self.__entity_backref = backref_rc_descr.entity_attr
             else:
                 self.__entity_backref = self.resource_backref
     return self.__entity_backref
Example #42
0
def find_connected_resources(resource, dependency_graph=None):
    """
    Collects all resources connected to the given resource and returns a
    dictionary mapping member resource classes to new collections containing
    the members found.
    """
    # Build a resource_graph.
    resource_graph = \
                build_resource_graph(resource,
                                     dependency_graph=dependency_graph)
    entity_map = OrderedDict()
    for mb in topological_sorting(resource_graph):
        mb_cls = get_member_class(mb)
        ents = entity_map.get(mb_cls)
        if ents is None:
            ents = []
            entity_map[mb_cls] = ents
        ents.append(mb.get_entity())
    return entity_map
Example #43
0
 def __convert_to_entity_attr(self, rc_attr_name):
     entity_attr_tokens = []
     rc_class = self.__rc_class
     for rc_attr_token in rc_attr_name.split('.'):
         rc_attr = get_resource_class_attribute(rc_class, rc_attr_token)
         if rc_attr is None:
             raise AttributeError('%s resource does not have an attribute '
                                  '"%s".' %
                                  (rc_class.__name__, rc_attr_name))
         ent_attr_name = rc_attr.entity_attr
         if ent_attr_name is None:
             raise ValueError('Resource attribute "%s" does not have a '
                              'corresponding entity attribute.' %
                              rc_attr.resource_attr)
         if rc_attr.kind != RESOURCE_ATTRIBUTE_KINDS.TERMINAL:
             # Look up the member class for the specified member or
             # collection resource interface.
             rc_class = get_member_class(rc_attr.attr_type)
         entity_attr_tokens.append(ent_attr_name)
     return '.'.join(entity_attr_tokens)
Example #44
0
def build_resource_dependency_graph(resource_classes,
                                    include_backrefs=False):
    """
    Builds a graph of dependencies among the given resource classes.

    The dependency graph is a directed graph with member resource classes as 
    nodes. An edge between two nodes represents a member or collection
    attribute.
    
    :param resource_classes: resource classes to determine interdependencies
      of.
    :type resource_classes: sequence of registered resources.
    :param bool include_backrefs: flag indicating if dependencies
      introduced by back-references (e.g., a child resource referencing its
      parent) should be included in the dependency graph.
    """
    def visit(mb_cls, grph, path, incl_backrefs):
        for attr_name in mb_cls.get_attribute_names():
            if mb_cls.is_terminal(attr_name):
                continue
            child_descr = getattr(mb_cls, attr_name)
            child_mb_cls = get_member_class(child_descr.attr_type)
            # We do not follow cyclic references back to a resource class
            # that is last in the path.
            if len(path) > 0 and child_mb_cls is path[-1] \
               and not incl_backrefs:
                continue
            if not grph.has_node(child_mb_cls):
                grph.add_node(child_mb_cls)
                path.append(mb_cls)
                visit(child_mb_cls, grph, path, incl_backrefs)
                path.pop()
            if not grph.has_edge((mb_cls, child_mb_cls)):
                grph.add_edge((mb_cls, child_mb_cls))
    dep_grph = digraph()
    for resource_class in resource_classes:
        mb_cls = get_member_class(resource_class)
        if not dep_grph.has_node(mb_cls):
            dep_grph.add_node(mb_cls)
            visit(mb_cls, dep_grph, [], include_backrefs)
    return dep_grph
Example #45
0
def build_resource_dependency_graph(resource_classes, include_backrefs=False):
    """
    Builds a graph of dependencies among the given resource classes.

    The dependency graph is a directed graph with member resource classes as
    nodes. An edge between two nodes represents a member or collection
    attribute.

    :param resource_classes: resource classes to determine interdependencies
      of.
    :type resource_classes: sequence of registered resources.
    :param bool include_backrefs: flag indicating if dependencies
      introduced by back-references (e.g., a child resource referencing its
      parent) should be included in the dependency graph.
    """
    def visit(mb_cls, grph, path, incl_backrefs):
        for attr_name in get_resource_class_attribute_names(mb_cls):
            if is_resource_class_terminal_attribute(mb_cls, attr_name):
                continue
            child_descr = getattr(mb_cls, attr_name)
            child_mb_cls = get_member_class(child_descr.attr_type)
            # We do not follow cyclic references back to a resource class
            # that is last in the path.
            if len(path) > 0 and child_mb_cls is path[-1] \
               and not incl_backrefs:
                continue
            if not grph.has_node(child_mb_cls):
                grph.add_node(child_mb_cls)
                path.append(mb_cls)
                visit(child_mb_cls, grph, path, incl_backrefs)
                path.pop()
            if not grph.has_edge((mb_cls, child_mb_cls)):
                grph.add_edge((mb_cls, child_mb_cls))

    dep_grph = digraph()
    for resource_class in resource_classes:
        mb_cls = get_member_class(resource_class)
        if not dep_grph.has_node(mb_cls):
            dep_grph.add_node(mb_cls)
            visit(mb_cls, dep_grph, [], include_backrefs)
    return dep_grph
Example #46
0
def find_connected_resources(resource, dependency_graph=None):
    """
    Collects all resources connected to the given resource and returns a 
    dictionary mapping member resource classes to new collections containing
    the members found.
    """
    # Build a resource_graph.
    resource_graph = \
                build_resource_graph(resource,
                                     dependency_graph=dependency_graph)
    # Build an ordered dictionary of collections.
    collections = OrderedDict()
    for mb in topological_sorting(resource_graph):
        mb_cls = get_member_class(mb)
        coll = collections.get(mb_cls)
        if coll is None:
            # Create new collection.
            coll = create_staging_collection(mb)
            collections[mb_cls] = coll
        coll.add(mb)
    return collections
Example #47
0
def find_connected_resources(resource, dependency_graph=None):
    """
    Collects all resources connected to the given resource and returns a 
    dictionary mapping member resource classes to new collections containing
    the members found.
    """
    # Build a resource_graph.
    resource_graph = \
                build_resource_graph(resource,
                                     dependency_graph=dependency_graph)
    # Build an ordered dictionary of collections.
    collections = OrderedDict()
    for mb in topological_sorting(resource_graph):
        mb_cls = get_member_class(mb)
        coll = collections.get(mb_cls)
        if coll is None:
            # Create new collection.
            coll = create_staging_collection(mb)
            collections[mb_cls] = coll
        coll.add(mb)
    return collections
Example #48
0
 def __get_q_tag(self, attr):
     if not attr.namespace is None:
         q_tag = '{%s}%s' % (attr.namespace, attr.repr_name)
     else:
         if attr.kind == ResourceAttributeKinds.TERMINAL:
             xml_ns = \
               self.mapping.configuration.get_option(XML_NAMESPACE_OPTION)
         else:
             if attr.kind == ResourceAttributeKinds.MEMBER:
                 attr_type = get_member_class(attr.value_type)
             elif attr.kind == ResourceAttributeKinds.COLLECTION:
                 attr_type = get_collection_class(attr.value_type)
             mp = self.mapping.mapping_registry.find_mapping(attr_type)
             if not mp is None:
                 xml_ns = mp.configuration.get_option(XML_NAMESPACE_OPTION)
             else:
                 # Not mapped.
                 xml_ns = None
         if not xml_ns is None:
             q_tag = '{%s}%s' % (xml_ns, attr.repr_name)
         else:
             q_tag = attr.repr_name
     return q_tag
Example #49
0
 def visit(rc, grph, dep_grph):
     mb_cls = type(rc)
     attr_map = mb_cls.get_attributes()
     for attr_name, attr in attr_map.iteritems():
         if mb_cls.is_terminal(attr_name):
             continue
         # Only follow the resource attribute if the dependency graph
         # has an edge here.
         child_mb_cls = get_member_class(attr.value_type)
         if not dep_grph.has_edge((mb_cls, child_mb_cls)):
             continue
         child_rc = getattr(rc, attr_name)
         if mb_cls.is_collection(attr_name):
             for child_mb in child_rc:
                 if not grph.has_node(child_mb): # Ignore cyclic references.
                     grph.add_node(child_mb)
                     grph.add_edge((rc, child_mb))
                     visit(child_mb, grph, dep_grph)
         else: # Member.
             if not grph.has_node(child_rc): # Ignore cyclic references.
                 grph.add_node(child_rc)
                 grph.add_edge((rc, child_rc))
                 visit(child_rc, grph, dep_grph)
Example #50
0
 def visit(rc, grph, dep_grph):
     mb_cls = type(rc)
     attr_map = get_resource_class_attributes(mb_cls)
     for attr_name, attr in iteritems_(attr_map):
         if is_resource_class_terminal_attribute(mb_cls, attr_name):
             continue
         # Only follow the resource attribute if the dependency graph
         # has an edge here.
         child_mb_cls = get_member_class(attr.attr_type)
         if not dep_grph.has_edge((mb_cls, child_mb_cls)):
             continue
         child_rc = getattr(rc, attr_name)
         if is_resource_class_collection_attribute(mb_cls, attr_name):
             for child_mb in child_rc:
                 if not grph.has_node(
                         child_mb):  # Ignore cyclic references.
                     grph.add_node(child_mb)
                     grph.add_edge((rc, child_mb))
                     visit(child_mb, grph, dep_grph)
         else:  # Member.
             if not grph.has_node(child_rc):  # Ignore cyclic references.
                 grph.add_node(child_rc)
                 grph.add_edge((rc, child_rc))
                 visit(child_rc, grph, dep_grph)
Example #51
0
 def _create_member_data_element(self, attribute, member_node):
     if not attribute is None:
         mb_cls = get_member_class(attribute.value_type)
     else:
         mb_cls = get_member_class(self._mapping.mapped_class)
     return self._mapping.create_data_element(mapped_class=mb_cls)
Example #52
0
def get_collection_name(rc_class):
    coll_cls = get_member_class(rc_class)
    collection_name = coll_cls.relation.split('/')[-1]
    return "%s-collection" % collection_name
Example #53
0
 def create_from_resource_class(cls, resource_class):
     return cls(get_member_class(resource_class), cls.parser_factory)
Example #54
0
 def _create_member_data_element(self, attribute, member_node):
     if not attribute is None:
         mb_cls = get_member_class(attribute.value_type)
     else:
         mb_cls = get_member_class(self._mapping.mapped_class)
     return self._mapping.create_data_element(mapped_class=mb_cls)
Example #55
0
def get_collection_name(rc_class):
    coll_cls = get_member_class(rc_class)
    collection_name = coll_cls.relation.split('/')[-1]
    return "%s-collection" % collection_name
Example #56
0
 def __process_attr(self, attribute, attribute_key, data_el, row_data):
     try:
         attribute_value = row_data.pop(attribute.repr_name)
     except KeyError:
         attribute_value = None
         has_attribute = False
     else:
         has_attribute = True
     # In the first row, we check for extra field names by removing all
     # fields we found from the set of all field names.
     if self.__is_first_row:
         self.__first_row_field_names.discard(attribute.repr_name)
     if attribute.should_ignore(attribute_key):
         if not attribute_value in (None, ''):
             raise ValueError('Value for attribute "%s" found '
                              'which is configured to be ignored.' %
                              attribute.repr_name)
     else:
         if attribute.kind == RESOURCE_ATTRIBUTE_KINDS.TERMINAL:
             if not attribute_value is None:
                 data_el.set_terminal_converted(attribute, attribute_value)
         else:
             # FIXME: It is peculiar to treat the empty string as None
             #        here. However, this seems to be the way the csv
             #        module does it.
             if not attribute_value in (None, ''):
                 link_data_el = \
                         self.__process_link(attribute_value, attribute)
                 data_el.set_nested(attribute, link_data_el)
             elif not has_attribute and len(row_data) > 0:
                 nested_attr_key = attribute_key + (attribute, )
                 # We recursively look for nested resource attributes in
                 # other fields.
                 if attribute.kind == RESOURCE_ATTRIBUTE_KINDS.MEMBER:
                     # For polymorphic classes, this lookup will only work
                     # if a representer (and a mapping) was initialized
                     # for each derived class.
                     nested_rc_cls = get_member_class(attribute.value_type)
                 else:  # collection attribute.
                     nested_rc_cls = \
                                 get_collection_class(attribute.value_type)
                     if self.__coll_data is None:
                         self.__coll_data = \
                             self.__make_collection_data(nested_rc_cls,
                                                         nested_attr_key)
                         if self.__is_first_row:
                             self.__row_data_key = \
                                 self.__coll_data.make_key(
                                                     self.__first_row_data)
                     elif self.__coll_data.collection_class \
                                                      != nested_rc_cls:
                         raise ValueError('All but one nested collection '
                                          'resource attributes have to '
                                          'be provided as links.')
                 nested_data_el = \
                     self.__process_row(row_data, nested_rc_cls,
                                        nested_attr_key)
                 if attribute.kind == RESOURCE_ATTRIBUTE_KINDS.MEMBER:
                     if len(nested_data_el.data) > 0:
                         data_el.set_nested(attribute, nested_data_el)
                 elif len(nested_data_el) > 0:
                     data_el.set_nested(attribute, nested_data_el)
Example #57
0
 def __get_member_mapping_and_representer(self):
     rc_type = get_member_class(IMyEntity)
     return self.__get_mapping_and_representer(rc_type)