Example #1
0
    def cast2dump(cls, result: Any) -> Any:
        if result is None:
            return None
        if isinstance(result, FieldInfo):
            field_info = result
            result = (smart_deepcopy(field_info.default)
                      if field_info.default_factory is None else
                      field_info.default_factory())
            if result == Ellipsis:
                raise _InvalidArguments
            return result
        if isinstance(result, BaseModel):
            return cls.cast2dump(result.dict())
        if isinstance(result, (int, float, str, bool, type(None))):
            return result
        if isinstance(result, Mapping):
            res_dict = {}
            for key, value in result.items():
                try:
                    res_dict[key] = cls.cast2dump(value)
                except _InvalidArguments:
                    raise _InvalidArguments(
                        Exception(f'Missing required argument: {key}'))
            return res_dict
        if isinstance(result, Iterable):
            res_list = []
            for item in result:
                res_list.append(cls.cast2dump(item))
            return res_list

        for enc_type, enc_func in ENCODERS_BY_TYPE.items():
            if isinstance(result, enc_type):
                return enc_func(result)

        return pydantic_encoder(result)
Example #2
0
def _remove_trailing_underscore_from_keys(o: dict[str, Any]) -> dict[str, Any]:
    new_dict = smart_deepcopy(o)
    for key, value in o.items():
        if isinstance(value, dict):
            value = _remove_trailing_underscore_from_keys(value)
        new_dict[key.removesuffix("_")] = value
    return new_dict
Example #3
0
def test_smart_deepcopy_empty_collection(empty_collection, mocker):
    mocker.patch('pydantic.utils.deepcopy',
                 side_effect=RuntimeError)  # make sure deepcopy is not used
    if not isinstance(
            empty_collection,
        (tuple,
         frozenset)):  # empty tuple or frozenset are always the same object
        assert smart_deepcopy(empty_collection) is not empty_collection
Example #4
0
def get_default_factory_for_field(
        field: ModelField) -> Union[NoArgAnyCallable, _Unset]:
    """
    Gets the default factory for a pydantic field.

    Handles mutable defaults when making the dataclass by using pydantic's smart_deepcopy

    Returns optionally a NoArgAnyCallable representing a default_factory parameter
    """
    default_factory = field.default_factory
    default = field.default

    has_factory = default_factory is not None and not is_unset(default_factory)
    has_default = default is not None and not is_unset(default)

    # defining both default and default_factory is not supported

    if has_factory and has_default:
        default_factory = cast(NoArgAnyCallable, default_factory)

        raise BothDefaultAndDefaultFactoryDefinedError(
            default=default, default_factory=default_factory)

    # if we have a default_factory, we should return it

    if has_factory:
        default_factory = cast(NoArgAnyCallable, default_factory)

        return default_factory

    # if we have a default, we should return it

    if has_default:
        return lambda: smart_deepcopy(default)

    # if we don't have default or default_factory, but the field is not required,
    # we should return a factory that returns None

    if not field.required:
        return lambda: None

    return UNSET
Example #5
0
def test_smart_deepcopy_collection(collection, mocker):
    expected_value = object()
    mocker.patch('pydantic.utils.deepcopy', return_value=expected_value)
    assert smart_deepcopy(collection) is expected_value
Example #6
0
def test_smart_deepcopy_immutable_non_sequence(obj, mocker):
    # make sure deepcopy is not used
    # (other option will be to use obj.copy(), but this will produce error as none of given objects have this method)
    mocker.patch('pydantic.utils.deepcopy', side_effect=RuntimeError)
    assert smart_deepcopy(obj) is deepcopy(obj) is obj