lionweb 0.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- lionweb/__init__.py +2 -0
- lionweb/api/__init__.py +0 -0
- lionweb/api/classifier_instance_resolver.py +30 -0
- lionweb/api/composite_classifier_instance_resolver.py +29 -0
- lionweb/api/local_classifier_instance_resolver.py +24 -0
- lionweb/api/unresolved_classifier_instance_exception.py +8 -0
- lionweb/generation/__init__.py +0 -0
- lionweb/generation/deserializer_generation.py +165 -0
- lionweb/generation/generator.py +54 -0
- lionweb/generation/language_generation.py +332 -0
- lionweb/generation/node_classes_generation.py +519 -0
- lionweb/generation/utils.py +21 -0
- lionweb/language/__init__.py +22 -0
- lionweb/language/annotation.py +110 -0
- lionweb/language/classifier.py +184 -0
- lionweb/language/concept.py +127 -0
- lionweb/language/containment.py +87 -0
- lionweb/language/data_type.py +23 -0
- lionweb/language/debug_utils.py +20 -0
- lionweb/language/enumeration.py +40 -0
- lionweb/language/enumeration_literal.py +93 -0
- lionweb/language/feature.py +93 -0
- lionweb/language/field.py +80 -0
- lionweb/language/ikeyed.py +14 -0
- lionweb/language/inamed.py +9 -0
- lionweb/language/interface.py +80 -0
- lionweb/language/language.py +187 -0
- lionweb/language/language_entity.py +82 -0
- lionweb/language/link.py +66 -0
- lionweb/language/lioncore_builtins.py +164 -0
- lionweb/language/namespace_provider.py +13 -0
- lionweb/language/namespaced_entity.py +31 -0
- lionweb/language/primitive_type.py +28 -0
- lionweb/language/property.py +132 -0
- lionweb/language/reference.py +113 -0
- lionweb/language/structured_data_type.py +57 -0
- lionweb/lionweb_version.py +20 -0
- lionweb/model/__init__.py +2 -0
- lionweb/model/annotation_instance.py +20 -0
- lionweb/model/classifier_instance.py +73 -0
- lionweb/model/classifier_instance_utils.py +176 -0
- lionweb/model/has_feature_values.py +50 -0
- lionweb/model/has_settable_parent.py +10 -0
- lionweb/model/impl/__init__.py +0 -0
- lionweb/model/impl/abstract_classifier_instance.py +109 -0
- lionweb/model/impl/dynamic_annotation_instance.py +74 -0
- lionweb/model/impl/dynamic_classifier_instance.py +246 -0
- lionweb/model/impl/dynamic_node.py +117 -0
- lionweb/model/impl/dynamic_structured_datype_instance.py +64 -0
- lionweb/model/impl/enumeration_value.py +15 -0
- lionweb/model/impl/enumeration_value_impl.py +35 -0
- lionweb/model/impl/m3node.py +216 -0
- lionweb/model/impl/proxy_node.py +90 -0
- lionweb/model/node.py +189 -0
- lionweb/model/reference_value.py +39 -0
- lionweb/model/structured_data_type_instance.py +28 -0
- lionweb/model/structured_data_type_instance_utils.py +70 -0
- lionweb/presentation/__init__.py +0 -0
- lionweb/presentation/show_nodes.py +228 -0
- lionweb/repoclient/__init__.py +1 -0
- lionweb/repoclient/repo_client.py +303 -0
- lionweb/self/__init__.py +0 -0
- lionweb/self/lioncore.py +447 -0
- lionweb/serialization/__init__.py +7 -0
- lionweb/serialization/abstract_serialization.py +528 -0
- lionweb/serialization/classifier_resolver.py +57 -0
- lionweb/serialization/data/__init__.py +0 -0
- lionweb/serialization/data/metapointer.py +63 -0
- lionweb/serialization/data/raw_reference_value.py +7 -0
- lionweb/serialization/data/serialized_chunk.py +70 -0
- lionweb/serialization/data/serialized_classifier_instance.py +168 -0
- lionweb/serialization/data/serialized_containment_value.py +32 -0
- lionweb/serialization/data/serialized_property_value.py +32 -0
- lionweb/serialization/data/serialized_reference_value.py +67 -0
- lionweb/serialization/data/used_language.py +77 -0
- lionweb/serialization/deserialization_exception.py +11 -0
- lionweb/serialization/deserialization_status.py +82 -0
- lionweb/serialization/instantiator.py +131 -0
- lionweb/serialization/json_serialization.py +114 -0
- lionweb/serialization/json_utils.py +6 -0
- lionweb/serialization/low_level_json_serialization.py +325 -0
- lionweb/serialization/map_based_resolver.py +23 -0
- lionweb/serialization/node_populator.py +149 -0
- lionweb/serialization/primitives_values_serialization.py +204 -0
- lionweb/serialization/serialization_provider.py +50 -0
- lionweb/serialization/serialization_utils.py +103 -0
- lionweb/serialization/serialized_json_comparison_utils.py +185 -0
- lionweb/serialization/unavailable_node_policy.py +13 -0
- lionweb/utils/__init__.py +0 -0
- lionweb/utils/autoresolve.py +3 -0
- lionweb/utils/common_checks.py +14 -0
- lionweb/utils/id_utils.py +5 -0
- lionweb/utils/invalid_name.py +6 -0
- lionweb/utils/issue.py +43 -0
- lionweb/utils/issue_severity.py +6 -0
- lionweb/utils/language_validator.py +246 -0
- lionweb/utils/model_comparator.py +306 -0
- lionweb/utils/naming.py +21 -0
- lionweb/utils/node_tree_validator.py +60 -0
- lionweb/utils/validation_result.py +33 -0
- lionweb/utils/validator.py +12 -0
- lionweb-0.2.0.dist-info/METADATA +262 -0
- lionweb-0.2.0.dist-info/RECORD +106 -0
- lionweb-0.2.0.dist-info/WHEEL +5 -0
- lionweb-0.2.0.dist-info/licenses/LICENSE.txt +201 -0
- lionweb-0.2.0.dist-info/top_level.txt +1 -0
lionweb/__init__.py
ADDED
lionweb/api/__init__.py
ADDED
|
File without changes
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
from typing import Any, Optional
|
|
3
|
+
|
|
4
|
+
from lionweb.api.unresolved_classifier_instance_exception import \
|
|
5
|
+
UnresolvedClassifierInstanceException
|
|
6
|
+
from lionweb.model.impl.proxy_node import ProxyNode
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class ClassifierInstanceResolver(ABC):
|
|
10
|
+
|
|
11
|
+
@abstractmethod
|
|
12
|
+
def resolve(self, instance_id: str) -> Optional[Any]:
|
|
13
|
+
"""Return the classifier instance or None if not found."""
|
|
14
|
+
pass
|
|
15
|
+
|
|
16
|
+
def can_resolve(self, instance_id: str) -> bool:
|
|
17
|
+
"""Return True if the instance can be resolved, False otherwise."""
|
|
18
|
+
return self.resolve(instance_id) is not None
|
|
19
|
+
|
|
20
|
+
def strictly_resolve(self, instance_id: str) -> Any:
|
|
21
|
+
"""Return the classifier instance or raise an exception if not found."""
|
|
22
|
+
instance = self.resolve(instance_id)
|
|
23
|
+
if instance is None:
|
|
24
|
+
raise UnresolvedClassifierInstanceException(instance_id)
|
|
25
|
+
return instance
|
|
26
|
+
|
|
27
|
+
def resolve_or_proxy(self, instance_id: str) -> Any:
|
|
28
|
+
"""Return the classifier instance or a ProxyNode if not found."""
|
|
29
|
+
instance = self.resolve(instance_id)
|
|
30
|
+
return instance if instance is not None else ProxyNode(instance_id)
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
from typing import List, Optional
|
|
2
|
+
|
|
3
|
+
from lionweb.api.classifier_instance_resolver import ClassifierInstanceResolver
|
|
4
|
+
from lionweb.model import ClassifierInstance
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class CompositeClassifierInstanceResolver(ClassifierInstanceResolver):
|
|
8
|
+
def __init__(self, *classifier_instance_resolvers: ClassifierInstanceResolver):
|
|
9
|
+
self.classifier_instance_resolvers: List[ClassifierInstanceResolver] = list(
|
|
10
|
+
classifier_instance_resolvers
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
def add(
|
|
14
|
+
self, classifier_instance_resolver: ClassifierInstanceResolver
|
|
15
|
+
) -> "CompositeClassifierInstanceResolver":
|
|
16
|
+
self.classifier_instance_resolvers.append(classifier_instance_resolver)
|
|
17
|
+
return self
|
|
18
|
+
|
|
19
|
+
def resolve(self, instance_id: str) -> Optional[ClassifierInstance]:
|
|
20
|
+
for resolver in self.classifier_instance_resolvers:
|
|
21
|
+
instance = resolver.resolve(instance_id)
|
|
22
|
+
if instance is not None:
|
|
23
|
+
return instance
|
|
24
|
+
return None
|
|
25
|
+
|
|
26
|
+
def __str__(self) -> str:
|
|
27
|
+
return (
|
|
28
|
+
f"CompositeClassifierInstanceResolver({self.classifier_instance_resolvers})"
|
|
29
|
+
)
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
from lionweb.api.classifier_instance_resolver import ClassifierInstanceResolver
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class LocalClassifierInstanceResolver(ClassifierInstanceResolver):
|
|
5
|
+
def __init__(self, *instances):
|
|
6
|
+
self.instances = {instance.id: instance for instance in instances}
|
|
7
|
+
|
|
8
|
+
def add(self, instance):
|
|
9
|
+
self.instances[instance.id] = instance
|
|
10
|
+
|
|
11
|
+
def resolve(self, instance_id):
|
|
12
|
+
return self.instances.get(instance_id)
|
|
13
|
+
|
|
14
|
+
def add_all(self, instances):
|
|
15
|
+
for instance in instances:
|
|
16
|
+
self.add(instance)
|
|
17
|
+
|
|
18
|
+
def add_tree(self, root):
|
|
19
|
+
self.add(root)
|
|
20
|
+
for child in root.get_children():
|
|
21
|
+
self.add_tree(child)
|
|
22
|
+
|
|
23
|
+
def __str__(self):
|
|
24
|
+
return f"LocalClassifierInstanceResolver({list(self.instances.keys())})"
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
class UnresolvedClassifierInstanceException(RuntimeError):
|
|
2
|
+
|
|
3
|
+
def __init__(self, instance_id: str):
|
|
4
|
+
super().__init__("Unable to resolve classifier instance with ID=" + instance_id)
|
|
5
|
+
self._instance_id = instance_id
|
|
6
|
+
|
|
7
|
+
def get_instance_id(self) -> str:
|
|
8
|
+
return self._instance_id
|
|
File without changes
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import ast
|
|
2
|
+
from _ast import stmt
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import List, cast
|
|
5
|
+
|
|
6
|
+
import astor # type: ignore
|
|
7
|
+
|
|
8
|
+
from lionweb.language import Concept, Language
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def deserializer_generation(click, language: Language, output):
|
|
12
|
+
module_body = []
|
|
13
|
+
|
|
14
|
+
# Import statements
|
|
15
|
+
module_body.append(
|
|
16
|
+
ast.ImportFrom(
|
|
17
|
+
module="gen.language",
|
|
18
|
+
names=[
|
|
19
|
+
ast.alias(name=f"get_{cast(str, c.get_name()).lower()}", asname=None)
|
|
20
|
+
for c in language.get_elements()
|
|
21
|
+
if isinstance(c, Concept)
|
|
22
|
+
],
|
|
23
|
+
level=0,
|
|
24
|
+
)
|
|
25
|
+
)
|
|
26
|
+
module_body.append(
|
|
27
|
+
ast.ImportFrom(
|
|
28
|
+
module="gen.node_classes",
|
|
29
|
+
names=[
|
|
30
|
+
ast.alias(name=cast(str, c.get_name()), asname=None)
|
|
31
|
+
for c in language.get_elements()
|
|
32
|
+
if isinstance(c, Concept)
|
|
33
|
+
],
|
|
34
|
+
level=0,
|
|
35
|
+
)
|
|
36
|
+
)
|
|
37
|
+
module_body.append(
|
|
38
|
+
ast.ImportFrom(
|
|
39
|
+
module="lionweb.serialization",
|
|
40
|
+
names=[ast.alias(name="AbstractSerialization", asname=None)],
|
|
41
|
+
level=0,
|
|
42
|
+
)
|
|
43
|
+
)
|
|
44
|
+
module_body.append(
|
|
45
|
+
ast.ImportFrom(
|
|
46
|
+
module="lionweb.serialization.data.serialized_classifier_instance",
|
|
47
|
+
names=[ast.alias(name="SerializedClassifierInstance", asname=None)],
|
|
48
|
+
level=0,
|
|
49
|
+
)
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
register_func_body: List[stmt] = []
|
|
53
|
+
for language_element in language.get_elements():
|
|
54
|
+
if isinstance(language_element, Concept):
|
|
55
|
+
concept_name = cast(str, language_element.get_name())
|
|
56
|
+
# deserializer() inner function
|
|
57
|
+
register_func_body.append(
|
|
58
|
+
ast.FunctionDef(
|
|
59
|
+
name=f"deserializer_{concept_name.lower()}",
|
|
60
|
+
args=ast.arguments(
|
|
61
|
+
posonlyargs=[],
|
|
62
|
+
args=[
|
|
63
|
+
ast.arg(arg="classifier"),
|
|
64
|
+
ast.arg(
|
|
65
|
+
arg="serialized_instance",
|
|
66
|
+
annotation=ast.Name(
|
|
67
|
+
id="SerializedClassifierInstance", ctx=ast.Load()
|
|
68
|
+
),
|
|
69
|
+
),
|
|
70
|
+
ast.arg(arg="deserialized_instances_by_id"),
|
|
71
|
+
ast.arg(arg="properties_values"),
|
|
72
|
+
],
|
|
73
|
+
kwonlyargs=[],
|
|
74
|
+
kw_defaults=[],
|
|
75
|
+
defaults=[],
|
|
76
|
+
),
|
|
77
|
+
body=[
|
|
78
|
+
ast.Return(
|
|
79
|
+
value=ast.Call(
|
|
80
|
+
func=ast.Name(id=concept_name, ctx=ast.Load()),
|
|
81
|
+
args=[
|
|
82
|
+
ast.Attribute(
|
|
83
|
+
value=ast.Name(
|
|
84
|
+
id="serialized_instance", ctx=ast.Load()
|
|
85
|
+
),
|
|
86
|
+
attr="id",
|
|
87
|
+
ctx=ast.Load(),
|
|
88
|
+
)
|
|
89
|
+
],
|
|
90
|
+
keywords=[],
|
|
91
|
+
)
|
|
92
|
+
)
|
|
93
|
+
],
|
|
94
|
+
decorator_list=[],
|
|
95
|
+
returns=None,
|
|
96
|
+
)
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
# register_deserializers() function
|
|
100
|
+
register_func_body.append(
|
|
101
|
+
ast.Expr(
|
|
102
|
+
value=ast.Call(
|
|
103
|
+
func=ast.Attribute(
|
|
104
|
+
value=ast.Attribute(
|
|
105
|
+
value=ast.Name(id="serialization", ctx=ast.Load()),
|
|
106
|
+
attr="instantiator",
|
|
107
|
+
ctx=ast.Load(),
|
|
108
|
+
),
|
|
109
|
+
attr="register_custom_deserializer",
|
|
110
|
+
ctx=ast.Load(),
|
|
111
|
+
),
|
|
112
|
+
args=[
|
|
113
|
+
ast.Attribute(
|
|
114
|
+
value=ast.Call(
|
|
115
|
+
func=ast.Name(
|
|
116
|
+
id=f"get_{concept_name.lower()}", ctx=ast.Load()
|
|
117
|
+
),
|
|
118
|
+
args=[],
|
|
119
|
+
keywords=[],
|
|
120
|
+
),
|
|
121
|
+
attr="id",
|
|
122
|
+
ctx=ast.Load(),
|
|
123
|
+
)
|
|
124
|
+
],
|
|
125
|
+
keywords=[
|
|
126
|
+
ast.keyword(
|
|
127
|
+
arg="deserializer",
|
|
128
|
+
value=ast.Name(
|
|
129
|
+
id=f"deserializer_{concept_name.lower()}",
|
|
130
|
+
ctx=ast.Load(),
|
|
131
|
+
),
|
|
132
|
+
)
|
|
133
|
+
],
|
|
134
|
+
)
|
|
135
|
+
)
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
register_func = ast.FunctionDef(
|
|
139
|
+
name="register_deserializers",
|
|
140
|
+
args=ast.arguments(
|
|
141
|
+
posonlyargs=[],
|
|
142
|
+
args=[
|
|
143
|
+
ast.arg(
|
|
144
|
+
arg="serialization",
|
|
145
|
+
annotation=ast.Name(id="AbstractSerialization", ctx=ast.Load()),
|
|
146
|
+
)
|
|
147
|
+
],
|
|
148
|
+
kwonlyargs=[],
|
|
149
|
+
kw_defaults=[],
|
|
150
|
+
defaults=[],
|
|
151
|
+
),
|
|
152
|
+
body=register_func_body,
|
|
153
|
+
decorator_list=[],
|
|
154
|
+
returns=None,
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
# Final module
|
|
158
|
+
module = ast.Module(body=module_body + [register_func], type_ignores=[])
|
|
159
|
+
|
|
160
|
+
generated_code = astor.to_source(module)
|
|
161
|
+
output_path = Path(output)
|
|
162
|
+
output_path.mkdir(parents=True, exist_ok=True)
|
|
163
|
+
click.echo(f"📂 Saving deserializer to: {output}")
|
|
164
|
+
with Path(f"{output}/deserializer.py").open("w", encoding="utf-8") as f:
|
|
165
|
+
f.write(generated_code)
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
from typing import cast
|
|
2
|
+
|
|
3
|
+
import click
|
|
4
|
+
|
|
5
|
+
from lionweb.generation.language_generation import language_generation
|
|
6
|
+
from lionweb.language import Language
|
|
7
|
+
from lionweb.lionweb_version import LionWebVersion
|
|
8
|
+
from lionweb.serialization.serialization_provider import SerializationProvider
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@click.command()
|
|
12
|
+
@click.option(
|
|
13
|
+
"-d",
|
|
14
|
+
"--dependencies",
|
|
15
|
+
type=click.Path(exists=True, dir_okay=False, readable=True),
|
|
16
|
+
multiple=True,
|
|
17
|
+
)
|
|
18
|
+
@click.argument(
|
|
19
|
+
"lionweb-language", type=click.Path(exists=True, dir_okay=False, readable=True)
|
|
20
|
+
)
|
|
21
|
+
@click.argument("output", type=click.Path(exists=False, file_okay=False, writable=True))
|
|
22
|
+
def main(dependencies, lionweb_language, output):
|
|
23
|
+
from lionweb.generation.deserializer_generation import \
|
|
24
|
+
deserializer_generation
|
|
25
|
+
from lionweb.generation.node_classes_generation import \
|
|
26
|
+
node_classes_generation
|
|
27
|
+
|
|
28
|
+
"""Simple CLI that processes a file and writes results to a directory."""
|
|
29
|
+
serialization = SerializationProvider.get_standard_json_serialization(
|
|
30
|
+
LionWebVersion.V2023_1
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
for dep in dependencies:
|
|
34
|
+
click.echo(f"Processing dependency {dep}")
|
|
35
|
+
with open(dep, "r", encoding="utf-8") as f:
|
|
36
|
+
content = f.read()
|
|
37
|
+
language = cast(
|
|
38
|
+
Language, serialization.deserialize_string_to_nodes(content)[0]
|
|
39
|
+
)
|
|
40
|
+
serialization.register_language(language=language)
|
|
41
|
+
serialization.classifier_resolver.register_language(language)
|
|
42
|
+
serialization.instance_resolver.add_tree(language)
|
|
43
|
+
|
|
44
|
+
click.echo(f"📄 Processing file: {lionweb_language}")
|
|
45
|
+
with open(lionweb_language, "r", encoding="utf-8") as f:
|
|
46
|
+
content = f.read()
|
|
47
|
+
language = cast(Language, serialization.deserialize_string_to_nodes(content)[0])
|
|
48
|
+
language_generation(click, language, output)
|
|
49
|
+
node_classes_generation(click, language, output)
|
|
50
|
+
deserializer_generation(click, language, output)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
if __name__ == "__main__":
|
|
54
|
+
main()
|
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
import ast
|
|
2
|
+
from _ast import expr, stmt
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import List, cast
|
|
5
|
+
|
|
6
|
+
import astor # type: ignore
|
|
7
|
+
|
|
8
|
+
from lionweb.language import (Concept, Containment, DataType, Language,
|
|
9
|
+
LionCoreBuiltins, Property)
|
|
10
|
+
from lionweb.language.reference import Reference
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _set_lw_version(language: Language):
|
|
14
|
+
return ast.keyword(
|
|
15
|
+
arg="lion_web_version",
|
|
16
|
+
value=ast.Attribute(
|
|
17
|
+
value=ast.Name(id="LionWebVersion", ctx=ast.Load()),
|
|
18
|
+
attr=language.get_lionweb_version().name,
|
|
19
|
+
ctx=ast.Load(),
|
|
20
|
+
),
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _generate_language(language: Language) -> ast.Assign:
|
|
25
|
+
return ast.Assign(
|
|
26
|
+
targets=[ast.Name(id="language", ctx=ast.Store())],
|
|
27
|
+
value=ast.Call(
|
|
28
|
+
func=ast.Name(id="Language", ctx=ast.Load()),
|
|
29
|
+
args=[],
|
|
30
|
+
keywords=[
|
|
31
|
+
_set_lw_version(language),
|
|
32
|
+
ast.keyword(arg="id", value=ast.Constant(value=language.id)),
|
|
33
|
+
ast.keyword(arg="name", value=ast.Constant(value=language.get_name())),
|
|
34
|
+
ast.keyword(arg="key", value=ast.Constant(value=language.key)),
|
|
35
|
+
ast.keyword(
|
|
36
|
+
arg="version", value=ast.Constant(value=language.get_version())
|
|
37
|
+
),
|
|
38
|
+
],
|
|
39
|
+
),
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def language_generation(click, language: Language, output):
|
|
44
|
+
body: List[stmt] = []
|
|
45
|
+
body.append(
|
|
46
|
+
ast.ImportFrom(
|
|
47
|
+
module="lionweb.language",
|
|
48
|
+
names=[
|
|
49
|
+
ast.alias(name="Language", asname=None),
|
|
50
|
+
ast.alias(name="Concept", asname=None),
|
|
51
|
+
ast.alias(name="Property", asname=None),
|
|
52
|
+
ast.alias(name="Containment", asname=None),
|
|
53
|
+
ast.alias(name="Reference", asname=None),
|
|
54
|
+
ast.alias(name="LionCoreBuiltins", asname=None),
|
|
55
|
+
],
|
|
56
|
+
level=0,
|
|
57
|
+
)
|
|
58
|
+
)
|
|
59
|
+
body.append(
|
|
60
|
+
ast.ImportFrom(
|
|
61
|
+
module="lionweb.lionweb_version",
|
|
62
|
+
names=[ast.alias(name="LionWebVersion", asname=None)],
|
|
63
|
+
level=0,
|
|
64
|
+
)
|
|
65
|
+
)
|
|
66
|
+
body.append(
|
|
67
|
+
ast.ImportFrom(
|
|
68
|
+
module="functools",
|
|
69
|
+
names=[ast.alias(name="lru_cache", asname=None)],
|
|
70
|
+
level=0,
|
|
71
|
+
)
|
|
72
|
+
)
|
|
73
|
+
# Decorator: @lru_cache(maxsize=1)
|
|
74
|
+
decorator = ast.Call(
|
|
75
|
+
func=ast.Name(id="lru_cache", ctx=ast.Load()),
|
|
76
|
+
args=[],
|
|
77
|
+
keywords=[ast.keyword(arg="maxsize", value=ast.Constant(value=1))],
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
# Function body for get_language()
|
|
81
|
+
function_body: List[stmt] = []
|
|
82
|
+
function_body.append(_generate_language(language))
|
|
83
|
+
|
|
84
|
+
for language_element in language.get_elements():
|
|
85
|
+
if isinstance(language_element, Concept):
|
|
86
|
+
concept_name = cast(str, language_element.get_name())
|
|
87
|
+
function_body.append(
|
|
88
|
+
ast.Assign(
|
|
89
|
+
targets=[ast.Name(id=concept_name, ctx=ast.Store())],
|
|
90
|
+
value=ast.Call(
|
|
91
|
+
func=ast.Name(id="Concept", ctx=ast.Load()),
|
|
92
|
+
args=[],
|
|
93
|
+
keywords=[
|
|
94
|
+
_set_lw_version(language),
|
|
95
|
+
ast.keyword(
|
|
96
|
+
arg="id", value=ast.Constant(value=language_element.id)
|
|
97
|
+
),
|
|
98
|
+
ast.keyword(
|
|
99
|
+
arg="name", value=ast.Constant(value=concept_name)
|
|
100
|
+
),
|
|
101
|
+
ast.keyword(
|
|
102
|
+
arg="key",
|
|
103
|
+
value=ast.Constant(value=language_element.key),
|
|
104
|
+
),
|
|
105
|
+
],
|
|
106
|
+
),
|
|
107
|
+
)
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
if language_element.get_extended_concept():
|
|
111
|
+
ec = cast(Concept, language_element.get_extended_concept())
|
|
112
|
+
ec_name = cast(str, ec.get_name())
|
|
113
|
+
function_body.append(
|
|
114
|
+
ast.Expr(
|
|
115
|
+
ast.Call(
|
|
116
|
+
func=ast.Attribute(
|
|
117
|
+
value=ast.Name(id=concept_name, ctx=ast.Load()),
|
|
118
|
+
attr="set_extended_concept",
|
|
119
|
+
ctx=ast.Load(),
|
|
120
|
+
),
|
|
121
|
+
args=[ast.Name(id=ec_name, ctx=ast.Load())],
|
|
122
|
+
keywords=[],
|
|
123
|
+
)
|
|
124
|
+
)
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
for interf in language_element.get_implemented():
|
|
128
|
+
function_body.append(
|
|
129
|
+
ast.Expr(
|
|
130
|
+
ast.Call(
|
|
131
|
+
func=ast.Attribute(
|
|
132
|
+
value=ast.Name(id=concept_name, ctx=ast.Load()),
|
|
133
|
+
attr="add_implemented",
|
|
134
|
+
ctx=ast.Load(),
|
|
135
|
+
),
|
|
136
|
+
args=[],
|
|
137
|
+
keywords=[],
|
|
138
|
+
)
|
|
139
|
+
)
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
# language.add_element(concept1)
|
|
143
|
+
function_body.append(
|
|
144
|
+
ast.Expr(
|
|
145
|
+
value=ast.Call(
|
|
146
|
+
func=ast.Attribute(
|
|
147
|
+
value=ast.Name(id="language", ctx=ast.Load()),
|
|
148
|
+
attr="add_element",
|
|
149
|
+
ctx=ast.Load(),
|
|
150
|
+
),
|
|
151
|
+
args=[ast.Name(id=concept_name, ctx=ast.Load())],
|
|
152
|
+
keywords=[],
|
|
153
|
+
)
|
|
154
|
+
)
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
for feature in language_element.get_features():
|
|
158
|
+
if isinstance(feature, Reference):
|
|
159
|
+
feature_creation = ast.Call(
|
|
160
|
+
func=ast.Name(id="Reference", ctx=ast.Load()),
|
|
161
|
+
args=[],
|
|
162
|
+
keywords=[
|
|
163
|
+
_set_lw_version(language),
|
|
164
|
+
ast.keyword(arg="id", value=ast.Constant(value=feature.id)),
|
|
165
|
+
ast.keyword(
|
|
166
|
+
arg="name", value=ast.Constant(value=feature.get_name())
|
|
167
|
+
),
|
|
168
|
+
ast.keyword(
|
|
169
|
+
arg="key", value=ast.Constant(value=feature.key)
|
|
170
|
+
),
|
|
171
|
+
],
|
|
172
|
+
)
|
|
173
|
+
function_body.append(
|
|
174
|
+
ast.Expr(
|
|
175
|
+
value=ast.Call(
|
|
176
|
+
func=ast.Attribute(
|
|
177
|
+
value=ast.Name(id=concept_name, ctx=ast.Load()),
|
|
178
|
+
attr="add_feature",
|
|
179
|
+
ctx=ast.Load(),
|
|
180
|
+
),
|
|
181
|
+
args=[feature_creation],
|
|
182
|
+
keywords=[],
|
|
183
|
+
)
|
|
184
|
+
)
|
|
185
|
+
)
|
|
186
|
+
elif isinstance(feature, Property):
|
|
187
|
+
pt = cast(DataType, feature.type)
|
|
188
|
+
property_type: expr
|
|
189
|
+
if pt == LionCoreBuiltins.get_string(feature.lion_web_version):
|
|
190
|
+
property_type = ast.Call(
|
|
191
|
+
func=ast.Attribute(
|
|
192
|
+
value=ast.Name(id="LionCoreBuiltins", ctx=ast.Load()),
|
|
193
|
+
attr="get_string",
|
|
194
|
+
ctx=ast.Load(),
|
|
195
|
+
),
|
|
196
|
+
args=[],
|
|
197
|
+
keywords=[_set_lw_version(language)],
|
|
198
|
+
)
|
|
199
|
+
elif pt == LionCoreBuiltins.get_integer(feature.lion_web_version):
|
|
200
|
+
property_type = ast.Call(
|
|
201
|
+
func=ast.Attribute(
|
|
202
|
+
value=ast.Name(id="LionCoreBuiltins", ctx=ast.Load()),
|
|
203
|
+
attr="get_integer",
|
|
204
|
+
ctx=ast.Load(),
|
|
205
|
+
),
|
|
206
|
+
args=[],
|
|
207
|
+
keywords=[_set_lw_version(language)],
|
|
208
|
+
)
|
|
209
|
+
else:
|
|
210
|
+
raise ValueError(cast(str, pt.get_name()))
|
|
211
|
+
feature_creation = ast.Call(
|
|
212
|
+
func=ast.Name(id="Property", ctx=ast.Load()),
|
|
213
|
+
args=[],
|
|
214
|
+
keywords=[
|
|
215
|
+
_set_lw_version(language),
|
|
216
|
+
ast.keyword(arg="id", value=ast.Constant(value=feature.id)),
|
|
217
|
+
ast.keyword(
|
|
218
|
+
arg="name", value=ast.Constant(value=feature.get_name())
|
|
219
|
+
),
|
|
220
|
+
ast.keyword(
|
|
221
|
+
arg="key", value=ast.Constant(value=feature.key)
|
|
222
|
+
),
|
|
223
|
+
ast.keyword(arg="type", value=property_type),
|
|
224
|
+
],
|
|
225
|
+
)
|
|
226
|
+
function_body.append(
|
|
227
|
+
ast.Expr(
|
|
228
|
+
value=ast.Call(
|
|
229
|
+
func=ast.Attribute(
|
|
230
|
+
value=ast.Name(id=concept_name, ctx=ast.Load()),
|
|
231
|
+
attr="add_feature",
|
|
232
|
+
ctx=ast.Load(),
|
|
233
|
+
),
|
|
234
|
+
args=[feature_creation],
|
|
235
|
+
keywords=[],
|
|
236
|
+
)
|
|
237
|
+
)
|
|
238
|
+
)
|
|
239
|
+
elif isinstance(feature, Containment):
|
|
240
|
+
feature_creation = ast.Call(
|
|
241
|
+
func=ast.Name(id="Containment", ctx=ast.Load()),
|
|
242
|
+
args=[],
|
|
243
|
+
keywords=[
|
|
244
|
+
_set_lw_version(language),
|
|
245
|
+
ast.keyword(arg="id", value=ast.Constant(value=feature.id)),
|
|
246
|
+
ast.keyword(
|
|
247
|
+
arg="name", value=ast.Constant(value=feature.get_name())
|
|
248
|
+
),
|
|
249
|
+
ast.keyword(
|
|
250
|
+
arg="key", value=ast.Constant(value=feature.key)
|
|
251
|
+
),
|
|
252
|
+
],
|
|
253
|
+
)
|
|
254
|
+
function_body.append(
|
|
255
|
+
ast.Expr(
|
|
256
|
+
value=ast.Call(
|
|
257
|
+
func=ast.Attribute(
|
|
258
|
+
value=ast.Name(id=concept_name, ctx=ast.Load()),
|
|
259
|
+
attr="add_feature",
|
|
260
|
+
ctx=ast.Load(),
|
|
261
|
+
),
|
|
262
|
+
args=[feature_creation],
|
|
263
|
+
keywords=[],
|
|
264
|
+
)
|
|
265
|
+
)
|
|
266
|
+
)
|
|
267
|
+
|
|
268
|
+
# return language
|
|
269
|
+
function_body.append(ast.Return(value=ast.Name(id="language", ctx=ast.Load())))
|
|
270
|
+
|
|
271
|
+
# Define get_language function
|
|
272
|
+
get_language_def = ast.FunctionDef(
|
|
273
|
+
name="get_language",
|
|
274
|
+
args=ast.arguments(
|
|
275
|
+
posonlyargs=[], args=[], kwonlyargs=[], kw_defaults=[], defaults=[]
|
|
276
|
+
),
|
|
277
|
+
body=function_body,
|
|
278
|
+
decorator_list=[decorator],
|
|
279
|
+
returns=ast.Name(id="Language", ctx=ast.Load()),
|
|
280
|
+
type_comment=None,
|
|
281
|
+
)
|
|
282
|
+
|
|
283
|
+
# Wrap function in module
|
|
284
|
+
body.append(get_language_def)
|
|
285
|
+
|
|
286
|
+
for language_element in language.get_elements():
|
|
287
|
+
if isinstance(language_element, Concept):
|
|
288
|
+
concept_name = cast(str, language_element.get_name())
|
|
289
|
+
body.append(
|
|
290
|
+
ast.FunctionDef(
|
|
291
|
+
name=f"get_{concept_name.lower()}",
|
|
292
|
+
args=ast.arguments(
|
|
293
|
+
posonlyargs=[],
|
|
294
|
+
args=[],
|
|
295
|
+
kwonlyargs=[],
|
|
296
|
+
kw_defaults=[],
|
|
297
|
+
defaults=[],
|
|
298
|
+
),
|
|
299
|
+
body=[
|
|
300
|
+
ast.Return(
|
|
301
|
+
value=ast.Call(
|
|
302
|
+
func=ast.Attribute(
|
|
303
|
+
value=ast.Call(
|
|
304
|
+
func=ast.Name(
|
|
305
|
+
id="get_language", ctx=ast.Load()
|
|
306
|
+
),
|
|
307
|
+
args=[],
|
|
308
|
+
keywords=[],
|
|
309
|
+
),
|
|
310
|
+
attr="get_concept_by_name",
|
|
311
|
+
ctx=ast.Load(),
|
|
312
|
+
),
|
|
313
|
+
args=[ast.Constant(value=language_element.get_name())],
|
|
314
|
+
keywords=[],
|
|
315
|
+
)
|
|
316
|
+
)
|
|
317
|
+
],
|
|
318
|
+
decorator_list=[],
|
|
319
|
+
returns=ast.Name(id="Concept", ctx=ast.Load()),
|
|
320
|
+
type_comment=None,
|
|
321
|
+
)
|
|
322
|
+
)
|
|
323
|
+
|
|
324
|
+
module = ast.Module(body=body, type_ignores=[])
|
|
325
|
+
|
|
326
|
+
click.echo(f"📂 Saving language to: {output}")
|
|
327
|
+
generated_code = astor.to_source(module)
|
|
328
|
+
output_path = Path(output)
|
|
329
|
+
output_path.mkdir(parents=True, exist_ok=True)
|
|
330
|
+
|
|
331
|
+
with Path(f"{output}/language.py").open("w", encoding="utf-8") as f:
|
|
332
|
+
f.write(generated_code)
|