11from 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
33
44
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+ )
249
2510
26- class AnnotationFactory (ABC ):
11+ class _AnnotationFactory (ABC ):
2712 """
2813 Annotation factory class.
2914 Creates annotation by input other.
@@ -46,7 +31,7 @@ def _create_full_annotation_by(self, annotation: Any) -> Any:
4631 """Annotation Creation Method from an input annotation."""
4732
4833
49- class InputAnnotationAnnotation :
34+ class _InputAnnotationAnnotation :
5035 """
5136 Singleton class for the annotation of the conditional empty space, in which
5237 the input type in the CustomAnnotationFactory should be placed.
@@ -72,46 +57,50 @@ def __ror__(self, other: Any) -> Union:
7257 return Union [other , self ]
7358
7459
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 ):
7667 """
77- AnnotationFactory class delegating the construction of another factory's
68+ _AnnotationFactory class delegating the construction of another factory's
7869 annotation.
7970
80- When called, replaces the InputAnnotationAnnotation instances from its
71+ When called, replaces the _InputAnnotationAnnotation instances from its
8172 arguments and their subcollections with the input annotation.
8273
8374 Templateizes Union.
8475
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+
8582 Delegates responsibilities to other templates when passing them as
8683 annotations.
8784 """
8885
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
9188 self ._annotations = tuple (annotations )
9289
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-
10190 def __repr__ (self ) -> str :
10291 return "{factory}{arguments}" .format (
10392 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
10796 ),
10897 arguments = str (self .__recursively_format (self ._annotations )).replace ('\' ' , str ())
10998 )
11099
111100 def _create_full_annotation_by (self , annotation : Any ) -> Any :
112101 formatted_annotations = self .__get_formatted_annotations_from (self ._annotations , annotation )
113102
114- return self ._original_factory [
103+ return self ._factory [
115104 formatted_annotations [0 ]
116105 if len (formatted_annotations ) == 1
117106 else formatted_annotations
@@ -127,10 +116,10 @@ def __get_formatted_annotations_from(self, annotations: Iterable, replacement_an
127116 formatted_annotations = list ()
128117
129118 for annotation in annotations :
130- if isinstance (annotation , InputAnnotationAnnotation ):
119+ if isinstance (annotation , _InputAnnotationAnnotation ):
131120 annotation = replacement_annotation
132121
133- elif isinstance (annotation , Iterable ) and not isinstance ( annotation , str ):
122+ elif isinstance (annotation , list ):
134123 annotation = self .__get_formatted_annotations_from (
135124 annotation ,
136125 replacement_annotation
@@ -170,6 +159,27 @@ def __recursively_format(self, collection: Iterable) -> list:
170159 return formatted_collection
171160
172161
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+
173183class Special :
174184 """
175185 Annotation class for formally specifying specific behavior for subclasses.
@@ -183,7 +193,7 @@ class Special:
183193 """
184194
185195 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 ):
187197 return Any
188198
189199 elif len (annotation_resource ) != 2 :
@@ -194,18 +204,54 @@ def __class_getitem__(cls, annotation_resource: tuple[Any, Any] | Any) -> Any:
194204 return annotation_resource [1 ]
195205
196206
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+
198242
199243# 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
201248
202249
203250many_or_one : Final [AnnotationTemplate ] = AnnotationTemplate (
204251 Union ,
205252 [input_annotation , AnnotationTemplate (Iterable , [input_annotation ])]
206253)
207254
208-
209255method_of : Final [AnnotationTemplate ] = AnnotationTemplate (
210256 Callable ,
211257 [[input_annotation , ...], Any ]
0 commit comments