From bbdeb9cd31ddd3d79b98cec0f4c28e346faf445a Mon Sep 17 00:00:00 2001 From: anders-albert Date: Thu, 27 Jun 2024 10:14:11 +0200 Subject: [PATCH 01/11] feat: notebook representation of each module --- cognite/neat/graph/extractors/__init__.py | 17 +++++++++++++++++ cognite/neat/graph/loaders/__init__.py | 15 +++++++++++++++ cognite/neat/rules/exporters/__init__.py | 19 ++++++++++++++++++- cognite/neat/rules/importers/__init__.py | 15 +++++++++++++++ cognite/neat/rules/importers/_base.py | 7 +++++++ 5 files changed, 72 insertions(+), 1 deletion(-) diff --git a/cognite/neat/graph/extractors/__init__.py b/cognite/neat/graph/extractors/__init__.py index a5b06ed85..b7d7db1f8 100644 --- a/cognite/neat/graph/extractors/__init__.py +++ b/cognite/neat/graph/extractors/__init__.py @@ -1,3 +1,4 @@ +from ._base import BaseExtractor from ._classic_cdf._assets import AssetsExtractor from ._classic_cdf._events import EventsExtractor from ._classic_cdf._files import FilesExtractor @@ -10,6 +11,7 @@ from ._rdf_file import RdfFileExtractor __all__ = [ + "BaseExtractor", "AssetsExtractor", "MockGraphGenerator", "RelationshipsExtractor", @@ -35,3 +37,18 @@ | RdfFileExtractor | DexpiExtractor ) + + +def _repr_html_() -> str: + import pandas as pd + + return pd.DataFrame( # type: ignore[operator] + [ + { + "Extractor": name, + "Description": globals()[name].__doc__.strip().split("\n")[0] if globals()[name].__doc__ else "Missing", + } + for name in __all__ + if name != "BaseExtractor" + ] + )._repr_html_() diff --git a/cognite/neat/graph/loaders/__init__.py b/cognite/neat/graph/loaders/__init__.py index 0d1af13b4..c462da45d 100644 --- a/cognite/neat/graph/loaders/__init__.py +++ b/cognite/neat/graph/loaders/__init__.py @@ -2,3 +2,18 @@ from ._rdf2dms import DMSLoader __all__ = ["BaseLoader", "CDFLoader", "DMSLoader"] + + +def _repr_html_() -> str: + import pandas as pd + + return pd.DataFrame( # type: ignore[operator] + [ + { + "Loader": name, + "Description": globals()[name].__doc__.strip().split("\n")[0] if globals()[name].__doc__ else "Missing", + } + for name in __all__ + if name not in ("BaseLoader", "CDFLoader") + ] + )._repr_html_() diff --git a/cognite/neat/rules/exporters/__init__.py b/cognite/neat/rules/exporters/__init__.py index 30d386617..0982a6df5 100644 --- a/cognite/neat/rules/exporters/__init__.py +++ b/cognite/neat/rules/exporters/__init__.py @@ -1,9 +1,11 @@ -from ._rules2dms import CDFExporter, DMSExporter +from ._base import BaseExporter, CDFExporter +from ._rules2dms import DMSExporter from ._rules2excel import ExcelExporter from ._rules2ontology import GraphExporter, OWLExporter, SemanticDataModelExporter, SHACLExporter from ._rules2yaml import YAMLExporter __all__ = [ + "BaseExporter", "DMSExporter", "CDFExporter", "SemanticDataModelExporter", @@ -13,3 +15,18 @@ "ExcelExporter", "YAMLExporter", ] + + +def _repr_html_() -> str: + import pandas as pd + + return pd.DataFrame( # type: ignore[operator] + [ + { + "Exporter": name, + "Description": globals()[name].__doc__.strip().split("\n")[0] if globals()[name].__doc__ else "Missing", + } + for name in __all__ + if name not in ("BaseExporter", "CDFExporter") + ] + )._repr_html_() diff --git a/cognite/neat/rules/importers/__init__.py b/cognite/neat/rules/importers/__init__.py index 60b896687..8ca1d0216 100644 --- a/cognite/neat/rules/importers/__init__.py +++ b/cognite/neat/rules/importers/__init__.py @@ -16,3 +16,18 @@ "YAMLImporter", "InferenceImporter", ] + + +def _repr_html_() -> str: + import pandas as pd + + return pd.DataFrame( # type: ignore[operator] + [ + { + "Importer": name, + "Description": globals()[name].__doc__.strip().split("\n")[0] if globals()[name].__doc__ else "Missing", + } + for name in __all__ + if name != "BaseImporter" + ] + )._repr_html_() diff --git a/cognite/neat/rules/importers/_base.py b/cognite/neat/rules/importers/_base.py index fd4d20415..2d13fb10e 100644 --- a/cognite/neat/rules/importers/_base.py +++ b/cognite/neat/rules/importers/_base.py @@ -79,6 +79,13 @@ def _default_metadata(self): "description": f"Imported using {type(self).__name__}", } + @classmethod + def _repr_html_(cls) -> str: + if not cls.__doc__: + return f"

{cls.__name__}

Missing Description

" + docstring = cls.__doc__.replace("\n", "
") + return f"

{cls.__name__}

{docstring}

" + class _FutureResult: def __init__(self) -> None: From 5539b17323f35a369a75473a85260e830b64968d Mon Sep 17 00:00:00 2001 From: anders-albert Date: Thu, 27 Jun 2024 10:28:47 +0200 Subject: [PATCH 02/11] refactor: added definition --- cognite/neat/graph/extractors/__init__.py | 7 ++++++- cognite/neat/graph/loaders/__init__.py | 6 +++++- cognite/neat/rules/exporters/__init__.py | 7 ++++++- cognite/neat/rules/importers/__init__.py | 7 ++++++- 4 files changed, 23 insertions(+), 4 deletions(-) diff --git a/cognite/neat/graph/extractors/__init__.py b/cognite/neat/graph/extractors/__init__.py index b7d7db1f8..464d6b692 100644 --- a/cognite/neat/graph/extractors/__init__.py +++ b/cognite/neat/graph/extractors/__init__.py @@ -42,7 +42,7 @@ def _repr_html_() -> str: import pandas as pd - return pd.DataFrame( # type: ignore[operator] + table = pd.DataFrame( # type: ignore[operator] [ { "Extractor": name, @@ -52,3 +52,8 @@ def _repr_html_() -> str: if name != "BaseExtractor" ] )._repr_html_() + + return ( + "Extractor An extractor is used to read data from " + f"a source into Neat's internal triple storage.
{table}" + ) diff --git a/cognite/neat/graph/loaders/__init__.py b/cognite/neat/graph/loaders/__init__.py index c462da45d..026e81db1 100644 --- a/cognite/neat/graph/loaders/__init__.py +++ b/cognite/neat/graph/loaders/__init__.py @@ -7,7 +7,7 @@ def _repr_html_() -> str: import pandas as pd - return pd.DataFrame( # type: ignore[operator] + table = pd.DataFrame( # type: ignore[operator] [ { "Loader": name, @@ -17,3 +17,7 @@ def _repr_html_() -> str: if name not in ("BaseLoader", "CDFLoader") ] )._repr_html_() + + return ( + "Loader A loader writes data from Neat's triple storage into a target system" f"
{table}" + ) diff --git a/cognite/neat/rules/exporters/__init__.py b/cognite/neat/rules/exporters/__init__.py index 0982a6df5..140030efb 100644 --- a/cognite/neat/rules/exporters/__init__.py +++ b/cognite/neat/rules/exporters/__init__.py @@ -20,7 +20,7 @@ def _repr_html_() -> str: import pandas as pd - return pd.DataFrame( # type: ignore[operator] + table = pd.DataFrame( # type: ignore[operator] [ { "Exporter": name, @@ -30,3 +30,8 @@ def _repr_html_() -> str: if name not in ("BaseExporter", "CDFExporter") ] )._repr_html_() + + return ( + "Exporter An exporter converts Neat's representation of a data model called Rules" + f" into a schema/data model for a target format.
{table}" + ) diff --git a/cognite/neat/rules/importers/__init__.py b/cognite/neat/rules/importers/__init__.py index 8ca1d0216..5a48fb1b9 100644 --- a/cognite/neat/rules/importers/__init__.py +++ b/cognite/neat/rules/importers/__init__.py @@ -21,7 +21,7 @@ def _repr_html_() -> str: import pandas as pd - return pd.DataFrame( # type: ignore[operator] + table = pd.DataFrame( # type: ignore[operator] [ { "Importer": name, @@ -31,3 +31,8 @@ def _repr_html_() -> str: if name != "BaseImporter" ] )._repr_html_() + + return ( + "Importer An importer reads data/schema/data model from a source" + f" and converts it into Neat's representation of a data model called Rules.
{table}" + ) From 0740cdf48d0e1802d3060f7ca5cc294d4ed2856c Mon Sep 17 00:00:00 2001 From: anders-albert Date: Thu, 27 Jun 2024 10:56:13 +0200 Subject: [PATCH 03/11] refactor: changed and Provenance use neat object and list --- cognite/neat/_shared.py | 18 +++++++++++++++++- cognite/neat/graph/stores/_provenance.py | 14 +++++++++++--- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/cognite/neat/_shared.py b/cognite/neat/_shared.py index f3c183a2e..53e678dd3 100644 --- a/cognite/neat/_shared.py +++ b/cognite/neat/_shared.py @@ -17,8 +17,24 @@ def dump(self, aggregate: bool = True) -> dict[str, Any]: """Return a dictionary representation of the object.""" raise NotImplementedError() + def _repr_html(self) -> str: + return pd.Series(self.dump(aggregate=True)).to_frame(name="value")._repr_html_() -T_NeatObject = TypeVar("T_NeatObject", bound=NeatObject) + +@dataclass(frozen=True) +class FrozenNeatObject: + """A frozen neat object can be dumped to a dictionary.""" + + @abstractmethod + def dump(self, aggregate: bool = True) -> dict[str, Any]: + """Return a dictionary representation of the object.""" + raise NotImplementedError() + + def _repr_html(self) -> str: + return pd.Series(self.dump(aggregate=True)).to_frame(name="value")._repr_html_() + + +T_NeatObject = TypeVar("T_NeatObject", bound=NeatObject | FrozenNeatObject) class NeatList(list, Sequence[T_NeatObject]): diff --git a/cognite/neat/graph/stores/_provenance.py b/cognite/neat/graph/stores/_provenance.py index 8d941a8bf..53040542a 100644 --- a/cognite/neat/graph/stores/_provenance.py +++ b/cognite/neat/graph/stores/_provenance.py @@ -8,7 +8,6 @@ import uuid -from collections import UserList from collections.abc import Sequence from dataclasses import dataclass from datetime import datetime @@ -16,6 +15,7 @@ from rdflib import PROV, RDF, Literal, URIRef +from cognite.neat._shared import FrozenNeatObject, NeatList from cognite.neat.constants import DEFAULT_NAMESPACE @@ -64,7 +64,7 @@ def as_triples(self): @dataclass(frozen=True) -class Change: +class Change(FrozenNeatObject): agent: Agent activity: Activity entity: Entity @@ -81,11 +81,19 @@ def record(cls, activity: str, start: datetime, end: datetime, description: str) entity = Entity(was_generated_by=activity, was_attributed_to=agent) return cls(agent, activity, entity, description) + def dump(self, aggregate: bool = True) -> dict[str, str]: + return { + "Agent": self.agent.id_, + "Activity": self.activity.id_, + "Entity": self.entity.id_, + "Description": self.description, + } + T_Change = TypeVar("T_Change", bound=Change) -class Provenance(UserList[T_Change]): +class Provenance(NeatList[Change]): def __init__(self, changes: Sequence[T_Change] | None = None): super().__init__(changes or []) From 2ac4e6f132bc4cce9614960371de9a857dd09aea Mon Sep 17 00:00:00 2001 From: anders-albert Date: Thu, 27 Jun 2024 10:57:06 +0200 Subject: [PATCH 04/11] refactor: print store nicely in notebook --- cognite/neat/graph/stores/_base.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cognite/neat/graph/stores/_base.py b/cognite/neat/graph/stores/_base.py index 7cf04d217..3228537ee 100644 --- a/cognite/neat/graph/stores/_base.py +++ b/cognite/neat/graph/stores/_base.py @@ -278,3 +278,6 @@ def transform(self, transformer: Transformers) -> None: description=transformer.description, ) ) + + def _repr_html(self) -> str: + return self.provenance._repr_html_() From f9b38357e4c8c79fe9341c9729407235e3379281 Mon Sep 17 00:00:00 2001 From: anders-albert Date: Thu, 27 Jun 2024 10:58:13 +0200 Subject: [PATCH 05/11] refactor: fix --- cognite/neat/graph/stores/_base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cognite/neat/graph/stores/_base.py b/cognite/neat/graph/stores/_base.py index 3228537ee..d62110d7f 100644 --- a/cognite/neat/graph/stores/_base.py +++ b/cognite/neat/graph/stores/_base.py @@ -279,5 +279,5 @@ def transform(self, transformer: Transformers) -> None: ) ) - def _repr_html(self) -> str: + def _repr_html_(self) -> str: return self.provenance._repr_html_() From 9dbe98cbdd9f03dff6c2ad8eb64c09ed105d0641 Mon Sep 17 00:00:00 2001 From: anders-albert Date: Thu, 27 Jun 2024 11:02:39 +0200 Subject: [PATCH 06/11] refactor; more explaination --- cognite/neat/_shared.py | 4 ++-- cognite/neat/graph/stores/_base.py | 9 ++++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/cognite/neat/_shared.py b/cognite/neat/_shared.py index 53e678dd3..aaa1975f7 100644 --- a/cognite/neat/_shared.py +++ b/cognite/neat/_shared.py @@ -17,7 +17,7 @@ def dump(self, aggregate: bool = True) -> dict[str, Any]: """Return a dictionary representation of the object.""" raise NotImplementedError() - def _repr_html(self) -> str: + def _repr_html_(self) -> str: return pd.Series(self.dump(aggregate=True)).to_frame(name="value")._repr_html_() @@ -30,7 +30,7 @@ def dump(self, aggregate: bool = True) -> dict[str, Any]: """Return a dictionary representation of the object.""" raise NotImplementedError() - def _repr_html(self) -> str: + def _repr_html_(self) -> str: return pd.Series(self.dump(aggregate=True)).to_frame(name="value")._repr_html_() diff --git a/cognite/neat/graph/stores/_base.py b/cognite/neat/graph/stores/_base.py index d62110d7f..ae4ad8ca4 100644 --- a/cognite/neat/graph/stores/_base.py +++ b/cognite/neat/graph/stores/_base.py @@ -280,4 +280,11 @@ def transform(self, transformer: Transformers) -> None: ) def _repr_html_(self) -> str: - return self.provenance._repr_html_() + provenance = self.provenance._repr_html_() + + return ( + f"{type(self).__name__} A graph store is a container for storing triples. " + "It can be queried and transformed to extract information.
" + "Provenance Provenance is a record of changes that have occurred in the graph store.
" + f"{provenance}" + ) From ae371f96029a9f8048e307d31ab5662d181a9704 Mon Sep 17 00:00:00 2001 From: anders-albert Date: Thu, 27 Jun 2024 11:12:01 +0200 Subject: [PATCH 07/11] refactor: added helper to get classmethods --- cognite/neat/utils/auxiliary.py | 8 ++++++++ tests/tests_unit/test_utils/test_auxiliary.py | 12 ++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 tests/tests_unit/test_utils/test_auxiliary.py diff --git a/cognite/neat/utils/auxiliary.py b/cognite/neat/utils/auxiliary.py index 2a5272fee..affb6ac26 100644 --- a/cognite/neat/utils/auxiliary.py +++ b/cognite/neat/utils/auxiliary.py @@ -1,4 +1,6 @@ import importlib +import inspect +from collections.abc import Callable from types import ModuleType from cognite.neat.exceptions import NeatImportError @@ -9,3 +11,9 @@ def local_import(module: str, extra: str) -> ModuleType: return importlib.import_module(module) except ImportError as e: raise NeatImportError(module.split(".")[0], extra) from e + + +def get_classmethods(cls: type) -> list[Callable]: + return [ + func for _, func in inspect.getmembers(cls, lambda x: inspect.ismethod(x) and not x.__name__.startswith("_")) + ] diff --git a/tests/tests_unit/test_utils/test_auxiliary.py b/tests/tests_unit/test_utils/test_auxiliary.py new file mode 100644 index 000000000..e2d72de82 --- /dev/null +++ b/tests/tests_unit/test_utils/test_auxiliary.py @@ -0,0 +1,12 @@ +import pytest + +from cognite.neat.rules.importers import DMSImporter +from cognite.neat.utils.auxiliary import get_classmethods + + +@pytest.mark.parametrize( + "cls_, expected_methods", + [(DMSImporter, [DMSImporter.from_data_model_id, DMSImporter.from_directory, DMSImporter.from_zip_file])], +) +def test_get_classmethods(cls_, expected_methods: list) -> None: + assert get_classmethods(cls_) == expected_methods From c3aa085de58b52394aaea3cf717d974c13bc6f50 Mon Sep 17 00:00:00 2001 From: anders-albert Date: Thu, 27 Jun 2024 11:18:44 +0200 Subject: [PATCH 08/11] refactor: list factory methods --- cognite/neat/graph/extractors/_base.py | 16 ++++++++++++++++ cognite/neat/graph/loaders/_base.py | 16 ++++++++++++++++ cognite/neat/rules/importers/_base.py | 15 ++++++++++++--- 3 files changed, 44 insertions(+), 3 deletions(-) diff --git a/cognite/neat/graph/extractors/_base.py b/cognite/neat/graph/extractors/_base.py index 993bb174c..759265d42 100644 --- a/cognite/neat/graph/extractors/_base.py +++ b/cognite/neat/graph/extractors/_base.py @@ -2,6 +2,7 @@ from collections.abc import Iterable from cognite.neat.graph.models import Triple +from cognite.neat.utils.auxiliary import get_classmethods class BaseExtractor: @@ -12,3 +13,18 @@ class BaseExtractor: @abstractmethod def extract(self) -> Iterable[Triple]: raise NotImplementedError() + + @classmethod + def _repr_html_(cls) -> str: + if cls.__doc__: + docstring = cls.__doc__.split("Args:")[0].strip().replace("\n", "
") + else: + docstring = "Missing Description" + factory_methods = get_classmethods(cls) + if factory_methods: + factory_methods_str = "".join(f"
  • {m.__name__}
  • " for m in factory_methods) + docstring += ( + f"
    Factory Methods:
    " + f'
      {factory_methods_str}
    ' + ) + return f"

    {cls.__name__}

    {docstring}

    " diff --git a/cognite/neat/graph/loaders/_base.py b/cognite/neat/graph/loaders/_base.py index 6b954981f..b1e4ee76f 100644 --- a/cognite/neat/graph/loaders/_base.py +++ b/cognite/neat/graph/loaders/_base.py @@ -9,6 +9,7 @@ from cognite.neat.graph import NeatGraphStore from cognite.neat.graph.issues.loader import FailedAuthorizationError from cognite.neat.issues import NeatIssue, NeatIssueList +from cognite.neat.utils.auxiliary import get_classmethods from cognite.neat.utils.upload import UploadDiffsID, UploadResultIDs T_Output = TypeVar("T_Output") @@ -34,6 +35,21 @@ def _load(self, stop_on_exception: bool = False) -> Iterable[T_Output | NeatIssu """Load the graph with data.""" pass + @classmethod + def _repr_html_(cls) -> str: + if cls.__doc__: + docstring = cls.__doc__.split("Args:")[0].strip().replace("\n", "
    ") + else: + docstring = "Missing Description" + factory_methods = get_classmethods(cls) + if factory_methods: + factory_methods_str = "".join(f"
  • {m.__name__}
  • " for m in factory_methods) + docstring += ( + f"
    Factory Methods:
    " + f'
      {factory_methods_str}
    ' + ) + return f"

    {cls.__name__}

    {docstring}

    " + class CDFLoader(BaseLoader[T_Output]): _UPLOAD_BATCH_SIZE: ClassVar[int] = 1000 diff --git a/cognite/neat/rules/importers/_base.py b/cognite/neat/rules/importers/_base.py index 2d13fb10e..3dd397dff 100644 --- a/cognite/neat/rules/importers/_base.py +++ b/cognite/neat/rules/importers/_base.py @@ -12,6 +12,7 @@ from cognite.neat.rules._shared import Rules from cognite.neat.rules.issues.base import IssueList, NeatValidationError, ValidationWarning from cognite.neat.rules.models import DMSRules, InformationRules, RoleTypes +from cognite.neat.utils.auxiliary import get_classmethods class BaseImporter(ABC): @@ -81,9 +82,17 @@ def _default_metadata(self): @classmethod def _repr_html_(cls) -> str: - if not cls.__doc__: - return f"

    {cls.__name__}

    Missing Description

    " - docstring = cls.__doc__.replace("\n", "
    ") + if cls.__doc__: + docstring = cls.__doc__.split("Args:")[0].strip().replace("\n", "
    ") + else: + docstring = "Missing Description" + factory_methods = get_classmethods(cls) + if factory_methods: + factory_methods_str = "".join(f"
  • {m.__name__}
  • " for m in factory_methods) + docstring += ( + f"
    Factory Methods:
    " + f'
      {factory_methods_str}
    ' + ) return f"

    {cls.__name__}

    {docstring}

    " From 8f38ef1f5296dce65982ede1d675ba9c1f1fc05c Mon Sep 17 00:00:00 2001 From: anders-albert Date: Thu, 27 Jun 2024 11:22:58 +0200 Subject: [PATCH 09/11] refactor: nice representation of individuals --- cognite/neat/graph/extractors/_base.py | 15 ++------------- cognite/neat/graph/loaders/_base.py | 15 ++------------- cognite/neat/rules/exporters/_base.py | 5 +++++ cognite/neat/rules/importers/_base.py | 15 ++------------- cognite/neat/utils/auxiliary.py | 16 ++++++++++++++++ 5 files changed, 27 insertions(+), 39 deletions(-) diff --git a/cognite/neat/graph/extractors/_base.py b/cognite/neat/graph/extractors/_base.py index 759265d42..628a3d104 100644 --- a/cognite/neat/graph/extractors/_base.py +++ b/cognite/neat/graph/extractors/_base.py @@ -2,7 +2,7 @@ from collections.abc import Iterable from cognite.neat.graph.models import Triple -from cognite.neat.utils.auxiliary import get_classmethods +from cognite.neat.utils.auxiliary import class_html_doc class BaseExtractor: @@ -16,15 +16,4 @@ def extract(self) -> Iterable[Triple]: @classmethod def _repr_html_(cls) -> str: - if cls.__doc__: - docstring = cls.__doc__.split("Args:")[0].strip().replace("\n", "
    ") - else: - docstring = "Missing Description" - factory_methods = get_classmethods(cls) - if factory_methods: - factory_methods_str = "".join(f"
  • {m.__name__}
  • " for m in factory_methods) - docstring += ( - f"
    Factory Methods:
    " - f'
      {factory_methods_str}
    ' - ) - return f"

    {cls.__name__}

    {docstring}

    " + return class_html_doc(cls) diff --git a/cognite/neat/graph/loaders/_base.py b/cognite/neat/graph/loaders/_base.py index b1e4ee76f..ddaeaf3c5 100644 --- a/cognite/neat/graph/loaders/_base.py +++ b/cognite/neat/graph/loaders/_base.py @@ -9,7 +9,7 @@ from cognite.neat.graph import NeatGraphStore from cognite.neat.graph.issues.loader import FailedAuthorizationError from cognite.neat.issues import NeatIssue, NeatIssueList -from cognite.neat.utils.auxiliary import get_classmethods +from cognite.neat.utils.auxiliary import class_html_doc from cognite.neat.utils.upload import UploadDiffsID, UploadResultIDs T_Output = TypeVar("T_Output") @@ -37,18 +37,7 @@ def _load(self, stop_on_exception: bool = False) -> Iterable[T_Output | NeatIssu @classmethod def _repr_html_(cls) -> str: - if cls.__doc__: - docstring = cls.__doc__.split("Args:")[0].strip().replace("\n", "
    ") - else: - docstring = "Missing Description" - factory_methods = get_classmethods(cls) - if factory_methods: - factory_methods_str = "".join(f"
  • {m.__name__}
  • " for m in factory_methods) - docstring += ( - f"
    Factory Methods:
    " - f'
      {factory_methods_str}
    ' - ) - return f"

    {cls.__name__}

    {docstring}

    " + return class_html_doc(cls) class CDFLoader(BaseLoader[T_Output]): diff --git a/cognite/neat/rules/exporters/_base.py b/cognite/neat/rules/exporters/_base.py index d7d03729d..7122c89cd 100644 --- a/cognite/neat/rules/exporters/_base.py +++ b/cognite/neat/rules/exporters/_base.py @@ -7,6 +7,7 @@ from cognite.neat.rules._shared import Rules from cognite.neat.rules.models import DMSRules, InformationRules, RoleTypes +from cognite.neat.utils.auxiliary import class_html_doc from cognite.neat.utils.upload import UploadResult, UploadResultList T_Export = TypeVar("T_Export") @@ -34,6 +35,10 @@ def _convert_to_output_role(self, rules: Rules, output_role: RoleTypes | None = else: raise NotImplementedError(f"Role {output_role} is not supported for {type(rules).__name__} rules") + @classmethod + def _repr_html_(cls) -> str: + return class_html_doc(cls, include_factory_methods=False) + class CDFExporter(BaseExporter[T_Export]): @abstractmethod diff --git a/cognite/neat/rules/importers/_base.py b/cognite/neat/rules/importers/_base.py index 3dd397dff..eabd59f75 100644 --- a/cognite/neat/rules/importers/_base.py +++ b/cognite/neat/rules/importers/_base.py @@ -12,7 +12,7 @@ from cognite.neat.rules._shared import Rules from cognite.neat.rules.issues.base import IssueList, NeatValidationError, ValidationWarning from cognite.neat.rules.models import DMSRules, InformationRules, RoleTypes -from cognite.neat.utils.auxiliary import get_classmethods +from cognite.neat.utils.auxiliary import class_html_doc class BaseImporter(ABC): @@ -82,18 +82,7 @@ def _default_metadata(self): @classmethod def _repr_html_(cls) -> str: - if cls.__doc__: - docstring = cls.__doc__.split("Args:")[0].strip().replace("\n", "
    ") - else: - docstring = "Missing Description" - factory_methods = get_classmethods(cls) - if factory_methods: - factory_methods_str = "".join(f"
  • {m.__name__}
  • " for m in factory_methods) - docstring += ( - f"
    Factory Methods:
    " - f'
      {factory_methods_str}
    ' - ) - return f"

    {cls.__name__}

    {docstring}

    " + return class_html_doc(cls) class _FutureResult: diff --git a/cognite/neat/utils/auxiliary.py b/cognite/neat/utils/auxiliary.py index affb6ac26..92973e47b 100644 --- a/cognite/neat/utils/auxiliary.py +++ b/cognite/neat/utils/auxiliary.py @@ -17,3 +17,19 @@ def get_classmethods(cls: type) -> list[Callable]: return [ func for _, func in inspect.getmembers(cls, lambda x: inspect.ismethod(x) and not x.__name__.startswith("_")) ] + + +def class_html_doc(cls: type, include_factory_methods: bool = True) -> str: + if cls.__doc__: + docstring = cls.__doc__.split("Args:")[0].strip().replace("\n", "
    ") + else: + docstring = "Missing Description" + if include_factory_methods: + factory_methods = get_classmethods(cls) + if factory_methods: + factory_methods_str = "".join(f"
  • .{m.__name__}
  • " for m in factory_methods) + docstring += ( + f"
    Available factory methods:
    " + f'
      {factory_methods_str}
    ' + ) + return f"

    {cls.__name__}

    {docstring}

    " From 6073403f7239d6d437f4be34e3032bfaa0290511 Mon Sep 17 00:00:00 2001 From: anders-albert Date: Thu, 27 Jun 2024 11:34:15 +0200 Subject: [PATCH 10/11] docs; added missing descriptions --- cognite/neat/graph/loaders/_rdf2dms.py | 11 +++++++++++ cognite/neat/rules/exporters/__init__.py | 2 +- cognite/neat/rules/exporters/_rules2dms.py | 2 +- cognite/neat/rules/exporters/_rules2ontology.py | 6 ++++++ cognite/neat/rules/importers/_dms2rules.py | 10 ++++++++++ .../importers/_dtdl2rules/dtdl_importer.py | 2 +- .../neat/rules/importers/_inference2rules.py | 6 +++++- .../neat/rules/importers/_spreadsheet2rules.py | 17 +++++++++++++++++ 8 files changed, 52 insertions(+), 4 deletions(-) diff --git a/cognite/neat/graph/loaders/_rdf2dms.py b/cognite/neat/graph/loaders/_rdf2dms.py index 869b88053..c3d210150 100644 --- a/cognite/neat/graph/loaders/_rdf2dms.py +++ b/cognite/neat/graph/loaders/_rdf2dms.py @@ -28,6 +28,17 @@ class DMSLoader(CDFLoader[dm.InstanceApply]): + """Load data from Cognite Data Fusions Data Modeling Service (DMS) into Neat. + + Args: + graph_store (NeatGraphStore): The graph store to load the data into. + data_model (dm.DataModel[dm.View] | None): The data model to load. + instance_space (str): The instance space to load the data into. + class_by_view_id (dict[ViewId, str] | None): A mapping from view id to class name. Defaults to None. + creat_issues (Sequence[NeatIssue] | None): A list of issues that occurred during reading. Defaults to None. + tracker (type[Tracker] | None): The tracker to use. Defaults to None. + """ + def __init__( self, graph_store: NeatGraphStore, diff --git a/cognite/neat/rules/exporters/__init__.py b/cognite/neat/rules/exporters/__init__.py index 140030efb..3b0bec90c 100644 --- a/cognite/neat/rules/exporters/__init__.py +++ b/cognite/neat/rules/exporters/__init__.py @@ -27,7 +27,7 @@ def _repr_html_() -> str: "Description": globals()[name].__doc__.strip().split("\n")[0] if globals()[name].__doc__ else "Missing", } for name in __all__ - if name not in ("BaseExporter", "CDFExporter") + if name not in ("BaseExporter", "CDFExporter", "GraphExporter") ] )._repr_html_() diff --git a/cognite/neat/rules/exporters/_rules2dms.py b/cognite/neat/rules/exporters/_rules2dms.py index f2345d680..2627c4912 100644 --- a/cognite/neat/rules/exporters/_rules2dms.py +++ b/cognite/neat/rules/exporters/_rules2dms.py @@ -39,7 +39,7 @@ class DMSExporter(CDFExporter[DMSSchema]): - """Class for exporting rules object to CDF Data Model Storage (DMS). + """Export rules to Cognite Data Fusion's Data Model Storage (DMS) service. Args: export_components (frozenset[Literal["all", "spaces", "data_models", "views", "containers"]], optional): diff --git a/cognite/neat/rules/exporters/_rules2ontology.py b/cognite/neat/rules/exporters/_rules2ontology.py index d8a8eb902..149540d91 100644 --- a/cognite/neat/rules/exporters/_rules2ontology.py +++ b/cognite/neat/rules/exporters/_rules2ontology.py @@ -39,16 +39,22 @@ def export_to_file(self, rules: Rules, filepath: Path) -> None: class OWLExporter(GraphExporter): + """Exports rules to an OWL ontology.""" + def export(self, rules: Rules) -> Graph: return Ontology.from_rules(rules).as_owl() class SHACLExporter(GraphExporter): + """Exports rules to a SHACL graph.""" + def export(self, rules: Rules) -> Graph: return Ontology.from_rules(rules).as_shacl() class SemanticDataModelExporter(GraphExporter): + """Exports rules to a semantic data model.""" + def export(self, rules: Rules) -> Graph: return Ontology.from_rules(rules).as_semantic_data_model() diff --git a/cognite/neat/rules/importers/_dms2rules.py b/cognite/neat/rules/importers/_dms2rules.py index 389e6248c..d1f236493 100644 --- a/cognite/neat/rules/importers/_dms2rules.py +++ b/cognite/neat/rules/importers/_dms2rules.py @@ -46,6 +46,16 @@ class DMSImporter(BaseImporter): + """Imports a Data Model from Cognite Data Fusion. + + Args: + schema: The schema containing the data model. + read_issues: A list of issues that occurred during the import. + metadata: Metadata for the data model. + ref_metadata: Metadata for the reference data model. + + """ + def __init__( self, schema: DMSSchema, diff --git a/cognite/neat/rules/importers/_dtdl2rules/dtdl_importer.py b/cognite/neat/rules/importers/_dtdl2rules/dtdl_importer.py index 590c9616c..c0d94d0a4 100644 --- a/cognite/neat/rules/importers/_dtdl2rules/dtdl_importer.py +++ b/cognite/neat/rules/importers/_dtdl2rules/dtdl_importer.py @@ -18,7 +18,7 @@ class DTDLImporter(BaseImporter): - """Importer for DTDL (Digital Twin Definition Language). + """Importer from Azure Digital Twin - DTDL (Digital Twin Definition Language). This importer supports DTDL v2.0 and v3.0. diff --git a/cognite/neat/rules/importers/_inference2rules.py b/cognite/neat/rules/importers/_inference2rules.py index 0fa44b74e..a29b9f7d8 100644 --- a/cognite/neat/rules/importers/_inference2rules.py +++ b/cognite/neat/rules/importers/_inference2rules.py @@ -33,7 +33,11 @@ class InferenceImporter(BaseImporter): - """Rules inference through analysis of knowledge graph provided in various formats. + """Infers rules from a triple store. + + Rules inference through analysis of knowledge graph provided in various formats. + Use the factory methods to create an triples store from sources such as + RDF files, JSON files, YAML files, XML files, or directly from a graph store. Args: issue_list: Issue list to store issues diff --git a/cognite/neat/rules/importers/_spreadsheet2rules.py b/cognite/neat/rules/importers/_spreadsheet2rules.py index e5fe4780c..03749cd52 100644 --- a/cognite/neat/rules/importers/_spreadsheet2rules.py +++ b/cognite/neat/rules/importers/_spreadsheet2rules.py @@ -205,6 +205,12 @@ def _read_sheets( class ExcelImporter(BaseImporter): + """Import rules from an Excel file. + + Args: + filepath (Path): The path to the Excel file. + """ + def __init__(self, filepath: Path): self.filepath = filepath @@ -286,6 +292,17 @@ def to_rules( class GoogleSheetImporter(BaseImporter): + """Import rules from a Google Sheet. + + .. warning:: + + This importer is experimental and may not work as expected. + + Args: + sheet_id (str): The Google Sheet ID. + skiprows (int): The number of rows to skip when reading the Google Sheet. + """ + def __init__(self, sheet_id: str, skiprows: int = 1): self.sheet_id = sheet_id self.skiprows = skiprows From 97aea7307d632cd595f6da4cd4b8d814cb0e2054 Mon Sep 17 00:00:00 2001 From: anders-albert Date: Thu, 27 Jun 2024 11:40:04 +0200 Subject: [PATCH 11/11] refactor: added missind docstrings --- cognite/neat/graph/extractors/_classic_cdf/_assets.py | 7 +++++++ cognite/neat/graph/extractors/_classic_cdf/_events.py | 7 +++++++ cognite/neat/graph/extractors/_classic_cdf/_labels.py | 7 +++++++ .../neat/graph/extractors/_classic_cdf/_relationships.py | 7 +++++++ cognite/neat/graph/extractors/_classic_cdf/_sequences.py | 7 +++++++ cognite/neat/graph/extractors/_classic_cdf/_timeseries.py | 7 +++++++ cognite/neat/graph/extractors/_rdf_file.py | 8 ++++++++ 7 files changed, 50 insertions(+) diff --git a/cognite/neat/graph/extractors/_classic_cdf/_assets.py b/cognite/neat/graph/extractors/_classic_cdf/_assets.py index 3029cd7eb..6fa1fcc32 100644 --- a/cognite/neat/graph/extractors/_classic_cdf/_assets.py +++ b/cognite/neat/graph/extractors/_classic_cdf/_assets.py @@ -14,6 +14,13 @@ class AssetsExtractor(BaseExtractor): + """Extract data from Cognite Data Fusions Assets into Neat. + + Args: + assets (Iterable[Asset]): An iterable of assets. + namespace (Namespace, optional): The namespace to use. Defaults to DEFAULT_NAMESPACE. + """ + def __init__( self, assets: Iterable[Asset], diff --git a/cognite/neat/graph/extractors/_classic_cdf/_events.py b/cognite/neat/graph/extractors/_classic_cdf/_events.py index 1c82b133b..697f7d04e 100644 --- a/cognite/neat/graph/extractors/_classic_cdf/_events.py +++ b/cognite/neat/graph/extractors/_classic_cdf/_events.py @@ -15,6 +15,13 @@ class EventsExtractor(BaseExtractor): + """Extract data from Cognite Data Fusions Events into Neat. + + Args: + events (Iterable[Event]): An iterable of events. + namespace (Namespace, optional): The namespace to use. Defaults to DEFAULT_NAMESPACE. + """ + def __init__( self, events: Iterable[Event], diff --git a/cognite/neat/graph/extractors/_classic_cdf/_labels.py b/cognite/neat/graph/extractors/_classic_cdf/_labels.py index 9143d03b3..ef986f510 100644 --- a/cognite/neat/graph/extractors/_classic_cdf/_labels.py +++ b/cognite/neat/graph/extractors/_classic_cdf/_labels.py @@ -14,6 +14,13 @@ class LabelsExtractor(BaseExtractor): + """Extract data from Cognite Data Fusions Labels into Neat. + + Args: + labels (Iterable[LabelDefinition]): An iterable of labels. + namespace (Namespace, optional): The namespace to use. Defaults to DEFAULT_NAMESPACE. + """ + def __init__( self, labels: Iterable[LabelDefinition], diff --git a/cognite/neat/graph/extractors/_classic_cdf/_relationships.py b/cognite/neat/graph/extractors/_classic_cdf/_relationships.py index 3fbd56960..9b140202a 100644 --- a/cognite/neat/graph/extractors/_classic_cdf/_relationships.py +++ b/cognite/neat/graph/extractors/_classic_cdf/_relationships.py @@ -15,6 +15,13 @@ class RelationshipsExtractor(BaseExtractor): + """Extract data from Cognite Data Fusions Relationships into Neat. + + Args: + relationships (Iterable[Asset]): An iterable of relationships. + namespace (Namespace, optional): The namespace to use. Defaults to DEFAULT_NAMESPACE. + """ + def __init__( self, relationships: Iterable[Relationship], diff --git a/cognite/neat/graph/extractors/_classic_cdf/_sequences.py b/cognite/neat/graph/extractors/_classic_cdf/_sequences.py index d583a92b5..50d2ca090 100644 --- a/cognite/neat/graph/extractors/_classic_cdf/_sequences.py +++ b/cognite/neat/graph/extractors/_classic_cdf/_sequences.py @@ -15,6 +15,13 @@ class SequencesExtractor(BaseExtractor): + """Extract data from Cognite Data Fusions Sequences into Neat. + + Args: + sequence (Iterable[Sequence]): An iterable of sequences. + namespace (Namespace, optional): The namespace to use. Defaults to DEFAULT_NAMESPACE. + """ + def __init__( self, sequence: Iterable[Sequence], diff --git a/cognite/neat/graph/extractors/_classic_cdf/_timeseries.py b/cognite/neat/graph/extractors/_classic_cdf/_timeseries.py index 0575d9581..28b65e420 100644 --- a/cognite/neat/graph/extractors/_classic_cdf/_timeseries.py +++ b/cognite/neat/graph/extractors/_classic_cdf/_timeseries.py @@ -15,6 +15,13 @@ class TimeSeriesExtractor(BaseExtractor): + """Extract data from Cognite Data Fusions TimeSeries into Neat. + + Args: + timeseries (Iterable[TimeSeries]): An iterable of timeseries. + namespace (Namespace, optional): The namespace to use. Defaults to DEFAULT_NAMESPACE. + """ + def __init__( self, timeseries: Iterable[TimeSeries], diff --git a/cognite/neat/graph/extractors/_rdf_file.py b/cognite/neat/graph/extractors/_rdf_file.py index bb7d92176..2126ba536 100644 --- a/cognite/neat/graph/extractors/_rdf_file.py +++ b/cognite/neat/graph/extractors/_rdf_file.py @@ -7,6 +7,14 @@ class RdfFileExtractor(BaseExtractor): + """Extract data from RDF files into Neat. + + Args: + filepath (Path): The path to the RDF file. + mime_type (MIMETypes, optional): The MIME type of the RDF file. Defaults to "application/rdf+xml". + base_uri (URIRef, optional): The base URI to use. Defaults to None. + """ + def __init__( self, filepath: Path,