1
1
from abc import ABC , abstractmethod
2
- from typing import Optional , Union , Iterable , Self , Mapping , Final , Callable , _UnionGenericAlias
2
+ from typing import Optional , Any , Union , Iterable , Self , Mapping , Final , Callable , _UnionGenericAlias
3
3
4
4
5
5
class FormalAnnotation :
@@ -19,7 +19,7 @@ def __init__(self, instance_doc: Optional[str] = None):
19
19
def __repr__ (self ) -> str :
20
20
return f"<{ self .__class__ .__name__ } >"
21
21
22
- def __getitem__ (self , resource : any ) -> any :
22
+ def __getitem__ (self , resource : Any ) -> Any :
23
23
return resource
24
24
25
25
@@ -31,18 +31,18 @@ class AnnotationFactory(ABC):
31
31
Can be used via [] (preferred) or by normal call.
32
32
"""
33
33
34
- def __call__ (self , annotation : any ) -> any :
34
+ def __call__ (self , annotation : Any ) -> Any :
35
35
return self ._create_full_annotation_by (annotation )
36
36
37
- def __getitem__ (self , annotation : any ) -> any :
37
+ def __getitem__ (self , annotation : Any ) -> Any :
38
38
return self ._create_full_annotation_by (
39
39
Union [annotation ]
40
40
if isinstance (annotation , Iterable )
41
41
else annotation
42
42
)
43
43
44
44
@abstractmethod
45
- def _create_full_annotation_by (self , annotation : any ) -> any :
45
+ def _create_full_annotation_by (self , annotation : Any ) -> Any :
46
46
"""Annotation Creation Method from an input annotation."""
47
47
48
48
@@ -65,20 +65,25 @@ def __new__(cls, *args, **kwargs):
65
65
def __repr__ (self ) -> str :
66
66
return '<input_annotation>'
67
67
68
- def __or__ (self , other : any ) -> Union :
68
+ def __or__ (self , other : Any ) -> Union :
69
69
return Union [self , other ]
70
70
71
- def __ror__ (self , other : any ) -> Union :
71
+ def __ror__ (self , other : Any ) -> Union :
72
72
return Union [other , self ]
73
73
74
74
75
- class CustomAnnotationFactory (AnnotationFactory ):
75
+ class AnnotationTemplate (AnnotationFactory ):
76
76
"""
77
77
AnnotationFactory class delegating the construction of another factory's
78
78
annotation.
79
79
80
80
When called, replaces the InputAnnotationAnnotation instances from its
81
81
arguments and their subcollections with the input annotation.
82
+
83
+ Templateizes Union.
84
+
85
+ Delegates responsibilities to other templates when passing them as
86
+ annotations.
82
87
"""
83
88
84
89
def __init__ (self , original_factory : Mapping , annotations : Iterable ):
@@ -103,12 +108,16 @@ def __repr__(self) -> str:
103
108
arguments = str (self .__recursively_format (self ._annotations )).replace ('\' ' , str ())
104
109
)
105
110
106
- def _create_full_annotation_by (self , annotation : any ) -> any :
111
+ def _create_full_annotation_by (self , annotation : Any ) -> Any :
112
+ formatted_annotations = self .__get_formatted_annotations_from (self ._annotations , annotation )
113
+
107
114
return self ._original_factory [
108
- * self .__get_formatted_annotations_from (self ._annotations , annotation )
115
+ formatted_annotations [0 ]
116
+ if len (formatted_annotations ) == 1
117
+ else formatted_annotations
109
118
]
110
119
111
- def __get_formatted_annotations_from (self , annotations : Iterable , replacement_annotation : any ) -> tuple :
120
+ def __get_formatted_annotations_from (self , annotations : Iterable , replacement_annotation : Any ) -> tuple :
112
121
"""
113
122
Recursive function to replace element(s) of the input collection (and
114
123
its subcollections) equal to the annotation anonation with the input
@@ -120,11 +129,16 @@ def __get_formatted_annotations_from(self, annotations: Iterable, replacement_an
120
129
for annotation in annotations :
121
130
if isinstance (annotation , InputAnnotationAnnotation ):
122
131
annotation = replacement_annotation
132
+
123
133
elif isinstance (annotation , Iterable ) and not isinstance (annotation , str ):
124
134
annotation = self .__get_formatted_annotations_from (
125
135
annotation ,
126
136
replacement_annotation
127
137
)
138
+
139
+ elif isinstance (annotation , AnnotationTemplate ):
140
+ annotation = annotation [replacement_annotation ]
141
+
128
142
elif type (annotation ) in (Union , _UnionGenericAlias , type (int | float )):
129
143
annotation = Union [
130
144
* self .__get_formatted_annotations_from (
@@ -156,7 +170,43 @@ def __recursively_format(self, collection: Iterable) -> list:
156
170
return formatted_collection
157
171
158
172
173
+ class Special :
174
+ """
175
+ Annotation class for formally specifying specific behavior for subclasses.
176
+
177
+ Returns the second input annotation, or Any if none.
178
+
179
+ Specifies additional behavior for the first annotation.
180
+
181
+ Implies use like Special[type_for_special_behavior, generic_type] or
182
+ Special[type_for_special_behavior].
183
+ """
184
+
185
+ def __class_getitem__ (cls , annotation_resource : tuple [Any , Any ] | Any ) -> Any :
186
+ if not isinstance (annotation_resource , Iterable ):
187
+ return Any
188
+
189
+ elif len (annotation_resource ) != 2 :
190
+ raise TypeError (
191
+ "Special must be used as Special[type_for_special_behavior, generic_type] or Special[type_for_special_behavior]"
192
+ )
193
+
194
+ return annotation_resource [1 ]
195
+
196
+
197
+ number : Final = int | float | complex
198
+
159
199
# Pre-created instance without permanent formal creation of a new one.
160
200
input_annotation : Final [InputAnnotationAnnotation ] = InputAnnotationAnnotation ()
161
201
162
- number : Final = int | float | complex
202
+
203
+ many_or_one : Final [AnnotationTemplate ] = AnnotationTemplate (
204
+ Union ,
205
+ [input_annotation , AnnotationTemplate (Iterable , [input_annotation ])]
206
+ )
207
+
208
+
209
+ method_of : Final [AnnotationTemplate ] = AnnotationTemplate (
210
+ Callable ,
211
+ [[input_annotation , ...], Any ]
212
+ )
0 commit comments