pyMetaModel 0.5.2__tar.gz → 0.6.0__tar.gz
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.
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/.github/workflows/build.yml +4 -2
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/PKG-INFO +4 -6
- pymetamodel-0.6.0/meta/__init__.py +1 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/meta/metamodel.py +123 -115
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/meta/metamodel_cmd.py +1 -1
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/meta/mw.py +4 -2
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/meta/sidif2linkml.py +4 -1
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/meta/smw_type.py +3 -19
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/meta/uml.py +1 -1
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/pyproject.toml +11 -14
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/tests/test_linkml.py +1 -1
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/tests/test_metamodel.py +4 -4
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/tests/test_mw.py +10 -6
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/tests/test_sidif.py +9 -3
- pymetamodel-0.5.2/meta/__init__.py +0 -1
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/.github/workflows/upload-to-pypi.yml +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/.gitignore +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/.project +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/.pydevproject +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/LICENSE +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/README.md +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/docs/index.md +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/ceur-ws/ceur-ws.mermaid +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/ceur-ws/ceur-ws.puml +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/ceur-ws/ceur-ws.py +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/ceur-ws/ceur-ws.sidif +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/ceur-ws/ceur-ws.xlsx +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/ceur-ws/ceur-ws.yaml +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/ceur-ws/ceur-ws_puml.txt +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/city/city.mermaid +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/city/city.puml +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/city/city.py +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/city/city.sidif +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/city/city.xlsx +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/city/city.yaml +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/city/city_puml.txt +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/family/FamilyContext.mermaid +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/family/FamilyContext.puml +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/family/FamilyContext.py +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/family/FamilyContext.sidif +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/family/FamilyContext.xlsx +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/family/FamilyContext.yaml +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/family/FamilyContext_puml.txt +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/infrastructure/infrastructure.mermaid +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/infrastructure/infrastructure.puml +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/infrastructure/infrastructure.py +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/infrastructure/infrastructure.sidif +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/infrastructure/infrastructure.xlsx +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/infrastructure/infrastructure.yaml +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/infrastructure/infrastructure_puml.txt +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/metamodel/metamodel.mermaid +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/metamodel/metamodel.puml +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/metamodel/metamodel.py +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/metamodel/metamodel.sidif +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/metamodel/metamodel.xlsx +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/metamodel/metamodel.yaml +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/metamodel/metamodel_puml.txt +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/scientific-events/scientific-events.mermaid +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/scientific-events/scientific-events.puml +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/scientific-events/scientific-events.py +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/scientific-events/scientific-events.sidif +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/scientific-events/scientific-events.xlsx +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/scientific-events/scientific-events.yaml +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/scientific-events/scientific-events_puml.txt +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/smartRQM/smartRQM.mermaid +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/smartRQM/smartRQM.puml +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/smartRQM/smartRQM.py +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/smartRQM/smartRQM.sidif +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/smartRQM/smartRQM.yaml +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/smartRQM/smartRQM_puml.txt +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/smwcon/smwcon.mermaid +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/smwcon/smwcon.puml +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/smwcon/smwcon.py +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/smwcon/smwcon.sidif +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/smwcon/smwcon.xlsx +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/smwcon/smwcon.yaml +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/smwcon/smwcon_puml.txt +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/teaching/TeachingSchema.mermaid +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/teaching/TeachingSchema.puml +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/teaching/TeachingSchema.py +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/teaching/TeachingSchema.sidif +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/teaching/TeachingSchema.xlsx +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/teaching/TeachingSchema.yaml +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/teaching/TeachingSchema_puml.txt +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/wiki/wiki.mermaid +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/wiki/wiki.puml +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/wiki/wiki.py +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/wiki/wiki.sidif +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/wiki/wiki.xlsx +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/wiki/wiki.yaml +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/wiki/wiki_puml.txt +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/meta/profiler.py +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/meta/version.py +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/metamodel.puml +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/mkdocs.yml +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/scripts/blackisort +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/scripts/doc +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/scripts/genexamples +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/scripts/install +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/scripts/release +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/scripts/test +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/tests/__init__.py +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/tests/basemwtest.py +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/tests/basesmwtest.py +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/tests/basetest.py +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/tests/test_generators.py +0 -0
- {pymetamodel-0.5.2 → pymetamodel-0.6.0}/tests/test_plantuml.py +0 -0
|
@@ -18,8 +18,10 @@ jobs:
|
|
|
18
18
|
runs-on: ubuntu-latest
|
|
19
19
|
strategy:
|
|
20
20
|
matrix:
|
|
21
|
-
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
22
|
-
|
|
21
|
+
#os: [ubuntu-latest, macos-latest, windows-latest]
|
|
22
|
+
os: [ubuntu-latest]
|
|
23
|
+
#python-version: [ '3.9', '3.10', '3.11', '3.12' ]
|
|
24
|
+
python-version: [ '3.12' ]
|
|
23
25
|
|
|
24
26
|
steps:
|
|
25
27
|
- uses: actions/checkout@v4
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pyMetaModel
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.6.0
|
|
4
4
|
Dynamic: Summary
|
|
5
5
|
Project-URL: Home, https://github.com/WolfgangFahl/pyMetaModel
|
|
6
6
|
Project-URL: Documentation, https://wiki.bitplan.com/index.php/PyMetaModel
|
|
@@ -216,20 +216,18 @@ Classifier: Intended Audience :: Science/Research
|
|
|
216
216
|
Classifier: License :: OSI Approved :: Apache Software License
|
|
217
217
|
Classifier: Operating System :: OS Independent
|
|
218
218
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
219
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
220
219
|
Classifier: Programming Language :: Python :: 3.10
|
|
221
220
|
Classifier: Programming Language :: Python :: 3.11
|
|
222
221
|
Classifier: Programming Language :: Python :: 3.12
|
|
222
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
223
223
|
Classifier: Topic :: Software Development
|
|
224
|
-
Requires-Python: >=3.
|
|
225
|
-
Requires-Dist: dacite>=1.8.1
|
|
224
|
+
Requires-Python: >=3.10
|
|
226
225
|
Requires-Dist: py-sidif>=0.2.0
|
|
226
|
+
Requires-Dist: pybasemkit>=0.0.4
|
|
227
227
|
Requires-Dist: urllib3
|
|
228
228
|
Provides-Extra: linkml
|
|
229
229
|
Requires-Dist: linkml-runtime>=1.8.3; extra == 'linkml'
|
|
230
230
|
Requires-Dist: linkml>=1.8.5; extra == 'linkml'
|
|
231
|
-
Provides-Extra: lodstorage
|
|
232
|
-
Requires-Dist: pylodstorage>=0.13.3; extra == 'lodstorage'
|
|
233
231
|
Provides-Extra: smw
|
|
234
232
|
Requires-Dist: mwparserfromhell>=0.6.6; extra == 'smw'
|
|
235
233
|
Requires-Dist: py-3rdparty-mediawiki>=0.14.0; extra == 'smw'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.6.0"
|
|
@@ -4,66 +4,40 @@ Created on 2022-11-23
|
|
|
4
4
|
@author: wf
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
+
from dataclasses import field
|
|
8
|
+
from datetime import datetime
|
|
7
9
|
import sys
|
|
10
|
+
from typing import List, Optional, Tuple, Dict
|
|
8
11
|
import typing
|
|
9
|
-
from datetime import datetime
|
|
10
|
-
from typing import List, Optional, Tuple
|
|
11
|
-
|
|
12
|
-
import urllib3
|
|
13
|
-
from lodstorage.jsonable import JSONAble
|
|
14
|
-
from sidif.sidif import SiDIFParser
|
|
15
12
|
|
|
13
|
+
from basemkit.persistent_log import Log
|
|
14
|
+
from basemkit.yamlable import lod_storable
|
|
16
15
|
from meta.mw import MediaWikiContext
|
|
16
|
+
from meta.smw_type import SMW_Type
|
|
17
|
+
from sidif.sidif import SiDIFParser
|
|
18
|
+
import urllib3
|
|
17
19
|
|
|
18
20
|
|
|
19
|
-
class MetaModelElement(JSONAble):
|
|
20
|
-
"""
|
|
21
|
-
a generic MetaModelElement
|
|
22
|
-
|
|
23
|
-
to handle the technicalities of being a MetaModelElement so that derived
|
|
24
|
-
MetaModelElements can focus on the MetaModel domain specific aspects
|
|
25
|
-
"""
|
|
26
|
-
|
|
27
|
-
def __init__(self):
|
|
28
|
-
"""
|
|
29
|
-
construct me
|
|
30
|
-
"""
|
|
31
|
-
self.__metamodel_props = {}
|
|
32
|
-
cls = self.__class__
|
|
33
|
-
if hasattr(cls, "getSamples"):
|
|
34
|
-
for sample in cls.getSamples():
|
|
35
|
-
for key in sample.keys():
|
|
36
|
-
if not key in self.__metamodel_props:
|
|
37
|
-
self.__metamodel_props[key] = key # Property(self,key)
|
|
38
|
-
|
|
39
|
-
def __str__(self):
|
|
40
|
-
"""
|
|
41
|
-
get a string representation of me
|
|
42
|
-
"""
|
|
43
|
-
text = self.__class__.__name__
|
|
44
|
-
for prop_name in self.__metamodel_props.keys():
|
|
45
|
-
if not isinstance(prop_name, str):
|
|
46
|
-
pass
|
|
47
|
-
elif hasattr(self, prop_name):
|
|
48
|
-
value = getattr(self, prop_name)
|
|
49
|
-
text += f"\n {prop_name}={str(value)}"
|
|
50
|
-
return text
|
|
51
|
-
|
|
52
21
|
|
|
53
|
-
|
|
22
|
+
@lod_storable
|
|
23
|
+
class Context:
|
|
54
24
|
"""
|
|
55
25
|
A Context groups some topics like a Namespace/Package.
|
|
56
26
|
This class provides helper functions and constants to render a Context to corresponding wiki pages
|
|
57
27
|
"""
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
28
|
+
name: Optional[str] = None
|
|
29
|
+
since: Optional[str] = None # isodate string
|
|
30
|
+
updated: Optional[str] = None # isodate string
|
|
31
|
+
copyright: Optional[str] = None
|
|
32
|
+
master: Optional[str] = None
|
|
33
|
+
demo: Optional[str] = None
|
|
34
|
+
topics: Dict[str, 'Topic'] = field(default_factory=dict)
|
|
35
|
+
types: Dict[str, 'Topic'] = field(default_factory=dict)
|
|
36
|
+
errors: List[str] = field(default_factory=list)
|
|
37
|
+
|
|
38
|
+
def __post_init__(self):
|
|
39
|
+
self.log=Log()
|
|
40
|
+
pass
|
|
67
41
|
|
|
68
42
|
@classmethod
|
|
69
43
|
def getSamples(cls):
|
|
@@ -72,7 +46,7 @@ class Context(MetaModelElement):
|
|
|
72
46
|
"name": "MetaModel",
|
|
73
47
|
"since": datetime.strptime("2015-01-23", "%Y-%m-%d"),
|
|
74
48
|
"updated": datetime.strptime("2024-08-07", "%Y-%m-%d"),
|
|
75
|
-
"copyright": "2015-
|
|
49
|
+
"copyright": "2015-2025 BITPlan GmbH",
|
|
76
50
|
"master": "https://contexts.bitplan.com",
|
|
77
51
|
"demo": "https://wiki.bitplan.com/index.php/List_of_Contexts"
|
|
78
52
|
}
|
|
@@ -210,6 +184,7 @@ class Context(MetaModelElement):
|
|
|
210
184
|
prop.type = "Page"
|
|
211
185
|
prop.topicLink = tl
|
|
212
186
|
prop.isLink = True
|
|
187
|
+
prop.showInGrid = False
|
|
213
188
|
return prop
|
|
214
189
|
|
|
215
190
|
@classmethod
|
|
@@ -225,51 +200,53 @@ class Context(MetaModelElement):
|
|
|
225
200
|
"""
|
|
226
201
|
context = None
|
|
227
202
|
for key, record in did.items():
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
203
|
+
try:
|
|
204
|
+
isA = record.get("isA")
|
|
205
|
+
if isA == "Context":
|
|
206
|
+
context = Context.from_dict2(record)
|
|
207
|
+
context.sanitize(key)
|
|
208
|
+
elif isA == "TopicLink":
|
|
209
|
+
"""
|
|
210
|
+
# Event n : 1 City
|
|
211
|
+
Event_in_City isA TopicLink
|
|
212
|
+
"eventInCity" is name of it
|
|
213
|
+
"city" is sourceRole of it
|
|
214
|
+
false is sourceMultiple of it
|
|
215
|
+
"City" is source of it
|
|
216
|
+
"event" is targetRole of it
|
|
217
|
+
true is targetMultiple of it
|
|
218
|
+
"Event" is target of it
|
|
219
|
+
"""
|
|
220
|
+
tl = TopicLink.from_dict2(record)
|
|
221
|
+
context.addLink(tl)
|
|
222
|
+
elif isA == "Property":
|
|
223
|
+
prop = Property.from_dict2(record)
|
|
224
|
+
prop.sanitize()
|
|
225
|
+
context.addProperty(prop)
|
|
226
|
+
elif isA == "SMW_Type":
|
|
227
|
+
smw_type=SMW_Type.from_dict2(record) # @UndefinedVariable
|
|
228
|
+
context.types[smw_type.type]=smw_type
|
|
229
|
+
else: # isA == Topic or in declared topics
|
|
230
|
+
topic = Topic.from_dict2(record)
|
|
231
|
+
topic.sanitize()
|
|
232
|
+
if context is None:
|
|
233
|
+
context = Context()
|
|
234
|
+
context.name = "GlobalContext"
|
|
235
|
+
context.since = "2022-11-26"
|
|
236
|
+
context.master = "http://contexts.bitplan.com"
|
|
237
|
+
context.error(f"topic {topic.name} has no defined context")
|
|
238
|
+
if hasattr(topic, "name") and topic.name:
|
|
239
|
+
context.topics[topic.name] = topic
|
|
240
|
+
topic.context_obj=context
|
|
241
|
+
else:
|
|
242
|
+
# potential foreign or extends declaration
|
|
243
|
+
context.error(f"missing name for topic {topic} {key} - foreign declaration?")
|
|
244
|
+
except Exception as ex:
|
|
245
|
+
if context:
|
|
246
|
+
msg=f"invalid dict {record}: {str(ex)}"
|
|
247
|
+
context.log.log("❌","dict",msg)
|
|
269
248
|
else:
|
|
270
|
-
|
|
271
|
-
context.error(f"missing name for topic {topic} {key} - foreign declaration?")
|
|
272
|
-
|
|
249
|
+
raise ex
|
|
273
250
|
# link topic to concepts and add topicLinks
|
|
274
251
|
for topic in context.topics.values():
|
|
275
252
|
topic.setConceptProperty()
|
|
@@ -355,8 +332,9 @@ class Context(MetaModelElement):
|
|
|
355
332
|
error = None
|
|
356
333
|
errMsg = None
|
|
357
334
|
sidif = None
|
|
335
|
+
msg=f"reading sidif for {mw_context.context} from {mw_context.wikiId}"
|
|
358
336
|
if debug:
|
|
359
|
-
print(
|
|
337
|
+
print(msg)
|
|
360
338
|
try:
|
|
361
339
|
sidif = mw_context.read_sidif()
|
|
362
340
|
except BaseException as ex:
|
|
@@ -366,24 +344,29 @@ class Context(MetaModelElement):
|
|
|
366
344
|
context, error, errMsg = cls.fromSiDIF(
|
|
367
345
|
sidif=sidif, title=mw_context.wikiId, depth=depth, debug=debug
|
|
368
346
|
)
|
|
347
|
+
else:
|
|
348
|
+
errMsg=f"{msg} failed"
|
|
349
|
+
error=ValueError(msg)
|
|
369
350
|
return context, error, errMsg
|
|
370
351
|
|
|
371
|
-
|
|
372
|
-
class Topic
|
|
352
|
+
@lod_storable
|
|
353
|
+
class Topic:
|
|
373
354
|
"""
|
|
374
355
|
A Topic is a Concept/Class/Thing/Entity
|
|
375
356
|
"""
|
|
357
|
+
name: Optional[str] = None
|
|
358
|
+
_pluralName: Optional[str] = None
|
|
359
|
+
documentation: Optional[str] = None
|
|
360
|
+
wikiDocumentation: Optional[str] = None
|
|
361
|
+
defaultstoremode: str = "property"
|
|
362
|
+
extends: Optional[str] = None
|
|
363
|
+
context_obj: Optional[Context] = None
|
|
364
|
+
conceptProperty: Optional['Property'] = None
|
|
365
|
+
listLimit: int = 200
|
|
366
|
+
properties: Dict[str, 'Property'] = field(default_factory=dict)
|
|
367
|
+
sourceTopicLinks: Dict[str, 'TopicLink'] = field(default_factory=dict)
|
|
368
|
+
targetTopicLinks: Dict[str, 'TopicLink'] = field(default_factory=dict)
|
|
376
369
|
|
|
377
|
-
def __init__(self):
|
|
378
|
-
"""
|
|
379
|
-
constructor
|
|
380
|
-
"""
|
|
381
|
-
MetaModelElement.__init__(self)
|
|
382
|
-
self._pluralName = None # Initialize with underscore to indicate a protected attribute
|
|
383
|
-
|
|
384
|
-
self.properties = {}
|
|
385
|
-
self.sourceTopicLinks = {}
|
|
386
|
-
self.targetTopicLinks = {}
|
|
387
370
|
|
|
388
371
|
def get_extends_topics(self, l: List['Topic'] = None) -> List['Topic']:
|
|
389
372
|
"""
|
|
@@ -569,7 +552,7 @@ class Topic(MetaModelElement):
|
|
|
569
552
|
props_count = len(props)
|
|
570
553
|
|
|
571
554
|
# Sort properties locally by index
|
|
572
|
-
sorted_props = sorted(props, key=lambda p:
|
|
555
|
+
sorted_props = sorted(props, key=lambda p: p.index or props_count)
|
|
573
556
|
|
|
574
557
|
return sorted_props
|
|
575
558
|
|
|
@@ -637,16 +620,26 @@ class Topic(MetaModelElement):
|
|
|
637
620
|
markup += f"""{self.askSort()}}}}}"""
|
|
638
621
|
return markup
|
|
639
622
|
|
|
640
|
-
|
|
623
|
+
@lod_storable
|
|
624
|
+
class Property:
|
|
641
625
|
"""
|
|
642
626
|
Provides helper functions and constants for properties
|
|
643
627
|
"""
|
|
628
|
+
name: Optional[str] = None
|
|
629
|
+
label: Optional[str] = None
|
|
630
|
+
type: Optional[str] = None
|
|
631
|
+
topic: Optional[str] = None
|
|
632
|
+
documentation: Optional[str] = None
|
|
633
|
+
namespace: str = "Property"
|
|
634
|
+
showInGrid: bool = True
|
|
635
|
+
isLink: bool = False
|
|
636
|
+
topicLink: Optional['TopicLink'] = None
|
|
637
|
+
index: Optional[int] = None
|
|
638
|
+
sortPos: Optional[int] = None
|
|
639
|
+
primaryKey: bool = False
|
|
640
|
+
mandatory: bool = False
|
|
641
|
+
sortAscending: bool = True
|
|
644
642
|
|
|
645
|
-
def __init__(self):
|
|
646
|
-
"""
|
|
647
|
-
constructor
|
|
648
|
-
"""
|
|
649
|
-
MetaModelElement.__init__(self)
|
|
650
643
|
|
|
651
644
|
@classmethod
|
|
652
645
|
def getSamples(cls):
|
|
@@ -697,13 +690,28 @@ class Property(MetaModelElement):
|
|
|
697
690
|
self.topicLink=None
|
|
698
691
|
if hasattr(self, "scope"):
|
|
699
692
|
pass
|
|
693
|
+
if not hasattr(self, "showInGrid"):
|
|
694
|
+
self.showInGrid=True
|
|
700
695
|
pass
|
|
701
696
|
|
|
702
|
-
|
|
697
|
+
@lod_storable
|
|
698
|
+
class TopicLink:
|
|
703
699
|
"""
|
|
704
700
|
A TopicLink links two Concepts/Topics
|
|
705
701
|
"""
|
|
706
702
|
|
|
703
|
+
name: Optional[str] = None
|
|
704
|
+
source: Optional[str] = None
|
|
705
|
+
target: Optional[str] = None
|
|
706
|
+
sourceRole: Optional[str] = None
|
|
707
|
+
targetRole: Optional[str] = None
|
|
708
|
+
sourceMultiple: bool = False
|
|
709
|
+
targetMultiple: bool = False
|
|
710
|
+
sourceDocumentation: Optional[str] = None
|
|
711
|
+
targetDocumentation: Optional[str] = None
|
|
712
|
+
sourceTopic: Optional[Topic] = None
|
|
713
|
+
targetTopic: Optional[Topic] = None
|
|
714
|
+
|
|
707
715
|
@classmethod
|
|
708
716
|
def getSamples(cls):
|
|
709
717
|
samples = [
|
|
@@ -43,7 +43,7 @@ class MetaModelCmd:
|
|
|
43
43
|
program_license = """%s
|
|
44
44
|
|
|
45
45
|
Created by %s on %s.
|
|
46
|
-
Copyright 2022-
|
|
46
|
+
Copyright 2022-2025 Wolfgang Fahl. All rights reserved.
|
|
47
47
|
|
|
48
48
|
Licensed under the Apache License 2.0
|
|
49
49
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"""
|
|
2
|
-
Created on 23
|
|
2
|
+
Created on 2022-11-23
|
|
3
3
|
|
|
4
4
|
@author: wf
|
|
5
5
|
"""
|
|
@@ -40,7 +40,9 @@ class MediaWikiContext:
|
|
|
40
40
|
"""
|
|
41
41
|
sidif = None
|
|
42
42
|
wikiusers = WikiUser.getWikiUsers(lenient=True)
|
|
43
|
-
if self.wikiId in wikiusers:
|
|
43
|
+
if not self.wikiId in wikiusers:
|
|
44
|
+
raise ValueError(f"unknown wiki {self.wikiId}")
|
|
45
|
+
else:
|
|
44
46
|
wikiUser = wikiusers[self.wikiId]
|
|
45
47
|
self.wikiClient = WikiClient.ofWikiId(wikiUser.wikiId)
|
|
46
48
|
if self.wikiClient.needsLogin():
|
|
@@ -50,6 +50,8 @@ class SiDIF2LinkML:
|
|
|
50
50
|
master = "http://example.com"
|
|
51
51
|
uri = f"{master}/{context.name}"
|
|
52
52
|
for topic in self.context.topics.values():
|
|
53
|
+
if not topic.name:
|
|
54
|
+
continue
|
|
53
55
|
cd = ClassDefinition(name=topic.name)
|
|
54
56
|
cd.description = topic.documentation
|
|
55
57
|
sv.add_class(cd)
|
|
@@ -59,7 +61,8 @@ class SiDIF2LinkML:
|
|
|
59
61
|
qname = prop.name
|
|
60
62
|
if prop.name in sd.slots:
|
|
61
63
|
slot = sd.slots[prop.name]
|
|
62
|
-
|
|
64
|
+
if prop.documentation:
|
|
65
|
+
slot.description += "," + prop.documentation
|
|
63
66
|
else:
|
|
64
67
|
qname = f"{topic.name}{delim}{prop.name}"
|
|
65
68
|
if slot is None:
|
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
from dataclasses import dataclass
|
|
2
1
|
from typing import Optional
|
|
3
2
|
|
|
4
|
-
import
|
|
3
|
+
from basemkit.yamlable import lod_storable
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
@dataclass
|
|
5
|
+
@lod_storable
|
|
8
6
|
class SMW_Type:
|
|
9
7
|
"""
|
|
10
8
|
an SMW_Type is a data type which determines the possible values for that type e.g. a Boolean can hold true/false values while a Number can hold 3.1459 or 20. A Page can hold the name of a Wiki page see https://semantic-mediawiki.org/wiki/Help:List_of_datatypes
|
|
@@ -40,18 +38,4 @@ class SMW_Type:
|
|
|
40
38
|
|?SMW_Type javaType = javaType
|
|
41
39
|
| limit=200
|
|
42
40
|
}}"""
|
|
43
|
-
return ask
|
|
44
|
-
|
|
45
|
-
@classmethod
|
|
46
|
-
def fromDict(cls, data: dict)->'SMW_Type':
|
|
47
|
-
"""
|
|
48
|
-
create a SMW_Type from the given dict
|
|
49
|
-
|
|
50
|
-
Args:
|
|
51
|
-
data (dict): the dict to create the SMW_Type from
|
|
52
|
-
|
|
53
|
-
Returns:
|
|
54
|
-
SMW_Type: the freshly created SMW_Type
|
|
55
|
-
"""
|
|
56
|
-
smw_type = dacite.from_dict(data_class=cls, data=data)
|
|
57
|
-
return smw_type
|
|
41
|
+
return ask
|
|
@@ -17,7 +17,7 @@ class PlantUml(object):
|
|
|
17
17
|
# redundant to skinparams in pylodstorage.uml
|
|
18
18
|
skinparams = """
|
|
19
19
|
' BITPlan Corporate identity skin params
|
|
20
|
-
' Copyright (c) 2015-
|
|
20
|
+
' Copyright (c) 2015-2025 BITPlan GmbH
|
|
21
21
|
' see http://wiki.bitplan.com/PlantUmlSkinParams#BITPlanCI
|
|
22
22
|
' skinparams generated by com.bitplan.restmodelmanager
|
|
23
23
|
skinparam note {
|
|
@@ -17,23 +17,25 @@ readme = "README.md"
|
|
|
17
17
|
# flit_core.config.ConfigError: license field should be <class 'dict'>, not <class 'str'>
|
|
18
18
|
license = { file="LICENSE" }
|
|
19
19
|
dependencies = [
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
20
|
+
# https://pypi.org/project/pybasemkit/
|
|
21
|
+
# https://github.com/WolfgangFahl/pybasemkit
|
|
22
|
+
# Python base module kit: YAML/JSON I/O, structured logging, CLI tooling, shell execution, and remote pydevd debug support.
|
|
23
|
+
"pybasemkit>=0.0.4",
|
|
24
|
+
# https://pypi.org/project/py-sidif/
|
|
25
|
+
'py-sidif>=0.2.0',
|
|
26
|
+
# https://github.com/urllib3/urllib3
|
|
27
|
+
'urllib3',
|
|
28
|
+
]
|
|
27
29
|
|
|
28
|
-
requires-python = ">=3.
|
|
30
|
+
requires-python = ">=3.10"
|
|
29
31
|
classifiers=[
|
|
30
32
|
"Development Status :: 4 - Beta",
|
|
31
33
|
"Environment :: Web Environment",
|
|
32
34
|
"Programming Language :: Python :: 3 :: Only",
|
|
33
|
-
"Programming Language :: Python :: 3.9",
|
|
34
35
|
"Programming Language :: Python :: 3.10",
|
|
35
36
|
"Programming Language :: Python :: 3.11",
|
|
36
37
|
"Programming Language :: Python :: 3.12",
|
|
38
|
+
"Programming Language :: Python :: 3.13",
|
|
37
39
|
"Operating System :: OS Independent",
|
|
38
40
|
"Topic :: Software Development",
|
|
39
41
|
"Intended Audience :: Developers",
|
|
@@ -53,11 +55,6 @@ Source = "https://github.com/WolfgangFahl/pyMetaModel"
|
|
|
53
55
|
test = [
|
|
54
56
|
"green",
|
|
55
57
|
]
|
|
56
|
-
# python List of Dict (Table) Storage library
|
|
57
|
-
lodstorage = [
|
|
58
|
-
# https://pypi.org/project/pylodstorage/
|
|
59
|
-
'pyLodStorage>=0.13.3',
|
|
60
|
-
]
|
|
61
58
|
# LinkML support
|
|
62
59
|
# https://linkml.io/
|
|
63
60
|
linkml = [
|
|
@@ -29,7 +29,7 @@ class TestLinkML(BaseMediawikiTest):
|
|
|
29
29
|
test conversion from SiDIF to LinkML
|
|
30
30
|
"""
|
|
31
31
|
debug = self.debug
|
|
32
|
-
debug = True
|
|
32
|
+
#debug = True
|
|
33
33
|
parser = MetaModelCmd.getArgParser()
|
|
34
34
|
mm_cmd = MetaModelCmd(debug=debug)
|
|
35
35
|
for wikiId, context_name in [("wiki", "MetaModel"), ("cr", "CrSchema")]:
|
|
@@ -25,12 +25,12 @@ class TestMetaModel(BaseMediawikiTest):
|
|
|
25
25
|
"""
|
|
26
26
|
test SMW_Type handling
|
|
27
27
|
"""
|
|
28
|
-
debug =
|
|
28
|
+
debug = self.debug
|
|
29
29
|
smwAccess = self.smwAccessMap["wiki"]
|
|
30
30
|
ask_query = SMW_Type.askQuery()
|
|
31
31
|
did = smwAccess.smw.query(ask_query)
|
|
32
32
|
for record in did.values():
|
|
33
|
-
|
|
33
|
+
smw_type = SMW_Type.from_dict(record) # @UndefinedVariable
|
|
34
34
|
if debug:
|
|
35
|
-
print(
|
|
36
|
-
|
|
35
|
+
print(smw_type)
|
|
36
|
+
self.assertIsInstance(smw_type, SMW_Type)
|
|
@@ -7,7 +7,7 @@ Created on 2022-11-23
|
|
|
7
7
|
import json
|
|
8
8
|
|
|
9
9
|
from wikibot3rd.wikiuser import WikiUser
|
|
10
|
-
|
|
10
|
+
from tqdm import tqdm
|
|
11
11
|
from meta.metamodel import Context
|
|
12
12
|
from tests.basesmwtest import BaseSemanticMediawikiTest
|
|
13
13
|
|
|
@@ -137,13 +137,17 @@ class TestMediawiki(BaseSemanticMediawikiTest):
|
|
|
137
137
|
"""
|
|
138
138
|
test reading meta models from wikis
|
|
139
139
|
"""
|
|
140
|
-
debug =
|
|
140
|
+
debug = False
|
|
141
141
|
lenient = True
|
|
142
|
-
|
|
142
|
+
with_progress=False
|
|
143
|
+
wiki_users = WikiUser.getWikiUsers(lenient=True)
|
|
144
|
+
wiki_iter = tqdm(wiki_users, desc="Wikis") if with_progress else wiki_users
|
|
145
|
+
for wikiId in wiki_iter:
|
|
143
146
|
_smwAccess, mw_contexts = self.check_contexts(wikiId)
|
|
144
147
|
for context_name in mw_contexts:
|
|
148
|
+
context_info=f"{context_name}@{wikiId}"
|
|
145
149
|
if debug:
|
|
146
|
-
print(f"reading context {
|
|
150
|
+
print(f"reading context {context_info}")
|
|
147
151
|
cc = self.getContextContext(wikiId=wikiId, context_name=context_name)
|
|
148
152
|
context = cc.context
|
|
149
153
|
if not lenient:
|
|
@@ -156,8 +160,8 @@ class TestMediawiki(BaseSemanticMediawikiTest):
|
|
|
156
160
|
print(context)
|
|
157
161
|
for _name, topic in context.topics.items():
|
|
158
162
|
print(topic)
|
|
159
|
-
for _name,
|
|
160
|
-
print(
|
|
163
|
+
for _name, prop in topic.properties.items():
|
|
164
|
+
print(prop)
|
|
161
165
|
if len(context.errors) > 0:
|
|
162
166
|
for error in context.errors:
|
|
163
167
|
print(error)
|
|
@@ -18,6 +18,9 @@ class TestSiDIF(Basetest):
|
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
def check_sidif(self,sidif_path,file)->Context:
|
|
21
|
+
"""
|
|
22
|
+
check the given SiDIF input
|
|
23
|
+
"""
|
|
21
24
|
debug=self.debug
|
|
22
25
|
context, error, errMsg = Context.fromSiDIF_input(sidif_path, debug=debug)
|
|
23
26
|
self.assertFalse(error, f"Error in {file}: {errMsg}")
|
|
@@ -38,9 +41,12 @@ class TestSiDIF(Basetest):
|
|
|
38
41
|
|
|
39
42
|
# Check if all properties have names and types
|
|
40
43
|
for topic in context.topics.values():
|
|
41
|
-
for prop in topic.properties.
|
|
42
|
-
|
|
43
|
-
|
|
44
|
+
for key, prop in topic.properties.items():
|
|
45
|
+
for needed_prop in ["name", "type", "showInGrid"]:
|
|
46
|
+
self.assertTrue(
|
|
47
|
+
hasattr(prop, needed_prop),
|
|
48
|
+
f"Property '{key}' missing attribute '{needed_prop}' in {file}"
|
|
49
|
+
)
|
|
44
50
|
return context
|
|
45
51
|
|
|
46
52
|
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.5.2"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/scientific-events/scientific-events.mermaid
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pymetamodel-0.5.2 → pymetamodel-0.6.0}/examples/scientific-events/scientific-events_puml.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|