Exemple #1
0
def build_schema(cls: typing.Type[A], mixin, infer_missing,
                 partial) -> typing.Type[SchemaType]:
    Meta = type(
        'Meta', (), {
            'fields':
            tuple(field.name for field in dc_fields(cls)
                  if field.name != 'dataclass_json_config')
        })

    @post_load
    def make_instance(self, kvs):
        return _decode_dataclass(cls, kvs, partial)

    def dumps(self, *args, **kwargs):
        if 'cls' not in kwargs:
            kwargs['cls'] = _ExtendedEncoder

        return Schema.dumps(self, *args, **kwargs)

    schema_ = schema(cls, mixin, infer_missing)
    DataClassSchema: typing.Type[SchemaType] = type(
        f'{cls.__name__.capitalize()}Schema', (Schema, ), {
            'Meta': Meta,
            f'make_{cls.__name__.lower()}': make_instance,
            'dumps': dumps,
            **schema_
        })

    return DataClassSchema
Exemple #2
0
def schema(cls, mixin, infer_missing):
    schema = {}
    for field in dc_fields(cls):
        if 'dc_json' in (field.metadata or {}):
            schema[field.name] = field.metadata['dc_json'].get('mm_field')
        else:
            type_ = field.type
            options = {}
            missing_key = 'missing' if infer_missing else 'default'
            if field.default is not MISSING:
                options[missing_key] = field.default
            elif field.default_factory is not MISSING:
                options[missing_key] = field.default_factory

            if options.get(missing_key, ...) is None:
                options['allow_none'] = True

            if _is_optional(type_):
                options.setdefault(missing_key, None)
                type_ = type_.__args__[0]
                options['allow_none'] = True

            t = build_type(type_, options, mixin, field, cls)
            #if type(t) is not fields.Field:  # If we use `isinstance` we would return nothing.
            schema[field.name] = t
    return schema
Exemple #3
0
def schema(cls, mixin, infer_missing):
    schema = {}
    for field in dc_fields(cls):
        metadata = (field.metadata or {}).get('dataclasses_json', {})
        if 'mm_field' in metadata:
            schema[field.name] = metadata['mm_field']
        else:
            type_ = field.type
            options = {}
            missing_key = 'missing' if infer_missing else 'default'
            if field.default is not MISSING:
                options[missing_key] = field.default
            elif field.default_factory is not MISSING:
                options[missing_key] = field.default_factory

            if options.get(missing_key, ...) is None:
                options['allow_none'] = True

            if _is_optional(type_):
                options.setdefault(missing_key, None)
                options['allow_none'] = True
                if len(type_.__args__) == 2:
                    # Union[str, int, None] is optional too, but it has more than 1 typed field.
                    type_ = type_.__args__[0]

            t = build_type(type_, options, mixin, field, cls)
            # if type(t) is not fields.Field:  # If we use `isinstance` we would return nothing.
            schema[field.name] = t
    return schema
Exemple #4
0
def parse_gpg_errors(status_out):  # type: (str) -> t.Iterator[GpgBaseError]
    for line in status_out.splitlines():
        if not line:
            continue
        try:
            _dummy, status, remainder = line.split(maxsplit=2)
        except ValueError:
            _dummy, status = line.split(maxsplit=1)
            remainder = None

        try:
            cls = GPG_ERROR_MAP[status]
        except KeyError:
            continue

        fields = [status]
        if remainder:
            fields.extend(
                remainder.split(
                    None,
                    len(dc_fields(cls)) - 2
                )
            )

        yield cls(*fields)
Exemple #5
0
def build_schema(cls: typing.Type[A], mixin, infer_missing,
                 partial) -> typing.Type[SchemaType]:
    Meta = type(
        'Meta',
        (),
        {
            'fields':
            tuple(field.name for field in dc_fields(cls)
                  if field.name != 'dataclass_json_config'
                  and field.type != typing.Optional[CatchAllVar]),
            # TODO #180
            # 'render_module': global_config.json_module
        })

    @post_load
    def make_instance(self, kvs, **kwargs):
        return _decode_dataclass(cls, kvs, partial)

    def dumps(self, *args, **kwargs):
        if 'cls' not in kwargs:
            kwargs['cls'] = _ExtendedEncoder

        return Schema.dumps(self, *args, **kwargs)

    def dump(self, obj, *, many=None):
        many = self.many if many is None else bool(many)
        dumped = Schema.dump(self, obj, many=many)
        # TODO This is hacky, but the other option I can think of is to generate a different schema
        #  depending on dump and load, which is even more hacky

        # The only problem is the catch all field, we can't statically create a schema for it
        # so we just update the dumped dict
        if many:
            for i, _obj in enumerate(obj):
                dumped[i].update(
                    _handle_undefined_parameters_safe(cls=_obj,
                                                      kvs={},
                                                      usage="dump"))
        else:
            dumped.update(
                _handle_undefined_parameters_safe(cls=obj,
                                                  kvs={},
                                                  usage="dump"))
        return dumped

    schema_ = schema(cls, mixin, infer_missing)
    DataClassSchema: typing.Type[SchemaType] = type(
        f'{cls.__name__.capitalize()}Schema', (Schema, ), {
            'Meta': Meta,
            f'make_{cls.__name__.lower()}': make_instance,
            'dumps': dumps,
            'dump': dump,
            **schema_
        })

    return DataClassSchema
Exemple #6
0
def _get_schema_dict(schema: Type[Schema],
                     settings: _SchemaGenSettings) -> Dict[str, Any]:
    """Monkey-patches marshmallow fields to schema"""
    class_dict: Dict[str, Any] = dict()
    if sys.version_info[:2] >= (3, 7):
        class_typevar_mapping(settings.data_class, settings.type_var_index)

    this_field: DCField
    for this_field in dc_fields(settings.data_class):
        class_dict[this_field.name] = _convert_type(this_field, settings)

    if issubclass(schema, DataSchemaConcrete):
        class_dict["__model__"] = settings.data_class

        f: DCField
        class_dict["_dump_only"] = [
            f.name for f in dc_fields(settings.data_class)
            if f.metadata is not None
            and f.metadata.get("garams", Garams()).dump_only
        ]

    return class_dict
Exemple #7
0
def build_schema(cls, mixin, infer_missing, partial):
    Meta = type('Meta', (),
                {'fields': tuple(field.name for field in dc_fields(cls))})

    @post_load
    def make_instance(self, kvs):
        return _decode_dataclass(cls, kvs, partial)

    schema_ = schema(cls, mixin, infer_missing)
    DataClassSchema = type(f'{cls.__name__.capitalize()}Schema', (Schema, ), {
        'Meta': Meta,
        f'make_{cls.__name__.lower()}': make_instance,
        **schema_
    })

    return DataClassSchema
Exemple #8
0
def create_simple_dataclass_from_dict(
        input_dict: Dict, dataclass: Type) -> Any:
    buffer = {}
    for field in dc_fields(dataclass):
        value = input_dict.get(field.name, MISSING)
        typ = field.type
        if value is MISSING:
            if hasattr(typ, '__args__') and type(None) in typ.__args__:
                buffer[field.name] = None
            continue

        if hasattr(typ, '__args__'):
            typ = typ.__args__[0]
        if typ in (str, int, float, bool):
            value = typ(value)
        buffer[field.name] = value
    return dataclass(**buffer)
Exemple #9
0
def schema(cls, mixin, infer_missing):
    schema = {}
    overrides = _user_overrides(cls)
    # TODO check the undefined parameters and add the proper schema action
    #  https://marshmallow.readthedocs.io/en/stable/quickstart.html
    for field in dc_fields(cls):
        metadata = (field.metadata or {}).get('dataclasses_json', {})
        metadata = overrides[field.name]
        if metadata.mm_field is not None:
            schema[field.name] = metadata.mm_field
        else:
            type_ = field.type
            options = {}
            missing_key = 'missing' if infer_missing else 'default'
            if field.default is not MISSING:
                options[missing_key] = field.default
            elif field.default_factory is not MISSING:
                options[missing_key] = field.default_factory

            if options.get(missing_key, ...) is None:
                options['allow_none'] = True

            if _is_optional(type_):
                options.setdefault(missing_key, None)
                options['allow_none'] = True
                if len(type_.__args__) == 2:
                    # Union[str, int, None] is optional too, but it has more than 1 typed field.
                    type_ = type_.__args__[0]

            if metadata.letter_case is not None:
                options['data_key'] = metadata.letter_case(field.name)

            t = build_type(type_, options, mixin, field, cls)
            # if type(t) is not fields.Field:  # If we use `isinstance` we would return nothing.
            if field.type != typing.Optional[CatchAllVar]:
                schema[field.name] = t

    return schema
Exemple #10
0
 def __post_init__(self):
     for field in dc_fields(self):
         super(GpgBaseError, self).__setattr__(field.name, field.type(getattr(self, field.name)))
Exemple #11
0
 def data_class_fields(class_or_instance: Any):
     x = extract_type_from_possible_optional_type(
         possible_optional_type=class_or_instance)
     return dc_fields(class_or_instance=x)