Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python typing Union of class and it's instance

Say I have

class Foo:
   pass

and I want to write a function that may accept Foo instance or some of Foo subclasses (not instances). So I wrote

def bar(o: Union[Foo, Type[Foo]]):
    print(1)

And get such errors:

TypeError                                 Traceback (most recent call last) <ipython-input-161-2a8355efa688> in <module>()
----> 1 def bar(o: Union[Foo, Type[Foo]]):
      2     print(1)
      3 

/usr/lib/python3.5/typing.py in __getitem__(self, parameters)
    550             parameters = (parameters,)
    551         return self.__class__(self.__name__, self.__bases__,
--> 552                               dict(self.__dict__), parameters, _root=True)
    553 
    554     def __eq__(self, other):

/usr/lib/python3.5/typing.py in __new__(cls, name, bases, namespace, parameters, _root)
    510                 continue
    511             if any(isinstance(t2, type) and issubclass(t1, t2)
--> 512                    for t2 in all_params - {t1} if not isinstance(t2, TypeVar)):
    513                 all_params.remove(t1)
    514         # It's not a union if there's only one type left.

/usr/lib/python3.5/typing.py in <genexpr>(.0)
    510                 continue
    511             if any(isinstance(t2, type) and issubclass(t1, t2)
--> 512                    for t2 in all_params - {t1} if not isinstance(t2, TypeVar)):
    513                 all_params.remove(t1)
    514         # It's not a union if there's only one type left.

/usr/lib/python3.5/typing.py in __subclasscheck__(self, cls)    1075   return True    1076                 # If we break out of the loop, the superclass gets a chance.
-> 1077         if super().__subclasscheck__(cls):    1078             return True    1079         if self.__extra__ is None or isinstance(cls, GenericMeta):

/home/alexey/dev/gcore/django/lib/python3.5/abc.py in
__subclasscheck__(cls, subclass)
    223                 return True
    224         # Check if it's a subclass of a subclass (recursive)
--> 225         for scls in cls.__subclasses__():
    226             if issubclass(subclass, scls):
    227                 cls._abc_cache.add(subclass)

TypeError: descriptor '__subclasses__' of 'type' object needs an argument

Is it impossible to specify that type in python, or I used wrong approach?

like image 287
fantom Avatar asked Oct 29 '22 05:10

fantom


1 Answers

See typing/issue 266. This has been fixed and no longer appears in updated versions of Python.

With Python 3.6.1, the function is compiled fine and the annotations stored correctly:

>>> def bar(o: Union[Foo, Type[Foo]]):
...     print(1)
>>> typing.get_type_hints(bar)
{'o': typing.Union[__main__.Foo, typing.Type[__main__.Foo]]}
like image 93
Dimitris Fasarakis Hilliard Avatar answered Nov 15 '22 06:11

Dimitris Fasarakis Hilliard