Skip to content

Commit

Permalink
Implement and document ListProperty and DictProperty (#67)
Browse files Browse the repository at this point in the history
  • Loading branch information
jtv8 committed Mar 12, 2021
1 parent 10aecec commit 42e1951
Show file tree
Hide file tree
Showing 7 changed files with 174 additions and 6 deletions.
16 changes: 15 additions & 1 deletion docs/source/user_docs.rst
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ of :class:`~wysdom.UserProperty`, or an instance of :class:`~wysdom.Schema`::
class Person(UserObject, additional_properties=Address):
...

class Person(UserObject, additional_properties=SchemaDict[Vehicle]):
class Person(UserObject, additional_properties=SchemaDict(Vehicle)):
...


Expand Down Expand Up @@ -183,12 +183,26 @@ function identically to a Python list (specifically a

related_people = UserProperty(SchemaArray(Person))


From 0.3.0, you can use the data descriptor :class:`wysdom.ListProperty`
to aid readability by equivalently writing::

related_people = ListProperty(Person)


For an dictionary, use the :class:`wysdom.SchemaDict`. Properties of this type
function identically to a Python dict (specifically a
:class:`collections.abc.MutableMapping` with keys of type :class:`str`)::

related_people = UserProperty(SchemaDict(Person))


From 0.3.0, you can use the data descriptor :class:`wysdom.DictProperty`
to aid readability by equivalently writing::

related_people = DictProperty(Person)


A `SchemaDict` is a special case of a :class:`wysdom.SchemaObject` with
no named properties and with additional_properties set to the type
specification that you supply.
Expand Down
16 changes: 16 additions & 0 deletions docs/source/wysdom.user_objects.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,19 @@ UserProperty
:members:
:undoc-members:
:show-inheritance:

ListProperty
----------------------------------------

.. autoclass:: wysdom.ListProperty
:members:
:undoc-members:
:show-inheritance:

DictProperty
----------------------------------------

.. autoclass:: wysdom.DictProperty
:members:
:undoc-members:
:show-inheritance:
9 changes: 5 additions & 4 deletions features/examples/modules/dict_module.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from typing import Dict, List
from enum import Enum

from wysdom import UserObject, UserProperty, SchemaArray, SchemaDict, key
from wysdom import UserObject, UserProperty, ListProperty, DictProperty, key


class Color(Enum):
Expand Down Expand Up @@ -31,8 +31,9 @@ class Person(UserObject):
current_address: Address = UserProperty(
Address,
default_function=lambda person: person.previous_addresses[0])
previous_addresses: List[Address] = UserProperty(SchemaArray(Address))
vehicles: Dict[str, Vehicle] = UserProperty(
SchemaDict(Vehicle, key_pattern=r"^[a-f0-9]{6}$"),
previous_addresses: List[Address] = ListProperty(Address)
vehicles: Dict[str, Vehicle] = DictProperty(
Vehicle,
key_pattern=r"^[a-f0-9]{6}$",
default={},
persist_defaults=True)
2 changes: 1 addition & 1 deletion wysdom/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@
from . import dom
from .base_schema import Schema, SchemaType, SchemaNone, SchemaPrimitive, SchemaAnything, SchemaConst
from .object_schema import SchemaArray, SchemaDict, SchemaAnyOf, SchemaObject
from .user_objects import UserProperty, UserObject, properties
from .user_objects import UserObject, UserProperty, ListProperty, DictProperty, properties
from .mixins import ReadsJSON, ReadsYAML, RegistersSubclasses

69 changes: 69 additions & 0 deletions wysdom/user_objects/DictProperty.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
from typing import Type, Any, Union, Optional, Callable

from ..base_schema import Schema
from ..object_schema import SchemaDict

from .UserProperty import UserProperty


class DictProperty(UserProperty):
"""
A data descriptor for creating attributes in user-defined subclasses
of :class:`~.wysdom.user_objects.UserObject` with a property_type
of :class:`~.wysdom.object_schema.SchemaDict`.
:param items: The permitted data type or schema for the properties of the underlying
:class:`~.wysdom.object_schema.SchemaDict`. Must be one of:
A primitive Python type (str, int, bool, float)
A subclass of :class:`~.wysdom.user_objects.UserObject`.
An instance of :class:`~.wysdom.base_schema.Schema`.
:param optional: Determines whether this property is optional in the underlying
data object. If default or default_function are set, this
will default to True, otherwise False.
:param name: The name of this property in the underlying
data object. If not provided, this defaults to
the name of the attribute on the :class:`~.wysdom.user_objects.UserObject`
instance that owns the property.
:param default: A static value which provides a default value
for this property. Cannot be set in conjunction
with `default_function`.
:param default_function: A function which provides a default value
for this property. The function must have a
single positional argument, `self`, which is
passed the :class:`~.wysdom.user_objects.UserObject` instance that
owns the property. Cannot be set in conjunction
with `default`.
:param persist_defaults: If this property is set to True and a UserProperty has either the
`default` or `default_function` property, when the UserProperty returns
a default value that value will also be explicitly stored in the underlying
data object. This is often desirable behavior if the UserProperty
returns another object and your code expects it to return the same
object instance each time it is accessed.
:param key_pattern: A regex pattern to validate the keys of the dictionary against.
"""

def __init__(
self,
items: Union[Type, Schema],
optional: Optional[bool] = None,
name: Optional[str] = None,
default: Optional[Any] = None,
default_function: Optional[Callable] = None,
persist_defaults: Optional[bool] = None,
key_pattern: Optional[str] = None
) -> None:
super().__init__(
property_type=SchemaDict(items, key_pattern=key_pattern),
optional=optional,
name=name,
default=default,
default_function=default_function,
persist_defaults=persist_defaults
)
66 changes: 66 additions & 0 deletions wysdom/user_objects/ListProperty.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
from typing import Type, Any, Union, Optional, Callable

from ..base_schema import Schema
from ..object_schema import SchemaArray

from .UserProperty import UserProperty


class ListProperty(UserProperty):
"""
A data descriptor for creating attributes in user-defined subclasses
of :class:`~.wysdom.user_objects.UserObject` with a property_type
of :class:`~.wysdom.object_schema.SchemaArray`.
:param items: The permitted data type or schema for the items of the underlying
:class:`~.wysdom.object_schema.SchemaArray`. Must be one of:
A primitive Python type (str, int, bool, float)
A subclass of :class:`~.wysdom.user_objects.UserObject`.
An instance of :class:`~.wysdom.base_schema.Schema`.
:param optional: Determines whether this property is optional in the underlying
data object. If default or default_function are set, this
will default to True, otherwise False.
:param name: The name of this property in the underlying
data object. If not provided, this defaults to
the name of the attribute on the :class:`~.wysdom.user_objects.UserObject`
instance that owns the property.
:param default: A static value which provides a default value
for this property. Cannot be set in conjunction
with `default_function`.
:param default_function: A function which provides a default value
for this property. The function must have a
single positional argument, `self`, which is
passed the :class:`~.wysdom.user_objects.UserObject` instance that
owns the property. Cannot be set in conjunction
with `default`.
:param persist_defaults: If this property is set to True and a UserProperty has either the
`default` or `default_function` property, when the UserProperty returns
a default value that value will also be explicitly stored in the underlying
data object. This is often desirable behavior if the UserProperty
returns another object and your code expects it to return the same
object instance each time it is accessed.
"""

def __init__(
self,
items: Union[Type, Schema],
optional: Optional[bool] = None,
name: Optional[str] = None,
default: Optional[Any] = None,
default_function: Optional[Callable] = None,
persist_defaults: Optional[bool] = None
) -> None:
super().__init__(
property_type=SchemaArray(items),
optional=optional,
name=name,
default=default,
default_function=default_function,
persist_defaults=persist_defaults
)
2 changes: 2 additions & 0 deletions wysdom/user_objects/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from .UserObject import UserObject, UserProperties
from .UserProperty import UserProperty
from .ListProperty import ListProperty
from .DictProperty import DictProperty
from .functions import properties

0 comments on commit 42e1951

Please sign in to comment.