1
1
from abc import ABC , abstractmethod
2
- from typing import Optional , Any , Union , Iterable , Self , Mapping , Final , Callable , _UnionGenericAlias
2
+ from typing import Optional , Any , Union , Iterable , Self , Protocol , Final , TypeVar , Generic , Type , Callable , _UnionGenericAlias
3
3
4
4
5
- class FormalAnnotation :
6
- """
7
- Class allowing to formally specify additional information about the input
8
- resource.
9
-
10
- When annotating, returns the input.
11
-
12
- Can be called via [] with some resource.
13
- """
14
-
15
- def __init__ (self , instance_doc : Optional [str ] = None ):
16
- if instance_doc is not None :
17
- self .__doc__ = instance_doc
18
-
19
- def __repr__ (self ) -> str :
20
- return f"<{ self .__class__ .__name__ } >"
21
-
22
- def __getitem__ (self , resource : Any ) -> Any :
23
- return resource
5
+ __all__ = (
6
+ "AnnotationTemplate" , "FormalAnnotation" , "Special" , "Subgroup" ,
7
+ "input_annotation" , "number" , "many_or_one" , "method_of"
8
+ )
24
9
25
10
26
- class AnnotationFactory (ABC ):
11
+ class _AnnotationFactory (ABC ):
27
12
"""
28
13
Annotation factory class.
29
14
Creates annotation by input other.
@@ -46,7 +31,7 @@ def _create_full_annotation_by(self, annotation: Any) -> Any:
46
31
"""Annotation Creation Method from an input annotation."""
47
32
48
33
49
- class InputAnnotationAnnotation :
34
+ class _InputAnnotationAnnotation :
50
35
"""
51
36
Singleton class for the annotation of the conditional empty space, in which
52
37
the input type in the CustomAnnotationFactory should be placed.
@@ -72,46 +57,50 @@ def __ror__(self, other: Any) -> Union:
72
57
return Union [other , self ]
73
58
74
59
75
- class AnnotationTemplate (AnnotationFactory ):
60
+ class _ItemStorage (Protocol ):
61
+ @abstractmethod
62
+ def __getitem__ (self , key : Any ) -> Any :
63
+ pass
64
+
65
+
66
+ class AnnotationTemplate (_AnnotationFactory ):
76
67
"""
77
- AnnotationFactory class delegating the construction of another factory's
68
+ _AnnotationFactory class delegating the construction of another factory's
78
69
annotation.
79
70
80
- When called, replaces the InputAnnotationAnnotation instances from its
71
+ When called, replaces the _InputAnnotationAnnotation instances from its
81
72
arguments and their subcollections with the input annotation.
82
73
83
74
Templateizes Union.
84
75
76
+ Recognize nesting of annotations only by `list` i.e
77
+ ```
78
+ AnnotationTemplate(Callable, [[input_annotation], Any]) # works
79
+ AnnotationTemplate(Callable, [(input_annotation, ), Any]) # does not work
80
+ ```
81
+
85
82
Delegates responsibilities to other templates when passing them as
86
83
annotations.
87
84
"""
88
85
89
- def __init__ (self , original_factory : Mapping , annotations : Iterable ):
90
- self ._original_factory = original_factory
86
+ def __init__ (self , factory : _ItemStorage , annotations : list ):
87
+ self ._factory = factory
91
88
self ._annotations = tuple (annotations )
92
89
93
- @property
94
- def original_factory (self ) -> Mapping :
95
- return self ._original_factory
96
-
97
- @property
98
- def annotations (self ) -> tuple :
99
- return self ._annotations
100
-
101
90
def __repr__ (self ) -> str :
102
91
return "{factory}{arguments}" .format (
103
92
factory = (
104
- self ._original_factory .__name__
105
- if hasattr (self ._original_factory , '__name__' )
106
- else self ._original_factory
93
+ self ._factory .__name__
94
+ if hasattr (self ._factory , '__name__' )
95
+ else self ._factory
107
96
),
108
97
arguments = str (self .__recursively_format (self ._annotations )).replace ('\' ' , str ())
109
98
)
110
99
111
100
def _create_full_annotation_by (self , annotation : Any ) -> Any :
112
101
formatted_annotations = self .__get_formatted_annotations_from (self ._annotations , annotation )
113
102
114
- return self ._original_factory [
103
+ return self ._factory [
115
104
formatted_annotations [0 ]
116
105
if len (formatted_annotations ) == 1
117
106
else formatted_annotations
@@ -127,10 +116,10 @@ def __get_formatted_annotations_from(self, annotations: Iterable, replacement_an
127
116
formatted_annotations = list ()
128
117
129
118
for annotation in annotations :
130
- if isinstance (annotation , InputAnnotationAnnotation ):
119
+ if isinstance (annotation , _InputAnnotationAnnotation ):
131
120
annotation = replacement_annotation
132
121
133
- elif isinstance (annotation , Iterable ) and not isinstance ( annotation , str ):
122
+ elif isinstance (annotation , list ):
134
123
annotation = self .__get_formatted_annotations_from (
135
124
annotation ,
136
125
replacement_annotation
@@ -170,6 +159,27 @@ def __recursively_format(self, collection: Iterable) -> list:
170
159
return formatted_collection
171
160
172
161
162
+ class FormalAnnotation :
163
+ """
164
+ Class allowing to formally specify additional information about the input
165
+ resource.
166
+
167
+ When annotating, returns the input.
168
+
169
+ Can be called via [] with some resource.
170
+ """
171
+
172
+ def __init__ (self , instance_doc : Optional [str ] = None ):
173
+ if instance_doc is not None :
174
+ self .__doc__ = instance_doc
175
+
176
+ def __repr__ (self ) -> str :
177
+ return f"<{ self .__class__ .__name__ } >"
178
+
179
+ def __getitem__ (self , resource : Any ) -> Any :
180
+ return resource
181
+
182
+
173
183
class Special :
174
184
"""
175
185
Annotation class for formally specifying specific behavior for subclasses.
@@ -183,7 +193,7 @@ class Special:
183
193
"""
184
194
185
195
def __class_getitem__ (cls , annotation_resource : tuple [Any , Any ] | Any ) -> Any :
186
- if not isinstance (annotation_resource , Iterable ):
196
+ if not isinstance (annotation_resource , tuple ):
187
197
return Any
188
198
189
199
elif len (annotation_resource ) != 2 :
@@ -194,18 +204,54 @@ def __class_getitem__(cls, annotation_resource: tuple[Any, Any] | Any) -> Any:
194
204
return annotation_resource [1 ]
195
205
196
206
197
- number : Final = int | float | complex
207
+ _BasicT = TypeVar ("_BasicT" )
208
+
209
+
210
+ class Subgroup (Generic [_BasicT ]):
211
+ """
212
+ Class for defining a subgroup in an already existing type.
213
+
214
+ Delegates the definition of a subgroup from a particular type to
215
+ `determinant` attribute.
216
+ """
217
+
218
+ def __init__ (self , type_ : Type [_BasicT ], determinant : Callable [[_BasicT ], bool ]):
219
+ self ._type = type_
220
+ self ._determinant = determinant
221
+
222
+ @property
223
+ def type_ (self ) -> Type [_BasicT ]:
224
+ return self ._type
225
+
226
+ @property
227
+ def determinant (self ) -> Callable [[_BasicT ], bool ]:
228
+ return self ._determinant
229
+
230
+ def __instancecheck__ (self , instance : Any ) -> bool :
231
+ return self ._has (instance )
232
+
233
+ def __contains__ (self , object_ : Any ) -> bool :
234
+ return self ._has (object_ )
235
+
236
+ def __repr__ (self ) -> str :
237
+ return f"<{ self .__class__ .__name__ } of { self ._type .__name__ } >"
238
+
239
+ def _has (self , object_ : Any ) -> bool :
240
+ return isinstance (object_ , self .type_ ) and self ._determinant (object_ )
241
+
198
242
199
243
# Pre-created instance without permanent formal creation of a new one.
200
- input_annotation : Final [InputAnnotationAnnotation ] = InputAnnotationAnnotation ()
244
+ input_annotation : Final [_InputAnnotationAnnotation ] = _InputAnnotationAnnotation ()
245
+
246
+
247
+ number : Final = int | float | complex
201
248
202
249
203
250
many_or_one : Final [AnnotationTemplate ] = AnnotationTemplate (
204
251
Union ,
205
252
[input_annotation , AnnotationTemplate (Iterable , [input_annotation ])]
206
253
)
207
254
208
-
209
255
method_of : Final [AnnotationTemplate ] = AnnotationTemplate (
210
256
Callable ,
211
257
[[input_annotation , ...], Any ]
0 commit comments