cognite-neat 0.84.1__py3-none-any.whl → 0.85.1__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.

Files changed (39) hide show
  1. cognite/neat/__init__.py +2 -1
  2. cognite/neat/_shared.py +17 -1
  3. cognite/neat/_version.py +1 -1
  4. cognite/neat/graph/extractors/__init__.py +22 -0
  5. cognite/neat/graph/extractors/_base.py +5 -0
  6. cognite/neat/graph/extractors/_classic_cdf/_assets.py +7 -0
  7. cognite/neat/graph/extractors/_classic_cdf/_events.py +7 -0
  8. cognite/neat/graph/extractors/_classic_cdf/_files.py +10 -3
  9. cognite/neat/graph/extractors/_classic_cdf/_labels.py +7 -0
  10. cognite/neat/graph/extractors/_classic_cdf/_relationships.py +7 -0
  11. cognite/neat/graph/extractors/_classic_cdf/_sequences.py +7 -0
  12. cognite/neat/graph/extractors/_classic_cdf/_timeseries.py +7 -0
  13. cognite/neat/graph/extractors/_dexpi.py +1 -1
  14. cognite/neat/graph/extractors/_rdf_file.py +8 -0
  15. cognite/neat/graph/loaders/__init__.py +19 -0
  16. cognite/neat/graph/loaders/_base.py +22 -45
  17. cognite/neat/graph/loaders/_rdf2dms.py +21 -9
  18. cognite/neat/graph/queries/_base.py +24 -0
  19. cognite/neat/graph/stores/_base.py +10 -0
  20. cognite/neat/graph/stores/_provenance.py +11 -3
  21. cognite/neat/rules/exporters/__init__.py +23 -1
  22. cognite/neat/rules/exporters/_base.py +5 -0
  23. cognite/neat/rules/exporters/_rules2dms.py +1 -1
  24. cognite/neat/rules/exporters/_rules2ontology.py +6 -0
  25. cognite/neat/rules/importers/__init__.py +20 -0
  26. cognite/neat/rules/importers/_base.py +5 -0
  27. cognite/neat/rules/importers/_dms2rules.py +10 -0
  28. cognite/neat/rules/importers/_dtdl2rules/dtdl_importer.py +1 -1
  29. cognite/neat/rules/importers/_inference2rules.py +8 -4
  30. cognite/neat/rules/importers/_spreadsheet2rules.py +17 -0
  31. cognite/neat/utils/auth.py +305 -0
  32. cognite/neat/utils/auxiliary.py +24 -0
  33. cognite/neat/utils/upload.py +5 -42
  34. {cognite_neat-0.84.1.dist-info → cognite_neat-0.85.1.dist-info}/METADATA +3 -1
  35. {cognite_neat-0.84.1.dist-info → cognite_neat-0.85.1.dist-info}/RECORD +39 -38
  36. /cognite/neat/utils/{xml.py → xml_.py} +0 -0
  37. {cognite_neat-0.84.1.dist-info → cognite_neat-0.85.1.dist-info}/LICENSE +0 -0
  38. {cognite_neat-0.84.1.dist-info → cognite_neat-0.85.1.dist-info}/WHEEL +0 -0
  39. {cognite_neat-0.84.1.dist-info → cognite_neat-0.85.1.dist-info}/entry_points.txt +0 -0
@@ -46,6 +46,16 @@ from cognite.neat.rules.models.entities import (
46
46
 
47
47
 
48
48
  class DMSImporter(BaseImporter):
49
+ """Imports a Data Model from Cognite Data Fusion.
50
+
51
+ Args:
52
+ schema: The schema containing the data model.
53
+ read_issues: A list of issues that occurred during the import.
54
+ metadata: Metadata for the data model.
55
+ ref_metadata: Metadata for the reference data model.
56
+
57
+ """
58
+
49
59
  def __init__(
50
60
  self,
51
61
  schema: DMSSchema,
@@ -18,7 +18,7 @@ from cognite.neat.utils.text import to_pascal
18
18
 
19
19
 
20
20
  class DTDLImporter(BaseImporter):
21
- """Importer for DTDL (Digital Twin Definition Language).
21
+ """Importer from Azure Digital Twin - DTDL (Digital Twin Definition Language).
22
22
 
23
23
  This importer supports DTDL v2.0 and v3.0.
24
24
 
@@ -7,7 +7,7 @@ from rdflib import Graph, Namespace, URIRef
7
7
  from rdflib import Literal as RdfLiteral
8
8
 
9
9
  import cognite.neat.rules.issues as issues
10
- from cognite.neat.constants import PREFIXES
10
+ from cognite.neat.constants import DEFAULT_NAMESPACE, PREFIXES
11
11
  from cognite.neat.graph.stores import NeatGraphStore
12
12
  from cognite.neat.rules.importers._base import BaseImporter, Rules, _handle_issues
13
13
  from cognite.neat.rules.issues import IssueList
@@ -33,7 +33,11 @@ INSTANCE_PROPERTIES_DEFINITION = """SELECT ?property (count(?property) as ?occur
33
33
 
34
34
 
35
35
  class InferenceImporter(BaseImporter):
36
- """Rules inference through analysis of knowledge graph provided in various formats.
36
+ """Infers rules from a triple store.
37
+
38
+ Rules inference through analysis of knowledge graph provided in various formats.
39
+ Use the factory methods to create an triples store from sources such as
40
+ RDF files, JSON files, YAML files, XML files, or directly from a graph store.
37
41
 
38
42
  Args:
39
43
  issue_list: Issue list to store issues
@@ -242,8 +246,8 @@ class InferenceImporter(BaseImporter):
242
246
  created=datetime.now(),
243
247
  updated=datetime.now(),
244
248
  description="Inferred model from knowledge graph",
245
- prefix="inferred",
246
- namespace="http://purl.org/cognite/neat/inferred/",
249
+ prefix="neat",
250
+ namespace=DEFAULT_NAMESPACE,
247
251
  )
248
252
 
249
253
  @classmethod
@@ -205,6 +205,12 @@ class SpreadsheetReader:
205
205
 
206
206
 
207
207
  class ExcelImporter(BaseImporter):
208
+ """Import rules from an Excel file.
209
+
210
+ Args:
211
+ filepath (Path): The path to the Excel file.
212
+ """
213
+
208
214
  def __init__(self, filepath: Path):
209
215
  self.filepath = filepath
210
216
 
@@ -286,6 +292,17 @@ class ExcelImporter(BaseImporter):
286
292
 
287
293
 
288
294
  class GoogleSheetImporter(BaseImporter):
295
+ """Import rules from a Google Sheet.
296
+
297
+ .. warning::
298
+
299
+ This importer is experimental and may not work as expected.
300
+
301
+ Args:
302
+ sheet_id (str): The Google Sheet ID.
303
+ skiprows (int): The number of rows to skip when reading the Google Sheet.
304
+ """
305
+
289
306
  def __init__(self, sheet_id: str, skiprows: int = 1):
290
307
  self.sheet_id = sheet_id
291
308
  self.skiprows = skiprows
@@ -0,0 +1,305 @@
1
+ import os
2
+ import subprocess
3
+ from contextlib import suppress
4
+ from dataclasses import dataclass, fields
5
+ from pathlib import Path
6
+ from typing import Literal, TypeAlias, get_args
7
+
8
+ from cognite.client import CogniteClient
9
+ from cognite.client.credentials import CredentialProvider, OAuthClientCredentials, OAuthInteractive, Token
10
+
11
+ from cognite.neat import _version
12
+ from cognite.neat.utils.auxiliary import local_import
13
+
14
+ __all__ = ["get_cognite_client"]
15
+
16
+ _LOGIN_FLOW: TypeAlias = Literal["infer", "client_credentials", "interactive", "token"]
17
+ _VALID_LOGIN_FLOWS = get_args(_LOGIN_FLOW)
18
+ _CLIENT_NAME = f"CogniteNeat:{_version.__version__}"
19
+
20
+
21
+ def get_cognite_client(env_file_name: str = ".env") -> CogniteClient:
22
+ if not env_file_name.endswith(".env"):
23
+ raise ValueError("env_file_name must end with '.env'")
24
+ with suppress(KeyError):
25
+ variables = _EnvironmentVariables.create_from_environ()
26
+ return variables.get_client()
27
+
28
+ repo_root = _repo_root()
29
+ if repo_root:
30
+ with suppress(KeyError, FileNotFoundError, TypeError):
31
+ variables = _from_dotenv(repo_root / env_file_name)
32
+ client = variables.get_client()
33
+ print("Found .env file in repository root. Loaded variables from .env file.")
34
+ return client
35
+ variables = _prompt_user()
36
+ if repo_root and _env_in_gitignore(repo_root, env_file_name):
37
+ local_import("rich", "jupyter")
38
+ from rich.prompt import Prompt
39
+
40
+ env_file = repo_root / env_file_name
41
+ answer = Prompt.ask(
42
+ "Do you store the variables in an .env file in the repository root for easy reuse?", choices=["y", "n"]
43
+ )
44
+ if env_file.exists():
45
+ answer = Prompt.ask(f"{env_file} already exists. Overwrite?", choices=["y", "n"])
46
+ if answer == "y":
47
+ env_file.write_text(variables.create_env_file())
48
+ print("Created .env file in repository root.")
49
+
50
+ return variables.get_client()
51
+
52
+
53
+ @dataclass
54
+ class _EnvironmentVariables:
55
+ CDF_CLUSTER: str
56
+ CDF_PROJECT: str
57
+ LOGIN_FLOW: _LOGIN_FLOW = "infer"
58
+ IDP_CLIENT_ID: str | None = None
59
+ IDP_CLIENT_SECRET: str | None = None
60
+ TOKEN: str | None = None
61
+
62
+ IDP_TENANT_ID: str | None = None
63
+ IDP_TOKEN_URL: str | None = None
64
+
65
+ CDF_URL: str | None = None
66
+ IDP_AUDIENCE: str | None = None
67
+ IDP_SCOPES: str | None = None
68
+ IDP_AUTHORITY_URL: str | None = None
69
+
70
+ def __post_init__(self):
71
+ if self.LOGIN_FLOW.lower() not in _VALID_LOGIN_FLOWS:
72
+ raise ValueError(f"LOGIN_FLOW must be one of {_VALID_LOGIN_FLOWS}")
73
+
74
+ @property
75
+ def cdf_url(self) -> str:
76
+ return self.CDF_URL or f"https://{self.CDF_CLUSTER}.cognitedata.com"
77
+
78
+ @property
79
+ def idp_token_url(self) -> str:
80
+ if self.IDP_TOKEN_URL:
81
+ return self.IDP_TOKEN_URL
82
+ if not self.IDP_TENANT_ID:
83
+ raise KeyError("IDP_TENANT_ID or IDP_TOKEN_URL must be set in the environment.")
84
+ return f"https://login.microsoftonline.com/{self.IDP_TENANT_ID}/oauth2/v2.0/token"
85
+
86
+ @property
87
+ def idp_audience(self) -> str:
88
+ return self.IDP_AUDIENCE or f"https://{self.CDF_CLUSTER}.cognitedata.com"
89
+
90
+ @property
91
+ def idp_scopes(self) -> list[str]:
92
+ if self.IDP_SCOPES:
93
+ return self.IDP_SCOPES.split(",")
94
+ return [f"https://{self.CDF_CLUSTER}.cognitedata.com/.default"]
95
+
96
+ @property
97
+ def idp_authority_url(self) -> str:
98
+ if self.IDP_AUTHORITY_URL:
99
+ return self.IDP_AUTHORITY_URL
100
+ if not self.IDP_TENANT_ID:
101
+ raise KeyError("IDP_TENANT_ID or IDP_AUTHORITY_URL must be set in the environment.")
102
+ return f"https://login.microsoftonline.com/{self.IDP_TENANT_ID}"
103
+
104
+ @classmethod
105
+ def create_from_environ(cls) -> "_EnvironmentVariables":
106
+ if "CDF_CLUSTER" not in os.environ or "CDF_PROJECT" not in os.environ:
107
+ raise KeyError("CDF_CLUSTER and CDF_PROJECT must be set in the environment.", "CDF_CLUSTER", "CDF_PROJECT")
108
+
109
+ return cls(
110
+ CDF_CLUSTER=os.environ["CDF_CLUSTER"],
111
+ CDF_PROJECT=os.environ["CDF_PROJECT"],
112
+ LOGIN_FLOW=os.environ.get("LOGIN_FLOW", "infer"), # type: ignore[arg-type]
113
+ IDP_CLIENT_ID=os.environ.get("IDP_CLIENT_ID"),
114
+ IDP_CLIENT_SECRET=os.environ.get("IDP_CLIENT_SECRET"),
115
+ TOKEN=os.environ.get("TOKEN"),
116
+ CDF_URL=os.environ.get("CDF_URL"),
117
+ IDP_TOKEN_URL=os.environ.get("IDP_TOKEN_URL"),
118
+ IDP_TENANT_ID=os.environ.get("IDP_TENANT_ID"),
119
+ IDP_AUDIENCE=os.environ.get("IDP_AUDIENCE"),
120
+ IDP_SCOPES=os.environ.get("IDP_SCOPES"),
121
+ IDP_AUTHORITY_URL=os.environ.get("IDP_AUTHORITY_URL"),
122
+ )
123
+
124
+ def get_credentials(self) -> CredentialProvider:
125
+ method_by_flow = {
126
+ "client_credentials": self.get_oauth_client_credentials,
127
+ "interactive": self.get_oauth_interactive,
128
+ "token": self.get_token,
129
+ }
130
+ if self.LOGIN_FLOW in method_by_flow:
131
+ return method_by_flow[self.LOGIN_FLOW]()
132
+ key_options: list[tuple[str, ...]] = []
133
+ for method in method_by_flow.values():
134
+ try:
135
+ return method()
136
+ except KeyError as e:
137
+ key_options += e.args[1:]
138
+ raise KeyError(
139
+ f"LOGIN_FLOW={self.LOGIN_FLOW} requires one of the following environment set variables to be set.",
140
+ *key_options,
141
+ )
142
+
143
+ def get_oauth_client_credentials(self) -> OAuthClientCredentials:
144
+ if not self.IDP_CLIENT_ID or not self.IDP_CLIENT_SECRET:
145
+ raise KeyError(
146
+ "IDP_CLIENT_ID and IDP_CLIENT_SECRET must be set in the environment.",
147
+ "IDP_CLIENT_ID",
148
+ "IDP_CLIENT_SECRET",
149
+ )
150
+ return OAuthClientCredentials(
151
+ client_id=self.IDP_CLIENT_ID,
152
+ client_secret=self.IDP_CLIENT_SECRET,
153
+ token_url=self.idp_token_url,
154
+ audience=self.idp_audience,
155
+ scopes=self.idp_scopes,
156
+ )
157
+
158
+ def get_oauth_interactive(self) -> OAuthInteractive:
159
+ if not self.IDP_CLIENT_ID:
160
+ raise KeyError("IDP_CLIENT_ID must be set in the environment.", "IDP_CLIENT_ID")
161
+ return OAuthInteractive(
162
+ client_id=self.IDP_CLIENT_ID,
163
+ authority_url=self.idp_authority_url,
164
+ redirect_port=53_000,
165
+ scopes=self.idp_scopes,
166
+ )
167
+
168
+ def get_token(self) -> Token:
169
+ if not self.TOKEN:
170
+ raise KeyError("TOKEN must be set in the environment", "TOKEN")
171
+ return Token(self.TOKEN)
172
+
173
+ def get_client(self) -> CogniteClient:
174
+ return CogniteClient.default(
175
+ self.CDF_PROJECT, self.CDF_CLUSTER, credentials=self.get_credentials(), client_name=_CLIENT_NAME
176
+ )
177
+
178
+ def create_env_file(self) -> str:
179
+ lines: list[str] = []
180
+ first_optional = True
181
+ for field in fields(self):
182
+ is_optional = hasattr(self, field.name.lower())
183
+ if is_optional and first_optional:
184
+ lines.append(
185
+ "# The below variables are the defaults, they are automatically " "constructed unless they are set."
186
+ )
187
+ first_optional = False
188
+ name = field.name.lower() if is_optional else field.name
189
+ value = getattr(self, name)
190
+ if value is not None:
191
+ if isinstance(value, list):
192
+ value = ",".join(value)
193
+ lines.append(f"{field.name}={value}")
194
+ return "\n".join(lines)
195
+
196
+
197
+ def _from_dotenv(evn_file: Path) -> _EnvironmentVariables:
198
+ if not evn_file.exists():
199
+ raise FileNotFoundError(f"{evn_file} does not exist.")
200
+ content = evn_file.read_text()
201
+ valid_variables = {f.name for f in fields(_EnvironmentVariables)}
202
+ variables: dict[str, str] = {}
203
+ for line in content.splitlines():
204
+ if line.startswith("#") or "=" not in line:
205
+ continue
206
+ key, value = line.split("=", 1)
207
+ if key in valid_variables:
208
+ variables[key] = value
209
+ return _EnvironmentVariables(**variables) # type: ignore[arg-type]
210
+
211
+
212
+ def _prompt_user() -> _EnvironmentVariables:
213
+ local_import("rich", "jupyter")
214
+ from rich.prompt import Prompt
215
+
216
+ try:
217
+ variables = _EnvironmentVariables.create_from_environ()
218
+ continue_ = Prompt.ask(
219
+ f"Use environment variables for CDF Cluster '{variables.CDF_CLUSTER}' "
220
+ f"and Project '{variables.CDF_PROJECT}'? [y/n]",
221
+ choices=["y", "n"],
222
+ default="y",
223
+ )
224
+ if continue_ == "n":
225
+ variables = _prompt_cluster_and_project()
226
+ except KeyError:
227
+ variables = _prompt_cluster_and_project()
228
+
229
+ login_flow = Prompt.ask("Login flow", choices=[f for f in _VALID_LOGIN_FLOWS if f != "infer"])
230
+ variables.LOGIN_FLOW = login_flow # type: ignore[assignment]
231
+ if login_flow == "token":
232
+ token = Prompt.ask("Enter token")
233
+ variables.TOKEN = token
234
+ return variables
235
+
236
+ variables.IDP_CLIENT_ID = Prompt.ask("Enter IDP Client ID")
237
+ if login_flow == "client_credentials":
238
+ variables.IDP_CLIENT_SECRET = Prompt.ask("Enter IDP Client Secret", password=True)
239
+ tenant_id = Prompt.ask("Enter IDP_TENANT_ID (leave empty to enter IDP_TOKEN_URL instead)")
240
+ if tenant_id:
241
+ variables.IDP_TENANT_ID = tenant_id
242
+ else:
243
+ token_url = Prompt.ask("Enter IDP_TOKEN_URL")
244
+ variables.IDP_TOKEN_URL = token_url
245
+ optional = ["IDP_AUDIENCE", "IDP_SCOPES"]
246
+ else: # login_flow == "interactive"
247
+ tenant_id = Prompt.ask("Enter IDP_TENANT_ID (leave empty to enter IDP_AUTHORITY_URL instead)")
248
+ if tenant_id:
249
+ variables.IDP_TENANT_ID = tenant_id
250
+ else:
251
+ variables.IDP_AUTHORITY_URL = Prompt.ask("Enter IDP_TOKEN_URL")
252
+ optional = ["IDP_SCOPES"]
253
+
254
+ defaults = "".join(f"\n - {name}: {getattr(variables, name.lower())}" for name in optional)
255
+ use_defaults = Prompt.ask(
256
+ f"Use default values for the following variables?{defaults}", choices=["y", "n"], default="y"
257
+ )
258
+ if use_defaults:
259
+ return variables
260
+ for name in optional:
261
+ value = Prompt.ask(f"Enter {name}")
262
+ setattr(variables, name, value)
263
+ return variables
264
+
265
+
266
+ def _prompt_cluster_and_project() -> _EnvironmentVariables:
267
+ from rich.prompt import Prompt
268
+
269
+ cluster = Prompt.ask("Enter CDF Cluster (example 'greenfield', 'bluefield', 'westeurope-1)")
270
+ project = Prompt.ask("Enter CDF Project")
271
+ return _EnvironmentVariables(cluster, project)
272
+
273
+
274
+ def _is_notebook() -> bool:
275
+ try:
276
+ shell = get_ipython().__class__.__name__ # type: ignore[name-defined]
277
+ if shell == "ZMQInteractiveShell":
278
+ return True # Jupyter notebook or qtconsole
279
+ elif shell == "TerminalInteractiveShell":
280
+ return False # Terminal running IPython
281
+ else:
282
+ return False # Other type (?)
283
+ except NameError:
284
+ return False # Probably standard Python interpreter
285
+
286
+
287
+ def _repo_root() -> Path | None:
288
+ with suppress(Exception):
289
+ result = subprocess.run("git rev-parse --show-toplevel".split(), stdout=subprocess.PIPE)
290
+ return Path(result.stdout.decode().strip())
291
+ return None
292
+
293
+
294
+ def _env_in_gitignore(repo_root: Path, env_file_name: str) -> bool:
295
+ ignore_file = repo_root / ".gitignore"
296
+ if not ignore_file.exists():
297
+ return False
298
+ else:
299
+ ignored = {line.strip() for line in ignore_file.read_text().splitlines()}
300
+ return env_file_name in ignored or "*.env" in ignored
301
+
302
+
303
+ if __name__ == "__main__":
304
+ c = get_cognite_client()
305
+ print(c.iam.token.inspect())
@@ -1,4 +1,6 @@
1
1
  import importlib
2
+ import inspect
3
+ from collections.abc import Callable
2
4
  from types import ModuleType
3
5
 
4
6
  from cognite.neat.exceptions import NeatImportError
@@ -9,3 +11,25 @@ def local_import(module: str, extra: str) -> ModuleType:
9
11
  return importlib.import_module(module)
10
12
  except ImportError as e:
11
13
  raise NeatImportError(module.split(".")[0], extra) from e
14
+
15
+
16
+ def get_classmethods(cls: type) -> list[Callable]:
17
+ return [
18
+ func for _, func in inspect.getmembers(cls, lambda x: inspect.ismethod(x) and not x.__name__.startswith("_"))
19
+ ]
20
+
21
+
22
+ def class_html_doc(cls: type, include_factory_methods: bool = True) -> str:
23
+ if cls.__doc__:
24
+ docstring = cls.__doc__.split("Args:")[0].strip().replace("\n", "<br />")
25
+ else:
26
+ docstring = "Missing Description"
27
+ if include_factory_methods:
28
+ factory_methods = get_classmethods(cls)
29
+ if factory_methods:
30
+ factory_methods_str = "".join(f"<li><em>.{m.__name__}</em></li>" for m in factory_methods)
31
+ docstring += (
32
+ f"<br /><strong>Available factory methods:</strong><br />"
33
+ f'<ul style="list-style-type:circle;">{factory_methods_str}</ul>'
34
+ )
35
+ return f"<h3>{cls.__name__}</h3><p>{docstring}</p>"
@@ -41,15 +41,18 @@ class UploadResult(UploadResultCore, Generic[T_ID]):
41
41
  unchanged: set[T_ID] = field(default_factory=set)
42
42
  skipped: set[T_ID] = field(default_factory=set)
43
43
  failed_created: set[T_ID] = field(default_factory=set)
44
+ failed_upserted: set[T_ID] = field(default_factory=set)
44
45
  failed_changed: set[T_ID] = field(default_factory=set)
45
46
  failed_deleted: set[T_ID] = field(default_factory=set)
46
47
 
47
48
  @property
48
49
  def failed(self) -> int:
49
- return len(self.failed_created) + len(self.failed_changed) + len(self.failed_deleted)
50
+ return (
51
+ len(self.failed_created) + len(self.failed_changed) + len(self.failed_deleted) + len(self.failed_upserted)
52
+ )
50
53
 
51
54
  @property
52
- def total(self) -> int:
55
+ def success(self) -> int:
53
56
  return len(self.created) + len(self.deleted) + len(self.changed) + len(self.unchanged) + len(self.skipped)
54
57
 
55
58
  def dump(self, aggregate: bool = True) -> dict[str, Any]:
@@ -84,43 +87,3 @@ class UploadResult(UploadResultCore, Generic[T_ID]):
84
87
  continue
85
88
  lines.append(f"{key}: {value}")
86
89
  return f"{self.name.title()}: {', '.join(lines)}"
87
-
88
-
89
- @dataclass
90
- class UploadResultIDs(UploadResultCore):
91
- success: list[str] = field(default_factory=list)
92
- failed: list[str] = field(default_factory=list)
93
-
94
- def dump(self, aggregate: bool = True) -> dict[str, Any]:
95
- output = super().dump(aggregate)
96
- if self.success:
97
- output["success"] = len(self.success) if aggregate else self.success
98
- if self.failed:
99
- output["failed"] = len(self.failed) if aggregate else self.failed
100
- return output
101
-
102
-
103
- @dataclass
104
- class UploadDiffsID(UploadResultCore):
105
- created: list[str] = field(default_factory=list)
106
- changed: list[str] = field(default_factory=list)
107
- unchanged: list[str] = field(default_factory=list)
108
- failed: list[str] = field(default_factory=list)
109
-
110
- def as_upload_result_ids(self) -> UploadResultIDs:
111
- result = UploadResultIDs(name=self.name, error_messages=self.error_messages, issues=self.issues)
112
- result.success = self.created + self.changed + self.unchanged
113
- result.failed = self.failed
114
- return result
115
-
116
- def dump(self, aggregate: bool = True) -> dict[str, Any]:
117
- output = super().dump(aggregate)
118
- if self.created:
119
- output["created"] = len(self.created) if aggregate else self.created
120
- if self.changed:
121
- output["changed"] = len(self.changed) if aggregate else self.changed
122
- if self.unchanged:
123
- output["unchanged"] = len(self.unchanged) if aggregate else self.unchanged
124
- if self.failed:
125
- output["failed"] = len(self.failed) if aggregate else self.failed
126
- return output
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cognite-neat
3
- Version: 0.84.1
3
+ Version: 0.85.1
4
4
  Summary: Knowledge graph transformation
5
5
  Home-page: https://cognite-neat.readthedocs-hosted.com/
6
6
  License: Apache-2.0
@@ -16,6 +16,7 @@ Provides-Extra: all
16
16
  Provides-Extra: docs
17
17
  Provides-Extra: google
18
18
  Provides-Extra: graphql
19
+ Provides-Extra: jupyter
19
20
  Provides-Extra: oxi
20
21
  Provides-Extra: service
21
22
  Requires-Dist: PyYAML
@@ -46,6 +47,7 @@ Requires-Dist: pymdown-extensions ; extra == "docs"
46
47
  Requires-Dist: pyoxigraph (==0.3.19) ; extra == "oxi" or extra == "all"
47
48
  Requires-Dist: rdflib
48
49
  Requires-Dist: requests
50
+ Requires-Dist: rich[jupyter] (>=13.7.1,<14.0.0) ; extra == "jupyter"
49
51
  Requires-Dist: schedule (>=1,<2) ; extra == "service" or extra == "all"
50
52
  Requires-Dist: tomli (>=2.0.1,<3.0.0) ; python_version < "3.11"
51
53
  Requires-Dist: typing_extensions (>=4.8,<5.0) ; python_version < "3.11"
@@ -1,6 +1,6 @@
1
- cognite/neat/__init__.py,sha256=v-rRiDOgZ3sQSMQKq0vgUQZvpeOkoHFXissAx6Ktg84,61
2
- cognite/neat/_shared.py,sha256=afQiTM0SvIKqeBRTvpfwwIvZL7QMQevt4F7lqRagAFg,968
3
- cognite/neat/_version.py,sha256=V73U5VqNMlTo-QuWNLjECQI8_59YjD0cHrTa5BEP1lg,23
1
+ cognite/neat/__init__.py,sha256=AiexNcHdAHFbrrbo9c65gtil1dqx_SGraDH1PSsXjKE,126
2
+ cognite/neat/_shared.py,sha256=RSaHm2eJceTlvb-hMMe4nHgoHdPYDfN3XcxDXo24k3A,1530
3
+ cognite/neat/_version.py,sha256=sk0eWFSjbWEX7EzVd5yu_1v9UXy1EjwkxYnNft6Eslw,23
4
4
  cognite/neat/app/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
5
  cognite/neat/app/api/asgi/metrics.py,sha256=nxFy7L5cChTI0a-zkCiJ59Aq8yLuIJp5c9Dg0wRXtV0,152
6
6
  cognite/neat/app/api/configuration.py,sha256=2U5M6M252swvQPQyooA1EBzFUZNtcTmuSaywfJDgckM,4232
@@ -54,34 +54,34 @@ cognite/neat/graph/examples/Knowledge-Graph-Nordic44.xml,sha256=U2Ns-M4LRjT1fBkh
54
54
  cognite/neat/graph/examples/__init__.py,sha256=yAjHVY3b5jOjmbW-iLbhvu7BG014TpGi3K4igkDqW5I,368
55
55
  cognite/neat/graph/examples/skos-capturing-sheet-wind-topics.xlsx,sha256=CV_yK5ZSbYS_ktfIZUPD8Sevs47zpswLXQUDFkGE4Gw,45798
56
56
  cognite/neat/graph/exceptions.py,sha256=R6pyOH774n9w2x_X_nrUr8OMAdjJMf_XPIqAvxIQaWo,3401
57
- cognite/neat/graph/extractors/__init__.py,sha256=ozXL6ZLK36wp3uX4UACRVs6rbvynQg2JQlDgL1UM1Wk,1025
58
- cognite/neat/graph/extractors/_base.py,sha256=TOXDnlqske8DgnJwA0THDVRgmR79Acjm56yF0E-2w7I,356
57
+ cognite/neat/graph/extractors/__init__.py,sha256=nXcNp6i3-1HteIkr8Ujxk4b09W5jk27Q3eWuwjcnGnM,1647
58
+ cognite/neat/graph/extractors/_base.py,sha256=8IWygpkQTwo0UOmbbwWVI7540_klTVdUVX2JjVPFRIs,498
59
59
  cognite/neat/graph/extractors/_classic_cdf/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
60
- cognite/neat/graph/extractors/_classic_cdf/_assets.py,sha256=6e_glBuYl6ArBabOblERQ57g55qsiA0UHrmHVvBqk_s,3895
61
- cognite/neat/graph/extractors/_classic_cdf/_events.py,sha256=Z0vPcyOz4mCwY0Dqa5wAQZjczO1dbTUGM0X4Y10NLGQ,3995
62
- cognite/neat/graph/extractors/_classic_cdf/_files.py,sha256=-6nCkXUCAnDsv4eDFDEiQ-U4SGhmW1VLxZJFUcszqjU,4831
63
- cognite/neat/graph/extractors/_classic_cdf/_labels.py,sha256=nGQyrOZrZzxniIKWROzS1jYrLDT861NARyi-VM_u9-0,2587
64
- cognite/neat/graph/extractors/_classic_cdf/_relationships.py,sha256=w16hu_REIFEVEenhdxEInOmgCouZaBwxXSlxl9_7vTA,5398
65
- cognite/neat/graph/extractors/_classic_cdf/_sequences.py,sha256=o4yxkf81FGFrKkflvlyDYie05fTYsT_LcRFM63OTVCI,3406
66
- cognite/neat/graph/extractors/_classic_cdf/_timeseries.py,sha256=KTYmL8vhXijlmkN1UFQrGpaCllpRekr1y55SoLhlLbg,4559
67
- cognite/neat/graph/extractors/_dexpi.py,sha256=CYSLt0Fl7Y2RCqOfIAT0N8Cjs-Yu2lRLvB13axtAaWw,9384
60
+ cognite/neat/graph/extractors/_classic_cdf/_assets.py,sha256=Hu-RoTBhn4LFm38G51L5tc0MVy4-zr1POHWyrIB-vUc,4130
61
+ cognite/neat/graph/extractors/_classic_cdf/_events.py,sha256=SGZWKCxppECIQkwQs5M2e_SoF-eGilCW2KiyXk2PmzM,4230
62
+ cognite/neat/graph/extractors/_classic_cdf/_files.py,sha256=o35K0_ouq7hjR_lAVRjWbuRsuAzlS78S_97am5TFU5A,5129
63
+ cognite/neat/graph/extractors/_classic_cdf/_labels.py,sha256=4JxQHPDciMjbk7F6GxMa-HfhOgAv8LT3VO3mRfEgQ0E,2832
64
+ cognite/neat/graph/extractors/_classic_cdf/_relationships.py,sha256=jgIN__nztlhLwoIJw59s2-Blc9gxIm7YDha5qEoXBSg,5654
65
+ cognite/neat/graph/extractors/_classic_cdf/_sequences.py,sha256=5FuhwpgDiGG51C0bQacQ4LD6KkutUaU1cX2NSy_krhU,3652
66
+ cognite/neat/graph/extractors/_classic_cdf/_timeseries.py,sha256=Ui7WRAvot3KJFwpzqmEYvRs3cN0qh93ocJjYaNLfH30,4811
67
+ cognite/neat/graph/extractors/_dexpi.py,sha256=xIw3kSaQ17k_bAuecvrVRic70PUhFHtcyy-ReLt36Q4,9385
68
68
  cognite/neat/graph/extractors/_mock_graph_generator.py,sha256=1TjgbxDVwgZjivIqx1lLKwggn_zHqWLiYM26esgDAMs,14694
69
- cognite/neat/graph/extractors/_rdf_file.py,sha256=w4-XgPgNsmZOkNxjO1ZQCcopTntmmtxfDBkQxn1se6E,463
69
+ cognite/neat/graph/extractors/_rdf_file.py,sha256=ialMCLv9WH5k6v1YMfozfcmAYhz8OVo9jVhsKMyQkDA,763
70
70
  cognite/neat/graph/issues/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
71
71
  cognite/neat/graph/issues/loader.py,sha256=v8YDsehkUT1QUG61JM9BDV_lqowMUnDmGmbay0aFzN4,3085
72
- cognite/neat/graph/loaders/__init__.py,sha256=hHC9sfFfbnGSVFTYeuNTIEu4tdLSJ2mWV07fereLelo,125
73
- cognite/neat/graph/loaders/_base.py,sha256=bdYC6CwsHVqnQa1QzOhL68qQhF1OtrsearqH6D-z3E4,4037
72
+ cognite/neat/graph/loaders/__init__.py,sha256=BteVkTklPVUB2W-bbzZug-cEUrx8ZFA-YcQPSxWVpTI,678
73
+ cognite/neat/graph/loaders/_base.py,sha256=t33I-Olw0xYz3Icf2RJZq9cs5_dEKeY87npxsA597Sw,3012
74
74
  cognite/neat/graph/loaders/_rdf2asset.py,sha256=aFby7BwIrW253LEJ4XqGeUuf4jG9VUe8Lg7OlUnXMlM,4493
75
- cognite/neat/graph/loaders/_rdf2dms.py,sha256=ZijbUsKOT01LBmTxsCgTw6lW65ysyxYe5aGOzD1l_r0,12991
75
+ cognite/neat/graph/loaders/_rdf2dms.py,sha256=xyr0SfIusfjYjlAXZcIGS1-IQ6LoVWeOB3_q6D304oo,13603
76
76
  cognite/neat/graph/models.py,sha256=AtLgZh2qyRP6NRetjQCy9qLMuTQB0CH52Zsev-qa2sk,149
77
77
  cognite/neat/graph/queries/__init__.py,sha256=BgDd-037kvtWwAoGAy8eORVNMiZ5-E9sIV0txIpeaN4,50
78
- cognite/neat/graph/queries/_base.py,sha256=20A7GDBdmc35VmHVz5n0YCGPcnBAmUX-bM2ImHPManc,3844
78
+ cognite/neat/graph/queries/_base.py,sha256=pSc6nHpcDEStGtIeeboAI-QD2PbckWaaNMK3As04jOI,4658
79
79
  cognite/neat/graph/queries/_construct.py,sha256=FxzSQqzCpo7lKVYerlLAY03oqCeFM5L6MozfBUblzr4,7341
80
80
  cognite/neat/graph/queries/_shared.py,sha256=EwW2RbPttt7-z7QTgfKWlthA2Nq5d3bYyyewFkCA7R4,5043
81
81
  cognite/neat/graph/stores/__init__.py,sha256=G-VG_YwfRt1kuPao07PDJyZ3w_0-eguzLUM13n-Z_RA,64
82
- cognite/neat/graph/stores/_base.py,sha256=7NnJUh7SQ1lDfJruOgKWc2IesT1DC81Yi6Xqp44RFwM,10140
82
+ cognite/neat/graph/stores/_base.py,sha256=z69uhzBhzl1JQJU9U-h9zAyySn25ZQTJRXam4BavnoY,10586
83
83
  cognite/neat/graph/stores/_oxrdflib.py,sha256=A5zeRm5_e8ui_ihGpgstRDg_N7qcLZ3QZBRGrOXSGI0,9569
84
- cognite/neat/graph/stores/_provenance.py,sha256=Hr9WBhFj-eoet4czL8XSBGYnu9Yn66YsTgH_G0n3QpY,3293
84
+ cognite/neat/graph/stores/_provenance.py,sha256=HIXa-p7yc2l3HFkQWMnGPhn-t_FROEG21thADGkgy0c,3590
85
85
  cognite/neat/graph/transformers/__init__.py,sha256=wXrNSyJNGnis3haaCKVPZ5y5kKSUsOUHnh-860ekatk,555
86
86
  cognite/neat/graph/transformers/_base.py,sha256=b37Ek-9njuM5pTR_3XhnxCMrg_ip_2BMwM7ZhKpAAlw,328
87
87
  cognite/neat/graph/transformers/_classic_cdf.py,sha256=ZHHJU-1-lXeufuZJSuDa2Zmu56PS9PcGeFYI91VZNI4,12214
@@ -188,28 +188,28 @@ cognite/neat/rules/analysis/_information_rules.py,sha256=fdSMyInsPJdgLHKwSkj2N9b
188
188
  cognite/neat/rules/examples/__init__.py,sha256=nxIwueAcHgZhkYriGxnDLQmIyiT8PByPHbScjYKDKe0,374
189
189
  cognite/neat/rules/examples/wind-energy.owl,sha256=NuomCA9FuuLF0JlSuG3OKqD4VBcHgSjDKFLV17G1zV8,65934
190
190
  cognite/neat/rules/exceptions.py,sha256=YLnsbXXJdDSr_szQoioEtOdqDV8PR7RdQjpMP2SWeCs,123868
191
- cognite/neat/rules/exporters/__init__.py,sha256=Gn3CjkVKHJF9Po1ZPH4wAJ-sRW9up7b2CpXm-eReV3Q,413
192
- cognite/neat/rules/exporters/_base.py,sha256=TkdpmliKjKVDITBAE4ySq_Zc8edFDQzHkbvHll4ODkg,1763
193
- cognite/neat/rules/exporters/_rules2dms.py,sha256=xnmq4FbMAvYVtJzDM-wwTRwVq_t3XWf8ffmhpE27BSk,14547
191
+ cognite/neat/rules/exporters/__init__.py,sha256=nRMUBUf7yr1QPjyITeX2rTLtLLawHv24hhRE39d2-e0,1109
192
+ cognite/neat/rules/exporters/_base.py,sha256=qZt236sNKTbiM41sgVEYcEtuK5v8Pt14LMLBNiZrNWs,1936
193
+ cognite/neat/rules/exporters/_rules2dms.py,sha256=xK9xXJ7lLQnzrRlBUJQVLlY4SC-vnnjGUXOzaWvOKmY,14553
194
194
  cognite/neat/rules/exporters/_rules2excel.py,sha256=HvUdXYHxfLMijYWdTnfqCsw3Izf8S-XDSve-2ZbqF8Y,14248
195
- cognite/neat/rules/exporters/_rules2ontology.py,sha256=Od53uLdcC2Q7UiF5PA2P0gw3O14eTD3MeJ1-trd64ZM,20388
195
+ cognite/neat/rules/exporters/_rules2ontology.py,sha256=bt8IuxaAYFRyZc1AlS-gYw9Jf6jBr5CYFOaJ3qPeoaA,20527
196
196
  cognite/neat/rules/exporters/_rules2yaml.py,sha256=GA8eUYRxUfIU6IMvlyGO5JidkOD5eUKSbH3qAiFiaCg,3026
197
197
  cognite/neat/rules/exporters/_validation.py,sha256=OlKIyf4nhSDehJwFHDQ8Zdf6HpNfW7dSe2s67eywHu4,4078
198
- cognite/neat/rules/importers/__init__.py,sha256=gR6_TAEa3iO5NCLKRztHg-FMiLdBnx47Z3iSzbwLfcE,481
199
- cognite/neat/rules/importers/_base.py,sha256=_hvxYnLiK8zf0MFes1VJ5TFisdZl-bOB6tFi3DQgYpc,4374
200
- cognite/neat/rules/importers/_dms2rules.py,sha256=5yJGYkM7lAMu-QfO0_r59WE4RGtMu2smMqLm16ohgLQ,18994
198
+ cognite/neat/rules/importers/__init__.py,sha256=Vxl2Iq1dMXUsI6Wb411xPI3rromdq50xZUci-S8faSw,1097
199
+ cognite/neat/rules/importers/_base.py,sha256=3LmDfR-f0nlLGcioWB8IbeZJ6uW5dvnzxJlqaMWc-u0,4516
200
+ cognite/neat/rules/importers/_dms2rules.py,sha256=Dqoh4qO5IVvjRpxLHZaqCgPC99_r4y7ncEo2WYMxwqU,19302
201
201
  cognite/neat/rules/importers/_dtdl2rules/__init__.py,sha256=CNR-sUihs2mnR1bPMKs3j3L4ds3vFTsrl6YycExZTfU,68
202
202
  cognite/neat/rules/importers/_dtdl2rules/_unit_lookup.py,sha256=wW4saKva61Q_i17guY0dc4OseJDQfqHy_QZBtm0OD6g,12134
203
203
  cognite/neat/rules/importers/_dtdl2rules/dtdl_converter.py,sha256=ysmWUxZ0npwrTB0uiH5jA0v37sfCwowGaYk17IyxPUU,12663
204
- cognite/neat/rules/importers/_dtdl2rules/dtdl_importer.py,sha256=QDyGt5YBaxzF4v_oCFSgKRSpwVdVruDU3-VW0DEiHbY,6718
204
+ cognite/neat/rules/importers/_dtdl2rules/dtdl_importer.py,sha256=Psj3C2jembY_Wu7WWJIFIwrMawvjISjeqfBnoRy_csw,6740
205
205
  cognite/neat/rules/importers/_dtdl2rules/spec.py,sha256=tim_MfN1J0F3Oeqk3BMgIA82d_MZvhRuRMsLK3B4PYc,11897
206
- cognite/neat/rules/importers/_inference2rules.py,sha256=vN3l6gfca19FHGzPb9fwolZaq4Z8KkeiR-iK1up8Kqk,11478
206
+ cognite/neat/rules/importers/_inference2rules.py,sha256=bBpzrioIZl3xdzz5Pal_GJyVPx08ascYW7uckixUy0Q,11667
207
207
  cognite/neat/rules/importers/_owl2rules/__init__.py,sha256=tdGcrgtozdQyST-pTlxIa4cLBNTLvtk1nNYR4vOdFSw,63
208
208
  cognite/neat/rules/importers/_owl2rules/_owl2classes.py,sha256=QpTxvrTGczIa48X8lgXGnMN1AWPhHK0DR6uNq175xak,7357
209
209
  cognite/neat/rules/importers/_owl2rules/_owl2metadata.py,sha256=nwnUaBNAAYMoBre2UmsnkJXUuaqGEpR3U3txDrH2w6g,7527
210
210
  cognite/neat/rules/importers/_owl2rules/_owl2properties.py,sha256=eKr-e-ZTTV54PJ9UXNVPTT_c9XxszNPraS4Y43AF7qQ,7297
211
211
  cognite/neat/rules/importers/_owl2rules/_owl2rules.py,sha256=41_wZFvt0A6TI55zlT04oQkvU7V73li4aGLgc4T4Lxo,6358
212
- cognite/neat/rules/importers/_spreadsheet2rules.py,sha256=32Mnu74cSKQ0XcnAshwL6XTS_TxqYBUm5u29U7sirCg,12684
212
+ cognite/neat/rules/importers/_spreadsheet2rules.py,sha256=vyYXNvP64dBGTWRWfrg7wtUcs0PdPiGLAHwE8itItAA,13072
213
213
  cognite/neat/rules/importers/_yaml2rules.py,sha256=F0uksSz1A3po5OlRM2152_w5j8D9oYTLB9NFTkSMlWI,4275
214
214
  cognite/neat/rules/issues/__init__.py,sha256=c12m0HAHHzF6oR8lKbULE3TxOPimTi9s1O9IIrtgh0g,549
215
215
  cognite/neat/rules/issues/base.py,sha256=x2YLCfmqtPlFLoURq3qHaprXCpFaQdf0iWkql-EMyps,2446
@@ -251,7 +251,8 @@ cognite/neat/rules/models/information/_serializer.py,sha256=yti9I_xJruxrib66YIBI
251
251
  cognite/neat/rules/models/information/_validation.py,sha256=Is2GzL2lZU3A5zPu3NjvlXfmIU2_Y10C5Nxi5Denz4g,7528
252
252
  cognite/neat/rules/models/wrapped_entities.py,sha256=ThhjnNNrpgz0HeORIQ8Q894trxP73P7T_TuZj6qH2CU,7157
253
253
  cognite/neat/utils/__init__.py,sha256=l5Nyqhqo25bcQXCOb_lk01cr-UXsG8cczz_y_I0u6bg,68
254
- cognite/neat/utils/auxiliary.py,sha256=E2-YtddzScvN7l7j0kNYIMlfqIUT9NWMqLpcJYPK4rY,309
254
+ cognite/neat/utils/auth.py,sha256=rBzx92IN4xGj3UK95UExKlK2dCwQi3svTZ_YBMWaTVo,11739
255
+ cognite/neat/utils/auxiliary.py,sha256=IOVbr6lPQulMJUyrrhfSsF6lIHch0Aw6KszMkBomprc,1248
255
256
  cognite/neat/utils/cdf.py,sha256=piRx-6GRz4cCfBZD5rU0OM6ixQ3cj5TMzI0yCYUveR8,2422
256
257
  cognite/neat/utils/cdf_classes.py,sha256=NEmz5UprBlqfqZnqJkRk5xjSpzazwHbhcWsMH_GNxP8,5831
257
258
  cognite/neat/utils/cdf_loaders/__init__.py,sha256=s2aPR5XLo6WZ0ybstAJlcGFYkA7CyHW1XO-NYpL0V6o,483
@@ -262,9 +263,9 @@ cognite/neat/utils/cdf_loaders/data_classes.py,sha256=0apspfwVlFltYOZfmk_PNknS3Z
262
263
  cognite/neat/utils/exceptions.py,sha256=-w4cAcvcoWLf-_ZwAl7QV_NysfqtQzIOd1Ti-mpxJgM,981
263
264
  cognite/neat/utils/spreadsheet.py,sha256=LI0c7dlW0zXHkHw0NvB-gg6Df6cDcE3FbiaHBYLXdzQ,2714
264
265
  cognite/neat/utils/text.py,sha256=4bg1_Q0lg7KsoxaDOvXrVyeY78BJN8i-27BlyDzUCls,3082
265
- cognite/neat/utils/upload.py,sha256=opAB8oDtpgcrugcjbUg0tjGqtFUnAS7zixtLiRYZ3TA,5084
266
+ cognite/neat/utils/upload.py,sha256=nZEuDu22A1kTbl-ctzAJ2vx1cjiQtqdDdpC_mRRMvUI,3597
266
267
  cognite/neat/utils/utils.py,sha256=1LEwR8gpHw_6pvEeLkW_cDU_lUun4qSsw_Rr3JsKwgA,14172
267
- cognite/neat/utils/xml.py,sha256=ppLT3lQKVp8wOP-m8-tFY8uB2P4R76l7R_-kUtsABng,992
268
+ cognite/neat/utils/xml_.py,sha256=ppLT3lQKVp8wOP-m8-tFY8uB2P4R76l7R_-kUtsABng,992
268
269
  cognite/neat/workflows/__init__.py,sha256=oiKub_U9f5cA0I1nKl5dFkR4BD8_6Be9eMzQ_50PwP0,396
269
270
  cognite/neat/workflows/_exceptions.py,sha256=ugI_X1XNpikAiL8zIggBjcx6q7WvOpRIgvxHrj2Rhr4,1348
270
271
  cognite/neat/workflows/base.py,sha256=2cSnxfc9GSoTluneTWLJbE9rImp0wJt8--LHkQHQfi4,26800
@@ -309,8 +310,8 @@ cognite/neat/workflows/steps_registry.py,sha256=fkTX14ZA7_gkUYfWIlx7A1XbCidvqR23
309
310
  cognite/neat/workflows/tasks.py,sha256=dqlJwKAb0jlkl7abbY8RRz3m7MT4SK8-7cntMWkOYjw,788
310
311
  cognite/neat/workflows/triggers.py,sha256=_BLNplzoz0iic367u1mhHMHiUrCwP-SLK6_CZzfODX0,7071
311
312
  cognite/neat/workflows/utils.py,sha256=gKdy3RLG7ctRhbCRwaDIWpL9Mi98zm56-d4jfHDqP1E,453
312
- cognite_neat-0.84.1.dist-info/LICENSE,sha256=W8VmvFia4WHa3Gqxq1Ygrq85McUNqIGDVgtdvzT-XqA,11351
313
- cognite_neat-0.84.1.dist-info/METADATA,sha256=i54w9dUQS9DCWAsl2IR-P14CUA1uMLpjrdISbJXnL8o,9400
314
- cognite_neat-0.84.1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
315
- cognite_neat-0.84.1.dist-info/entry_points.txt,sha256=61FPqiWb25vbqB0KI7znG8nsg_ibLHBvTjYnkPvNFso,50
316
- cognite_neat-0.84.1.dist-info/RECORD,,
313
+ cognite_neat-0.85.1.dist-info/LICENSE,sha256=W8VmvFia4WHa3Gqxq1Ygrq85McUNqIGDVgtdvzT-XqA,11351
314
+ cognite_neat-0.85.1.dist-info/METADATA,sha256=Unag55Klk--tBNb8WHFDEtuysPn704Nv6vQkRpnziWo,9493
315
+ cognite_neat-0.85.1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
316
+ cognite_neat-0.85.1.dist-info/entry_points.txt,sha256=61FPqiWb25vbqB0KI7znG8nsg_ibLHBvTjYnkPvNFso,50
317
+ cognite_neat-0.85.1.dist-info/RECORD,,