Skip to content

Commit 70997e8

Browse files
author
Paolo Tranquilli
committed
Codegen: move default_doc_name to parametrized pragma
1 parent 9f1d50e commit 70997e8

File tree

6 files changed

+83
-54
lines changed

6 files changed

+83
-54
lines changed

misc/codegen/generators/qlgen.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ def _get_doc(cls: schema.Class, prop: schema.Property, plural=None):
9696
return format.format(**{noun: transform(noun) for noun in nouns})
9797

9898
prop_name = _humanize(prop.name)
99-
class_name = cls.default_doc_name or _humanize(inflection.underscore(cls.name))
99+
class_name = cls.pragmas.get("ql_default_doc_name", _humanize(inflection.underscore(cls.name)))
100100
if prop.is_predicate:
101101
return f"this {class_name} {prop_name}"
102102
if plural is not None:

misc/codegen/lib/schema.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,6 @@ class Class:
9696
synth: Optional[Union[SynthInfo, bool]] = None
9797
"""^^^ filled with `True` for non-final classes with only synthesized final descendants """
9898
doc: List[str] = field(default_factory=list)
99-
default_doc_name: Optional[str] = None
10099
hideable: bool = False
101100
test_with: Optional[str] = None
102101
rust_doc_test_function: Optional["FunctionInfo"] = "() -> ()" # TODO: parametrized pragmas

misc/codegen/lib/schemadefs.py

Lines changed: 65 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import Callable as _Callable, Dict as _Dict
1+
from typing import Callable as _Callable, Dict as _Dict, ClassVar as _ClassVar
22
from misc.codegen.lib import schema as _schema
33
import inspect as _inspect
44
from 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
6566
class _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"):
71+
self.__dict__[pragma.pragma] = pragma
72+
pragma.pragma = f"{self.name}_{pragma.pragma}"
7073

7174

7275
@_dataclass
@@ -77,35 +80,27 @@ 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)
8184

8285

83-
qltest = _Namespace()
84-
ql = _Namespace()
85-
cpp = _Namespace()
86-
rust = _Namespace()
87-
synth = _SynthModifier()
86+
qltest = _Namespace("qltest")
87+
ql = _Namespace("ql")
88+
cpp = _Namespace("cpp")
89+
rust = _Namespace("rust")
90+
synth = _SynthModifier("synth")
8891

8992

9093
@_dataclass
91-
class _Pragma(_schema.PropertyModifier):
92-
""" A class or property pragma.
93-
For properties, it functions similarly to a `_PropertyModifier` with `|`, adding the pragma.
94-
For schema classes it acts as a python decorator with `@`.
95-
"""
94+
class _PragmaBase:
9695
pragma: str
97-
value: object = None
98-
remove: bool = False
99-
100-
def __post_init__(self):
101-
namespace, _, name = self.pragma.partition('_')
102-
setattr(globals()[namespace], name, self)
10396

104-
def modify(self, prop: _schema.Property):
105-
self._apply(prop.pragmas)
10697

107-
def negate(self) -> "PropertyModifier":
108-
return _Pragma(self.pragma, remove=True)
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
109104

110105
def __call__(self, cls: type) -> type:
111106
""" use this pragma as a decorator on classes """
@@ -115,23 +110,53 @@ def __call__(self, cls: type) -> type:
115110
self._apply(cls._pragmas)
116111
return cls
117112

113+
def _apply(self, pragmas: _Dict[str, object]) -> None:
114+
pragmas[self.pragma] = self.value
115+
116+
117+
@_dataclass
118+
class _Pragma(_ClassPragma, _schema.PropertyModifier):
119+
""" A class or property pragma.
120+
For properties, it functions similarly to a `_PropertyModifier` with `|`, adding the pragma.
121+
For schema classes it acts as a python decorator with `@`.
122+
"""
123+
remove: bool = False
124+
125+
def modify(self, prop: _schema.Property):
126+
self._apply(prop.pragmas)
127+
128+
def negate(self) -> "PropertyModifier":
129+
return _Pragma(self.pragma, remove=True)
130+
118131
def _apply(self, pragmas: _Dict[str, object]) -> None:
119132
if self.remove:
120133
pragmas.pop(self.pragma, None)
121134
else:
122-
pragmas[self.pragma] = self.value
135+
super()._apply(pragmas)
123136

124137

125138
@_dataclass
126-
class _ParametrizedPragma:
127-
""" A class or property parametrized pragma.
128-
Needs to be applied to a parameter to give a pragma.
139+
class _ParametrizedClassPragma(_PragmaBase):
140+
""" A class parametrized pragma.
141+
Needs to be applied to a parameter to give a class pragma.
129142
"""
130-
pragma: str
143+
_pragma_class: _ClassVar[type] = _ClassPragma
144+
131145
function: _Callable[[...], object] = None
132146

133-
def __call__(self, *args, **kwargs) -> _Pragma:
134-
return _Pragma(self.pragma, value=self.function(*args, **kwargs))
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
135160

136161
def __invert__(self) -> _Pragma:
137162
return _Pragma(self.pragma, remove=True)
@@ -203,18 +228,18 @@ def f(cls: type) -> type:
203228

204229
use_for_null = _annotate(null=True)
205230

206-
_Pragma("qltest_skip")
207-
_Pragma("qltest_collapse_hierarchy")
208-
_Pragma("qltest_uncollapse_hierarchy")
209-
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
210235

211-
ql.default_doc_name = lambda doc: _annotate(doc_name=doc)
212-
ql.hideable = _annotate(hideable=True)
213-
_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"))
214239

215-
_Pragma("cpp_skip")
240+
cpp.add(_Pragma("skip"))
216241

217-
_Pragma("rust_skip_doc_test")
242+
rust.add(_Pragma("skip_doc_test"))
218243

219244
rust.doc_test_signature = lambda signature: _annotate(rust_doc_test_function=signature)
220245

misc/codegen/loaders/schemaloader.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@ def _get_class(cls: type) -> schema.Class:
5656
for n, a in cls.__dict__.get("__annotations__", {}).items()
5757
],
5858
doc=schema.split_doc(cls.__doc__),
59-
default_doc_name=cls.__dict__.get("_doc_name"),
6059
rust_doc_test_function=cls.__dict__.get("_rust_doc_test_function",
6160
schema.Class.rust_doc_test_function)
6261
)

misc/codegen/test/test_qlgen.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -922,7 +922,7 @@ def test_property_on_class_with_default_doc_name(generate_classes):
922922
assert generate_classes([
923923
schema.Class("MyObject", properties=[
924924
schema.SingleProperty("foo", "bar")],
925-
default_doc_name="baz"),
925+
pragmas={"ql_default_doc_name": "baz"}),
926926
]) == {
927927
"MyObject.qll": (a_ql_class_public(name="MyObject"),
928928
a_ql_stub(name="MyObject"),

misc/codegen/test/test_schemaloader.py

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -269,15 +269,21 @@ class A:
269269
x: spec | defs.child
270270

271271

272-
_pragmas = [(defs.qltest.skip, "qltest_skip"),
273-
(defs.qltest.collapse_hierarchy, "qltest_collapse_hierarchy"),
274-
(defs.qltest.uncollapse_hierarchy, "qltest_uncollapse_hierarchy"),
275-
(defs.cpp.skip, "cpp_skip"),
276-
(defs.ql.internal, "ql_internal"),
277-
]
272+
_class_pragmas = [
273+
(defs.qltest.collapse_hierarchy, "qltest_collapse_hierarchy"),
274+
(defs.qltest.uncollapse_hierarchy, "qltest_uncollapse_hierarchy"),
275+
]
278276

277+
_property_pragmas = [
278+
(defs.qltest.skip, "qltest_skip"),
279+
(defs.cpp.skip, "cpp_skip"),
280+
(defs.ql.internal, "ql_internal"),
281+
]
279282

280-
@pytest.mark.parametrize("pragma,expected", _pragmas)
283+
_pragmas = _class_pragmas + _property_pragmas
284+
285+
286+
@pytest.mark.parametrize("pragma,expected", _property_pragmas)
281287
def test_property_with_pragma(pragma, expected):
282288
@load
283289
class data:
@@ -293,7 +299,7 @@ class A:
293299

294300
def test_property_with_pragmas():
295301
spec = defs.string
296-
for pragma, _ in _pragmas:
302+
for pragma, _ in _property_pragmas:
297303
spec |= pragma
298304

299305
@load
@@ -303,7 +309,7 @@ class A:
303309

304310
assert data.classes == {
305311
'A': schema.Class('A', properties=[
306-
schema.SingleProperty('x', 'string', pragmas=[expected for _, expected in _pragmas]),
312+
schema.SingleProperty('x', 'string', pragmas=[expected for _, expected in _property_pragmas]),
307313
]),
308314
}
309315

@@ -636,7 +642,7 @@ class A:
636642
pass
637643

638644
assert data.classes == {
639-
'A': schema.Class('A', default_doc_name="b"),
645+
'A': schema.Class('A', pragmas={"ql_default_doc_name": "b"}),
640646
}
641647

642648

0 commit comments

Comments
 (0)