コード例 #1
0
    def wrapper(cls: Type[T]) -> Table[T]:
        name = table_name or cls.__name__

        if cls.__bases__ == (object,):
            cls = dataclass(cls)

        cons: List[Union[Column, Index]] = list(args)
        if issubclass(cls, tuple):
            defaults = getattr(cls, "_field_defaults", {})
        else:
            defaults = {
                k: (NO_DEFAULT if a.default == NOTHING else a.default)
                for k, a in fields_dict(cls).items()
            }
        for key, value in get_type_hints(cls).items():
            cons.append(
                Column(
                    key,
                    ctype=value,
                    table_name=name,
                    default=defaults.get(key, NO_DEFAULT),
                )
            )

        return Table(name, cons=cons, source=cls)
コード例 #2
0
def dataclass(_cls: type = None,
              *,
              repr=True,
              eq=True,
              order=False,
              unsafe_hash=False,
              frozen=False) -> type:
    """
    This decorator does the same as attr.dataclass, but also applies :func:`add_schema`.
    It adds a `.Schema` attribute to the class object

    >>> @dataclass
    ... class Artist:
    ...    name: str
    >>> Artist.Schema
    <class 'marshmallow.schema.Artist'>

    >>> from marshmallow import Schema
    >>> @dataclass(order=True) # preserve field order
    ... class Point:
    ...   x:float
    ...   y:float
    ...   Schema: ClassVar[Type[Schema]] = Schema # For the type checker
    ...
    >>> Point.Schema(strict=True).load({'x':0, 'y':0}).data # This line can be statically type checked
    Point(x=0.0, y=0.0)
    """
    dc = attr.dataclass(_cls,
                        repr=repr,
                        eq=eq,
                        order=order,
                        unsafe_hash=unsafe_hash,
                        frozen=frozen)
    return add_schema(dc) if _cls else lambda cls: add_schema(dc(cls))
コード例 #3
0
def dataclass(
    _cls: type = None,
    *,
    these=None,
    repr_ns=None,
    repr=True,
    cmp=True,
    hash=None,
    init=True,
    slots=False,
    frozen=False,
    weakref_slot=True,
    str=False,
    kw_only=False,
    cache_hash=False,
    auto_exc=False,
) -> type:
    """
    This decorator does the same as attr.dataclass, but also applies :func:`add_schema`.
    It adds a `.Schema` attribute to the class object

    >>> @dataclass
    ... class Artist:
    ...    name: str
    >>> Artist.Schema
    <class 'marshmallow.schema.Artist'>

    >>> from marshmallow import Schema
    >>> @dataclass
    ... class Point:
    ...   x:float
    ...   y:float
    ...   Schema: ClassVar[Type[Schema]] = Schema # For the type checker
    ...
    >>> Point.Schema(strict=True).load({'x':0, 'y':0}).data # This line can be statically type checked
    Point(x=0.0, y=0.0)
    """
    dc = attr.dataclass(
        _cls,
        these=these,
        repr_ns=repr_ns,
        repr=repr,
        cmp=cmp,
        hash=hash,
        init=init,
        slots=slots,
        frozen=frozen,
        weakref_slot=weakref_slot,
        str=str,
        kw_only=kw_only,
        cache_hash=cache_hash,
        auto_exc=auto_exc,
    )
    return add_schema(dc) if _cls else lambda cls: add_schema(dc(cls))
コード例 #4
0
ファイル: _base.py プロジェクト: alanghartJC/reformat-gherkin
def prepare(cls=None, slots=True, frozen=True, cmp=False):
    """
    A common class decorator to decorate AST node classes. We can either use `@prepare`
    with default parameters, or `@prepare(...)` to override the default values of the
    parameters. By default, `cmp=False` makes the objects hashable, and the hash is an
    object's id. Therefore, every AST node is unique, even if they have identical
    attributes (think of two identical rows or steps at two different places in a
    document).
    """
    wrapper = dataclass(slots=slots, frozen=frozen, cmp=cmp)

    if cls is None:
        return wrapper

    return wrapper(cls)
コード例 #5
0
ファイル: config.py プロジェクト: franciscod/corrscope
    def __init_subclass__(cls,
                          kw_only: bool = False,
                          always_dump: str = "",
                          exclude: str = ""):
        _yaml_loadable(attr.dataclass(cls, kw_only=kw_only))

        # Merge always_dump with superclass's __always_dump.
        super_always_dump = cls.__always_dump
        super_exclude = cls.__exclude
        assert type(super_always_dump) == frozenset
        assert type(super_exclude) == frozenset

        cls.__always_dump = super_always_dump | frozenset(always_dump.split())
        cls.__exclude = super_exclude | frozenset(exclude.split())

        del super_always_dump, always_dump
        del super_exclude, exclude

        all_fields = {f.name for f in attr.fields(cls)}
        dump_fields = cls.__always_dump - {"*"}  # remove "*" if exists
        exclude_fields = cls.__exclude

        if "*" in cls.__always_dump:
            assert (
                not dump_fields
            ), f"Invalid always_dump, contains * and elements {dump_fields}"

            for exclude_field in exclude_fields:
                assert (
                    exclude_field in all_fields
                ), f'Invalid exclude, contains "{exclude_field}" missing from class {cls.__name__}'

        else:
            assert (not exclude_fields
                    ), f"Invalid exclude, always_dump does not contain *"

            for dump_field in dump_fields:
                assert (
                    dump_field in all_fields
                ), f'Invalid always_dump, contains "{dump_field}" missing from class {cls.__name__}'
コード例 #6
0
ファイル: test_renderer.py プロジェクト: jimbo1qaz/corrscope
WIDTH = 64
HEIGHT = 64

RENDER_Y_ZEROS = np.full((2, 1), 0.5)
RENDER_Y_STEREO = np.full((2, 2), 0.5)
OPACITY = 2 / 3


def behead(string: str, header: str) -> str:
    if not string.startswith(header):
        raise ValueError(f"{string} does not start with {header}")
    return string[len(header) :]


my_dataclass = attr.dataclass(frozen=True, repr=False)


@my_dataclass
class NamedDebug:
    name: str

    def __init_subclass__(cls):
        my_dataclass(cls)

    def __repr__(self):
        return self.name

    if TYPE_CHECKING:

        def __init__(self, *args, **kwargs):
コード例 #7
0
def class_schema(clazz: type) -> Type[marshmallow.Schema]:
    """
    Convert a class to a marshmallow schema

    :param clazz: A python class (may be a dataclass)
    :return: A marshmallow Schema corresponding to the dataclass

    .. note::
        All the arguments supported by marshmallow field classes are can
        be passed in the `metadata` dictionary of a field.


    If you want to use a custom marshmallow field
    (one that has no equivalent python type), you can pass it as the
    ``marshmallow_field`` key in the metadata dictionary.

    >>> Meters = NewType('Meters', float)
    >>> @attr.dataclass()
    ... class Building:
    ...   height: Optional[Meters]
    ...   name: str = attr.ib(default="anonymous")
    ...   class Meta: # marshmallow meta attributes are supported
    ...     ordered = True
    ...
    >>> class_schema(Building) # Returns a marshmallow schema class (not an instance)
    <class 'marshmallow.schema.Building'>

    >>> @attr.dataclass()
    ... class City:
    ...   name: str = attr.ib(metadata={'required':True})
    ...   best_building: Building # Reference to another attr. A schema will be created for it too.
    ...   other_buildings: List[Building] = attr.ib(factory=list)
    ...
    >>> citySchema = class_schema(City)(strict=True)
    >>> city, _ = citySchema.load({"name":"Paris", "best_building": {"name": "Eiffel Tower"}, "other_buildings": []})
    >>> city
    City(name='Paris', best_building=Building(height=None, name='Eiffel Tower'), other_buildings=[])

    >>> citySchema.load({"name":"Paris"})
    Traceback (most recent call last):
        ...
    marshmallow.exceptions.ValidationError: {'best_building': ['Missing data for required field.']}

    >>> city_json, _ = class_schema(Building)(strict=True).dump(city.best_building)
    >>> city_json # We get an OrderedDict because we specified order = True in the Meta class
    OrderedDict([('height', None), ('name', 'Eiffel Tower')])

    >>> @attr.dataclass()
    ... class Person:
    ...   name: str = attr.ib(default="Anonymous")
    ...   friends: List['Person'] = attr.ib(factory=list) # Recursive field
    ...
    >>> person, _ = class_schema(Person)(strict=True).load({
    ...     "friends": [{"name": "Roger Boucher"}]
    ... })
    >>> person
    Person(name='Anonymous', friends=[Person(name='Roger Boucher', friends=[])])

    >>> @attr.dataclass()
    ... class C:
    ...   important: int = attr.ib(init=True, default=0)
    ...   unimportant: int = attr.ib(init=False, default=0) # Only fields that are in the __init__ method will be added:
    ...
    >>> c, _ = class_schema(C)(strict=True).load({
    ...     "important": 9, # This field will be imported
    ...     "unimportant": 9 # This field will NOT be imported
    ... })
    >>> c
    C(important=9, unimportant=0)

    >>> @attr.dataclass
    ... class Website:
    ...  url:str = attr.ib(metadata = {
    ...    "marshmallow_field": marshmallow.fields.Url() # Custom marshmallow field
    ...  })
    ...
    >>> class_schema(Website)(strict=True).load({"url": "I am not a good URL !"})
    Traceback (most recent call last):
        ...
    marshmallow.exceptions.ValidationError: {'url': ['Not a valid URL.']}

    >>> @attr.dataclass
    ... class NeverValid:
    ...     @marshmallow.validates_schema
    ...     def validate(self, data):
    ...         raise marshmallow.ValidationError('never valid')
    ...
    >>> _, err = class_schema(NeverValid)().load({})
    >>> err
    {'_schema': ['never valid']}

    >>> # noinspection PyTypeChecker
    >>> class_schema(None)  # unsupported type
    Traceback (most recent call last):
      ...
    TypeError: None is not a dataclass and cannot be turned into one.
    """

    try:
        # noinspection PyDataclass
        fields: Tuple[attr.ib] = attr.fields(clazz)
    except TypeError:  # Not a dataclass
        try:
            return class_schema(attr.dataclass(clazz))
        except Exception:
            raise TypeError(
                f"{getattr(clazz, '__name__', repr(clazz))} is not a dataclass and cannot be turned into one."
            )

    # Copy all public members of the dataclass to the schema
    attributes = {
        k: v
        for k, v in inspect.getmembers(clazz) if not k.startswith("_")
    }
    # Update the schema members to contain marshmallow fields instead of dataclass fields
    attributes.update((
        field.name,
        field_for_schema(field.type, _get_field_default(field),
                         field.metadata),
    ) for field in fields if field.init)

    schema_class = type(clazz.__name__, (_base_schema(clazz), ), attributes)
    return cast(Type[marshmallow.Schema], schema_class)