numerary.protocol
package reference
Experimental
This package is an attempt to ease compatibility between Python’s numbers and types.
If that sounds like it shouldn’t be a thing, you won’t get any argument out of me.
Anyhoo, this package should be considered experimental.
I am working toward stability as quickly as possible, but be warned that future release may introduce incompatibilities or remove this package altogether.
Feedback, suggestions, and contributions are desperately appreciated.
numerary
has donated its core caching protocol implementation to (and now depends on) beartype
.
beartype
is awesome, and its author is even awesomer.
numerary
’s version (in this package) augments that implementation to allow for runtime check overrides.
Bases: _BeartypeCachingProtocolMeta
An extension of beartype.typing.Protocol
that allows
overriding runtime checks.
Source code in numerary/protocol.py
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171 | class CachingProtocolMeta(_BeartypeCachingProtocolMeta):
# TODO(posita): Add more precise link to beartype.typing.Protocol documentation once
# it becomes available.
r"""
An extension of [``#!python
beartype.typing.Protocol``](https://github.com/beartype/beartype) that allows
overriding runtime checks.
"""
_abc_inst_check_cache_overridden: Dict[Type, bool]
_abc_inst_check_cache_listeners: Set[CachingProtocolMeta]
# Defined in beartype.typing.Protocol from which we inherit
_abc_inst_check_cache: Dict[type, bool]
def __new__(
mcls: Type[_TT],
name: str,
bases: Tuple[Type, ...],
namespace: Dict[str, Any],
**kw: Any,
) -> _TT:
cls = super().__new__(mcls, name, bases, namespace, **kw)
# Prefixing this class member with "_abc_" is necessary to prevent it from being
# considered part of the Protocol. (See
# <https://github.com/python/cpython/blob/main/Lib/typing.py>.)
cls._abc_inst_check_cache_overridden = defaultdict(bool) # defaults to False
cls._abc_inst_check_cache_listeners = set()
for base in bases:
if hasattr(base, "_abc_inst_check_cache_listeners"):
base._abc_inst_check_cache_listeners.add(cls)
return cls
def includes(cls, inst_t: Type) -> None:
r"""
Registers *inst_t* as supporting the interface in the runtime type-checking cache.
This overrides any prior cached value.
``` python
>>> from abc import abstractmethod
>>> from numerary.types import CachingProtocolMeta, Protocol, runtime_checkable
>>> @runtime_checkable
... class SupportsSpam(
... Protocol,
... metaclass=CachingProtocolMeta
... ):
... @abstractmethod
... def spam(self) -> str:
... pass
>>> class NoSpam:
... pass
>>> isinstance(NoSpam(), SupportsSpam)
False
>>> SupportsSpam.includes(NoSpam)
>>> isinstance(NoSpam(), SupportsSpam)
True
```
!!! note
This does not affect static type-checking.
``` python
>>> my_spam: SupportsSpam = NoSpam() # type: ignore [assignment] # still generates a Mypy warning
```
"""
cls._abc_inst_check_cache[inst_t] = True
cls._abc_inst_check_cache_overridden[inst_t] = True
cls._dirty_for(inst_t)
def excludes(cls, inst_t: Type) -> None:
r"""
Registers *inst_t* as supporting the interface in the runtime type-checking cache.
This overrides any prior cached value.
``` python
>>> from abc import abstractmethod
>>> from numerary.types import CachingProtocolMeta, Protocol, runtime_checkable
>>> @runtime_checkable
... class SupportsHam(
... Protocol,
... metaclass=CachingProtocolMeta
... ):
... @abstractmethod
... def ham(self) -> str:
... pass
>>> class NoHam:
... def ham(self) -> str:
... raise NotImplementedError
>>> isinstance(NoHam(), SupportsHam)
True
>>> SupportsHam.excludes(NoHam)
>>> isinstance(NoHam(), SupportsHam)
False
```
!!! note
This does not affect static type-checking.
``` python
>>> my_ham: SupportsHam = NoHam() # does *not* generate a Mypy warning
```
"""
cls._abc_inst_check_cache[inst_t] = False
cls._abc_inst_check_cache_overridden[inst_t] = True
cls._dirty_for(inst_t)
def reset_for(cls, inst_t: Type) -> None:
r"""
Clears any cached instance check for *inst_t*.
"""
if inst_t in cls._abc_inst_check_cache:
del cls._abc_inst_check_cache[inst_t]
del cls._abc_inst_check_cache_overridden[inst_t]
cls._dirty_for(inst_t)
def _dirty_for(cls, inst_t: Type) -> None:
for inheriting_cls in cls._abc_inst_check_cache_listeners:
if (
inst_t in inheriting_cls._abc_inst_check_cache
and not inheriting_cls._abc_inst_check_cache_overridden[inst_t]
):
del inheriting_cls._abc_inst_check_cache[inst_t]
del inheriting_cls._abc_inst_check_cache_overridden[inst_t]
|
Registers inst_t as supporting the interface in the runtime type-checking cache.
This overrides any prior cached value.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 | >>> from abc import abstractmethod
>>> from numerary.types import CachingProtocolMeta, Protocol, runtime_checkable
>>> @runtime_checkable
... class SupportsHam(
... Protocol,
... metaclass=CachingProtocolMeta
... ):
... @abstractmethod
... def ham(self) -> str:
... pass
>>> class NoHam:
... def ham(self) -> str:
... raise NotImplementedError
>>> isinstance(NoHam(), SupportsHam)
True
>>> SupportsHam.excludes(NoHam)
>>> isinstance(NoHam(), SupportsHam)
False
|
Note
This does not affect static type-checking.
| >>> my_ham: SupportsHam = NoHam() # does *not* generate a Mypy warning
|
Source code in numerary/protocol.py
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153 | def excludes(cls, inst_t: Type) -> None:
r"""
Registers *inst_t* as supporting the interface in the runtime type-checking cache.
This overrides any prior cached value.
``` python
>>> from abc import abstractmethod
>>> from numerary.types import CachingProtocolMeta, Protocol, runtime_checkable
>>> @runtime_checkable
... class SupportsHam(
... Protocol,
... metaclass=CachingProtocolMeta
... ):
... @abstractmethod
... def ham(self) -> str:
... pass
>>> class NoHam:
... def ham(self) -> str:
... raise NotImplementedError
>>> isinstance(NoHam(), SupportsHam)
True
>>> SupportsHam.excludes(NoHam)
>>> isinstance(NoHam(), SupportsHam)
False
```
!!! note
This does not affect static type-checking.
``` python
>>> my_ham: SupportsHam = NoHam() # does *not* generate a Mypy warning
```
"""
cls._abc_inst_check_cache[inst_t] = False
cls._abc_inst_check_cache_overridden[inst_t] = True
cls._dirty_for(inst_t)
|
Registers inst_t as supporting the interface in the runtime type-checking cache.
This overrides any prior cached value.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 | >>> from abc import abstractmethod
>>> from numerary.types import CachingProtocolMeta, Protocol, runtime_checkable
>>> @runtime_checkable
... class SupportsSpam(
... Protocol,
... metaclass=CachingProtocolMeta
... ):
... @abstractmethod
... def spam(self) -> str:
... pass
>>> class NoSpam:
... pass
>>> isinstance(NoSpam(), SupportsSpam)
False
>>> SupportsSpam.includes(NoSpam)
>>> isinstance(NoSpam(), SupportsSpam)
True
|
Note
This does not affect static type-checking.
| >>> my_spam: SupportsSpam = NoSpam() # type: ignore [assignment] # still generates a Mypy warning
|
Source code in numerary/protocol.py
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110 | def includes(cls, inst_t: Type) -> None:
r"""
Registers *inst_t* as supporting the interface in the runtime type-checking cache.
This overrides any prior cached value.
``` python
>>> from abc import abstractmethod
>>> from numerary.types import CachingProtocolMeta, Protocol, runtime_checkable
>>> @runtime_checkable
... class SupportsSpam(
... Protocol,
... metaclass=CachingProtocolMeta
... ):
... @abstractmethod
... def spam(self) -> str:
... pass
>>> class NoSpam:
... pass
>>> isinstance(NoSpam(), SupportsSpam)
False
>>> SupportsSpam.includes(NoSpam)
>>> isinstance(NoSpam(), SupportsSpam)
True
```
!!! note
This does not affect static type-checking.
``` python
>>> my_spam: SupportsSpam = NoSpam() # type: ignore [assignment] # still generates a Mypy warning
```
"""
cls._abc_inst_check_cache[inst_t] = True
cls._abc_inst_check_cache_overridden[inst_t] = True
cls._dirty_for(inst_t)
|
Clears any cached instance check for inst_t.
Source code in numerary/protocol.py
155
156
157
158
159
160
161
162 | def reset_for(cls, inst_t: Type) -> None:
r"""
Clears any cached instance check for *inst_t*.
"""
if inst_t in cls._abc_inst_check_cache:
del cls._abc_inst_check_cache[inst_t]
del cls._abc_inst_check_cache_overridden[inst_t]
cls._dirty_for(inst_t)
|