def _get_value_for_attr( obj, cls, orig_cls, sig_key, sig, meta_hints, attr_getters, **kwargs): # Find a value for the attribute (with signature sig_key). if obj and sig_key in obj: # This argument is in obj. result = sig_key, _get_value_from_obj(obj, cls, sig, sig_key, meta_hints, **kwargs) elif sig_key in attr_getters: # There exists an attr_getter for this argument. attr_getter = attr_getters.pop(sig_key) result = sig_key, attr_getter() elif sig.default != inspect.Parameter.empty: # There is a default value for this argument. result = sig_key, sig.default elif sig.kind in (inspect.Parameter.VAR_POSITIONAL, inspect.Parameter.VAR_KEYWORD): # This argument is either *args or **kwargs. result = None, None elif can_match_with_none(cls): # It is fine that there is no value. result = sig_key, None else: raise UnfulfilledArgumentError( 'No value found for "{}"'.format(sig_key), sig_key, obj, orig_cls) return result
def default_namedtuple_deserializer(obj: Union[list, dict], cls: type, **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) args = [] for index, field_name in enumerate(cls._fields): if index < len(obj): key = field_name if is_dict else index field = obj[key] else: field = cls._field_defaults.get(field_name, None) if field is None: hint = getattr(cls, '_field_types', {}).get(field_name) if type(None) 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) field_types = getattr(cls, '_field_types', None) cls_ = field_types.get(field_name) if field_types else None loaded_field = load(field, cls_, **kwargs) args.append(loaded_field) inst = cls(*args) return inst
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__'): field_types = getattr(cls, '__annotations__', {}) 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
def _get_value_for_attr(obj, cls, sig_key, sig, attr_getters, **kwargs): result = None, None if obj and sig_key in obj: # This argument is in obj. arg_cls = None if sig.annotation != inspect.Parameter.empty: arg_cls = sig.annotation value = load(obj[sig_key], arg_cls, **kwargs) result = sig_key, value elif sig_key in attr_getters: # There exists an attr_getter for this argument. attr_getter = attr_getters.pop(sig_key) result = sig_key, attr_getter() elif sig.default != inspect.Parameter.empty: # There is a default value for this argument. result = sig_key, sig.default elif sig.kind not in (inspect.Parameter.VAR_POSITIONAL, inspect.Parameter.VAR_KEYWORD): # This argument is no *args or **kwargs and has no value. raise UnfulfilledArgumentError( 'No value found for "{}"'.format(sig_key), sig_key, obj, cls) return result
def default_namedtuple_deserializer(obj: list, cls: type, **kwargs) -> object: """ Deserialize a (JSON) list into a named tuple by deserializing all items of that list. :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). """ args = [] for index, field_name in enumerate(cls._fields): if index < len(obj): field = obj[index] else: field = cls._field_defaults.get(field_name, None) if not field: msg = ('No value present in {} for argument "{}"' .format(obj, field_name)) raise UnfulfilledArgumentError(msg, field_name, obj, cls) cls_ = cls._field_types.get(field_name, None) loaded_field = load(field, cls_, **kwargs) args.append(loaded_field) inst = cls(*args) return inst