Ejemplo n.º 1
0
    def test_dunder_json(self):
        from kotti.sqla import NestedMutationDict

        data = {"some": ["other", {"stuff": 1}]}
        mdict = NestedMutationDict(data)

        assert json.loads(json.dumps(mdict.__json__(None))) == data
Ejemplo n.º 2
0
    def test_dunder_json(self):
        from kotti.sqla import NestedMutationDict

        data = {"some": ["other", {"stuff": 1}]}
        mdict = NestedMutationDict(data)

        assert json.loads(json.dumps(mdict.__json__(None))) == data
Ejemplo n.º 3
0
    def test_dictwrapper_wraps(self):
        from kotti.sqla import NestedMutationDict
        from kotti.sqla import NestedMutationList

        wrapper = NestedMutationDict(
            {'name': 'andy', 'age': 77, 'children': []})
        changed = wrapper.changed = MagicMock()

        wrapper['name'] = 'randy'
        assert changed.call_count == 1

        assert isinstance(wrapper['children'], NestedMutationList)
        wrapper['children'].append({'name': 'sandy', 'age': 33})
        assert changed.call_count == 2
        assert len(wrapper['children']), 1
        assert isinstance(wrapper['children'][0], NestedMutationDict)
Ejemplo n.º 4
0
    def test_dictwrapper_wraps(self):
        from kotti.sqla import NestedMutationDict
        from kotti.sqla import NestedMutationList

        wrapper = NestedMutationDict({
            "name": "andy",
            "age": 77,
            "children": []
        })
        assert getattr(wrapper, "get", False) is not False
        changed = wrapper.changed = MagicMock()

        wrapper["name"] = "randy"
        assert changed.call_count == 1

        assert isinstance(wrapper["children"], NestedMutationList)
        wrapper["children"].append({"name": "sandy", "age": 33})
        assert changed.call_count == 2
        assert len(wrapper["children"]), 1
        assert isinstance(wrapper["children"][0], NestedMutationDict)
Ejemplo n.º 5
0
    def test_dictwrapper_changed(self):
        from kotti.sqla import NestedMutationDict

        data = {}
        wrapper = NestedMutationDict(data)
        changed = wrapper.changed = MagicMock()

        wrapper['name'] = 'andy'
        assert data == {'name': 'andy'}
        assert wrapper == {'name': 'andy'}
        assert wrapper['name'] == 'andy'
        assert changed.call_count == 1

        wrapper['age'] = 77
        assert data == {'name': 'andy', 'age': 77}
        assert wrapper['age'] == 77
        assert wrapper['name'] == 'andy'
        assert changed.call_count == 2

        wrapper['age'] += 1
        assert data == {'name': 'andy', 'age': 78}
        assert wrapper['age'] == 78
        assert changed.call_count == 3
Ejemplo n.º 6
0
    def test_dictwrapper_changed(self):
        from kotti.sqla import NestedMutationDict

        data = {}
        wrapper = NestedMutationDict(data)
        changed = wrapper.changed = MagicMock()

        wrapper["name"] = "andy"
        assert data == {"name": "andy"}
        assert wrapper == {"name": "andy"}
        assert wrapper["name"] == "andy"
        assert changed.call_count == 1

        wrapper["age"] = 77
        assert data == {"name": "andy", "age": 77}
        assert wrapper["age"] == 77
        assert wrapper["name"] == "andy"
        assert changed.call_count == 2

        wrapper["age"] += 1
        assert data == {"name": "andy", "age": 78}
        assert wrapper["age"] == 78
        assert changed.call_count == 3
Ejemplo n.º 7
0
 def test_setdefault_list(self):
     from kotti.sqla import NestedMutationDict
     from kotti.sqla import NestedMutationList
     mdict = NestedMutationDict({})
     assert isinstance(mdict.setdefault('bar', []), NestedMutationList)
Ejemplo n.º 8
0
class Node(Base, ContainerMixin, PersistentACLMixin, metaclass=NodeMeta):
    """Basic node in the persistance hierarchy.
    """

    __table_args__ = (UniqueConstraint("parent_id", "name"), )
    __mapper_args__ = dict(polymorphic_on="type",
                           polymorphic_identity="node",
                           with_polymorphic="*")

    #: Primary key for the node in the DB
    #: (:class:`sqlalchemy.types.Integer`)
    id = Column(Integer(), primary_key=True)
    #: Lowercase class name of the node instance
    #: (:class:`sqlalchemy.types.String`)
    type = Column(String(30), nullable=False)
    #: ID of the node's parent
    #: (:class:`sqlalchemy.types.Integer`)
    parent_id = Column(ForeignKey("nodes.id"), index=True)
    #: Position of the node within its container / parent
    #: (:class:`sqlalchemy.types.Integer`)
    position = Column(Integer())
    _acl = Column(MutationList.as_mutable(ACLType))
    #: Name of the node as used in the URL
    #: (:class:`sqlalchemy.types.Unicode`)
    name = Column(Unicode(250), nullable=False)
    #: Title of the node, e.g. as shown in search results
    #: (:class:`sqlalchemy.types.Unicode`)
    title = Column(Unicode(250))
    #: Annotations can be used to store arbitrary data in a nested dictionary
    #: (:class:`kotti.sqla.NestedMustationDict`)
    annotations = Column(NestedMutationDict.as_mutable(JsonType))
    #: The path can be used to efficiently filter for child objects
    #: (:class:`sqlalchemy.types.Unicode`).
    path = Column(Unicode(2000), index=True)

    parent = relation(
        "Node",
        remote_side=[id],
        backref=backref(
            "_children",
            collection_class=ordering_list("position", reorder_on_append=True),
            order_by=[position],
            cascade="all",
        ),
    )

    local_groups = relation(LocalGroup,
                            backref=backref("node"),
                            cascade="all",
                            lazy="joined")

    __hash__ = Base.__hash__

    def __init__(self,
                 name: str = None,
                 parent: "Node" = None,
                 title: str = "",
                 annotations: dict = None,
                 **kwargs):
        """Constructor"""

        super().__init__(**kwargs)

        if annotations is None:
            annotations = {}
        self.parent = parent
        self.name = name
        self.title = title
        self.annotations = annotations

    @property
    def __name__(self):
        return self.name

    @property
    def __parent__(self):
        return self.parent

    @__parent__.setter
    def __parent__(self, value):
        self.parent = value

    def __repr__(self) -> str:
        return "<{} {} at {}>".format(self.__class__.__name__, self.id,
                                      resource_path(self))

    def __eq__(self, other: Any) -> bool:
        return isinstance(other, Node) and self.id == other.id

    def __ne__(self, other: Any) -> bool:
        return not self == other

    copy_properties_blacklist = (
        "id",
        "parent",
        "parent_id",
        "_children",
        "local_groups",
        "_tags",
    )

    def clear(self) -> None:

        DBSession.query(Node).filter(Node.parent == self).delete()

    def copy(self, **kwargs) -> "Node":
        """
        :result: A copy of the current instance
        :rtype: :class:`~kotti.resources.Node`
        """

        children = list(self.children)
        copy = self.__class__()
        for prop in object_mapper(self).iterate_properties:
            if prop.key not in self.copy_properties_blacklist:
                setattr(copy, prop.key, getattr(self, prop.key))
        for key, value in kwargs.items():
            setattr(copy, key, value)
        for child in children:
            copy.children.append(child.copy())

        return copy
Ejemplo n.º 9
0
    def test_dictwrapper_comparison(self):
        from kotti.sqla import NestedMutationDict

        assert NestedMutationDict({}) == NestedMutationDict({})
        assert (NestedMutationDict({'a':
                                    'ok'}) == NestedMutationDict({'a': 'ok'}))
Ejemplo n.º 10
0
 def test_setdefault_parent(self):
     from kotti.sqla import NestedMutationDict
     mdict = NestedMutationDict({})
     assert mdict.setdefault('bar', []).__parent__ is mdict
Ejemplo n.º 11
0
 def test_setdefault_list(self):
     from kotti.sqla import NestedMutationDict
     from kotti.sqla import NestedMutationList
     mdict = NestedMutationDict({})
     assert isinstance(mdict.setdefault('bar', []), NestedMutationList)
Ejemplo n.º 12
0
class Node(Base, ContainerMixin, PersistentACLMixin):
    implements(INode)

    __table_args__ = (UniqueConstraint('parent_id', 'name'), )
    __mapper_args__ = dict(
        polymorphic_on='type',
        polymorphic_identity='node',
        with_polymorphic='*',
    )

    id = Column(Integer(), primary_key=True)
    type = Column(String(30), nullable=False)
    parent_id = Column(ForeignKey('nodes.id'))
    position = Column(Integer())
    _acl = Column(MutationList.as_mutable(ACLType))
    name = Column(Unicode(50), nullable=False)
    title = Column(Unicode(100))
    annotations = Column(NestedMutationDict.as_mutable(JsonType))

    _children = relation(
        'Node',
        collection_class=ordering_list('position'),
        order_by=[position],
        backref=backref('parent', remote_side=[id]),
        cascade='all',
    )

    local_groups = relation(
        LocalGroup,
        backref=backref('node'),
        cascade='all',
    )

    def __init__(self, name=None, parent=None, title=u"", annotations=None):
        if annotations is None:
            annotations = {}
        self.name = name
        self.parent = parent
        self.title = title
        self.annotations = annotations

    @property
    def __name__(self):
        return self.name

    @property
    def __parent__(self):
        return self.parent

    @__parent__.setter
    def __parent__(self, value):
        self.parent = value

    def __repr__(self):
        return '<%s %s at %s>' % (self.__class__.__name__, self.id,
                                  resource_path(self))

    def __eq__(self, other):
        return isinstance(other, Node) and self.id == other.id

    def __ne__(self, other):
        return not self == other

    copy_properties_blacklist = ('id', 'parent', 'parent_id', '_children',
                                 'local_groups', '_tags')

    def copy(self, **kwargs):
        children = list(self.children)
        copy = self.__class__()
        for prop in object_mapper(self).iterate_properties:
            if prop.key not in self.copy_properties_blacklist:
                setattr(copy, prop.key, getattr(self, prop.key))
        for key, value in kwargs.items():
            setattr(copy, key, value)
        for child in children:
            copy.children.append(child.copy())
        return copy
Ejemplo n.º 13
0
    def test_dictwrapper_comparison(self):
        from kotti.sqla import NestedMutationDict

        assert NestedMutationDict({}) == NestedMutationDict({})
        assert NestedMutationDict({"a":
                                   "ok"}) == NestedMutationDict({"a": "ok"})
Ejemplo n.º 14
0
    def test_setdefault_dict(self):
        from kotti.sqla import NestedMutationDict

        mdict = NestedMutationDict({})
        assert isinstance(mdict.setdefault("bar", {}), NestedMutationDict)
Ejemplo n.º 15
0
 def test_setdefault_parent(self):
     from kotti.sqla import NestedMutationDict
     mdict = NestedMutationDict({})
     assert mdict.setdefault('bar', []).__parent__ is mdict
Ejemplo n.º 16
0
class Node(Base, ContainerMixin, PersistentACLMixin):
    """Basic node in the persistance hierarchy.
    """

    __table_args__ = (UniqueConstraint('parent_id', 'name'), )
    __mapper_args__ = dict(
        polymorphic_on='type',
        polymorphic_identity='node',
        with_polymorphic='*',
    )

    #: Primary key for the node in the DB
    #: (:class:`sqlalchemy.types.Integer`)
    id = Column(Integer(), primary_key=True)
    #: Lowercase class name of the node instance
    #: (:class:`sqlalchemy.types.String`)
    type = Column(String(30), nullable=False)
    #: ID of the node's parent
    #: (:class:`sqlalchemy.types.Integer`)
    parent_id = Column(ForeignKey('nodes.id'), index=True)
    #: Position of the node within its container / parent
    #: (:class:`sqlalchemy.types.Integer`)
    position = Column(Integer())
    _acl = Column(MutationList.as_mutable(ACLType))
    #: Name of the node as used in the URL
    #: (:class:`sqlalchemy.types.Unicode`)
    name = Column(Unicode(250), nullable=False)
    #: Title of the node, e.g. as shown in search results
    #: (:class:`sqlalchemy.types.Unicode`)
    title = Column(Unicode(250))
    #: Annotations can be used to store arbitrary data in a nested dictionary
    #: (:class:`kotti.sqla.NestedMustationDict`)
    annotations = Column(NestedMutationDict.as_mutable(JsonType))
    #: The path can be used to efficiently filter for child objects
    #: (:class:`sqlalchemy.types.Unicode`).
    path = Column(Unicode(2000), index=True)

    parent = relation('Node',
                      remote_side=[id],
                      backref=backref(
                          '_children',
                          collection_class=ordering_list(
                              'position', reorder_on_append=True),
                          order_by=[position],
                          cascade='all',
                      ))

    local_groups = relation(
        LocalGroup,
        backref=backref('node'),
        cascade='all',
        lazy='joined',
    )

    def __init__(self,
                 name=None,
                 parent=None,
                 title=u"",
                 annotations=None,
                 **kwargs):
        """Constructor"""

        super(Node, self).__init__(**kwargs)

        if annotations is None:
            annotations = {}
        self.parent = parent
        self.name = name
        self.title = title
        self.annotations = annotations

    @property
    def __name__(self):
        return self.name

    @property
    def __parent__(self):
        return self.parent

    @__parent__.setter
    def __parent__(self, value):
        self.parent = value

    def __repr__(self):
        return u'<{0} {1} at {2}>'.format(self.__class__.__name__, self.id,
                                          resource_path(self))

    def __eq__(self, other):
        return isinstance(other, Node) and self.id == other.id

    def __ne__(self, other):
        return not self == other

    copy_properties_blacklist = ('id', 'parent', 'parent_id', '_children',
                                 'local_groups', '_tags')

    def copy(self, **kwargs):
        """
        :result: A copy of the current instance
        :rtype: :class:`~kotti.resources.Node`
        """

        children = list(self.children)
        copy = self.__class__()
        for prop in object_mapper(self).iterate_properties:
            if prop.key not in self.copy_properties_blacklist:
                setattr(copy, prop.key, getattr(self, prop.key))
        for key, value in kwargs.items():
            setattr(copy, key, value)
        for child in children:
            copy.children.append(child.copy())

        return copy
Ejemplo n.º 17
0
    def test_setdefault_dict(self):
        from kotti.sqla import NestedMutationDict

        mdict = NestedMutationDict({})
        assert isinstance(mdict.setdefault("bar", {}), NestedMutationDict)