From 6ae3314fd11e9140ec728174fbd0440484721735 Mon Sep 17 00:00:00 2001 From: iripiri Date: Fri, 22 Apr 2022 14:22:06 +0000 Subject: [PATCH 1/6] generate json_ld files Signed-off-by: iripiri --- json_ld/__init__.py | 1 + json_ld/langPack.py | 113 ++++++++++++++++++++ json_ld/templates/json_ld_template.mustache | 27 +++++ 3 files changed, 141 insertions(+) create mode 100644 json_ld/__init__.py create mode 100644 json_ld/langPack.py create mode 100644 json_ld/templates/json_ld_template.mustache diff --git a/json_ld/__init__.py b/json_ld/__init__.py new file mode 100644 index 00000000..f2fb1323 --- /dev/null +++ b/json_ld/__init__.py @@ -0,0 +1 @@ +import json_ld.langPack \ No newline at end of file diff --git a/json_ld/langPack.py b/json_ld/langPack.py new file mode 100644 index 00000000..d1e36e8c --- /dev/null +++ b/json_ld/langPack.py @@ -0,0 +1,113 @@ +import os +import chevron +import logging +import glob +import sys +logger = logging.getLogger(__name__) + +# This makes sure we have somewhere to write the classes, and +# creates a couple of files the python implementation needs. +def setup(version_path): + if not os.path.exists(version_path): + os.makedirs(version_path) + _create_init(version_path) + _create_base(version_path) + +def location(version): + return "cimpy." + version + ".Base"; + +base = { + "base_class": "Base", + "class_location": location +} + +template_files=[ { "filename": "json_ld_template.mustache", "ext": ".py" } ] + +def get_class_location(class_name, class_map, version): + # Check if the current class has a parent class + if class_map[class_name].superClass(): + if class_map[class_name].superClass() in class_map: + return 'cimpy.' + version + "." + class_map[class_name].superClass() + elif class_map[class_name].superClass() == 'Base' or class_map[class_name].superClass() == None: + return location(version) + else: + return location(version) + +partials = {} + +# called by chevron, text contains the label {{dataType}}, which is evaluated by the renderer (see class template) +def _set_default(text, render): + result = render(text) + + # the field {{dataType}} either contains the multiplicity of an attribute if it is a reference or otherwise the + # datatype of the attribute. If no datatype is set and there is also no multiplicity entry for an attribute, the + # default value is set to None. The multiplicity is set for all attributes, but the datatype is only set for basic + # data types. If the data type entry for an attribute is missing, the attribute contains a reference and therefore + # the default value is either None or [] depending on the mutliplicity. See also write_python_files + if result in ['M:1', 'M:0..1', 'M:1..1', '']: + return 'None' + elif result in ['M:0..n', 'M:1..n'] or 'M:' in result: + return '"list"' + + result = result.split('#')[1] + if result in ['integer', 'Integer', 'Seconds' ]: + return '0' + elif result in ['String', 'DateTime', 'Date']: + return "''" + elif result == 'Boolean': + return 'False' + else: + # everything else should be a float + return '0.0' + +def set_enum_classes(new_enum_classes): + return + +def set_float_classes(new_float_classes): + return + +def run_template(version_path, class_details): + for template_info in template_files: + class_file = os.path.join(version_path, class_details['class_name'] + template_info["ext"]) + if not os.path.exists(class_file): + with open(class_file, 'w') as file: + template_path = os.path.join(os.getcwd(), 'json_ld/templates', template_info["filename"]) + class_details['setDefault'] = _set_default + with open(template_path) as f: + args = { + 'data': class_details, + 'template': f, + 'partials_dict': partials + } + output = chevron.render(**args) + file.write(output) + + +def _create_init(path): + init_file = path + "/__init__.py" + with open(init_file, 'w'): + pass + +# creates the Base class file, all classes inherit from this class +def _create_base(path): + base_path = path + "/Base.py" + base = ['from enum import Enum\n\n', '\n', 'class Base():\n', ' """\n', ' Base Class for CIM\n', + ' """\n\n', + ' cgmesProfile = Enum("cgmesProfile", {"EQ": 0, "SSH": 1, "TP": 2, "SV": 3, "DY": 4, "GL": 5, "DL": 6, "TP_BD": 7, "EQ_BD": 8})', + '\n\n', ' def __init__(self, *args, **kw_args):\n', ' pass\n', + '\n', ' def printxml(self, dict={}):\n', ' return dict\n'] + + with open(base_path, 'w') as f: + for line in base: + f.write(line) + + +def resolve_headers(path): + filenames = glob.glob(path + "/*.py") + include_names = [] + for filename in filenames: + include_names.append(os.path.splitext(os.path.basename(filename))[0]) + with open(path + "/__init__.py", "w") as header_file: + for include_name in include_names: + header_file.write("from " + "." + include_name + " import " + include_name + " as " + include_name + "\n") + header_file.close() diff --git a/json_ld/templates/json_ld_template.mustache b/json_ld/templates/json_ld_template.mustache new file mode 100644 index 00000000..9bdbbe28 --- /dev/null +++ b/json_ld/templates/json_ld_template.mustache @@ -0,0 +1,27 @@ +{ + "$schema": "http://json-schema.org/schema#", + "$schemaVersion": "0.0.1", + "modelTags": "", + "title": "{{class_name}}", + "description": "{{class_comment}}", + "type": "object", + "allOf": [ + { + "properties": { + "type": { + "type": "string", + "enum": [ + "{{class_name}}" + ], + "description": "Property, NGSI type. Has to be {{class_name}}." + }, +{{#attributes}} + "{{label}}": { + "description": "{{comment}}", + "type": "number" + }, +{{/attributes}} + } + } + ] +} \ No newline at end of file From 856f38ac969aed7642a933505335d62d1d28e221 Mon Sep 17 00:00:00 2001 From: iripiri Date: Thu, 12 May 2022 17:38:51 +0000 Subject: [PATCH 2/6] extend json template Signed-off-by: iripiri --- json_ld/templates/json_ld_template.mustache | 48 ++++++++++++--------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/json_ld/templates/json_ld_template.mustache b/json_ld/templates/json_ld_template.mustache index 9bdbbe28..bfc144e1 100644 --- a/json_ld/templates/json_ld_template.mustache +++ b/json_ld/templates/json_ld_template.mustache @@ -1,27 +1,33 @@ { - "$schema": "http://json-schema.org/schema#", + "$schema": "http://json-schema.org/schema#", "$schemaVersion": "0.0.1", "modelTags": "", - "title": "{{class_name}}", - "description": "{{class_comment}}", - "type": "object", - "allOf": [ - { - "properties": { - "type": { - "type": "string", - "enum": [ - "{{class_name}}" - ], - "description": "Property, NGSI type. Has to be {{class_name}}." - }, + "title": "Smart Data Models - {{class_name}}", + "description": "{{class_comment}}", + "type": "object", + "allOf": [ + { + "$ref": "https://smart-data-models.github.io/data-models/common-schema.json#/definitions/GSMA-Commons" + }, + { + "$ref": "https://smart-data-models.github.io/data-models/common-schema.json#/definitions/Location-Commons" + }, + { + "properties": { + "type": { + "type": "string", + "enum": [ + "{{class_name}}" + ], + "description": "Property. NGSI type. It has to be {{class_name}}" + }, {{#attributes}} - "{{label}}": { - "description": "{{comment}}", - "type": "number" - }, + "{{label}}": { + "description": "Property. Model:'https://schema.org/Number'. {{comment}} Default: {{#setDefault}}{{dataType}}{{/setDefault}}", + "type": "number" + }, {{/attributes}} - } - } - ] + } + } + ] } \ No newline at end of file From 413106bae6ceeff521b6208cda251c04c749f8a1 Mon Sep 17 00:00:00 2001 From: iripiri Date: Wed, 15 Jun 2022 15:08:31 +0000 Subject: [PATCH 3/6] clean up code Signed-off-by: iripiri --- json_ld/langPack.py | 95 ++++++++++----------------------------------- 1 file changed, 21 insertions(+), 74 deletions(-) diff --git a/json_ld/langPack.py b/json_ld/langPack.py index d1e36e8c..cd4727a1 100644 --- a/json_ld/langPack.py +++ b/json_ld/langPack.py @@ -1,113 +1,60 @@ import os import chevron import logging -import glob -import sys logger = logging.getLogger(__name__) -# This makes sure we have somewhere to write the classes, and -# creates a couple of files the python implementation needs. + +# This makes sure we have somewhere to write the generated files def setup(version_path): if not os.path.exists(version_path): os.makedirs(version_path) - _create_init(version_path) - _create_base(version_path) + def location(version): - return "cimpy." + version + ".Base"; + return "cimpy." + version + ".Base" + base = { "base_class": "Base", "class_location": location } -template_files=[ { "filename": "json_ld_template.mustache", "ext": ".py" } ] +template_files = [{"filename": "json_ld_template.mustache", "ext": ".json"}] + def get_class_location(class_name, class_map, version): - # Check if the current class has a parent class - if class_map[class_name].superClass(): - if class_map[class_name].superClass() in class_map: - return 'cimpy.' + version + "." + class_map[class_name].superClass() - elif class_map[class_name].superClass() == 'Base' or class_map[class_name].superClass() == None: - return location(version) - else: - return location(version) - -partials = {} - -# called by chevron, text contains the label {{dataType}}, which is evaluated by the renderer (see class template) + pass + + def _set_default(text, render): - result = render(text) - - # the field {{dataType}} either contains the multiplicity of an attribute if it is a reference or otherwise the - # datatype of the attribute. If no datatype is set and there is also no multiplicity entry for an attribute, the - # default value is set to None. The multiplicity is set for all attributes, but the datatype is only set for basic - # data types. If the data type entry for an attribute is missing, the attribute contains a reference and therefore - # the default value is either None or [] depending on the mutliplicity. See also write_python_files - if result in ['M:1', 'M:0..1', 'M:1..1', '']: - return 'None' - elif result in ['M:0..n', 'M:1..n'] or 'M:' in result: - return '"list"' - - result = result.split('#')[1] - if result in ['integer', 'Integer', 'Seconds' ]: - return '0' - elif result in ['String', 'DateTime', 'Date']: - return "''" - elif result == 'Boolean': - return 'False' - else: - # everything else should be a float - return '0.0' + return '0.0' + def set_enum_classes(new_enum_classes): return + def set_float_classes(new_float_classes): return + def run_template(version_path, class_details): for template_info in template_files: - class_file = os.path.join(version_path, class_details['class_name'] + template_info["ext"]) + class_file = os.path.join(version_path, class_details['class_name'] + + template_info["ext"]) if not os.path.exists(class_file): with open(class_file, 'w') as file: - template_path = os.path.join(os.getcwd(), 'json_ld/templates', template_info["filename"]) + template_path = os.path.join(os.getcwd(), 'json_ld/templates', + template_info["filename"]) class_details['setDefault'] = _set_default with open(template_path) as f: args = { 'data': class_details, - 'template': f, - 'partials_dict': partials - } + 'template': f + } output = chevron.render(**args) file.write(output) -def _create_init(path): - init_file = path + "/__init__.py" - with open(init_file, 'w'): - pass - -# creates the Base class file, all classes inherit from this class -def _create_base(path): - base_path = path + "/Base.py" - base = ['from enum import Enum\n\n', '\n', 'class Base():\n', ' """\n', ' Base Class for CIM\n', - ' """\n\n', - ' cgmesProfile = Enum("cgmesProfile", {"EQ": 0, "SSH": 1, "TP": 2, "SV": 3, "DY": 4, "GL": 5, "DL": 6, "TP_BD": 7, "EQ_BD": 8})', - '\n\n', ' def __init__(self, *args, **kw_args):\n', ' pass\n', - '\n', ' def printxml(self, dict={}):\n', ' return dict\n'] - - with open(base_path, 'w') as f: - for line in base: - f.write(line) - - def resolve_headers(path): - filenames = glob.glob(path + "/*.py") - include_names = [] - for filename in filenames: - include_names.append(os.path.splitext(os.path.basename(filename))[0]) - with open(path + "/__init__.py", "w") as header_file: - for include_name in include_names: - header_file.write("from " + "." + include_name + " import " + include_name + " as " + include_name + "\n") - header_file.close() + pass From b9293ad7f3c36bba9559dbfcac596d0aa6cde2a8 Mon Sep 17 00:00:00 2001 From: Markus Mirz Date: Sat, 18 Jan 2025 22:41:36 +0100 Subject: [PATCH 4/6] fix pre-commit checks Signed-off-by: Markus Mirz --- json_ld/__init__.py | 1 - json_ld/langPack.py | 23 +++++++-------------- json_ld/templates/json_ld_template.mustache | 2 +- 3 files changed, 9 insertions(+), 17 deletions(-) diff --git a/json_ld/__init__.py b/json_ld/__init__.py index f2fb1323..e69de29b 100644 --- a/json_ld/__init__.py +++ b/json_ld/__init__.py @@ -1 +0,0 @@ -import json_ld.langPack \ No newline at end of file diff --git a/json_ld/langPack.py b/json_ld/langPack.py index cd4727a1..bad246b0 100644 --- a/json_ld/langPack.py +++ b/json_ld/langPack.py @@ -1,6 +1,7 @@ import os import chevron import logging + logger = logging.getLogger(__name__) @@ -14,10 +15,7 @@ def location(version): return "cimpy." + version + ".Base" -base = { - "base_class": "Base", - "class_location": location -} +base = {"base_class": "Base", "class_location": location} template_files = [{"filename": "json_ld_template.mustache", "ext": ".json"}] @@ -27,7 +25,7 @@ def get_class_location(class_name, class_map, version): def _set_default(text, render): - return '0.0' + return "0.0" def set_enum_classes(new_enum_classes): @@ -40,18 +38,13 @@ def set_float_classes(new_float_classes): def run_template(version_path, class_details): for template_info in template_files: - class_file = os.path.join(version_path, class_details['class_name'] - + template_info["ext"]) + class_file = os.path.join(version_path, class_details["class_name"] + template_info["ext"]) if not os.path.exists(class_file): - with open(class_file, 'w') as file: - template_path = os.path.join(os.getcwd(), 'json_ld/templates', - template_info["filename"]) - class_details['setDefault'] = _set_default + with open(class_file, "w") as file: + template_path = os.path.join(os.getcwd(), "json_ld/templates", template_info["filename"]) + class_details["setDefault"] = _set_default with open(template_path) as f: - args = { - 'data': class_details, - 'template': f - } + args = {"data": class_details, "template": f} output = chevron.render(**args) file.write(output) diff --git a/json_ld/templates/json_ld_template.mustache b/json_ld/templates/json_ld_template.mustache index bfc144e1..8a3bea97 100644 --- a/json_ld/templates/json_ld_template.mustache +++ b/json_ld/templates/json_ld_template.mustache @@ -30,4 +30,4 @@ } } ] -} \ No newline at end of file +} From 5e76228f5a7adba60fd70ea88184a1ddea6d885d Mon Sep 17 00:00:00 2001 From: Markus Mirz Date: Sat, 18 Jan 2025 22:43:13 +0100 Subject: [PATCH 5/6] move json-ld files Signed-off-by: Markus Mirz --- {json_ld => cimgen/languages/json_ld}/__init__.py | 0 {json_ld => cimgen/languages/json_ld}/langPack.py | 0 .../languages/json_ld}/templates/json_ld_template.mustache | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename {json_ld => cimgen/languages/json_ld}/__init__.py (100%) rename {json_ld => cimgen/languages/json_ld}/langPack.py (100%) rename {json_ld => cimgen/languages/json_ld}/templates/json_ld_template.mustache (100%) diff --git a/json_ld/__init__.py b/cimgen/languages/json_ld/__init__.py similarity index 100% rename from json_ld/__init__.py rename to cimgen/languages/json_ld/__init__.py diff --git a/json_ld/langPack.py b/cimgen/languages/json_ld/langPack.py similarity index 100% rename from json_ld/langPack.py rename to cimgen/languages/json_ld/langPack.py diff --git a/json_ld/templates/json_ld_template.mustache b/cimgen/languages/json_ld/templates/json_ld_template.mustache similarity index 100% rename from json_ld/templates/json_ld_template.mustache rename to cimgen/languages/json_ld/templates/json_ld_template.mustache From 5bd397e441ba2a4234ec44697c65e0338d7bca0d Mon Sep 17 00:00:00 2001 From: Markus Mirz Date: Sun, 19 Jan 2025 22:40:23 +0100 Subject: [PATCH 6/6] adapt jsonld langpack to new structure Signed-off-by: Markus Mirz --- cimgen/languages/json_ld/langPack.py | 53 ----------- cimgen/languages/json_ld/lang_pack.py | 89 +++++++++++++++++++ .../templates/json_ld_template.mustache | 33 ++----- 3 files changed, 98 insertions(+), 77 deletions(-) delete mode 100644 cimgen/languages/json_ld/langPack.py create mode 100644 cimgen/languages/json_ld/lang_pack.py diff --git a/cimgen/languages/json_ld/langPack.py b/cimgen/languages/json_ld/langPack.py deleted file mode 100644 index bad246b0..00000000 --- a/cimgen/languages/json_ld/langPack.py +++ /dev/null @@ -1,53 +0,0 @@ -import os -import chevron -import logging - -logger = logging.getLogger(__name__) - - -# This makes sure we have somewhere to write the generated files -def setup(version_path): - if not os.path.exists(version_path): - os.makedirs(version_path) - - -def location(version): - return "cimpy." + version + ".Base" - - -base = {"base_class": "Base", "class_location": location} - -template_files = [{"filename": "json_ld_template.mustache", "ext": ".json"}] - - -def get_class_location(class_name, class_map, version): - pass - - -def _set_default(text, render): - return "0.0" - - -def set_enum_classes(new_enum_classes): - return - - -def set_float_classes(new_float_classes): - return - - -def run_template(version_path, class_details): - for template_info in template_files: - class_file = os.path.join(version_path, class_details["class_name"] + template_info["ext"]) - if not os.path.exists(class_file): - with open(class_file, "w") as file: - template_path = os.path.join(os.getcwd(), "json_ld/templates", template_info["filename"]) - class_details["setDefault"] = _set_default - with open(template_path) as f: - args = {"data": class_details, "template": f} - output = chevron.render(**args) - file.write(output) - - -def resolve_headers(path): - pass diff --git a/cimgen/languages/json_ld/lang_pack.py b/cimgen/languages/json_ld/lang_pack.py new file mode 100644 index 00000000..31b04957 --- /dev/null +++ b/cimgen/languages/json_ld/lang_pack.py @@ -0,0 +1,89 @@ +from importlib.resources import files +import os +from typing import Callable +import chevron +import logging + +logger = logging.getLogger(__name__) + + +# This makes sure we have somewhere to write the generated files +def setup(output_path: str, cgmes_profile_details: list[dict], cim_namespace: str) -> None: + if not os.path.exists(output_path): + os.makedirs(output_path) + else: + for filename in os.listdir(output_path): + os.remove(os.path.join(output_path, filename)) + + +def get_base_class() -> str: + return "Base" + + +# called by chevron, text contains the label {{datatype}}, which is evaluated by the renderer (see class template) +def _set_default(text: str, render: Callable[[str], str]) -> str: + result = render(text) + + # the field {{datatype}} either contains the multiplicity of an attribute if it is a reference or otherwise the + # datatype of the attribute. If no datatype is set and there is also no multiplicity entry for an attribute, the + # default value is set to None. The multiplicity is set for all attributes, but the datatype is only set for basic + # data types. If the data type entry for an attribute is missing, the attribute contains a reference and therefore + # the default value is either None or [] depending on the multiplicity. See also write_python_files + if result in ["M:1", "M:0..1", "M:1..1", ""]: + return "None" + elif result in ["M:0..n", "M:1..n"] or "M:" in result: + return "[]" + + result = result.split("#")[1] + if result in ["integer", "Integer"]: + return "0" + elif result in ["String", "DateTime", "Date"]: + return "''" + elif result == "Boolean": + return "False" + else: + # everything else should be a float + return "0.0" + + +# These are the template files that are used to generate the class files. +class_template_file = {"filename": "json_ld_template.mustache", "ext": ".json"} + + +def run_template(output_path: str, class_details: dict) -> None: + class_file = os.path.join(output_path, class_details["class_name"] + class_template_file["ext"]) + with open(class_file, "w") as file: + class_details["set_default"] = _set_default + templates = files("cimgen.languages.json_ld.templates") + with templates.joinpath(class_template_file["filename"]).open(encoding="utf-8") as f: + args = { + "data": class_details, + "template": f, + } + output = chevron.render(**args) + file.write(output) + + +def location(version): + return "cimpy." + version + ".Base" + + +base = {"base_class": "Base", "class_location": location} + +template_files = [{"filename": "json_ld_template.mustache", "ext": ".json"}] + + +def get_class_location(class_name, class_map, version): + pass + + +def set_enum_classes(new_enum_classes): + return + + +def set_float_classes(new_float_classes): + return + + +def resolve_headers(path: str, version: str) -> None: # NOSONAR + pass diff --git a/cimgen/languages/json_ld/templates/json_ld_template.mustache b/cimgen/languages/json_ld/templates/json_ld_template.mustache index 8a3bea97..860f2331 100644 --- a/cimgen/languages/json_ld/templates/json_ld_template.mustache +++ b/cimgen/languages/json_ld/templates/json_ld_template.mustache @@ -1,33 +1,18 @@ { "$schema": "http://json-schema.org/schema#", + "$id": "schema:{{class_name}}", + "$ref": "schema:{{subclass_of}}", "$schemaVersion": "0.0.1", "modelTags": "", - "title": "Smart Data Models - {{class_name}}", + "title": "{{class_name}}", "description": "{{class_comment}}", "type": "object", - "allOf": [ - { - "$ref": "https://smart-data-models.github.io/data-models/common-schema.json#/definitions/GSMA-Commons" - }, - { - "$ref": "https://smart-data-models.github.io/data-models/common-schema.json#/definitions/Location-Commons" - }, - { - "properties": { - "type": { - "type": "string", - "enum": [ - "{{class_name}}" - ], - "description": "Property. NGSI type. It has to be {{class_name}}" - }, + "properties": { {{#attributes}} - "{{label}}": { - "description": "Property. Model:'https://schema.org/Number'. {{comment}} Default: {{#setDefault}}{{dataType}}{{/setDefault}}", - "type": "number" - }, + "{{label}}": { + "description": "{{comment}} Default: {{#set_default}}{{datatype}}{{/set_default}}", + "type": "{{datatype}}" + }, {{/attributes}} - } - } - ] + } }