1- from typing import Callable as _Callable , List as _List
1+ from typing import Callable as _Callable , Dict as _Dict , ClassVar as _ClassVar
22from misc .codegen .lib import schema as _schema
33import inspect as _inspect
44from dataclasses import dataclass as _dataclass
@@ -62,11 +62,14 @@ def include(source: str):
6262 _inspect .currentframe ().f_back .f_locals .setdefault ("includes" , []).append (source )
6363
6464
65+ @_dataclass
6566class _Namespace :
6667 """ simple namespacing mechanism """
68+ name : str
6769
68- def __init__ (self , ** kwargs ):
69- self .__dict__ .update (kwargs )
70+ def add (self , pragma : "_PragmaBase" , key : str | None = None ):
71+ self .__dict__ [pragma .pragma ] = pragma
72+ pragma .pragma = key or f"{ self .name } _{ pragma .pragma } "
7073
7174
7275@_dataclass
@@ -77,51 +80,86 @@ def modify(self, prop: _schema.Property):
7780 prop .synth = self .synth
7881
7982 def negate (self ) -> "PropertyModifier" :
80- return _SynthModifier (False )
83+ return _SynthModifier (self .name , False )
84+
85+
86+ qltest = _Namespace ("qltest" )
87+ ql = _Namespace ("ql" )
88+ cpp = _Namespace ("cpp" )
89+ rust = _Namespace ("rust" )
90+ synth = _SynthModifier ("synth" )
91+
92+
93+ @_dataclass
94+ class _PragmaBase :
95+ pragma : str
96+
97+
98+ @_dataclass
99+ class _ClassPragma (_PragmaBase ):
100+ """ A class pragma.
101+ For schema classes it acts as a python decorator with `@`.
102+ """
103+ value : object = None
81104
105+ def __call__ (self , cls : type ) -> type :
106+ """ use this pragma as a decorator on classes """
107+ # not using hasattr as we don't want to land on inherited pragmas
108+ if "_pragmas" not in cls .__dict__ :
109+ cls ._pragmas = {}
110+ self ._apply (cls ._pragmas )
111+ return cls
82112
83- qltest = _Namespace ()
84- ql = _Namespace ()
85- cpp = _Namespace ()
86- rust = _Namespace ()
87- synth = _SynthModifier ()
113+ def _apply (self , pragmas : _Dict [str , object ]) -> None :
114+ pragmas [self .pragma ] = self .value
88115
89116
90117@_dataclass
91- class _Pragma (_schema .PropertyModifier ):
118+ class _Pragma (_ClassPragma , _schema .PropertyModifier ):
92119 """ A class or property pragma.
93120 For properties, it functions similarly to a `_PropertyModifier` with `|`, adding the pragma.
94121 For schema classes it acts as a python decorator with `@`.
95122 """
96- pragma : str
97123 remove : bool = False
98124
99- def __post_init__ (self ):
100- namespace , _ , name = self .pragma .partition ('_' )
101- setattr (globals ()[namespace ], name , self )
102-
103125 def modify (self , prop : _schema .Property ):
104126 self ._apply (prop .pragmas )
105127
106128 def negate (self ) -> "PropertyModifier" :
107129 return _Pragma (self .pragma , remove = True )
108130
109- def __call__ (self , cls : type ) -> type :
110- """ use this pragma as a decorator on classes """
111- if "_pragmas" in cls .__dict__ : # not using hasattr as we don't want to land on inherited pragmas
112- self ._apply (cls ._pragmas )
113- elif not self .remove :
114- cls ._pragmas = [self .pragma ]
115- return cls
116-
117- def _apply (self , pragmas : _List [str ]) -> None :
131+ def _apply (self , pragmas : _Dict [str , object ]) -> None :
118132 if self .remove :
119- try :
120- pragmas .remove (self .pragma )
121- except ValueError :
122- pass
133+ pragmas .pop (self .pragma , None )
123134 else :
124- pragmas .append (self .pragma )
135+ super ()._apply (pragmas )
136+
137+
138+ @_dataclass
139+ class _ParametrizedClassPragma (_PragmaBase ):
140+ """ A class parametrized pragma.
141+ Needs to be applied to a parameter to give a class pragma.
142+ """
143+ _pragma_class : _ClassVar [type ] = _ClassPragma
144+
145+ function : _Callable [..., object ] = None
146+
147+ def __post_init__ (self ):
148+ self .__signature__ = _inspect .signature (self .function ).replace (return_annotation = self ._pragma_class )
149+
150+ def __call__ (self , * args , ** kwargs ) -> _pragma_class :
151+ return self ._pragma_class (self .pragma , value = self .function (* args , ** kwargs ))
152+
153+
154+ @_dataclass
155+ class _ParametrizedPragma (_ParametrizedClassPragma ):
156+ """ A class or property parametrized pragma.
157+ Needs to be applied to a parameter to give a pragma.
158+ """
159+ _pragma_class : _ClassVar [type ] = _Pragma
160+
161+ def __invert__ (self ) -> _Pragma :
162+ return _Pragma (self .pragma , remove = True )
125163
126164
127165class _Optionalizer (_schema .PropertyModifier ):
@@ -190,30 +228,30 @@ def f(cls: type) -> type:
190228
191229use_for_null = _annotate (null = True )
192230
193- _Pragma ("qltest_skip" )
194- _Pragma ( "qltest_collapse_hierarchy" )
195- _Pragma ( "qltest_uncollapse_hierarchy" )
196- qltest .test_with = lambda cls : _annotate (test_with = cls )
231+ qltest . add ( _Pragma ("skip" ) )
232+ qltest . add ( _ClassPragma ( "collapse_hierarchy" ) )
233+ qltest . add ( _ClassPragma ( "uncollapse_hierarchy" ) )
234+ qltest .test_with = lambda cls : _annotate (test_with = cls ) # inheritable
197235
198- ql .default_doc_name = lambda doc : _annotate ( doc_name = doc )
199- ql .hideable = _annotate (hideable = True )
200- _Pragma ("ql_internal" )
236+ ql .add ( _ParametrizedClassPragma ( " default_doc_name" , lambda doc : doc ) )
237+ ql .hideable = _annotate (hideable = True ) # inheritable
238+ ql . add ( _Pragma ("internal" ) )
201239
202- _Pragma ("cpp_skip" )
240+ cpp . add ( _Pragma ("skip" ) )
203241
204- _Pragma ("rust_skip_doc_test" )
242+ rust . add ( _Pragma ("skip_doc_test" ) )
205243
206- rust .doc_test_signature = lambda signature : _annotate ( rust_doc_test_function = signature )
244+ rust .add ( _ParametrizedClassPragma ( " doc_test_signature" , lambda signature : signature ) )
207245
208246
209247def group (name : str = "" ) -> _ClassDecorator :
210248 return _annotate (group = name )
211249
212250
213- synth .from_class = lambda ref : _annotate ( synth = _schema .SynthInfo (
214- from_class = _schema .get_type_name (ref )))
215- synth .on_arguments = lambda ** kwargs : _annotate (
216- synth = _schema .SynthInfo (on_arguments = {k : _schema .get_type_name (t ) for k , t in kwargs .items ()}))
251+ synth .add ( _ParametrizedClassPragma ( " from_class" , lambda ref : _schema .SynthInfo (
252+ from_class = _schema .get_type_name (ref ))), key = "synth" )
253+ synth .add ( _ParametrizedClassPragma ( " on_arguments" , lambda ** kwargs :
254+ _schema .SynthInfo (on_arguments = {k : _schema .get_type_name (t ) for k , t in kwargs .items ()})), key = "synth" )
217255
218256
219257class _PropertyModifierList (_schema .PropertyModifier ):
@@ -251,9 +289,9 @@ def decorator(cls: type) -> _PropertyAnnotation:
251289 if cls .__doc__ is not None :
252290 annotated_cls .__doc__ = cls .__doc__
253291 old_pragmas = getattr (annotated_cls , "_pragmas" , None )
254- new_pragmas = getattr (cls , "_pragmas" , [] )
292+ new_pragmas = getattr (cls , "_pragmas" , {} )
255293 if old_pragmas :
256- old_pragmas .extend (new_pragmas )
294+ old_pragmas .update (new_pragmas )
257295 else :
258296 annotated_cls ._pragmas = new_pragmas
259297 for a , v in cls .__dict__ .items ():
0 commit comments