File: _subscriptable_type.py

package info (click to toggle)
python-typish 1.9.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 324 kB
  • sloc: python: 1,632; makefile: 2
file content (50 lines) | stat: -rw-r--r-- 1,580 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
class _SubscribedType(type):
    """
    This class is a placeholder to let the IDE know the attributes of the
    returned type after a __getitem__.
    """
    __origin__ = None
    __args__ = None


class SubscriptableType(type):
    """
    This metaclass will allow a type to become subscriptable.

    >>> class SomeType(metaclass=SubscriptableType):
    ...     pass
    >>> SomeTypeSub = SomeType['some args']
    >>> SomeTypeSub.__args__
    'some args'
    >>> SomeTypeSub.__origin__.__name__
    'SomeType'
    """
    def __init_subclass__(mcs, **kwargs):
        mcs._hash = None
        mcs.__args__ = None
        mcs.__origin__ = None

    def __getitem__(self, item) -> _SubscribedType:
        body = {
            **self.__dict__,
            '__args__': item,
            '__origin__': self,
        }
        bases = self, *self.__bases__
        result = type(self.__name__, bases, body)
        if hasattr(result, '_after_subscription'):
            # TODO check if _after_subscription is static
            result._after_subscription(item)
        return result

    def __eq__(self, other):
        self_args = getattr(self, '__args__', None)
        self_origin = getattr(self, '__origin__', None)
        other_args = getattr(other, '__args__', None)
        other_origin = getattr(other, '__origin__', None)
        return self_args == other_args and self_origin == other_origin

    def __hash__(self):
        if not getattr(self, '_hash', None):
            self._hash = hash('{}{}'.format(self.__origin__, self.__args__))
        return self._hash