Comments (8)
Hey @xbanke, @floriandorre,
I've got PR #175 open which I believe resolves all the issues mentioned here:
- Not cleaning up the string repr for subscripted generics
- Attempting to initialize abstract base classes rather than simply validate against them
- Using subclass checks to narrow down which type to target withing a generic union of constrained or primitive types.
If you could try your code against that branch and verify the output I'd really appreciate it!
from typical.
Hey @xbanke -
On the latest version, I'm seeing the correct behavior here:
>>> import typic, typing
...
... PositiveFloat = typic.constrained(float, gt=0)
... PositiveInt = typic.constrained(int, gt=0)
...
... proto = typic.protocol(typing.Union[PositiveFloat, PositiveInt])
>>> isinstance(proto.transmute("1.0"), PositiveFloat)
True
>>> isinstance(proto.transmute(1.0), PositiveFloat)
True
from typical.
Note that mixing float and int are going to be problematic, since they're overlapping types. By that, I mean that in Python's runtime type system, float can be coerced to int and vice-versa without any sort of complaint.
From my testing, other libraries (e.g., pydantic, etc.) have the same behavior in this case. I'd consider this a limitation of Python's runtime type system more than an implementation issue in typical. Hate to pass the buck, but I don't see a good way to implement determinism in this case.
// edit:
You may consider taking advantage of the decimal module for these cases.
from typical.
Hey, @seandstewart . In your case PositiveFloat
is at first place, all numbers will be converted to float
, but in my case the PositiveInt
is at the first, all numbers will be converted to int
. I think it maybe should consider adding the father class for the constrainted types to choose the first converter. For example if given the value 1.2
, it should first try to convert with PositiveFloat
, even if the PositiveInt
is the head.
One more thing, typical
did not support abstract types that can not be instantiated.
import typic, numbers
@typic.al
def foo(a: numbers.Number):
return a
foo(42) # TypeError: Number() takes no arguments
Because it check type by is
, but isinstance
or issubclass
.
proto = typic.protocol(numbers.Number)
print(proto.transmute.__raw__)
def deserializer__1872423425688238822(val):
_, val = __eval(val) if isinstance(val, (str, bytes)) else (False, val)
vtype = val.__class__
if vtype is Number_94020002862272:
return val
# Happy path - deserialize a mapping into the object.
if issubclass(vtype, Mapping):
val = Number_94020002862272(**{x: desers[x](val[x]) for x in fields_in.keys() & val.keys()})
# Unknown path, just try casting it directly.
elif isbuiltinsubtype(vtype):
val = Number_94020002862272(val)
# Two user-defined types, try to translate the input into the desired output.
else:
val = translate(val, Number_94020002862272)
return val
Here, the __raw__
shows that it check the type by if vtype is Number_94020002862272
, not if isintance(val, Number_94020002862272)
or issubclass(vtype, Number_94020002862272)
. This is simlar with Union
from typical.
Hi,
I'm not sure if my issue is related to this topic but i also get an error when using Literal and Union
What i am doing :
from typing import Union
import typic
from typing_extensions import Literal
@typic.al
def dummy(arg_a: Union[float, Literal["A", "B"]] = "A"):
return arg_a
if __name__ == '__main__':
dummy()
Output :
Traceback (most recent call last):
File "C:/Users/Florian DORRE/RTC/wastewater_toolkit/configuration/test.py", line 8, in <module>
def dummy(arg_a: Union[str, Literal["A", "B"]] = "A"):
File "C:\Users\Florian DORRE\Envs\ww-toolkit\lib\site-packages\typic\api.py", line 385, in typed
return _typed(_cls_or_callable) if _cls_or_callable is not None else _typed
File "C:\Users\Florian DORRE\Envs\ww-toolkit\lib\site-packages\typic\api.py", line 379, in _typed
return wrap(obj, delay=delay, strict=strict) # type: ignore
File "C:\Users\Florian DORRE\Envs\ww-toolkit\lib\site-packages\typic\api.py", line 173, in wrap
protocols(func)
File "C:\Users\Florian DORRE\Envs\ww-toolkit\lib\site-packages\typic\serde\resolver.py", line 794, in protocols
annotation, name=name, parameter=param, is_strict=strict, namespace=obj
File "C:\Users\Florian DORRE\Envs\ww-toolkit\lib\site-packages\typic\serde\resolver.py", line 720, in resolve
resolved = self._resolve_from_annotation(anno, namespace=namespace)
File "C:\Users\Florian DORRE\Envs\ww-toolkit\lib\site-packages\typic\serde\resolver.py", line 533, in _resolve_from_annotation
anno, constraints, namespace=namespace
File "C:\Users\Florian DORRE\Envs\ww-toolkit\lib\site-packages\typic\serde\des.py", line 907, in factory
deserializer = self._build_des(annotation, key, namespace)
File "C:\Users\Florian DORRE\Envs\ww-toolkit\lib\site-packages\typic\serde\des.py", line 782, in _build_des
deserializer = main.compile(ns=ns, name=func_name)
File "C:\Users\Florian DORRE\Envs\ww-toolkit\lib\site-packages\typic\gen.py", line 191, in compile
bytecode = compile(code, fname, "exec")
File "<typical generated deserializer__2069376713718722944>", line 14
return Literal['A', 'B']_des(val)
^
SyntaxError: invalid syntax
NB: I am using python 3.7.6 so Literal comes from typing_extensions and not typing itself.
Thanks
from typical.
This branch indeed fix my issue, Thanks !
from typical.
Yes, this branch fix my issue. But there is some other problem:
import typic, typing
proto = typic.protocol(typing.Union[list, typing.Dict[int, int]])
proto.transmute(1) # [1, 0, 1, 1]
This looks likely related to #174
from typical.
Yes, this branch fix my issue. But there is some other problem:
import typic, typing proto = typic.protocol(typing.Union[list, typing.Dict[int, int]]) proto.transmute(1) # [1, 0, 1, 1]This looks likely related to #174
Yes, I think I know the issue - it has to do with our iterator factory:
import typic
[*typic.iterate(1)]
This factory will iterate over a class's fields if it is not natively iterable. Very useful for user-defined classes (e.g., data models), not so useful for primitives.
I will patch this up as well.
from typical.
Related Issues (20)
- Support new type union operator `|` in Python3.10
- Still not working with PEP 604 Union Operators HOT 5
- Unpredictable behavior with Union[pd.Series, pd.DataFrame] HOT 1
- float should not been converted to int with Union[float, int] HOT 3
- typic.field not compatible with old version, parameter `default` should be postional
- Couldn't evaluate type ForwardRef pandas DataFrame HOT 2
- callable instance should be the treated as a function or class? HOT 1
- Not compatible with pandas v1.3.3 HOT 2
- add parameter to typic.klass
- Transmute is broken with dicts of dataclasses with default values HOT 2
- TypeError if annotated typing.Deque[int]
- issubclass error after version 2.6.4
- tojson and primitive fails when class is derived
- Decimal serialization and deserialization HOT 2
- Use orjson for other libraries benchmark
- Version conflicts installed the pinned typing-extensions HOT 2
- Is there a way to use choices with values and labels when generating schemas? HOT 2
- Question on your approach to strict mode HOT 2
- When using my with typic.mypy plugin get error cannot import name 'TypingType' from 'mypy.typeops' HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from typical.