Exemple #1
0
    def test_process_bind_param_with_mutationlist(self):
        from kotti.sqla import MutationList

        value = self.make().process_bind_param(
            MutationList([{'foo': 'bar'}]), None)

        assert value == '[{"foo": "bar"}]'
Exemple #2
0
class Principal(Base):
    """A minimal 'Principal' implementation.

    The attributes on this object correspond to what one ought to
    implement to get full support by the system.  You're free to add
    additional attributes.

      - As convenience, when passing 'password' in the initializer, it
        is hashed using 'get_principals().hash_password'

      - The boolean 'active' attribute defines whether a principal may
        log in.  This allows the deactivation of accounts without
        deleting them.

      - The 'confirm_token' attribute is set whenever a user has
        forgotten their password.  This token is used to identify the
        receiver of the email.  This attribute should be set to
        'None' once confirmation has succeeded.
    """

    id = Column(Integer, primary_key=True)
    name = Column(Unicode(100), unique=True)
    password = Column(Unicode(100))
    active = Column(Boolean)
    confirm_token = Column(Unicode(100))
    title = Column(Unicode(100), nullable=False)
    email = Column(Unicode(100), unique=True)
    groups = Column(MutationList.as_mutable(JsonType), nullable=False)
    creation_date = Column(DateTime(), nullable=False)
    last_login_date = Column(DateTime())

    __tablename__ = "principals"
    # __mapper_args__ = dict(order_by=name)

    def __init__(
        self,
        name: str,
        password: Optional[str] = None,
        active: Optional[bool] = True,
        confirm_token: Optional[str] = None,
        title: Optional[str] = "",
        email: Optional[str] = None,
        groups: Optional[List[str]] = None,
    ):
        self.name = name
        if password is not None:
            password = get_principals().hash_password(password)
        self.password = password
        self.active = active
        self.confirm_token = confirm_token
        self.title = title
        self.email = email
        if groups is None:
            groups = []
        self.groups = groups
        self.creation_date = datetime.now()
        self.last_login_date = None

    def __repr__(self):  # pragma: no cover
        return f"<Principal {self.name!r}>"
Exemple #3
0
    def test_dunder_json_recursive(self):
        from kotti.sqla import MutationList
        from kotti.sqla import MutationDict

        mlist = MutationList([
            MutationDict({'foo': MutationList([{'bar': 'baz'}])}),
            {'foo': ['bar', 'baz']},
            ])

        json.loads(json.dumps(mlist.__json__())) == [
            {'foo': [{'bar': 'baz'}]},
            {'foo': ['bar', 'baz']},
            ]

        mdict = MutationDict({
            'foo': MutationList([{'bar': 'baz'}]),
            'bar': ['bar', 'baz'],
            })

        json.loads(json.dumps(mdict.__json__())) == {
            'foo': [{'bar': 'baz'}],
            'bar': ['bar', 'baz'],
            }
Exemple #4
0
    def test_dunder_json_recursive(self):
        from kotti.sqla import MutationList
        from kotti.sqla import MutationDict

        mlist = MutationList([
            MutationDict({'foo': MutationList([{'bar': 'baz'}])}),
            {'foo': ['bar', 'baz']},
            ])

        json.loads(json.dumps(mlist.__json__())) == [
            {'foo': [{'bar': 'baz'}]},
            {'foo': ['bar', 'baz']},
            ]

        mdict = MutationDict({
            'foo': MutationList([{'bar': 'baz'}]),
            'bar': ['bar', 'baz'],
            })

        json.loads(json.dumps(mdict.__json__())) == {
            'foo': [{'bar': 'baz'}],
            'bar': ['bar', 'baz'],
            }
Exemple #5
0
    def test_dunder_json_recursive(self):
        from kotti.sqla import MutationList
        from kotti.sqla import MutationDict

        mlist = MutationList([
            MutationDict({"foo": MutationList([{
                "bar": "baz"
            }])}),
            {
                "foo": ["bar", "baz"]
            },
        ])

        json.loads(json.dumps(mlist.__json__())) == [
            {
                "foo": [{
                    "bar": "baz"
                }]
            },
            {
                "foo": ["bar", "baz"]
            },
        ]

        mdict = MutationDict({
            "foo": MutationList([{
                "bar": "baz"
            }]),
            "bar": ["bar", "baz"]
        })

        json.loads(json.dumps(mdict.__json__())) == {
            "foo": [{
                "bar": "baz"
            }],
            "bar": ["bar", "baz"],
        }
Exemple #6
0
    def test_dunder_json_recursive(self):
        from kotti.sqla import MutationList
        from kotti.sqla import MutationDict

        mlist = MutationList(
            [
                MutationDict({"foo": MutationList([{"bar": "baz"}])}),
                {"foo": ["bar", "baz"]},
            ]
        )

        json.loads(json.dumps(mlist.__json__())) == [
            {"foo": [{"bar": "baz"}]},
            {"foo": ["bar", "baz"]},
        ]

        mdict = MutationDict(
            {"foo": MutationList([{"bar": "baz"}]), "bar": ["bar", "baz"]}
        )

        json.loads(json.dumps(mdict.__json__())) == {
            "foo": [{"bar": "baz"}],
            "bar": ["bar", "baz"],
        }
Exemple #7
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
Exemple #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
Exemple #9
0
 def test_dunder_json(self):
     from kotti.sqla import MutationList
     mlist = MutationList(['foo'])
     json.loads(json.dumps(mlist.__json__())) == ['foo']
Exemple #10
0
 def test_radd(self):
     from kotti.sqla import MutationList
     mlist = MutationList(['foo'])
     assert ['bar'] + mlist == ['bar', 'foo']
Exemple #11
0
    def test_dunder_json(self):
        from kotti.sqla import MutationList

        mlist = MutationList(["foo"])
        json.loads(json.dumps(mlist.__json__())) == ["foo"]
Exemple #12
0
    def test_radd(self):
        from kotti.sqla import MutationList

        mlist = MutationList(["foo"])
        assert ["bar"] + mlist == ["bar", "foo"]
Exemple #13
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