cognite-neat 0.92.3__py3-none-any.whl → 0.94.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.
Potentially problematic release.
This version of cognite-neat might be problematic. Click here for more details.
- cognite/neat/__init__.py +3 -2
- cognite/neat/{app → _app}/api/configuration.py +9 -7
- cognite/neat/_app/api/context_manager/__init__.py +3 -0
- cognite/neat/{app → _app}/api/context_manager/manager.py +1 -1
- cognite/neat/{app → _app}/api/explorer.py +5 -5
- cognite/neat/{app → _app}/api/routers/configuration.py +2 -2
- cognite/neat/{app → _app}/api/routers/crud.py +4 -4
- cognite/neat/{app → _app}/api/routers/workflows.py +7 -7
- cognite/neat/{app → _app}/main.py +1 -1
- cognite/neat/_app/ui/neat-app/package-lock.json +18306 -0
- cognite/neat/_app/ui/neat-app/package.json +62 -0
- cognite/neat/_app/ui/neat-app/public/favicon.ico +0 -0
- cognite/neat/_app/ui/neat-app/public/img/architect-icon.svg +116 -0
- cognite/neat/_app/ui/neat-app/public/img/developer-icon.svg +112 -0
- cognite/neat/_app/ui/neat-app/public/img/sme-icon.svg +34 -0
- cognite/neat/_app/ui/neat-app/public/index.html +43 -0
- cognite/neat/_app/ui/neat-app/public/logo192.png +0 -0
- cognite/neat/_app/ui/neat-app/public/manifest.json +25 -0
- cognite/neat/_app/ui/neat-app/public/robots.txt +3 -0
- cognite/neat/_app/ui/neat-app/src/App.css +38 -0
- cognite/neat/_app/ui/neat-app/src/App.js +17 -0
- cognite/neat/_app/ui/neat-app/src/App.test.js +8 -0
- cognite/neat/_app/ui/neat-app/src/MainContainer.tsx +70 -0
- cognite/neat/_app/ui/neat-app/src/components/JsonViewer.tsx +43 -0
- cognite/neat/_app/ui/neat-app/src/components/LocalUploader.tsx +124 -0
- cognite/neat/_app/ui/neat-app/src/components/OverviewComponentEditorDialog.tsx +63 -0
- cognite/neat/_app/ui/neat-app/src/components/StepEditorDialog.tsx +511 -0
- cognite/neat/_app/ui/neat-app/src/components/TabPanel.tsx +36 -0
- cognite/neat/_app/ui/neat-app/src/components/Utils.tsx +56 -0
- cognite/neat/_app/ui/neat-app/src/components/WorkflowDeleteDialog.tsx +60 -0
- cognite/neat/_app/ui/neat-app/src/components/WorkflowExecutionReport.tsx +112 -0
- cognite/neat/_app/ui/neat-app/src/components/WorkflowImportExportDialog.tsx +67 -0
- cognite/neat/_app/ui/neat-app/src/components/WorkflowMetadataDialog.tsx +79 -0
- cognite/neat/_app/ui/neat-app/src/index.css +13 -0
- cognite/neat/_app/ui/neat-app/src/index.js +13 -0
- cognite/neat/_app/ui/neat-app/src/logo.svg +1 -0
- cognite/neat/_app/ui/neat-app/src/reportWebVitals.js +13 -0
- cognite/neat/_app/ui/neat-app/src/setupTests.js +5 -0
- cognite/neat/_app/ui/neat-app/src/types/WorkflowTypes.ts +388 -0
- cognite/neat/_app/ui/neat-app/src/views/AboutView.tsx +61 -0
- cognite/neat/_app/ui/neat-app/src/views/ConfigView.tsx +184 -0
- cognite/neat/_app/ui/neat-app/src/views/GlobalConfigView.tsx +180 -0
- cognite/neat/_app/ui/neat-app/src/views/WorkflowView.tsx +570 -0
- cognite/neat/_app/ui/neat-app/tsconfig.json +27 -0
- cognite/neat/{config.py → _config.py} +3 -3
- cognite/neat/{constants.py → _constants.py} +13 -5
- cognite/neat/_graph/_shared.py +34 -0
- cognite/neat/{graph → _graph}/_tracking/base.py +1 -1
- cognite/neat/{graph → _graph}/_tracking/log.py +1 -1
- cognite/neat/{graph → _graph}/extractors/__init__.py +5 -0
- cognite/neat/{graph → _graph}/extractors/_base.py +2 -2
- cognite/neat/{graph → _graph}/extractors/_classic_cdf/_assets.py +1 -1
- cognite/neat/{graph → _graph}/extractors/_classic_cdf/_base.py +4 -4
- cognite/neat/{graph → _graph}/extractors/_classic_cdf/_classic.py +5 -5
- cognite/neat/{graph → _graph}/extractors/_classic_cdf/_data_sets.py +1 -1
- cognite/neat/{graph → _graph}/extractors/_classic_cdf/_events.py +1 -1
- cognite/neat/{graph → _graph}/extractors/_classic_cdf/_files.py +1 -1
- cognite/neat/{graph → _graph}/extractors/_classic_cdf/_labels.py +1 -1
- cognite/neat/{graph → _graph}/extractors/_classic_cdf/_relationships.py +2 -2
- cognite/neat/{graph → _graph}/extractors/_classic_cdf/_sequences.py +1 -1
- cognite/neat/{graph → _graph}/extractors/_classic_cdf/_timeseries.py +1 -1
- cognite/neat/{graph → _graph}/extractors/_dexpi.py +5 -5
- cognite/neat/{graph → _graph}/extractors/_dms.py +3 -3
- cognite/neat/_graph/extractors/_iodd.py +402 -0
- cognite/neat/{graph → _graph}/extractors/_mock_graph_generator.py +9 -8
- cognite/neat/_graph/extractors/_rdf_file.py +49 -0
- cognite/neat/{graph → _graph}/loaders/_base.py +5 -5
- cognite/neat/{graph → _graph}/loaders/_rdf2asset.py +11 -10
- cognite/neat/{graph → _graph}/loaders/_rdf2dms.py +10 -10
- cognite/neat/{graph → _graph}/queries/_base.py +91 -19
- cognite/neat/{graph → _graph}/queries/_construct.py +5 -5
- cognite/neat/{graph → _graph}/queries/_shared.py +3 -3
- cognite/neat/{graph → _graph}/transformers/__init__.py +6 -0
- cognite/neat/{graph → _graph}/transformers/_classic_cdf.py +135 -3
- cognite/neat/_graph/transformers/_iodd.py +25 -0
- cognite/neat/_graph/transformers/_prune_graph.py +126 -0
- cognite/neat/{graph → _graph}/transformers/_rdfpath.py +3 -3
- cognite/neat/_graph/transformers/_value_type.py +66 -0
- cognite/neat/{issues → _issues}/_base.py +32 -17
- cognite/neat/{issues → _issues}/errors/__init__.py +1 -1
- cognite/neat/{issues → _issues}/errors/_external.py +8 -8
- cognite/neat/{issues → _issues}/errors/_general.py +5 -5
- cognite/neat/{issues → _issues}/errors/_properties.py +7 -7
- cognite/neat/{issues → _issues}/errors/_resources.py +11 -11
- cognite/neat/{issues → _issues}/errors/_workflow.py +5 -5
- cognite/neat/{issues → _issues}/warnings/__init__.py +1 -1
- cognite/neat/{issues → _issues}/warnings/_external.py +5 -5
- cognite/neat/{issues → _issues}/warnings/_general.py +4 -4
- cognite/neat/{issues → _issues}/warnings/_models.py +10 -10
- cognite/neat/{issues → _issues}/warnings/_properties.py +6 -6
- cognite/neat/{issues → _issues}/warnings/_resources.py +5 -5
- cognite/neat/{issues → _issues}/warnings/user_modeling.py +9 -9
- cognite/neat/_rules/_constants.py +190 -0
- cognite/neat/{rules → _rules}/_shared.py +5 -5
- cognite/neat/_rules/analysis/__init__.py +5 -0
- cognite/neat/{rules → _rules}/analysis/_asset.py +5 -5
- cognite/neat/{rules → _rules}/analysis/_base.py +5 -5
- cognite/neat/_rules/analysis/_dms.py +43 -0
- cognite/neat/{rules → _rules}/analysis/_information.py +12 -6
- cognite/neat/_rules/catalog/__init__.py +6 -0
- cognite/neat/_rules/catalog/info-rules-imf.xlsx +0 -0
- cognite/neat/{rules → _rules}/exporters/__init__.py +2 -0
- cognite/neat/{rules → _rules}/exporters/_base.py +3 -3
- cognite/neat/{rules → _rules}/exporters/_rules2dms.py +5 -5
- cognite/neat/{rules → _rules}/exporters/_rules2excel.py +12 -8
- cognite/neat/_rules/exporters/_rules2instance_template.py +152 -0
- cognite/neat/{rules → _rules}/exporters/_rules2ontology.py +10 -9
- cognite/neat/{rules → _rules}/exporters/_rules2yaml.py +1 -3
- cognite/neat/{rules → _rules}/exporters/_validation.py +2 -2
- cognite/neat/{rules → _rules}/importers/_base.py +3 -3
- cognite/neat/{rules → _rules}/importers/_dms2rules.py +9 -9
- cognite/neat/{rules → _rules}/importers/_dtdl2rules/dtdl_converter.py +7 -7
- cognite/neat/{rules → _rules}/importers/_dtdl2rules/dtdl_importer.py +9 -9
- cognite/neat/{rules → _rules}/importers/_dtdl2rules/spec.py +1 -1
- cognite/neat/_rules/importers/_rdf/_base.py +144 -0
- cognite/neat/{rules → _rules}/importers/_rdf/_imf2rules/_imf2classes.py +1 -1
- cognite/neat/{rules → _rules}/importers/_rdf/_imf2rules/_imf2metadata.py +4 -4
- cognite/neat/{rules → _rules}/importers/_rdf/_imf2rules/_imf2properties.py +2 -1
- cognite/neat/{rules → _rules}/importers/_rdf/_imf2rules/_imf2rules.py +8 -39
- cognite/neat/{rules → _rules}/importers/_rdf/_inference2rules.py +33 -106
- cognite/neat/{rules → _rules}/importers/_rdf/_owl2rules/_owl2classes.py +1 -1
- cognite/neat/{rules → _rules}/importers/_rdf/_owl2rules/_owl2metadata.py +5 -5
- cognite/neat/{rules → _rules}/importers/_rdf/_owl2rules/_owl2properties.py +1 -1
- cognite/neat/_rules/importers/_rdf/_owl2rules/_owl2rules.py +39 -0
- cognite/neat/{rules → _rules}/importers/_rdf/_shared.py +4 -4
- cognite/neat/{rules → _rules}/importers/_spreadsheet2rules.py +7 -7
- cognite/neat/{rules → _rules}/importers/_yaml2rules.py +5 -5
- cognite/neat/{rules → _rules}/models/__init__.py +5 -5
- cognite/neat/{rules → _rules}/models/_base_input.py +15 -6
- cognite/neat/{rules → _rules}/models/_base_rules.py +14 -2
- cognite/neat/{rules → _rules}/models/_rdfpath.py +1 -1
- cognite/neat/_rules/models/_types.py +151 -0
- cognite/neat/{rules → _rules}/models/asset/_rules.py +4 -4
- cognite/neat/{rules → _rules}/models/asset/_rules_input.py +4 -4
- cognite/neat/{rules → _rules}/models/asset/_validation.py +7 -7
- cognite/neat/{rules → _rules}/models/data_types.py +15 -12
- cognite/neat/{rules → _rules}/models/dms/_exporter.py +60 -12
- cognite/neat/{rules → _rules}/models/dms/_rules.py +26 -23
- cognite/neat/{rules → _rules}/models/dms/_rules_input.py +4 -4
- cognite/neat/{rules → _rules}/models/dms/_schema.py +15 -14
- cognite/neat/{rules → _rules}/models/dms/_validation.py +8 -8
- cognite/neat/{rules → _rules}/models/domain.py +6 -6
- cognite/neat/{rules → _rules}/models/entities/__init__.py +1 -2
- cognite/neat/_rules/models/entities/_constants.py +15 -0
- cognite/neat/{rules → _rules}/models/entities/_loaders.py +2 -2
- cognite/neat/{rules → _rules}/models/entities/_multi_value.py +15 -2
- cognite/neat/{rules → _rules}/models/entities/_single_value.py +7 -4
- cognite/neat/{rules → _rules}/models/information/_rules.py +34 -22
- cognite/neat/{rules → _rules}/models/information/_rules_input.py +3 -3
- cognite/neat/{rules → _rules}/models/information/_validation.py +6 -5
- cognite/neat/_rules/models/mapping/__init__.py +4 -0
- cognite/neat/_rules/models/mapping/_base.py +131 -0
- cognite/neat/_rules/models/mapping/_classic2core.py +150 -0
- cognite/neat/{rules → _rules}/transformers/__init__.py +15 -2
- cognite/neat/{rules → _rules}/transformers/_base.py +3 -3
- cognite/neat/{rules → _rules}/transformers/_converters.py +289 -20
- cognite/neat/{rules/transformers/_map_onto.py → _rules/transformers/_mapping.py} +46 -4
- cognite/neat/{rules → _rules}/transformers/_pipelines.py +4 -4
- cognite/neat/{rules → _rules}/transformers/_verification.py +10 -4
- cognite/neat/_session/__init__.py +3 -0
- cognite/neat/_session/_base.py +86 -0
- cognite/neat/_session/_prepare.py +61 -0
- cognite/neat/_session/_read.py +118 -0
- cognite/neat/_session/_show.py +274 -0
- cognite/neat/_session/_state.py +69 -0
- cognite/neat/_session/_to.py +70 -0
- cognite/neat/_session/_wizard.py +39 -0
- cognite/neat/_session/exceptions.py +42 -0
- cognite/neat/{store → _store}/_base.py +62 -31
- cognite/neat/{store → _store}/_provenance.py +11 -1
- cognite/neat/{utils → _utils}/auth.py +14 -3
- cognite/neat/{utils → _utils}/auxiliary.py +1 -1
- cognite/neat/{utils → _utils}/cdf/loaders/_data_modeling.py +8 -2
- cognite/neat/{utils → _utils}/cdf/loaders/_ingestion.py +1 -1
- cognite/neat/{utils → _utils}/upload.py +1 -1
- cognite/neat/_version.py +1 -1
- cognite/neat/_workflows/__init__.py +17 -0
- cognite/neat/{workflows → _workflows}/base.py +10 -10
- cognite/neat/{workflows → _workflows}/cdf_store.py +3 -3
- cognite/neat/{workflows → _workflows}/examples/Export_DMS/workflow.yaml +89 -89
- cognite/neat/{workflows → _workflows}/manager.py +6 -6
- cognite/neat/{workflows → _workflows}/steps/data_contracts.py +3 -3
- cognite/neat/{workflows → _workflows}/steps/lib/current/graph_extractor.py +8 -31
- cognite/neat/{workflows → _workflows}/steps/lib/current/graph_loader.py +4 -4
- cognite/neat/{workflows → _workflows}/steps/lib/current/graph_store.py +4 -4
- cognite/neat/{workflows → _workflows}/steps/lib/current/rules_exporter.py +8 -8
- cognite/neat/{workflows → _workflows}/steps/lib/current/rules_importer.py +13 -13
- cognite/neat/{workflows → _workflows}/steps/lib/current/rules_validator.py +8 -8
- cognite/neat/{workflows → _workflows}/steps/lib/io/io_steps.py +3 -3
- cognite/neat/{workflows → _workflows}/steps/step_model.py +3 -3
- cognite/neat/{workflows → _workflows}/steps_registry.py +9 -9
- cognite/neat/{workflows → _workflows}/tasks.py +1 -1
- cognite/neat/{workflows → _workflows}/triggers.py +2 -2
- {cognite_neat-0.92.3.dist-info → cognite_neat-0.94.0.dist-info}/METADATA +6 -2
- cognite_neat-0.94.0.dist-info/RECORD +276 -0
- {cognite_neat-0.92.3.dist-info → cognite_neat-0.94.0.dist-info}/WHEEL +1 -1
- cognite_neat-0.94.0.dist-info/entry_points.txt +3 -0
- cognite/neat/app/api/context_manager/__init__.py +0 -3
- cognite/neat/graph/_shared.py +0 -5
- cognite/neat/graph/extractors/_iodd.py +0 -160
- cognite/neat/graph/extractors/_rdf_file.py +0 -26
- cognite/neat/rules/analysis/__init__.py +0 -6
- cognite/neat/rules/examples/__init__.py +0 -10
- cognite/neat/rules/examples/info-rules-imf.xlsx +0 -0
- cognite/neat/rules/examples/wind-energy.owl +0 -1511
- cognite/neat/rules/importers/_rdf/_owl2rules/_owl2rules.py +0 -65
- cognite/neat/rules/models/_types.py +0 -96
- cognite/neat/rules/models/entities/_constants.py +0 -73
- cognite/neat/utils/regex_patterns.py +0 -58
- cognite/neat/workflows/__init__.py +0 -12
- cognite_neat-0.92.3.dist-info/RECORD +0 -224
- cognite_neat-0.92.3.dist-info/entry_points.txt +0 -3
- /cognite/neat/{app → _app}/api/__init__.py +0 -0
- /cognite/neat/{app → _app}/api/asgi/metrics.py +0 -0
- /cognite/neat/{app → _app}/api/data_classes/__init__.py +0 -0
- /cognite/neat/{app → _app}/api/data_classes/rest.py +0 -0
- /cognite/neat/{app → _app}/api/routers/metrics.py +0 -0
- /cognite/neat/{app → _app}/api/utils/__init__.py +0 -0
- /cognite/neat/{app → _app}/api/utils/data_mapping.py +0 -0
- /cognite/neat/{app → _app}/api/utils/logging.py +0 -0
- /cognite/neat/{app → _app}/api/utils/query_templates.py +0 -0
- /cognite/neat/{app → _app}/monitoring/__init__.py +0 -0
- /cognite/neat/{app → _app}/monitoring/metrics.py +0 -0
- /cognite/neat/{app → _app}/ui/index.html +0 -0
- /cognite/neat/{app → _app}/ui/neat-app/.gitignore +0 -0
- /cognite/neat/{app → _app}/ui/neat-app/README.md +0 -0
- /cognite/neat/{app → _app}/ui/neat-app/build/asset-manifest.json +0 -0
- /cognite/neat/{app → _app}/ui/neat-app/build/favicon.ico +0 -0
- /cognite/neat/{app → _app}/ui/neat-app/build/img/architect-icon.svg +0 -0
- /cognite/neat/{app → _app}/ui/neat-app/build/img/developer-icon.svg +0 -0
- /cognite/neat/{app → _app}/ui/neat-app/build/img/sme-icon.svg +0 -0
- /cognite/neat/{app → _app}/ui/neat-app/build/index.html +0 -0
- /cognite/neat/{app → _app}/ui/neat-app/build/logo192.png +0 -0
- /cognite/neat/{app → _app}/ui/neat-app/build/manifest.json +0 -0
- /cognite/neat/{app → _app}/ui/neat-app/build/robots.txt +0 -0
- /cognite/neat/{app → _app}/ui/neat-app/build/static/css/main.72e3d92e.css +0 -0
- /cognite/neat/{app → _app}/ui/neat-app/build/static/css/main.72e3d92e.css.map +0 -0
- /cognite/neat/{app → _app}/ui/neat-app/build/static/js/main.5a52cf09.js +0 -0
- /cognite/neat/{app → _app}/ui/neat-app/build/static/js/main.5a52cf09.js.LICENSE.txt +0 -0
- /cognite/neat/{app → _app}/ui/neat-app/build/static/js/main.5a52cf09.js.map +0 -0
- /cognite/neat/{app → _app}/ui/neat-app/build/static/media/logo.8093b84df9ed36a174c629d6fe0b730d.svg +0 -0
- /cognite/neat/{graph → _graph}/__init__.py +0 -0
- /cognite/neat/{graph → _graph}/_tracking/__init__.py +0 -0
- /cognite/neat/{graph → _graph}/examples/Knowledge-Graph-Nordic44-dirty.xml +0 -0
- /cognite/neat/{graph → _graph}/examples/Knowledge-Graph-Nordic44.xml +0 -0
- /cognite/neat/{graph → _graph}/examples/__init__.py +0 -0
- /cognite/neat/{graph → _graph}/examples/skos-capturing-sheet-wind-topics.xlsx +0 -0
- /cognite/neat/{graph → _graph}/extractors/_classic_cdf/__init__.py +0 -0
- /cognite/neat/{graph → _graph}/loaders/__init__.py +0 -0
- /cognite/neat/{graph → _graph}/models.py +0 -0
- /cognite/neat/{graph → _graph}/queries/__init__.py +0 -0
- /cognite/neat/{graph → _graph}/transformers/_base.py +0 -0
- /cognite/neat/{issues → _issues}/__init__.py +0 -0
- /cognite/neat/{issues → _issues}/formatters.py +0 -0
- /cognite/neat/{rules → _rules}/__init__.py +0 -0
- /cognite/neat/{rules → _rules}/importers/__init__.py +0 -0
- /cognite/neat/{rules → _rules}/importers/_dtdl2rules/__init__.py +0 -0
- /cognite/neat/{rules → _rules}/importers/_dtdl2rules/_unit_lookup.py +0 -0
- /cognite/neat/{rules → _rules}/importers/_rdf/__init__.py +0 -0
- /cognite/neat/{rules → _rules}/importers/_rdf/_imf2rules/__init__.py +0 -0
- /cognite/neat/{rules → _rules}/importers/_rdf/_owl2rules/__init__.py +0 -0
- /cognite/neat/{rules → _rules}/models/asset/__init__.py +0 -0
- /cognite/neat/{rules → _rules}/models/dms/__init__.py +0 -0
- /cognite/neat/{rules → _rules}/models/entities/_types.py +0 -0
- /cognite/neat/{rules → _rules}/models/entities/_wrapped.py +0 -0
- /cognite/neat/{rules → _rules}/models/information/__init__.py +0 -0
- /cognite/neat/{store → _store}/__init__.py +0 -0
- /cognite/neat/{utils → _utils}/__init__.py +0 -0
- /cognite/neat/{utils → _utils}/cdf/__init__.py +0 -0
- /cognite/neat/{utils → _utils}/cdf/data_classes.py +0 -0
- /cognite/neat/{utils → _utils}/cdf/loaders/__init__.py +0 -0
- /cognite/neat/{utils → _utils}/cdf/loaders/_base.py +0 -0
- /cognite/neat/{utils → _utils}/collection_.py +0 -0
- /cognite/neat/{utils → _utils}/rdf_.py +0 -0
- /cognite/neat/{utils → _utils}/spreadsheet.py +0 -0
- /cognite/neat/{utils → _utils}/text.py +0 -0
- /cognite/neat/{utils → _utils}/time_.py +0 -0
- /cognite/neat/{utils → _utils}/xml_.py +0 -0
- /cognite/neat/{workflows → _workflows}/examples/Export_Semantic_Data_Model/workflow.yaml +0 -0
- /cognite/neat/{workflows → _workflows}/examples/Import_DMS/workflow.yaml +0 -0
- /cognite/neat/{workflows → _workflows}/examples/Validate_Rules/workflow.yaml +0 -0
- /cognite/neat/{workflows → _workflows}/examples/Validate_Solution_Model/workflow.yaml +0 -0
- /cognite/neat/{workflows → _workflows}/model.py +0 -0
- /cognite/neat/{workflows → _workflows}/steps/__init__.py +0 -0
- /cognite/neat/{workflows → _workflows}/steps/lib/__init__.py +0 -0
- /cognite/neat/{workflows → _workflows}/steps/lib/current/__init__.py +0 -0
- /cognite/neat/{workflows → _workflows}/steps/lib/io/__init__.py +0 -0
- /cognite/neat/{workflows → _workflows}/utils.py +0 -0
- {cognite_neat-0.92.3.dist-info → cognite_neat-0.94.0.dist-info}/LICENSE +0 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
from collections.abc import Collection
|
|
2
|
+
from typing import Literal, cast
|
|
3
|
+
|
|
4
|
+
from cognite.client.data_classes.data_modeling import DataModelIdentifier
|
|
5
|
+
|
|
6
|
+
from cognite.neat._issues._base import IssueList
|
|
7
|
+
from cognite.neat._rules._shared import ReadRules
|
|
8
|
+
from cognite.neat._rules.models.information._rules_input import InformationInputRules
|
|
9
|
+
from cognite.neat._rules.transformers import ReduceCogniteModel, ToCompliantEntities, ToExtension
|
|
10
|
+
|
|
11
|
+
from ._state import SessionState
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class PrepareAPI:
|
|
15
|
+
def __init__(self, state: SessionState, verbose: bool) -> None:
|
|
16
|
+
self._state = state
|
|
17
|
+
self._verbose = verbose
|
|
18
|
+
self.data_model = DataModelPrepareAPI(state, verbose)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class DataModelPrepareAPI:
|
|
22
|
+
def __init__(self, state: SessionState, verbose: bool) -> None:
|
|
23
|
+
self._state = state
|
|
24
|
+
self._verbose = verbose
|
|
25
|
+
|
|
26
|
+
def cdf_compliant_external_ids(self) -> None:
|
|
27
|
+
"""Convert data model component external ids to CDF compliant entities."""
|
|
28
|
+
if input := self._state.information_input_rule:
|
|
29
|
+
output = ToCompliantEntities().transform(input)
|
|
30
|
+
self._state.input_rules.append(
|
|
31
|
+
ReadRules(
|
|
32
|
+
rules=cast(InformationInputRules, output.get_rules()),
|
|
33
|
+
issues=IssueList(),
|
|
34
|
+
read_context={},
|
|
35
|
+
)
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
def to_extension(self, new_data_model_id: DataModelIdentifier, org_name: str | None = None) -> None:
|
|
39
|
+
"""Uses the current data model as a basis to extend from.
|
|
40
|
+
|
|
41
|
+
Args:
|
|
42
|
+
new_data_model_id: The new data model that is extending the current data model.
|
|
43
|
+
org_name: Organization name to use for the views in the new data model. This is required if you are
|
|
44
|
+
creating an extension from a Cognite Data Model.
|
|
45
|
+
|
|
46
|
+
"""
|
|
47
|
+
if dms := self._state.last_verified_dms_rules:
|
|
48
|
+
output = ToExtension(new_data_model_id, org_name).transform(dms)
|
|
49
|
+
self._state.verified_rules.append(output.rules)
|
|
50
|
+
|
|
51
|
+
def reduce(self, drop: Collection[Literal["3D", "Annotation", "BaseViews"]]) -> None:
|
|
52
|
+
"""This is a special method that allow you to drop parts of the data model.
|
|
53
|
+
This only applies to Cognite Data Models.
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
drop: Which parts of the data model to drop.
|
|
57
|
+
|
|
58
|
+
"""
|
|
59
|
+
if dms := self._state.last_verified_dms_rules:
|
|
60
|
+
output = ReduceCogniteModel(drop).transform(dms)
|
|
61
|
+
self._state.verified_rules.append(output.rules)
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
from typing import Any
|
|
3
|
+
|
|
4
|
+
from cognite.client import CogniteClient
|
|
5
|
+
from cognite.client.data_classes.data_modeling import DataModelIdentifier
|
|
6
|
+
|
|
7
|
+
from cognite.neat._graph import examples as instances_examples
|
|
8
|
+
from cognite.neat._graph import extractors
|
|
9
|
+
from cognite.neat._issues import IssueList
|
|
10
|
+
from cognite.neat._rules import importers
|
|
11
|
+
from cognite.neat._rules._shared import ReadRules
|
|
12
|
+
|
|
13
|
+
from ._state import SessionState
|
|
14
|
+
from ._wizard import NeatObjectType, RDFFileType, object_wizard, rdf_dm_wizard
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class ReadAPI:
|
|
18
|
+
def __init__(self, state: SessionState, client: CogniteClient | None, verbose: bool) -> None:
|
|
19
|
+
self._state = state
|
|
20
|
+
self._verbose = verbose
|
|
21
|
+
self.cdf = CDFReadAPI(state, client, verbose)
|
|
22
|
+
self.rdf = RDFReadAPI(state, client, verbose)
|
|
23
|
+
self.excel = ExcelReadAPI(state, client, verbose)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class BaseReadAPI:
|
|
27
|
+
def __init__(self, state: SessionState, client: CogniteClient | None, verbose: bool) -> None:
|
|
28
|
+
self._state = state
|
|
29
|
+
self._verbose = verbose
|
|
30
|
+
self._client = client
|
|
31
|
+
|
|
32
|
+
def _store_rules(self, io: Any, input_rules: ReadRules, source: str) -> None:
|
|
33
|
+
if input_rules.rules:
|
|
34
|
+
self._state.input_rules.append(input_rules)
|
|
35
|
+
if self._verbose:
|
|
36
|
+
if input_rules.issues.has_errors:
|
|
37
|
+
print(f"{source} {type(io)} {io} read failed")
|
|
38
|
+
else:
|
|
39
|
+
print(f"{source} {type(io)} {io} read successfully")
|
|
40
|
+
|
|
41
|
+
def _return_filepath(self, io: Any) -> Path:
|
|
42
|
+
if isinstance(io, str):
|
|
43
|
+
return Path(io)
|
|
44
|
+
elif isinstance(io, Path):
|
|
45
|
+
return io
|
|
46
|
+
else:
|
|
47
|
+
raise ValueError(f"Expected str or Path, got {type(io)}")
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class CDFReadAPI(BaseReadAPI):
|
|
51
|
+
def data_model(self, data_model_id: DataModelIdentifier) -> IssueList:
|
|
52
|
+
if self._client is None:
|
|
53
|
+
raise ValueError("No client provided. Please provide a client to read a data model.")
|
|
54
|
+
|
|
55
|
+
importer = importers.DMSImporter.from_data_model_id(self._client, data_model_id)
|
|
56
|
+
input_rules = importer.to_rules()
|
|
57
|
+
self._store_rules(data_model_id, input_rules, "CDF")
|
|
58
|
+
return input_rules.issues
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class ExcelReadAPI(BaseReadAPI):
|
|
62
|
+
def __call__(self, io: Any) -> IssueList:
|
|
63
|
+
filepath = self._return_filepath(io)
|
|
64
|
+
input_rules: ReadRules = importers.ExcelImporter(filepath).to_rules()
|
|
65
|
+
self._store_rules(io, input_rules, "Excel")
|
|
66
|
+
return input_rules.issues
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class RDFReadAPI(BaseReadAPI):
|
|
70
|
+
def __init__(self, state: SessionState, client: CogniteClient | None, verbose: bool) -> None:
|
|
71
|
+
super().__init__(state, client, verbose)
|
|
72
|
+
self.examples = RDFExamples(state)
|
|
73
|
+
|
|
74
|
+
def _ontology(self, io: Any) -> IssueList:
|
|
75
|
+
filepath = self._return_filepath(io)
|
|
76
|
+
input_rules: ReadRules = importers.OWLImporter.from_file(filepath).to_rules()
|
|
77
|
+
self._store_rules(io, input_rules, "Ontology")
|
|
78
|
+
return input_rules.issues
|
|
79
|
+
|
|
80
|
+
def _imf(self, io: Any) -> IssueList:
|
|
81
|
+
filepath = self._return_filepath(io)
|
|
82
|
+
input_rules: ReadRules = importers.IMFImporter.from_file(filepath).to_rules()
|
|
83
|
+
self._store_rules(io, input_rules, "IMF Types")
|
|
84
|
+
return input_rules.issues
|
|
85
|
+
|
|
86
|
+
def __call__(
|
|
87
|
+
self,
|
|
88
|
+
io: Any,
|
|
89
|
+
type: NeatObjectType | None = None,
|
|
90
|
+
source: RDFFileType | None = None,
|
|
91
|
+
) -> IssueList:
|
|
92
|
+
if type is None:
|
|
93
|
+
type = object_wizard()
|
|
94
|
+
|
|
95
|
+
if type.lower() == "Data Model".lower():
|
|
96
|
+
source = source or rdf_dm_wizard("What type of data model is the RDF?")
|
|
97
|
+
if source == "Ontology":
|
|
98
|
+
return self._ontology(io)
|
|
99
|
+
elif source == "IMF":
|
|
100
|
+
return self._imf(io)
|
|
101
|
+
else:
|
|
102
|
+
raise ValueError(f"Expected ontology, imf or instances, got {source}")
|
|
103
|
+
|
|
104
|
+
elif type.lower() == "Instances".lower():
|
|
105
|
+
self._state.store.write(extractors.RdfFileExtractor(self._return_filepath(io)))
|
|
106
|
+
return IssueList()
|
|
107
|
+
else:
|
|
108
|
+
raise ValueError(f"Expected data model or instances, got {type}")
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
class RDFExamples:
|
|
112
|
+
def __init__(self, state: SessionState) -> None:
|
|
113
|
+
self._state = state
|
|
114
|
+
|
|
115
|
+
@property
|
|
116
|
+
def nordic44(self) -> IssueList:
|
|
117
|
+
self._state.store.write(extractors.RdfFileExtractor(instances_examples.nordic44_knowledge_graph))
|
|
118
|
+
return IssueList()
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
import random
|
|
2
|
+
from typing import Any, cast
|
|
3
|
+
|
|
4
|
+
import networkx as nx
|
|
5
|
+
from ipycytoscape import CytoscapeWidget # type: ignore
|
|
6
|
+
from IPython.display import display
|
|
7
|
+
|
|
8
|
+
from cognite.neat._rules._constants import EntityTypes
|
|
9
|
+
from cognite.neat._rules.models.dms._rules import DMSRules
|
|
10
|
+
from cognite.neat._rules.models.entities._single_value import ClassEntity, ViewEntity
|
|
11
|
+
from cognite.neat._rules.models.information._rules import InformationRules
|
|
12
|
+
from cognite.neat._session.exceptions import NeatSessionError
|
|
13
|
+
from cognite.neat._utils.rdf_ import remove_namespace_from_uri
|
|
14
|
+
|
|
15
|
+
from ._state import SessionState
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class ShowAPI:
|
|
19
|
+
def __init__(self, state: SessionState) -> None:
|
|
20
|
+
self._state = state
|
|
21
|
+
self.data_model = ShowDataModelAPI(self._state)
|
|
22
|
+
self.instances = ShowInstanceAPI(self._state)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class ShowInstanceAPI:
|
|
26
|
+
def __init__(self, state: SessionState) -> None:
|
|
27
|
+
self._state = state
|
|
28
|
+
|
|
29
|
+
def __call__(self) -> Any:
|
|
30
|
+
if not self._state.store.graph:
|
|
31
|
+
raise NeatSessionError("No instances available. Try using [bold].read[/bold] to load instances.")
|
|
32
|
+
|
|
33
|
+
widget = CytoscapeWidget()
|
|
34
|
+
widget.layout.height = "700px"
|
|
35
|
+
|
|
36
|
+
NxGraph, types = self._generate_instance_di_graph_and_types()
|
|
37
|
+
widget_style = self._generate_cytoscape_widget_style(types)
|
|
38
|
+
widget.set_style(widget_style)
|
|
39
|
+
|
|
40
|
+
widget.graph.add_graph_from_networkx(NxGraph)
|
|
41
|
+
print("Max of 100 nodes and edges are displayed, which are randomly selected.")
|
|
42
|
+
|
|
43
|
+
return display(widget)
|
|
44
|
+
|
|
45
|
+
def _generate_instance_di_graph_and_types(self) -> tuple[nx.DiGraph, set[str]]:
|
|
46
|
+
query = """
|
|
47
|
+
SELECT ?s ?p ?o ?ts ?to WHERE {
|
|
48
|
+
?s ?p ?o .
|
|
49
|
+
FILTER(isIRI(?o)) # Example filter to check if ?o is an IRI (object type)
|
|
50
|
+
FILTER(BOUND(?o))
|
|
51
|
+
FILTER(?p != rdf:type)
|
|
52
|
+
|
|
53
|
+
?s a ?ts .
|
|
54
|
+
?o a ?to .
|
|
55
|
+
}
|
|
56
|
+
LIMIT 100
|
|
57
|
+
"""
|
|
58
|
+
|
|
59
|
+
NxGraph = nx.DiGraph()
|
|
60
|
+
|
|
61
|
+
types = set()
|
|
62
|
+
|
|
63
|
+
for ( # type: ignore
|
|
64
|
+
subject,
|
|
65
|
+
property_,
|
|
66
|
+
object,
|
|
67
|
+
subject_type,
|
|
68
|
+
object_type,
|
|
69
|
+
) in self._state.store.graph.query(query):
|
|
70
|
+
subject = remove_namespace_from_uri(subject)
|
|
71
|
+
property_ = remove_namespace_from_uri(property_)
|
|
72
|
+
object = remove_namespace_from_uri(object)
|
|
73
|
+
subject_type = remove_namespace_from_uri(subject_type)
|
|
74
|
+
object_type = remove_namespace_from_uri(object_type)
|
|
75
|
+
|
|
76
|
+
NxGraph.add_node(subject, label=subject, type=subject_type)
|
|
77
|
+
NxGraph.add_node(object, label=object, type=object_type)
|
|
78
|
+
NxGraph.add_edge(subject, object, label=property_)
|
|
79
|
+
|
|
80
|
+
types.add(subject_type)
|
|
81
|
+
types.add(object_type)
|
|
82
|
+
|
|
83
|
+
return NxGraph, types
|
|
84
|
+
|
|
85
|
+
def _generate_cytoscape_widget_style(self, types: set[str]) -> list[dict]:
|
|
86
|
+
widget_style = [
|
|
87
|
+
{
|
|
88
|
+
"selector": "edge",
|
|
89
|
+
"style": {
|
|
90
|
+
"width": 1,
|
|
91
|
+
"target-arrow-shape": "triangle",
|
|
92
|
+
"curve-style": "bezier",
|
|
93
|
+
"label": "data(label)",
|
|
94
|
+
"font-size": "8px",
|
|
95
|
+
"line-color": "black",
|
|
96
|
+
"target-arrow-color": "black",
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
]
|
|
100
|
+
|
|
101
|
+
colors = self._generate_hex_colors(len(types))
|
|
102
|
+
|
|
103
|
+
for i, type_ in enumerate(types):
|
|
104
|
+
widget_style.append(self._generate_node_cytoscape_style(type_, colors[i]))
|
|
105
|
+
|
|
106
|
+
return widget_style
|
|
107
|
+
|
|
108
|
+
@staticmethod
|
|
109
|
+
def _generate_hex_colors(n: int) -> list[str]:
|
|
110
|
+
"""Generate a list of N random HEX color codes."""
|
|
111
|
+
random.seed(42) # Set a seed for deterministic behavior
|
|
112
|
+
hex_colors = []
|
|
113
|
+
for _ in range(n):
|
|
114
|
+
color = f"#{random.randint(0, 0xFFFFFF):06x}"
|
|
115
|
+
hex_colors.append(color)
|
|
116
|
+
return hex_colors
|
|
117
|
+
|
|
118
|
+
@staticmethod
|
|
119
|
+
def _generate_node_cytoscape_style(type_: str, color: str) -> dict:
|
|
120
|
+
template = {
|
|
121
|
+
"css": {
|
|
122
|
+
"content": "data(label)",
|
|
123
|
+
"text-valign": "center",
|
|
124
|
+
"color": "black",
|
|
125
|
+
"font-size": "10px",
|
|
126
|
+
"width": "mapData(score, 0, 1, 10, 50)",
|
|
127
|
+
"height": "mapData(score, 0, 1, 10, 50)",
|
|
128
|
+
},
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
template["selector"] = f'node[type = "{type_}"]' # type: ignore
|
|
132
|
+
template["css"]["background-color"] = color
|
|
133
|
+
|
|
134
|
+
return template
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
class ShowDataModelAPI:
|
|
138
|
+
def __init__(self, state: SessionState) -> None:
|
|
139
|
+
self._state = state
|
|
140
|
+
|
|
141
|
+
def __call__(self) -> Any:
|
|
142
|
+
if not self._state.last_verified_dms_rules and not self._state.last_verified_information_rules:
|
|
143
|
+
raise NeatSessionError(
|
|
144
|
+
"No verified data model available. Try using [bold].verify()[/bold] to verify data model."
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
if self._state.last_verified_dms_rules:
|
|
148
|
+
NxGraph = self._generate_dms_di_graph()
|
|
149
|
+
elif self._state.last_verified_information_rules:
|
|
150
|
+
NxGraph = self._generate_info_di_graph()
|
|
151
|
+
|
|
152
|
+
widget = self._generate_widget()
|
|
153
|
+
widget.graph.add_graph_from_networkx(NxGraph)
|
|
154
|
+
return display(widget)
|
|
155
|
+
|
|
156
|
+
def _generate_dms_di_graph(self) -> nx.DiGraph:
|
|
157
|
+
"""Generate a DiGraph from the last verified DMS rules."""
|
|
158
|
+
NxGraph = nx.DiGraph()
|
|
159
|
+
|
|
160
|
+
# Add nodes and edges from Views sheet
|
|
161
|
+
for view in cast(DMSRules, self._state.last_verified_dms_rules).views:
|
|
162
|
+
# if possible use human readable label coming from the view name
|
|
163
|
+
if not NxGraph.has_node(view.view.suffix):
|
|
164
|
+
NxGraph.add_node(view.view.suffix, label=view.name or view.view.suffix)
|
|
165
|
+
|
|
166
|
+
# add implements as edges
|
|
167
|
+
if view.implements:
|
|
168
|
+
for implement in view.implements:
|
|
169
|
+
if not NxGraph.has_node(implement.suffix):
|
|
170
|
+
NxGraph.add_node(implement.suffix, label=implement.suffix)
|
|
171
|
+
|
|
172
|
+
NxGraph.add_edge(view.view.suffix, implement.suffix, label="implements")
|
|
173
|
+
|
|
174
|
+
# Add nodes and edges from Properties sheet
|
|
175
|
+
for prop_ in cast(DMSRules, self._state.last_verified_dms_rules).properties:
|
|
176
|
+
if prop_.connection and isinstance(prop_.value_type, ViewEntity):
|
|
177
|
+
if not NxGraph.has_node(prop_.view.suffix):
|
|
178
|
+
NxGraph.add_node(prop_.view.suffix, label=prop_.view.suffix)
|
|
179
|
+
|
|
180
|
+
label = f"{prop_.property_} [{0 if prop_.nullable else 1}..{ '' if prop_.is_list else 1}]"
|
|
181
|
+
NxGraph.add_edge(prop_.view.suffix, prop_.value_type.suffix, label=label)
|
|
182
|
+
|
|
183
|
+
return NxGraph
|
|
184
|
+
|
|
185
|
+
def _generate_info_di_graph(self) -> nx.DiGraph:
|
|
186
|
+
"""Generate nodes and edges for the last verified Information rules for DiGraph."""
|
|
187
|
+
|
|
188
|
+
NxGraph = nx.DiGraph()
|
|
189
|
+
|
|
190
|
+
# Add nodes and edges from Views sheet
|
|
191
|
+
for class_ in cast(InformationRules, self._state.last_verified_information_rules).classes:
|
|
192
|
+
# if possible use human readable label coming from the view name
|
|
193
|
+
if not NxGraph.has_node(class_.class_.suffix):
|
|
194
|
+
NxGraph.add_node(
|
|
195
|
+
class_.class_.suffix,
|
|
196
|
+
label=class_.name or class_.class_.suffix,
|
|
197
|
+
)
|
|
198
|
+
|
|
199
|
+
# add implements as edges
|
|
200
|
+
if class_.parent:
|
|
201
|
+
for parent in class_.parent:
|
|
202
|
+
if not NxGraph.has_node(parent.suffix):
|
|
203
|
+
NxGraph.add_node(parent.suffix, label=parent.suffix)
|
|
204
|
+
|
|
205
|
+
NxGraph.add_edge(class_.class_.suffix, parent.suffix, label="subClassOf")
|
|
206
|
+
|
|
207
|
+
# Add nodes and edges from Properties sheet
|
|
208
|
+
for prop_ in cast(InformationRules, self._state.last_verified_information_rules).properties:
|
|
209
|
+
if prop_.type_ == EntityTypes.object_property:
|
|
210
|
+
if not NxGraph.has_node(prop_.class_.suffix):
|
|
211
|
+
NxGraph.add_node(prop_.class_.suffix, label=prop_.class_.suffix)
|
|
212
|
+
|
|
213
|
+
label = f"{prop_.property_} [{1 if prop_.is_mandatory else 0}..{ '' if prop_.is_list else 1}]"
|
|
214
|
+
NxGraph.add_edge(
|
|
215
|
+
prop_.class_.suffix,
|
|
216
|
+
cast(ClassEntity, prop_.value_type).suffix,
|
|
217
|
+
label=label,
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
return NxGraph
|
|
221
|
+
|
|
222
|
+
def _generate_widget(self):
|
|
223
|
+
"""Generates an empty a CytoscapeWidget."""
|
|
224
|
+
widget = CytoscapeWidget()
|
|
225
|
+
widget.layout.height = "700px"
|
|
226
|
+
|
|
227
|
+
widget.set_style(
|
|
228
|
+
[
|
|
229
|
+
{
|
|
230
|
+
"selector": "node",
|
|
231
|
+
"css": {
|
|
232
|
+
"content": "data(label)",
|
|
233
|
+
"text-valign": "center",
|
|
234
|
+
"color": "black",
|
|
235
|
+
"background-color": "#33C4FF",
|
|
236
|
+
"font-size": "10px",
|
|
237
|
+
"width": "mapData(score, 0, 1, 10, 50)",
|
|
238
|
+
"height": "mapData(score, 0, 1, 10, 50)",
|
|
239
|
+
},
|
|
240
|
+
},
|
|
241
|
+
{
|
|
242
|
+
"selector": "edge",
|
|
243
|
+
"style": {
|
|
244
|
+
"width": 1,
|
|
245
|
+
"target-arrow-shape": "triangle",
|
|
246
|
+
"curve-style": "bezier",
|
|
247
|
+
"label": "data(label)",
|
|
248
|
+
"font-size": "8px",
|
|
249
|
+
"line-color": "black",
|
|
250
|
+
"target-arrow-color": "black",
|
|
251
|
+
},
|
|
252
|
+
},
|
|
253
|
+
{
|
|
254
|
+
"selector": 'edge[label = "subClassOf"]',
|
|
255
|
+
"style": {
|
|
256
|
+
"line-color": "grey",
|
|
257
|
+
"target-arrow-color": "grey",
|
|
258
|
+
"line-style": "dashed",
|
|
259
|
+
"font-size": "8px",
|
|
260
|
+
},
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
"selector": 'edge[label = "implements"]',
|
|
264
|
+
"style": {
|
|
265
|
+
"line-color": "grey",
|
|
266
|
+
"target-arrow-color": "grey",
|
|
267
|
+
"line-style": "dashed",
|
|
268
|
+
"font-size": "8px",
|
|
269
|
+
},
|
|
270
|
+
},
|
|
271
|
+
]
|
|
272
|
+
)
|
|
273
|
+
|
|
274
|
+
return widget
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
from dataclasses import dataclass, field
|
|
2
|
+
from typing import Literal, cast
|
|
3
|
+
|
|
4
|
+
from cognite.neat._rules._shared import ReadRules, VerifiedRules
|
|
5
|
+
from cognite.neat._rules.models.dms._rules import DMSRules
|
|
6
|
+
from cognite.neat._rules.models.information._rules import InformationRules
|
|
7
|
+
from cognite.neat._rules.models.information._rules_input import InformationInputRules
|
|
8
|
+
from cognite.neat._store import NeatGraphStore
|
|
9
|
+
|
|
10
|
+
from .exceptions import NeatSessionError
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@dataclass
|
|
14
|
+
class SessionState:
|
|
15
|
+
store_type: Literal["memory", "oxigraph"]
|
|
16
|
+
input_rules: list[ReadRules] = field(default_factory=list)
|
|
17
|
+
verified_rules: list[VerifiedRules] = field(default_factory=list)
|
|
18
|
+
_store: NeatGraphStore | None = field(init=False, default=None)
|
|
19
|
+
|
|
20
|
+
@property
|
|
21
|
+
def store(self) -> NeatGraphStore:
|
|
22
|
+
if not self.has_store:
|
|
23
|
+
if self.store_type == "oxigraph":
|
|
24
|
+
self._store = NeatGraphStore.from_oxi_store()
|
|
25
|
+
else:
|
|
26
|
+
self._store = NeatGraphStore.from_memory_store()
|
|
27
|
+
return cast(NeatGraphStore, self._store)
|
|
28
|
+
|
|
29
|
+
@property
|
|
30
|
+
def input_rule(self) -> ReadRules:
|
|
31
|
+
if not self.input_rules:
|
|
32
|
+
raise NeatSessionError("No input data model available. Try using [bold].read[/bold] to load a data model.")
|
|
33
|
+
return self.input_rules[-1]
|
|
34
|
+
|
|
35
|
+
@property
|
|
36
|
+
def information_input_rule(self) -> ReadRules | None:
|
|
37
|
+
if self.input_rules:
|
|
38
|
+
for rule in self.input_rules[::-1]:
|
|
39
|
+
if isinstance(rule.rules, InformationInputRules):
|
|
40
|
+
return rule
|
|
41
|
+
return None
|
|
42
|
+
|
|
43
|
+
@property
|
|
44
|
+
def last_verified_rule(self) -> VerifiedRules:
|
|
45
|
+
if not self.verified_rules:
|
|
46
|
+
raise NeatSessionError(
|
|
47
|
+
"No data model available to verify. Try using [bold].read[/bold] to load a data model."
|
|
48
|
+
)
|
|
49
|
+
return self.verified_rules[-1]
|
|
50
|
+
|
|
51
|
+
@property
|
|
52
|
+
def last_verified_dms_rules(self) -> DMSRules | None:
|
|
53
|
+
if self.verified_rules:
|
|
54
|
+
for rules in self.verified_rules[::-1]:
|
|
55
|
+
if isinstance(rules, DMSRules):
|
|
56
|
+
return rules
|
|
57
|
+
return None
|
|
58
|
+
|
|
59
|
+
@property
|
|
60
|
+
def last_verified_information_rules(self) -> InformationRules | None:
|
|
61
|
+
if self.verified_rules:
|
|
62
|
+
for rules in self.verified_rules[::-1]:
|
|
63
|
+
if isinstance(rules, InformationRules):
|
|
64
|
+
return rules
|
|
65
|
+
return None
|
|
66
|
+
|
|
67
|
+
@property
|
|
68
|
+
def has_store(self) -> bool:
|
|
69
|
+
return self._store is not None
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
from typing import Any, overload
|
|
3
|
+
|
|
4
|
+
from cognite.client import CogniteClient
|
|
5
|
+
|
|
6
|
+
from cognite.neat._graph import loaders
|
|
7
|
+
from cognite.neat._rules import exporters
|
|
8
|
+
from cognite.neat._session._wizard import space_wizard
|
|
9
|
+
|
|
10
|
+
from ._state import SessionState
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class ToAPI:
|
|
14
|
+
def __init__(self, state: SessionState, client: CogniteClient | None, verbose: bool) -> None:
|
|
15
|
+
self._state = state
|
|
16
|
+
self._verbose = verbose
|
|
17
|
+
self.cdf = CDFToAPI(state, client, verbose)
|
|
18
|
+
|
|
19
|
+
def excel(
|
|
20
|
+
self,
|
|
21
|
+
io: Any,
|
|
22
|
+
) -> None:
|
|
23
|
+
exporter = exporters.ExcelExporter()
|
|
24
|
+
exporter.export_to_file(self._state.last_verified_rule, Path(io))
|
|
25
|
+
return None
|
|
26
|
+
|
|
27
|
+
@overload
|
|
28
|
+
def yaml(self, io: None) -> str: ...
|
|
29
|
+
|
|
30
|
+
@overload
|
|
31
|
+
def yaml(self, io: Any) -> None: ...
|
|
32
|
+
|
|
33
|
+
def yaml(self, io: Any | None = None) -> str | None:
|
|
34
|
+
exporter = exporters.YAMLExporter()
|
|
35
|
+
if io is None:
|
|
36
|
+
return exporter.export(self._state.last_verified_rule)
|
|
37
|
+
|
|
38
|
+
exporter.export_to_file(self._state.last_verified_rule, Path(io))
|
|
39
|
+
return None
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class CDFToAPI:
|
|
43
|
+
def __init__(self, state: SessionState, client: CogniteClient | None, verbose: bool) -> None:
|
|
44
|
+
self._client = client
|
|
45
|
+
self._state = state
|
|
46
|
+
self._verbose = verbose
|
|
47
|
+
|
|
48
|
+
def instances(self, space: str | None = None):
|
|
49
|
+
if not self._state.last_verified_dms_rules:
|
|
50
|
+
raise ValueError("No verified DMS data model available")
|
|
51
|
+
|
|
52
|
+
loader = loaders.DMSLoader.from_rules(
|
|
53
|
+
self._state.last_verified_dms_rules, self._state.store, space_wizard(space=space)
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
if not self._client:
|
|
57
|
+
raise ValueError("No client provided!")
|
|
58
|
+
|
|
59
|
+
return loader.load_into_cdf(self._client)
|
|
60
|
+
|
|
61
|
+
def data_model(self):
|
|
62
|
+
if not self._state.last_verified_dms_rules:
|
|
63
|
+
raise ValueError("No verified DMS data model available")
|
|
64
|
+
|
|
65
|
+
exporter = exporters.DMSExporter()
|
|
66
|
+
|
|
67
|
+
if not self._client:
|
|
68
|
+
raise ValueError("No client provided!")
|
|
69
|
+
|
|
70
|
+
return exporter.export_to_cdf(self._state.last_verified_dms_rules, self._client)
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
from collections.abc import Sequence
|
|
2
|
+
from typing import Literal, TypeVar, get_args
|
|
3
|
+
|
|
4
|
+
from rich.prompt import IntPrompt, Prompt
|
|
5
|
+
|
|
6
|
+
from cognite.neat._rules._constants import PATTERNS
|
|
7
|
+
|
|
8
|
+
RDFFileType = Literal["Ontology", "IMF Types", "Inference"]
|
|
9
|
+
NeatObjectType = Literal["Data Model", "Instances"]
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def object_wizard(message: str = "Select object") -> NeatObjectType:
|
|
13
|
+
return _selection(message, get_args(NeatObjectType))
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def rdf_dm_wizard(message: str = "Select source:") -> RDFFileType:
|
|
17
|
+
return _selection(message, get_args(RDFFileType))
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
_T_Option = TypeVar("_T_Option")
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _selection(message: str, options: Sequence[_T_Option]) -> _T_Option:
|
|
24
|
+
option_text = "\n ".join([f"{i+1}) {option}" for i, option in enumerate(options)])
|
|
25
|
+
selected_index = (
|
|
26
|
+
IntPrompt().ask(f"{message}\n {option_text}\n", choices=list(map(str, range(1, len(options) + 1)))) - 1
|
|
27
|
+
)
|
|
28
|
+
return options[selected_index]
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def space_wizard(message: str = "Set space", space: str | None = None) -> str:
|
|
32
|
+
while True:
|
|
33
|
+
user_input = space or Prompt().ask(f"{message}:")
|
|
34
|
+
if PATTERNS.space_compliance.match(str(user_input)):
|
|
35
|
+
return user_input
|
|
36
|
+
else:
|
|
37
|
+
print(f"Invalid input. Please provide a valid space name. {PATTERNS.space_compliance.pattern}")
|
|
38
|
+
|
|
39
|
+
space = ""
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import functools
|
|
2
|
+
from collections.abc import Callable
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
try:
|
|
6
|
+
from rich import print
|
|
7
|
+
|
|
8
|
+
_PREFIX = "[bold red][ERROR][/bold red]"
|
|
9
|
+
except ImportError:
|
|
10
|
+
_PREFIX = "[ERROR]"
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class NeatSessionError(Exception):
|
|
14
|
+
"""Base class for all exceptions raised by the NeatSession class."""
|
|
15
|
+
|
|
16
|
+
...
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _intercept_session_exceptions(func: Callable):
|
|
20
|
+
@functools.wraps(func)
|
|
21
|
+
def wrapper(*args: Any, **kwargs: Any):
|
|
22
|
+
try:
|
|
23
|
+
return func(*args, **kwargs)
|
|
24
|
+
except NeatSessionError as e:
|
|
25
|
+
action = func.__name__
|
|
26
|
+
print(f"{_PREFIX} Cannot {action}: {e}")
|
|
27
|
+
|
|
28
|
+
return wrapper
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def intercept_session_exceptions(cls: type):
|
|
32
|
+
to_check = [cls]
|
|
33
|
+
while to_check:
|
|
34
|
+
cls = to_check.pop()
|
|
35
|
+
for attr_name in dir(cls):
|
|
36
|
+
if not attr_name.startswith("_"):
|
|
37
|
+
attr = getattr(cls, attr_name)
|
|
38
|
+
if callable(attr):
|
|
39
|
+
setattr(cls, attr_name, _intercept_session_exceptions(attr))
|
|
40
|
+
elif isinstance(attr, type):
|
|
41
|
+
to_check.append(attr)
|
|
42
|
+
return cls
|