コード例 #1
0
def _get_constructor_args(
        obj,
        cls,
        meta_hints,
        attr_getters=None,
        **kwargs) -> dict:
    # Loop through the signature of cls: the type we try to deserialize to. For
    # every required parameter, we try to get the corresponding value from
    # json_obj.
    signature_parameters = _get_signature(cls)
    hints = get_type_hints(cls.__init__)
    attr_getters = dict(**(attr_getters or {}))

    result = {}
    for sig_key, sig in signature_parameters.items():
        if sig_key != 'self':
            key, value = _get_value_for_attr(obj=obj,
                                             orig_cls=cls,
                                             meta_hints=meta_hints,
                                             attr_getters=attr_getters,
                                             sig_key=sig_key,
                                             cls=hints.get(sig_key, None),
                                             sig=sig,
                                             **kwargs)
            if key:
                result[key] = value
    return result
コード例 #2
0
    def test_simple_dump_and_load_dataclass(self):

        class C:
            pass

        hints = get_type_hints(C.__init__)
        self.assertDictEqual({}, hints)
コード例 #3
0
def _set_remaining_attrs(instance,
                         remaining_attrs,
                         attr_getters,
                         **kwargs):
    # Set any remaining attributes on the newly created instance.
    attr_getters = attr_getters or {}
    for attr_name in remaining_attrs:
        annotations = get_type_hints(instance.__class__)
        attr_type = annotations.get(attr_name)

        if isinstance(remaining_attrs[attr_name], dict) \
                and '-keys' in remaining_attrs[attr_name] \
                and not attr_type:
            fork_inst = kwargs['fork_inst']
            fork_inst._warn('A dict with -keys was detected without a type '
                            'hint for attribute `{}`. This probably means '
                            'that you did not provide an annotation in your '
                            'class (ending up in __annotations__).'
                            .format(attr_name), 'hashed-keys-without-hint')
        attr_type = attr_type or type(remaining_attrs[attr_name])

        loaded_attr = load(remaining_attrs[attr_name], attr_type, **kwargs)
        try:
            setattr(instance, attr_name, loaded_attr)
        except AttributeError:
            pass  # This is raised when a @property does not have a setter.
    for attr_name, getter in attr_getters.items():
        setattr(instance, attr_name, getter())
コード例 #4
0
def _get_attributes_and_types(cls: type,
                              strict: bool) -> Dict[str, Optional[type]]:
    if '__slots__' in cls.__dict__:
        attributes = {attr: None for attr in cls.__slots__}
    elif hasattr(cls, '__annotations__'):
        attributes = get_type_hints(cls)
    elif strict:
        hints = get_type_hints(cls.__init__)
        attributes = {k: hints[k] for k in hints if k != 'self'}
    else:
        attributes = {}

    # Add properties and class variables.
    props, class_vars = _get_class_props(cls)
    for elem in props + class_vars:
        attributes[elem] = None

    return attributes
コード例 #5
0
    def test_get_type_hints(self):

        def get_type_hints_mock(_, globalns=None):
            if not globalns:
                raise NameError()
            get_type_hints_mock.globalns = globalns
            return {}

        orig = typing.get_type_hints

        try:
            typing.get_type_hints = MagicMock(side_effect=AttributeError)
            result = get_type_hints(lambda: 42)
            self.assertEqual({}, result)

            typing.get_type_hints = get_type_hints_mock
            result = get_type_hints(lambda: 42, 'builtins')

            self.assertEqual({}, result)
            self.assertDictEqual(sys.modules['builtins'].__dict__, get_type_hints_mock.globalns)
        finally:
            typing.get_type_hints = orig
コード例 #6
0
ファイル: default_tuple.py プロジェクト: ramonhagenaars/jsons
def default_namedtuple_deserializer(
        obj: Union[list, dict],
        cls: type,
        *,
        key_transformer: Optional[Callable[[str], str]] = None,
        **kwargs) -> object:
    """
    Deserialize a (JSON) list or dict into a named tuple by deserializing all
    items of that list/dict.
    :param obj: the tuple that needs deserializing.
    :param cls: the NamedTuple.
    :param kwargs: any keyword arguments.
    :return: a deserialized named tuple (i.e. an instance of a class).
    """
    is_dict = isinstance(obj, dict)
    key_tfr = key_transformer or (lambda key: key)

    if is_dict:
        tfm_obj = {key_tfr(k): v for k, v in obj.items()}

    args = []
    for index, field_name in enumerate(cls._fields):
        if index < len(obj):
            if is_dict:
                field = tfm_obj[field_name]
            else:
                field = obj[index]
        else:
            field = cls._field_defaults.get(field_name, None)

        # _field_types has been deprecated in favor of __annotations__ in Python 3.8
        if hasattr(cls, '__annotations__'):
            # It is important to use get_type_hints so that forward references get resolved,
            # rather than access __annotations__ directly
            field_types = get_type_hints(cls)
        else:
            field_types = getattr(cls, '_field_types', {})

        if field is None:
            hint = field_types.get(field_name)
            if NoneType not in (get_union_params(hint) or []):
                # The value 'None' is not permitted here.
                msg = ('No value present in {} for argument "{}"'
                       .format(obj, field_name))
                raise UnfulfilledArgumentError(msg, field_name, obj, cls)
        cls_ = field_types.get(field_name) if field_types else None
        loaded_field = load(field, cls_, key_transformer=key_transformer, **kwargs)
        args.append(loaded_field)
    inst = cls(*args)
    return inst
コード例 #7
0
def _get_constructor_args(obj,
                          cls,
                          meta_hints,
                          attr_getters=None,
                          **kwargs) -> dict:
    # Loop through the signature of cls: the type we try to deserialize to. For
    # every required parameter, we try to get the corresponding value from
    # json_obj.
    signature_parameters = inspect.signature(cls.__init__).parameters
    hints = get_type_hints(cls.__init__)
    attr_getters = dict(**(attr_getters or {}))
    value_for_attr_part = partial(_get_value_for_attr,
                                  obj=obj,
                                  orig_cls=cls,
                                  meta_hints=meta_hints,
                                  attr_getters=attr_getters,
                                  **kwargs)
    args_gen = (value_for_attr_part(sig_key=sig_key,
                                    cls=hints.get(sig_key, None),
                                    sig=sig)
                for sig_key, sig in signature_parameters.items()
                if sig_key != 'self')
    constructor_args_in_obj = {key: value for key, value in args_gen if key}
    return constructor_args_in_obj
コード例 #8
0
    def test_get_type_hints_for_class(self):
        from test_resources.simple_class_with_hints import C

        hints = get_type_hints(C)

        self.assertDictEqual({"x": int}, hints)