cognite-neat 0.123.26__py3-none-any.whl → 1.0.22__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.
- cognite/neat/__init__.py +4 -3
- cognite/neat/_client/__init__.py +5 -0
- cognite/neat/_client/api.py +8 -0
- cognite/neat/_client/client.py +21 -0
- cognite/neat/_client/config.py +40 -0
- cognite/neat/_client/containers_api.py +138 -0
- cognite/neat/_client/data_classes.py +44 -0
- cognite/neat/_client/data_model_api.py +115 -0
- cognite/neat/_client/init/credentials.py +70 -0
- cognite/neat/_client/init/env_vars.py +131 -0
- cognite/neat/_client/init/main.py +51 -0
- cognite/neat/_client/spaces_api.py +115 -0
- cognite/neat/_client/statistics_api.py +24 -0
- cognite/neat/_client/views_api.py +144 -0
- cognite/neat/_config.py +266 -0
- cognite/neat/_data_model/_analysis.py +571 -0
- cognite/neat/_data_model/_constants.py +74 -0
- cognite/neat/_data_model/_identifiers.py +61 -0
- cognite/neat/_data_model/_shared.py +41 -0
- cognite/neat/_data_model/_snapshot.py +134 -0
- cognite/neat/_data_model/deployer/_differ.py +140 -0
- cognite/neat/_data_model/deployer/_differ_container.py +360 -0
- cognite/neat/_data_model/deployer/_differ_data_model.py +54 -0
- cognite/neat/_data_model/deployer/_differ_space.py +9 -0
- cognite/neat/_data_model/deployer/_differ_view.py +299 -0
- cognite/neat/_data_model/deployer/data_classes.py +644 -0
- cognite/neat/_data_model/deployer/deployer.py +431 -0
- cognite/neat/_data_model/exporters/__init__.py +15 -0
- cognite/neat/_data_model/exporters/_api_exporter.py +37 -0
- cognite/neat/_data_model/exporters/_base.py +24 -0
- cognite/neat/_data_model/exporters/_table_exporter/exporter.py +128 -0
- cognite/neat/_data_model/exporters/_table_exporter/workbook.py +409 -0
- cognite/neat/_data_model/exporters/_table_exporter/writer.py +480 -0
- cognite/neat/_data_model/importers/__init__.py +5 -0
- cognite/neat/_data_model/importers/_api_importer.py +166 -0
- cognite/neat/_data_model/importers/_base.py +16 -0
- cognite/neat/_data_model/importers/_table_importer/data_classes.py +344 -0
- cognite/neat/_data_model/importers/_table_importer/importer.py +192 -0
- cognite/neat/_data_model/importers/_table_importer/reader.py +1102 -0
- cognite/neat/_data_model/importers/_table_importer/source.py +94 -0
- cognite/neat/_data_model/models/conceptual/_base.py +18 -0
- cognite/neat/_data_model/models/conceptual/_concept.py +67 -0
- cognite/neat/_data_model/models/conceptual/_data_model.py +51 -0
- cognite/neat/_data_model/models/conceptual/_properties.py +104 -0
- cognite/neat/_data_model/models/conceptual/_property.py +105 -0
- cognite/neat/_data_model/models/dms/__init__.py +206 -0
- cognite/neat/_data_model/models/dms/_base.py +31 -0
- cognite/neat/_data_model/models/dms/_constants.py +48 -0
- cognite/neat/_data_model/models/dms/_constraints.py +42 -0
- cognite/neat/_data_model/models/dms/_container.py +159 -0
- cognite/neat/_data_model/models/dms/_data_model.py +95 -0
- cognite/neat/_data_model/models/dms/_data_types.py +195 -0
- cognite/neat/_data_model/models/dms/_http.py +28 -0
- cognite/neat/_data_model/models/dms/_indexes.py +30 -0
- cognite/neat/_data_model/models/dms/_limits.py +96 -0
- cognite/neat/_data_model/models/dms/_references.py +141 -0
- cognite/neat/_data_model/models/dms/_schema.py +18 -0
- cognite/neat/_data_model/models/dms/_space.py +48 -0
- cognite/neat/_data_model/models/dms/_types.py +17 -0
- cognite/neat/_data_model/models/dms/_view_filter.py +310 -0
- cognite/neat/_data_model/models/dms/_view_property.py +235 -0
- cognite/neat/_data_model/models/dms/_views.py +216 -0
- cognite/neat/_data_model/models/entities/__init__.py +50 -0
- cognite/neat/_data_model/models/entities/_base.py +101 -0
- cognite/neat/_data_model/models/entities/_constants.py +22 -0
- cognite/neat/_data_model/models/entities/_data_types.py +144 -0
- cognite/neat/_data_model/models/entities/_identifiers.py +61 -0
- cognite/neat/_data_model/models/entities/_parser.py +226 -0
- cognite/neat/_data_model/validation/dms/__init__.py +75 -0
- cognite/neat/_data_model/validation/dms/_ai_readiness.py +381 -0
- cognite/neat/_data_model/validation/dms/_base.py +25 -0
- cognite/neat/_data_model/validation/dms/_connections.py +681 -0
- cognite/neat/_data_model/validation/dms/_consistency.py +58 -0
- cognite/neat/_data_model/validation/dms/_containers.py +199 -0
- cognite/neat/_data_model/validation/dms/_limits.py +368 -0
- cognite/neat/_data_model/validation/dms/_orchestrator.py +70 -0
- cognite/neat/_data_model/validation/dms/_views.py +164 -0
- cognite/neat/_exceptions.py +68 -0
- cognite/neat/_issues.py +68 -0
- cognite/neat/_session/__init__.py +3 -0
- cognite/neat/_session/_html/_render.py +30 -0
- cognite/neat/_session/_html/static/__init__.py +8 -0
- cognite/neat/_session/_html/static/deployment.css +476 -0
- cognite/neat/_session/_html/static/deployment.js +181 -0
- cognite/neat/_session/_html/static/issues.css +211 -0
- cognite/neat/_session/_html/static/issues.js +168 -0
- cognite/neat/_session/_html/static/shared.css +186 -0
- cognite/neat/_session/_html/templates/__init__.py +4 -0
- cognite/neat/_session/_html/templates/deployment.html +80 -0
- cognite/neat/_session/_html/templates/issues.html +45 -0
- cognite/neat/_session/_issues.py +81 -0
- cognite/neat/_session/_physical.py +294 -0
- cognite/neat/_session/_result/__init__.py +3 -0
- cognite/neat/_session/_result/_deployment/__init__.py +0 -0
- cognite/neat/_session/_result/_deployment/_physical/__init__.py +0 -0
- cognite/neat/_session/_result/_deployment/_physical/_changes.py +196 -0
- cognite/neat/_session/_result/_deployment/_physical/_statistics.py +180 -0
- cognite/neat/_session/_result/_deployment/_physical/serializer.py +35 -0
- cognite/neat/_session/_result/_result.py +31 -0
- cognite/neat/_session/_session.py +81 -0
- cognite/neat/_session/_usage_analytics/__init__.py +0 -0
- cognite/neat/_session/_usage_analytics/_collector.py +131 -0
- cognite/neat/_session/_usage_analytics/_constants.py +23 -0
- cognite/neat/_session/_usage_analytics/_storage.py +240 -0
- cognite/neat/_session/_wrappers.py +101 -0
- cognite/neat/_state_machine/__init__.py +10 -0
- cognite/neat/_state_machine/_base.py +37 -0
- cognite/neat/_state_machine/_states.py +52 -0
- cognite/neat/_store/__init__.py +3 -0
- cognite/neat/_store/_provenance.py +88 -0
- cognite/neat/_store/_store.py +220 -0
- cognite/neat/_utils/__init__.py +0 -0
- cognite/neat/_utils/_reader.py +194 -0
- cognite/neat/_utils/auxiliary.py +49 -0
- cognite/neat/_utils/collection.py +11 -0
- cognite/neat/_utils/http_client/__init__.py +39 -0
- cognite/neat/_utils/http_client/_client.py +245 -0
- cognite/neat/_utils/http_client/_config.py +19 -0
- cognite/neat/_utils/http_client/_data_classes.py +294 -0
- cognite/neat/_utils/http_client/_tracker.py +31 -0
- cognite/neat/_utils/repo.py +19 -0
- cognite/neat/_utils/text.py +71 -0
- cognite/neat/_utils/useful_types.py +37 -0
- cognite/neat/_utils/validation.py +154 -0
- cognite/neat/_v0/__init__.py +0 -0
- cognite/neat/_v0/core/__init__.py +0 -0
- cognite/neat/_v0/core/_client/_api/__init__.py +0 -0
- cognite/neat/{core → _v0/core}/_client/_api/data_modeling_loaders.py +8 -7
- cognite/neat/{core → _v0/core}/_client/_api/neat_instances.py +5 -5
- cognite/neat/{core → _v0/core}/_client/_api/schema.py +5 -5
- cognite/neat/{core → _v0/core}/_client/_api/statistics.py +3 -3
- cognite/neat/{core → _v0/core}/_client/_api_client.py +1 -1
- cognite/neat/_v0/core/_client/data_classes/__init__.py +0 -0
- cognite/neat/{core → _v0/core}/_client/data_classes/schema.py +4 -4
- cognite/neat/{core → _v0/core}/_client/testing.py +1 -1
- cognite/neat/{core → _v0/core}/_constants.py +5 -3
- cognite/neat/_v0/core/_data_model/__init__.py +0 -0
- cognite/neat/{core → _v0/core}/_data_model/_constants.py +7 -0
- cognite/neat/{core → _v0/core}/_data_model/_shared.py +4 -4
- cognite/neat/{core → _v0/core}/_data_model/analysis/_base.py +8 -8
- cognite/neat/{core → _v0/core}/_data_model/exporters/__init__.py +1 -2
- cognite/neat/{core → _v0/core}/_data_model/exporters/_base.py +7 -7
- cognite/neat/{core → _v0/core}/_data_model/exporters/_data_model2dms.py +9 -9
- cognite/neat/{core → _v0/core}/_data_model/exporters/_data_model2excel.py +12 -12
- cognite/neat/{core → _v0/core}/_data_model/exporters/_data_model2instance_template.py +4 -4
- cognite/neat/{core/_data_model/exporters/_data_model2ontology.py → _v0/core/_data_model/exporters/_data_model2semantic_model.py} +126 -116
- cognite/neat/{core → _v0/core}/_data_model/exporters/_data_model2yaml.py +1 -1
- cognite/neat/{core → _v0/core}/_data_model/importers/_base.py +5 -5
- cognite/neat/{core → _v0/core}/_data_model/importers/_base_file_reader.py +2 -2
- cognite/neat/{core → _v0/core}/_data_model/importers/_dict2data_model.py +5 -5
- cognite/neat/{core → _v0/core}/_data_model/importers/_dms2data_model.py +18 -15
- cognite/neat/{core → _v0/core}/_data_model/importers/_graph2data_model.py +12 -12
- cognite/neat/{core → _v0/core}/_data_model/importers/_rdf/_base.py +12 -12
- cognite/neat/{core → _v0/core}/_data_model/importers/_rdf/_inference2rdata_model.py +14 -14
- cognite/neat/{core → _v0/core}/_data_model/importers/_rdf/_owl2data_model.py +41 -21
- cognite/neat/{core → _v0/core}/_data_model/importers/_rdf/_shared.py +9 -9
- cognite/neat/{core → _v0/core}/_data_model/importers/_spreadsheet2data_model.py +92 -12
- cognite/neat/{core → _v0/core}/_data_model/models/__init__.py +3 -3
- cognite/neat/{core → _v0/core}/_data_model/models/_base_verified.py +5 -5
- cognite/neat/{core → _v0/core}/_data_model/models/_import_contexts.py +1 -1
- cognite/neat/{core → _v0/core}/_data_model/models/_types.py +5 -5
- cognite/neat/{core → _v0/core}/_data_model/models/conceptual/_unverified.py +16 -10
- cognite/neat/{core → _v0/core}/_data_model/models/conceptual/_validation.py +12 -12
- cognite/neat/{core → _v0/core}/_data_model/models/conceptual/_verified.py +9 -9
- cognite/neat/{core → _v0/core}/_data_model/models/data_types.py +14 -4
- cognite/neat/{core → _v0/core}/_data_model/models/entities/__init__.py +6 -0
- cognite/neat/_v0/core/_data_model/models/entities/_loaders.py +155 -0
- cognite/neat/{core → _v0/core}/_data_model/models/entities/_multi_value.py +2 -2
- cognite/neat/_v0/core/_data_model/models/entities/_restrictions.py +230 -0
- cognite/neat/{core → _v0/core}/_data_model/models/entities/_single_value.py +121 -16
- cognite/neat/{core → _v0/core}/_data_model/models/entities/_types.py +10 -0
- cognite/neat/{core → _v0/core}/_data_model/models/mapping/_classic2core.py +5 -5
- cognite/neat/{core → _v0/core}/_data_model/models/physical/__init__.py +1 -1
- cognite/neat/{core → _v0/core}/_data_model/models/physical/_exporter.py +26 -19
- cognite/neat/{core → _v0/core}/_data_model/models/physical/_unverified.py +133 -37
- cognite/neat/{core → _v0/core}/_data_model/models/physical/_validation.py +24 -20
- cognite/neat/{core → _v0/core}/_data_model/models/physical/_verified.py +95 -24
- cognite/neat/{core → _v0/core}/_data_model/transformers/_base.py +4 -4
- cognite/neat/{core → _v0/core}/_data_model/transformers/_converters.py +35 -28
- cognite/neat/{core → _v0/core}/_data_model/transformers/_mapping.py +7 -7
- cognite/neat/{core → _v0/core}/_data_model/transformers/_union_conceptual.py +5 -5
- cognite/neat/{core → _v0/core}/_data_model/transformers/_verification.py +7 -7
- cognite/neat/_v0/core/_instances/__init__.py +0 -0
- cognite/neat/{core → _v0/core}/_instances/_tracking/base.py +1 -1
- cognite/neat/{core → _v0/core}/_instances/_tracking/log.py +1 -1
- cognite/neat/{core → _v0/core}/_instances/extractors/__init__.py +3 -2
- cognite/neat/{core → _v0/core}/_instances/extractors/_base.py +6 -6
- cognite/neat/_v0/core/_instances/extractors/_classic_cdf/__init__.py +0 -0
- cognite/neat/{core → _v0/core}/_instances/extractors/_classic_cdf/_base.py +7 -7
- cognite/neat/{core → _v0/core}/_instances/extractors/_classic_cdf/_classic.py +12 -12
- cognite/neat/{core → _v0/core}/_instances/extractors/_classic_cdf/_relationships.py +3 -3
- cognite/neat/{core → _v0/core}/_instances/extractors/_classic_cdf/_sequences.py +2 -2
- cognite/neat/{core → _v0/core}/_instances/extractors/_dict.py +6 -3
- cognite/neat/{core → _v0/core}/_instances/extractors/_dms.py +6 -6
- cognite/neat/{core → _v0/core}/_instances/extractors/_dms_graph.py +11 -11
- cognite/neat/{core → _v0/core}/_instances/extractors/_mock_graph_generator.py +10 -10
- cognite/neat/{core → _v0/core}/_instances/extractors/_raw.py +3 -3
- cognite/neat/{core → _v0/core}/_instances/extractors/_rdf_file.py +7 -7
- cognite/neat/{core → _v0/core}/_instances/loaders/_base.py +5 -5
- cognite/neat/{core → _v0/core}/_instances/loaders/_rdf2dms.py +17 -17
- cognite/neat/{core → _v0/core}/_instances/loaders/_rdf_to_instance_space.py +11 -11
- cognite/neat/{core → _v0/core}/_instances/queries/_select.py +29 -3
- cognite/neat/{core → _v0/core}/_instances/queries/_update.py +1 -1
- cognite/neat/{core → _v0/core}/_instances/transformers/_base.py +4 -4
- cognite/neat/{core → _v0/core}/_instances/transformers/_classic_cdf.py +6 -6
- cognite/neat/{core → _v0/core}/_instances/transformers/_prune_graph.py +4 -4
- cognite/neat/{core → _v0/core}/_instances/transformers/_rdfpath.py +1 -1
- cognite/neat/{core → _v0/core}/_instances/transformers/_value_type.py +4 -4
- cognite/neat/{core → _v0/core}/_issues/_base.py +5 -5
- cognite/neat/{core → _v0/core}/_issues/_contextmanagers.py +1 -1
- cognite/neat/{core → _v0/core}/_issues/_factory.py +3 -3
- cognite/neat/{core → _v0/core}/_issues/errors/__init__.py +1 -1
- cognite/neat/{core → _v0/core}/_issues/errors/_external.py +1 -1
- cognite/neat/{core → _v0/core}/_issues/errors/_general.py +1 -1
- cognite/neat/{core → _v0/core}/_issues/errors/_properties.py +1 -1
- cognite/neat/{core → _v0/core}/_issues/errors/_resources.py +2 -2
- cognite/neat/{core → _v0/core}/_issues/errors/_wrapper.py +7 -3
- cognite/neat/{core → _v0/core}/_issues/warnings/__init__.py +1 -1
- cognite/neat/{core → _v0/core}/_issues/warnings/_external.py +1 -1
- cognite/neat/{core → _v0/core}/_issues/warnings/_general.py +1 -1
- cognite/neat/{core → _v0/core}/_issues/warnings/_models.py +2 -2
- cognite/neat/{core → _v0/core}/_issues/warnings/_properties.py +2 -2
- cognite/neat/{core → _v0/core}/_issues/warnings/_resources.py +1 -1
- cognite/neat/{core → _v0/core}/_issues/warnings/user_modeling.py +1 -1
- cognite/neat/{core → _v0/core}/_store/_data_model.py +12 -12
- cognite/neat/{core → _v0/core}/_store/_instance.py +43 -10
- cognite/neat/{core → _v0/core}/_store/_provenance.py +3 -3
- cognite/neat/{core → _v0/core}/_store/exceptions.py +4 -4
- cognite/neat/_v0/core/_utils/__init__.py +0 -0
- cognite/neat/{core → _v0/core}/_utils/auth.py +22 -12
- cognite/neat/{core → _v0/core}/_utils/auxiliary.py +1 -1
- cognite/neat/{core → _v0/core}/_utils/collection_.py +2 -2
- cognite/neat/{core → _v0/core}/_utils/graph_transformations_report.py +1 -1
- cognite/neat/{core → _v0/core}/_utils/rdf_.py +1 -1
- cognite/neat/{core → _v0/core}/_utils/reader/_base.py +1 -1
- cognite/neat/{core → _v0/core}/_utils/spreadsheet.py +18 -4
- cognite/neat/{core → _v0/core}/_utils/text.py +1 -1
- cognite/neat/{core → _v0/core}/_utils/upload.py +3 -3
- cognite/neat/{session → _v0}/engine/_load.py +1 -1
- cognite/neat/_v0/plugins/__init__.py +4 -0
- cognite/neat/_v0/plugins/_base.py +9 -0
- cognite/neat/_v0/plugins/_data_model.py +48 -0
- cognite/neat/{plugins → _v0/plugins}/_issues.py +1 -1
- cognite/neat/{plugins → _v0/plugins}/_manager.py +7 -16
- cognite/neat/{session → _v0/session}/_base.py +13 -15
- cognite/neat/{session → _v0/session}/_collector.py +1 -1
- cognite/neat/_v0/session/_diff.py +51 -0
- cognite/neat/{session → _v0/session}/_drop.py +3 -3
- cognite/neat/{session → _v0/session}/_explore.py +2 -2
- cognite/neat/{session → _v0/session}/_fix.py +2 -2
- cognite/neat/{session → _v0/session}/_inspect.py +3 -3
- cognite/neat/{session → _v0/session}/_mapping.py +3 -3
- cognite/neat/{session → _v0/session}/_plugin.py +4 -5
- cognite/neat/{session → _v0/session}/_prepare.py +8 -8
- cognite/neat/{session → _v0/session}/_read.py +34 -21
- cognite/neat/{session → _v0/session}/_set.py +8 -8
- cognite/neat/{session → _v0/session}/_show.py +5 -5
- cognite/neat/{session → _v0/session}/_state.py +10 -10
- cognite/neat/{session → _v0/session}/_subset.py +4 -4
- cognite/neat/{session → _v0/session}/_template.py +11 -11
- cognite/neat/{session → _v0/session}/_to.py +12 -12
- cognite/neat/{session → _v0/session}/_wizard.py +1 -1
- cognite/neat/{session → _v0/session}/exceptions.py +5 -5
- cognite/neat/_version.py +1 -1
- cognite/neat/legacy.py +6 -0
- cognite_neat-1.0.22.dist-info/METADATA +123 -0
- cognite_neat-1.0.22.dist-info/RECORD +329 -0
- cognite_neat-1.0.22.dist-info/WHEEL +4 -0
- cognite/neat/core/_data_model/models/entities/_loaders.py +0 -75
- cognite/neat/plugins/__init__.py +0 -3
- cognite/neat/plugins/data_model/importers/__init__.py +0 -5
- cognite/neat/plugins/data_model/importers/_base.py +0 -28
- cognite/neat/session/_session/_data_model/__init__.py +0 -3
- cognite/neat/session/_session/_data_model/_read.py +0 -193
- cognite/neat/session/_session/_data_model/_routes.py +0 -45
- cognite/neat/session/_session/_data_model/_show.py +0 -147
- cognite/neat/session/_session/_data_model/_write.py +0 -335
- cognite_neat-0.123.26.dist-info/METADATA +0 -144
- cognite_neat-0.123.26.dist-info/RECORD +0 -201
- cognite_neat-0.123.26.dist-info/WHEEL +0 -4
- cognite_neat-0.123.26.dist-info/licenses/LICENSE +0 -201
- /cognite/neat/{core → _client/init}/__init__.py +0 -0
- /cognite/neat/{core/_client/_api → _data_model}/__init__.py +0 -0
- /cognite/neat/{core/_client/data_classes → _data_model/deployer}/__init__.py +0 -0
- /cognite/neat/{core/_data_model → _data_model/exporters/_table_exporter}/__init__.py +0 -0
- /cognite/neat/{core/_instances → _data_model/importers/_table_importer}/__init__.py +0 -0
- /cognite/neat/{core/_instances/extractors/_classic_cdf → _data_model/models}/__init__.py +0 -0
- /cognite/neat/{core/_utils → _data_model/models/conceptual}/__init__.py +0 -0
- /cognite/neat/{plugins/data_model → _data_model/validation}/__init__.py +0 -0
- /cognite/neat/{session/_session → _session/_html}/__init__.py +0 -0
- /cognite/neat/{core → _v0/core}/_client/__init__.py +0 -0
- /cognite/neat/{core → _v0/core}/_client/data_classes/data_modeling.py +0 -0
- /cognite/neat/{core → _v0/core}/_client/data_classes/neat_sequence.py +0 -0
- /cognite/neat/{core → _v0/core}/_client/data_classes/statistics.py +0 -0
- /cognite/neat/{core → _v0/core}/_config.py +0 -0
- /cognite/neat/{core → _v0/core}/_data_model/analysis/__init__.py +0 -0
- /cognite/neat/{core → _v0/core}/_data_model/catalog/__init__.py +0 -0
- /cognite/neat/{core → _v0/core}/_data_model/catalog/classic_model.xlsx +0 -0
- /cognite/neat/{core → _v0/core}/_data_model/catalog/conceptual-imf-data-model.xlsx +0 -0
- /cognite/neat/{core → _v0/core}/_data_model/catalog/hello_world_pump.xlsx +0 -0
- /cognite/neat/{core → _v0/core}/_data_model/importers/__init__.py +0 -0
- /cognite/neat/{core → _v0/core}/_data_model/importers/_rdf/__init__.py +0 -0
- /cognite/neat/{core → _v0/core}/_data_model/models/_base_unverified.py +0 -0
- /cognite/neat/{core → _v0/core}/_data_model/models/conceptual/__init__.py +0 -0
- /cognite/neat/{core → _v0/core}/_data_model/models/entities/_constants.py +0 -0
- /cognite/neat/{core → _v0/core}/_data_model/models/entities/_wrapped.py +0 -0
- /cognite/neat/{core → _v0/core}/_data_model/models/mapping/__init__.py +0 -0
- /cognite/neat/{core → _v0/core}/_data_model/models/mapping/_classic2core.yaml +0 -0
- /cognite/neat/{core → _v0/core}/_data_model/transformers/__init__.py +0 -0
- /cognite/neat/{core → _v0/core}/_instances/_shared.py +0 -0
- /cognite/neat/{core → _v0/core}/_instances/_tracking/__init__.py +0 -0
- /cognite/neat/{core → _v0/core}/_instances/examples/Knowledge-Graph-Nordic44-dirty.xml +0 -0
- /cognite/neat/{core → _v0/core}/_instances/examples/Knowledge-Graph-Nordic44.xml +0 -0
- /cognite/neat/{core → _v0/core}/_instances/examples/__init__.py +0 -0
- /cognite/neat/{core → _v0/core}/_instances/examples/skos-capturing-sheet-wind-topics.xlsx +0 -0
- /cognite/neat/{core → _v0/core}/_instances/extractors/_classic_cdf/_assets.py +0 -0
- /cognite/neat/{core → _v0/core}/_instances/extractors/_classic_cdf/_data_sets.py +0 -0
- /cognite/neat/{core → _v0/core}/_instances/extractors/_classic_cdf/_events.py +0 -0
- /cognite/neat/{core → _v0/core}/_instances/extractors/_classic_cdf/_files.py +0 -0
- /cognite/neat/{core → _v0/core}/_instances/extractors/_classic_cdf/_labels.py +0 -0
- /cognite/neat/{core → _v0/core}/_instances/extractors/_classic_cdf/_timeseries.py +0 -0
- /cognite/neat/{core → _v0/core}/_instances/loaders/__init__.py +0 -0
- /cognite/neat/{core → _v0/core}/_instances/queries/__init__.py +0 -0
- /cognite/neat/{core → _v0/core}/_instances/queries/_base.py +0 -0
- /cognite/neat/{core → _v0/core}/_instances/queries/_queries.py +0 -0
- /cognite/neat/{core → _v0/core}/_instances/transformers/__init__.py +0 -0
- /cognite/neat/{core → _v0/core}/_issues/__init__.py +0 -0
- /cognite/neat/{core → _v0/core}/_issues/formatters.py +0 -0
- /cognite/neat/{core → _v0/core}/_shared.py +0 -0
- /cognite/neat/{core → _v0/core}/_store/__init__.py +0 -0
- /cognite/neat/{core → _v0/core}/_utils/io_.py +0 -0
- /cognite/neat/{core → _v0/core}/_utils/reader/__init__.py +0 -0
- /cognite/neat/{core → _v0/core}/_utils/tarjan.py +0 -0
- /cognite/neat/{core → _v0/core}/_utils/time_.py +0 -0
- /cognite/neat/{core → _v0/core}/_utils/xml_.py +0 -0
- /cognite/neat/{session → _v0}/engine/__init__.py +0 -0
- /cognite/neat/{session → _v0}/engine/_import.py +0 -0
- /cognite/neat/{session → _v0}/engine/_interface.py +0 -0
- /cognite/neat/{session → _v0/session}/__init__.py +0 -0
- /cognite/neat/{session → _v0/session}/_experimental.py +0 -0
- /cognite/neat/{session → _v0/session}/_state/README.md +0 -0
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import itertools
|
|
2
|
+
from typing import Any, Literal, cast, get_args
|
|
3
|
+
|
|
4
|
+
from pydantic import BaseModel, Field
|
|
5
|
+
|
|
6
|
+
from cognite.neat._data_model.deployer.data_classes import (
|
|
7
|
+
AppliedChanges,
|
|
8
|
+
DataModelEndpoint,
|
|
9
|
+
DeploymentResult,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class EndpointStatistics(BaseModel):
|
|
14
|
+
"""Statistics for a single endpoint."""
|
|
15
|
+
|
|
16
|
+
create: int = 0
|
|
17
|
+
update: int = 0
|
|
18
|
+
delete: int = 0
|
|
19
|
+
skip: int = 0
|
|
20
|
+
unchanged: int = 0
|
|
21
|
+
failed: int = 0
|
|
22
|
+
|
|
23
|
+
@property
|
|
24
|
+
def total(self) -> int:
|
|
25
|
+
"""Total number of changes for this endpoint."""
|
|
26
|
+
return self.create + self.update + self.delete + self.skip + self.unchanged + self.failed
|
|
27
|
+
|
|
28
|
+
def increment(self, change_type: Literal["create", "update", "delete", "unchanged", "skip", "failed"]) -> None:
|
|
29
|
+
"""Increment the count for a specific change type.
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
change_type: The type of change (create, update, delete, skip, unchanged, failed).
|
|
33
|
+
"""
|
|
34
|
+
if hasattr(self, change_type):
|
|
35
|
+
setattr(self, change_type, getattr(self, change_type) + 1)
|
|
36
|
+
else:
|
|
37
|
+
raise RuntimeError(f"Unknown change type: {change_type}. This is a bug in NEAT.")
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class ChangeTypeStatistics(BaseModel):
|
|
41
|
+
"""Statistics grouped by change type."""
|
|
42
|
+
|
|
43
|
+
create: int = 0
|
|
44
|
+
update: int = 0
|
|
45
|
+
delete: int = 0
|
|
46
|
+
skip: int = 0
|
|
47
|
+
unchanged: int = 0
|
|
48
|
+
failed: int = 0
|
|
49
|
+
|
|
50
|
+
def increment(self, change_type: Literal["create", "update", "delete", "unchanged", "skip", "failed"]) -> None:
|
|
51
|
+
"""Increment the count for a specific change type.
|
|
52
|
+
|
|
53
|
+
Args:
|
|
54
|
+
change_type: The type of change (create, update, delete, skip, unchanged, failed).
|
|
55
|
+
"""
|
|
56
|
+
if hasattr(self, change_type):
|
|
57
|
+
setattr(self, change_type, getattr(self, change_type) + 1)
|
|
58
|
+
else:
|
|
59
|
+
raise RuntimeError(f"Unknown change type: {change_type}. This is a bug in NEAT.")
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class SeverityStatistics(BaseModel):
|
|
63
|
+
"""Statistics grouped by severity."""
|
|
64
|
+
|
|
65
|
+
SAFE: int = 0
|
|
66
|
+
WARNING: int = 0
|
|
67
|
+
BREAKING: int = 0
|
|
68
|
+
|
|
69
|
+
def increment(self, severity: Literal["SAFE", "WARNING", "BREAKING"]) -> None:
|
|
70
|
+
"""Increment the count for a specific severity level.
|
|
71
|
+
|
|
72
|
+
Args:
|
|
73
|
+
severity: The severity level (SAFE, WARNING, BREAKING).
|
|
74
|
+
"""
|
|
75
|
+
if hasattr(self, severity):
|
|
76
|
+
setattr(self, severity, getattr(self, severity) + 1)
|
|
77
|
+
else:
|
|
78
|
+
raise RuntimeError(f"Unknown severity level: {severity}. This is a bug in NEAT.")
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
class DeploymentStatistics(BaseModel):
|
|
82
|
+
"""Overall deployment statistics."""
|
|
83
|
+
|
|
84
|
+
by_endpoint: dict[str, EndpointStatistics] = Field(default_factory=dict)
|
|
85
|
+
by_change_type: ChangeTypeStatistics = Field(default_factory=ChangeTypeStatistics)
|
|
86
|
+
by_severity: SeverityStatistics = Field(default_factory=SeverityStatistics)
|
|
87
|
+
|
|
88
|
+
@property
|
|
89
|
+
def total_changes(self) -> int:
|
|
90
|
+
"""Total number of changes in the deployment."""
|
|
91
|
+
return sum(endpoint_stats.total for endpoint_stats in self.by_endpoint.values())
|
|
92
|
+
|
|
93
|
+
def model_dump(self, **kwargs: Any) -> dict[str, Any]:
|
|
94
|
+
"""Include computed properties in serialization."""
|
|
95
|
+
data = super().model_dump(**kwargs)
|
|
96
|
+
data["total_changes"] = self.total_changes
|
|
97
|
+
return data
|
|
98
|
+
|
|
99
|
+
@classmethod
|
|
100
|
+
def from_deployment_result(cls, result: DeploymentResult) -> "DeploymentStatistics":
|
|
101
|
+
"""Create DeploymentStatistics from a DeploymentResult.
|
|
102
|
+
|
|
103
|
+
Args:
|
|
104
|
+
result: The deployment result to create statistics from.
|
|
105
|
+
|
|
106
|
+
Returns:
|
|
107
|
+
DeploymentStatistics instance with computed statistics.
|
|
108
|
+
"""
|
|
109
|
+
stats = cls(
|
|
110
|
+
by_endpoint={endpoint: EndpointStatistics() for endpoint in get_args(DataModelEndpoint)},
|
|
111
|
+
by_change_type=ChangeTypeStatistics(),
|
|
112
|
+
by_severity=SeverityStatistics(),
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
if result.is_dry_run:
|
|
116
|
+
stats._update_from_dry_run(result)
|
|
117
|
+
else:
|
|
118
|
+
stats._update_from_deployment(result)
|
|
119
|
+
|
|
120
|
+
return stats
|
|
121
|
+
|
|
122
|
+
def _update_from_dry_run(self, result: DeploymentResult) -> None:
|
|
123
|
+
"""Update statistics from dry run mode.
|
|
124
|
+
|
|
125
|
+
Args:
|
|
126
|
+
result: The deployment result in dry run mode.
|
|
127
|
+
"""
|
|
128
|
+
for plan in result.plan:
|
|
129
|
+
for resource in plan.resources:
|
|
130
|
+
self._update_single_stat(
|
|
131
|
+
endpoint=plan.endpoint,
|
|
132
|
+
change_type=resource.change_type,
|
|
133
|
+
severity=cast(Literal["SAFE", "WARNING", "BREAKING"], resource.severity.name),
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
def _update_from_deployment(self, result: DeploymentResult) -> None:
|
|
137
|
+
"""Update statistics from actual deployment mode.
|
|
138
|
+
|
|
139
|
+
Args:
|
|
140
|
+
result: The deployment result from actual deployment.
|
|
141
|
+
"""
|
|
142
|
+
applied_changes = cast(AppliedChanges, result.responses)
|
|
143
|
+
|
|
144
|
+
for response in itertools.chain(
|
|
145
|
+
applied_changes.created,
|
|
146
|
+
applied_changes.merged_updated,
|
|
147
|
+
applied_changes.deletions,
|
|
148
|
+
applied_changes.unchanged,
|
|
149
|
+
applied_changes.skipped,
|
|
150
|
+
):
|
|
151
|
+
self._update_single_stat(
|
|
152
|
+
endpoint=response.endpoint,
|
|
153
|
+
change_type=response.change.change_type if response.is_success else "failed",
|
|
154
|
+
severity=cast(Literal["SAFE", "WARNING", "BREAKING"], response.change.severity.name),
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
def _update_single_stat(
|
|
158
|
+
self,
|
|
159
|
+
endpoint: str,
|
|
160
|
+
change_type: Literal["create", "update", "delete", "unchanged", "skip", "failed"],
|
|
161
|
+
severity: Literal["SAFE", "WARNING", "BREAKING"],
|
|
162
|
+
) -> None:
|
|
163
|
+
"""Update all statistics for a single change.
|
|
164
|
+
|
|
165
|
+
Args:
|
|
166
|
+
endpoint: The endpoint type (spaces, containers, views, datamodels).
|
|
167
|
+
change_type: The type of change (create, update, delete, skip, unchanged, failed).
|
|
168
|
+
severity: The severity level (SAFE, WARNING, BREAKING).
|
|
169
|
+
"""
|
|
170
|
+
# Update by change type statistics
|
|
171
|
+
self.by_change_type.increment(change_type)
|
|
172
|
+
|
|
173
|
+
# Update by endpoint statistics
|
|
174
|
+
if endpoint in self.by_endpoint:
|
|
175
|
+
self.by_endpoint[endpoint].increment(change_type)
|
|
176
|
+
else:
|
|
177
|
+
raise RuntimeError(f"Unknown endpoint: {endpoint}. This is a bug in NEAT.")
|
|
178
|
+
|
|
179
|
+
# Update severity statistics
|
|
180
|
+
self.by_severity.increment(severity)
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import uuid
|
|
2
|
+
from typing import Any
|
|
3
|
+
|
|
4
|
+
from cognite.neat._data_model.deployer.data_classes import DeploymentResult
|
|
5
|
+
|
|
6
|
+
from ._changes import SerializedChanges
|
|
7
|
+
from ._statistics import DeploymentStatistics
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def serialize_deployment_result(result: DeploymentResult) -> dict[str, Any]:
|
|
11
|
+
"""Serialize deployment result into structured changes.
|
|
12
|
+
|
|
13
|
+
Args:
|
|
14
|
+
result: The deployment result to serialize.
|
|
15
|
+
|
|
16
|
+
Returns:
|
|
17
|
+
Serialized changes representing the deployment result.
|
|
18
|
+
"""
|
|
19
|
+
result_dict = {"unique_id": uuid.uuid4().hex[:8], "status": result.status, "is_dry_run": result.is_dry_run}
|
|
20
|
+
|
|
21
|
+
stats = DeploymentStatistics.from_deployment_result(result)
|
|
22
|
+
changes = SerializedChanges.from_deployment_result(result)
|
|
23
|
+
|
|
24
|
+
result_dict["total_changes"] = stats.total_changes
|
|
25
|
+
result_dict["created"] = stats.by_change_type.create
|
|
26
|
+
result_dict["updated"] = stats.by_change_type.update
|
|
27
|
+
result_dict["deleted"] = stats.by_change_type.delete
|
|
28
|
+
result_dict["skipped"] = stats.by_change_type.skip
|
|
29
|
+
result_dict["unchanged"] = stats.by_change_type.unchanged
|
|
30
|
+
result_dict["failed"] = stats.by_change_type.failed
|
|
31
|
+
|
|
32
|
+
result_dict["STATS_JSON"] = stats.model_dump_json()
|
|
33
|
+
result_dict["CHANGES_JSON"] = changes.model_dump_json_flat()
|
|
34
|
+
|
|
35
|
+
return result_dict
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
from cognite.neat._data_model.deployer.data_classes import DeploymentResult
|
|
2
|
+
from cognite.neat._session._html._render import render
|
|
3
|
+
from cognite.neat._store import NeatStore
|
|
4
|
+
|
|
5
|
+
from ._deployment._physical.serializer import serialize_deployment_result
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Result:
|
|
9
|
+
"""Class to handle deployment results in the NeatSession."""
|
|
10
|
+
|
|
11
|
+
def __init__(self, store: NeatStore) -> None:
|
|
12
|
+
self._store = store
|
|
13
|
+
|
|
14
|
+
@property
|
|
15
|
+
def _result(self) -> DeploymentResult | None:
|
|
16
|
+
"""Get deployment result from the last change in the store."""
|
|
17
|
+
if change := self._store.provenance.last_change:
|
|
18
|
+
if change.result:
|
|
19
|
+
return change.result
|
|
20
|
+
return None
|
|
21
|
+
|
|
22
|
+
def _repr_html_(self) -> str:
|
|
23
|
+
"""Generate interactive HTML representation."""
|
|
24
|
+
if not self._result:
|
|
25
|
+
return "<p>No deployment result available</p>"
|
|
26
|
+
|
|
27
|
+
if isinstance(self._result, DeploymentResult):
|
|
28
|
+
serialized_result = serialize_deployment_result(self._result)
|
|
29
|
+
return render("deployment", serialized_result)
|
|
30
|
+
else:
|
|
31
|
+
raise NotImplementedError(f"HTML rendering for the result type {type(self._result)} is not implemented.")
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import json
|
|
2
|
+
|
|
3
|
+
from cognite.client import ClientConfig, CogniteClient
|
|
4
|
+
|
|
5
|
+
from cognite.neat import _version
|
|
6
|
+
from cognite.neat._client import NeatClient
|
|
7
|
+
from cognite.neat._config import NeatConfig, PredefinedProfile
|
|
8
|
+
from cognite.neat._session._usage_analytics._collector import Collector
|
|
9
|
+
from cognite.neat._state_machine import EmptyState, PhysicalState
|
|
10
|
+
from cognite.neat._store import NeatStore
|
|
11
|
+
from cognite.neat._utils.http_client import ParametersRequest, SuccessResponse
|
|
12
|
+
|
|
13
|
+
from ._issues import Issues
|
|
14
|
+
from ._physical import PhysicalDataModel
|
|
15
|
+
from ._result import Result
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class NeatSession:
|
|
19
|
+
"""A session is an interface for neat operations."""
|
|
20
|
+
|
|
21
|
+
def __init__(
|
|
22
|
+
self, client: CogniteClient | ClientConfig, config: PredefinedProfile | NeatConfig = "legacy-additive"
|
|
23
|
+
) -> None:
|
|
24
|
+
"""Initialize a Neat session.
|
|
25
|
+
|
|
26
|
+
Args:
|
|
27
|
+
client (CogniteClient | ClientConfig): The Cognite client or client configuration to use for the session.
|
|
28
|
+
config (Literal["legacy-additive", "legacy-rebuild", "deep-additive", "deep-rebuild"] | NeatConfig):
|
|
29
|
+
The configuration profile to use for the session.
|
|
30
|
+
Defaults to "legacy-additive". This means Neat will perform additive modeling
|
|
31
|
+
and apply only validations that were part of the legacy Neat version.
|
|
32
|
+
"""
|
|
33
|
+
self._config = NeatConfig.create_predefined(config) if isinstance(config, str) else config
|
|
34
|
+
|
|
35
|
+
# Use configuration for physical data model
|
|
36
|
+
self._client = NeatClient(client)
|
|
37
|
+
self._store = NeatStore(config=self._config, client=self._client)
|
|
38
|
+
self.physical_data_model = PhysicalDataModel(self._store, self._client, self._config)
|
|
39
|
+
self.issues = Issues(self._store)
|
|
40
|
+
self.result = Result(self._store)
|
|
41
|
+
|
|
42
|
+
collector = Collector()
|
|
43
|
+
if collector.can_collect:
|
|
44
|
+
collector.collect("initSession", {"mode": self._config.modeling.mode})
|
|
45
|
+
|
|
46
|
+
self._welcome_message()
|
|
47
|
+
|
|
48
|
+
def _welcome_message(self) -> None:
|
|
49
|
+
cdf_project = self._client.config.project
|
|
50
|
+
message = f"Neat session started for CDF project: '{cdf_project}'"
|
|
51
|
+
responses = self._client.http_client.request(
|
|
52
|
+
ParametersRequest(endpoint_url=self._client.config.create_api_url(""), method="GET")
|
|
53
|
+
)
|
|
54
|
+
if len(responses) == 1 and isinstance(response := responses[0], SuccessResponse):
|
|
55
|
+
organization = ""
|
|
56
|
+
try:
|
|
57
|
+
organization = json.loads(response.body)["organization"]
|
|
58
|
+
except (KeyError, ValueError):
|
|
59
|
+
...
|
|
60
|
+
if organization:
|
|
61
|
+
message += f" (Organization: '{organization}')"
|
|
62
|
+
|
|
63
|
+
print(message)
|
|
64
|
+
print(self._config)
|
|
65
|
+
|
|
66
|
+
@property
|
|
67
|
+
def version(self) -> str:
|
|
68
|
+
"""Get the current version of neat."""
|
|
69
|
+
return _version.__version__
|
|
70
|
+
|
|
71
|
+
def _repr_html_(self) -> str:
|
|
72
|
+
if isinstance(self._store.state, EmptyState):
|
|
73
|
+
return (
|
|
74
|
+
"<strong>Empty session</strong>. Get started by reading for example physical data model"
|
|
75
|
+
" <em>.physical_data_model.read</em>"
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
if isinstance(self._store.state, PhysicalState):
|
|
79
|
+
return self.physical_data_model._repr_html_()
|
|
80
|
+
|
|
81
|
+
raise RuntimeError("Unknown session state, contact support.")
|
|
File without changes
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import platform
|
|
3
|
+
import threading
|
|
4
|
+
import uuid
|
|
5
|
+
from contextlib import suppress
|
|
6
|
+
from typing import Any, Literal
|
|
7
|
+
|
|
8
|
+
from mixpanel import Consumer, Mixpanel # type: ignore[import-untyped]
|
|
9
|
+
|
|
10
|
+
from cognite.neat._session._usage_analytics._constants import IN_NOTEBOOK, IN_PYODIDE
|
|
11
|
+
from cognite.neat._session._usage_analytics._storage import ManualReadResult, ReadResult, get_storage
|
|
12
|
+
|
|
13
|
+
_NEAT_MIXPANEL_TOKEN: str = "bd630ad149d19999df3989c3a3750c4f"
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class Collector:
|
|
17
|
+
"""Collects usage data and sends it to Mixpanel."""
|
|
18
|
+
|
|
19
|
+
_instance: "Collector | None" = None
|
|
20
|
+
_initialized: bool = False
|
|
21
|
+
|
|
22
|
+
def __new__(cls, *args: Any, **kwargs: Any) -> "Collector":
|
|
23
|
+
# Implementing Singleton pattern
|
|
24
|
+
if cls._instance is None:
|
|
25
|
+
cls._instance = super().__new__(cls)
|
|
26
|
+
return cls._instance
|
|
27
|
+
|
|
28
|
+
def __init__(self, skip_tracking: bool = False) -> None:
|
|
29
|
+
if self._initialized:
|
|
30
|
+
return
|
|
31
|
+
self.mp = Mixpanel(_NEAT_MIXPANEL_TOKEN, consumer=Consumer(api_host="api-eu.mixpanel.com"))
|
|
32
|
+
self._storage = get_storage()
|
|
33
|
+
self._opt_status_key = "neat-opt-status"
|
|
34
|
+
self._distinct_id_key = "neat-distinct-id"
|
|
35
|
+
self.skip_tracking = skip_tracking
|
|
36
|
+
self._initialized = True
|
|
37
|
+
# We trigger these reads immediately to have them ready when needed.
|
|
38
|
+
# This is necessary in a Pyodide environment were the read will not be available
|
|
39
|
+
self._opt_status_read: ReadResult | None = self._storage.read(self._opt_status_key)
|
|
40
|
+
self._distinct_id_read: ReadResult | None = self._storage.read(self._distinct_id_key)
|
|
41
|
+
|
|
42
|
+
@property
|
|
43
|
+
def _opt_status(self) -> str:
|
|
44
|
+
if self._opt_status_read is None:
|
|
45
|
+
self._opt_status_read = self._storage.read(self._opt_status_key)
|
|
46
|
+
if self._opt_status_read.is_ready:
|
|
47
|
+
return self._opt_status_read.get_data()
|
|
48
|
+
return "" # We do not have an opt status yet.
|
|
49
|
+
|
|
50
|
+
@property
|
|
51
|
+
def _distinct_id(self) -> str | None:
|
|
52
|
+
if self._distinct_id_read is None:
|
|
53
|
+
self._distinct_id_read = self._storage.read(self._distinct_id_key)
|
|
54
|
+
if self._distinct_id_read.is_ready:
|
|
55
|
+
return self._distinct_id_read.get_data()
|
|
56
|
+
return None
|
|
57
|
+
|
|
58
|
+
def bust_opt_status(self) -> None:
|
|
59
|
+
self._storage.delete(self._opt_status_key)
|
|
60
|
+
self._opt_status_read = None
|
|
61
|
+
|
|
62
|
+
@property
|
|
63
|
+
def is_opted_out(self) -> bool:
|
|
64
|
+
return False
|
|
65
|
+
|
|
66
|
+
@property
|
|
67
|
+
def is_opted_in(self) -> bool:
|
|
68
|
+
return True
|
|
69
|
+
|
|
70
|
+
def enable(self) -> None:
|
|
71
|
+
self._storage.write(self._opt_status_key, "opted-in")
|
|
72
|
+
# Override cached property
|
|
73
|
+
self._opt_status_read = ManualReadResult("opted-in")
|
|
74
|
+
|
|
75
|
+
def disable(self) -> None:
|
|
76
|
+
self._storage.write(self._opt_status_key, "opted-out")
|
|
77
|
+
# Override cached property
|
|
78
|
+
self._opt_status_read = ManualReadResult("opted-out")
|
|
79
|
+
|
|
80
|
+
def get_distinct_id(self) -> str:
|
|
81
|
+
existing_id = self._distinct_id
|
|
82
|
+
if existing_id:
|
|
83
|
+
return existing_id
|
|
84
|
+
|
|
85
|
+
distinct_id = f"{platform.system()}-{platform.python_version()}-{uuid.uuid4()!s}"
|
|
86
|
+
self._storage.write(self._distinct_id_key, distinct_id)
|
|
87
|
+
with suppress(ConnectionError):
|
|
88
|
+
self.mp.people_set(
|
|
89
|
+
distinct_id,
|
|
90
|
+
{
|
|
91
|
+
"$os": platform.system(),
|
|
92
|
+
"$python_version": platform.python_version(),
|
|
93
|
+
"$distinct_id": distinct_id,
|
|
94
|
+
"environment": self._get_environment(),
|
|
95
|
+
},
|
|
96
|
+
)
|
|
97
|
+
self._distinct_id_read = ManualReadResult(distinct_id)
|
|
98
|
+
return distinct_id
|
|
99
|
+
|
|
100
|
+
@staticmethod
|
|
101
|
+
def _get_environment() -> Literal["pyodide", "notebook", "python"]:
|
|
102
|
+
"""Get the current environment the user is running in."""
|
|
103
|
+
if IN_PYODIDE:
|
|
104
|
+
return "pyodide"
|
|
105
|
+
if IN_NOTEBOOK:
|
|
106
|
+
return "notebook"
|
|
107
|
+
return "python"
|
|
108
|
+
|
|
109
|
+
@property
|
|
110
|
+
def can_collect(self) -> bool:
|
|
111
|
+
"""Check if tracking is possible."""
|
|
112
|
+
return not self.skip_tracking and self.is_opted_in and "PYTEST_CURRENT_TEST" not in os.environ
|
|
113
|
+
|
|
114
|
+
def collect(
|
|
115
|
+
self, event_name: Literal["action", "initSession", "deployment"], event_properties: dict[str, Any]
|
|
116
|
+
) -> None:
|
|
117
|
+
distinct_id = self.get_distinct_id()
|
|
118
|
+
|
|
119
|
+
def track() -> None:
|
|
120
|
+
# If we are unable to connect to Mixpanel, we don't want to crash the program
|
|
121
|
+
with suppress(ConnectionError):
|
|
122
|
+
self.mp.track(distinct_id, event_name, event_properties)
|
|
123
|
+
|
|
124
|
+
if IN_PYODIDE:
|
|
125
|
+
# We cannot spawn threads in Pyodide
|
|
126
|
+
track()
|
|
127
|
+
return None
|
|
128
|
+
|
|
129
|
+
thread = threading.Thread(target=track, daemon=True)
|
|
130
|
+
thread.start()
|
|
131
|
+
return None
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
def _is_in_notebook() -> bool:
|
|
2
|
+
try:
|
|
3
|
+
from IPython import get_ipython
|
|
4
|
+
|
|
5
|
+
if "IPKernelApp" not in get_ipython().config: # pragma: no cover
|
|
6
|
+
return False
|
|
7
|
+
except ImportError:
|
|
8
|
+
return False
|
|
9
|
+
except AttributeError:
|
|
10
|
+
return False
|
|
11
|
+
return True
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def _is_in_browser() -> bool:
|
|
15
|
+
try:
|
|
16
|
+
from pyodide.ffi import IN_BROWSER # type: ignore [import-not-found]
|
|
17
|
+
except ModuleNotFoundError:
|
|
18
|
+
return False
|
|
19
|
+
return IN_BROWSER
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
IN_PYODIDE = _is_in_browser()
|
|
23
|
+
IN_NOTEBOOK = _is_in_notebook() or IN_PYODIDE
|