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