Error using enforce_types on a Python 3.6 dataclass: no attribute _SpecialForm

Viewed 701

I am using enforce_typing and dataclasses to create a simple - and hopefully robust - object to configure a model. I'm testing the code for the project using Travis and building on 3.6, 3.7 and 3.8.

The build on 3.6 fails with an error:

AttributeError: module 'typing' has no attribute '_SpecialForm'

I've put a simple reprex below showing the error in practice. Any ideas what I can do to fix this? It may be that I simply should stop trying to support 3.6!

Python 3.6.7 (default, Aug 12 2021, 12:48:47) 
Type 'copyright', 'credits' or 'license' for more information
IPython 7.16.1 -- An enhanced Interactive Python. Type '?' for help.

In [1]: import enforce_typing
In [3]: import dataclasses
In [5]: @enforce_typing.enforce_types
   ...: @dataclasses.dataclass
   ...: class Test():
   ...:     x: str = 'a'
   ...: 

In [6]: Test()
Out[6]: Test(x='a')

In [7]: Test(x='c')
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-7-54c6f8c04751> in <module>
----> 1 Test(x='c')

~/.pyenv/versions/3.6.7/lib/python3.6/site-packages/enforce_typing/decorator.py in wrapper(*args, **kwargs)
     26         @wraps(func)
     27         def wrapper(*args, **kwargs):
---> 28             check_types(*args, **kwargs)
     29             return func(*args, **kwargs)
     30 

~/.pyenv/versions/3.6.7/lib/python3.6/site-packages/enforce_typing/decorator.py in check_types(*args, **kwargs)
     14             with suppress(KeyError):
     15                 type_hint = spec.annotations[name]
---> 16                 if isinstance(type_hint, typing._SpecialForm):
     17                     continue
     18                 actual_type = getattr(type_hint, "__origin__", type_hint)

AttributeError: module 'typing' has no attribute '_SpecialForm'


1 Answers

The error message makes clear that the enforce_typing library assumes that Python's typing module has a _SpecialForm class in it. This is a very unwise assumption for that library to make, given that _SpecialForm is explicitly marked as an implementation detail of the module by the fact that the class's name starts with a single underscore. This is especially true for the typing module, which is still new and under very active development, with lots of implementation details undergoing significant changes in each version of python.

By the way, I'm not actually throwing shade at the enforce_typing library here. The unfortunate reality is that there's not a particularly safe way (at the moment) to generalise this kind of runtime type-checking, due to the fact that so many things in the typing module are marked as implementation details.

Related