cimprofiles 0.1.0a2__tar.gz

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.
Files changed (78) hide show
  1. cimprofiles-0.1.0a2/.gitignore +69 -0
  2. cimprofiles-0.1.0a2/CIMTool_plugin/LICENSE +29 -0
  3. cimprofiles-0.1.0a2/LICENSE +29 -0
  4. cimprofiles-0.1.0a2/PKG-INFO +128 -0
  5. cimprofiles-0.1.0a2/README.md +105 -0
  6. cimprofiles-0.1.0a2/pyproject.toml +57 -0
  7. cimprofiles-0.1.0a2/src/cimprofiles/README.md +291 -0
  8. cimprofiles-0.1.0a2/src/cimprofiles/__init__.py +36 -0
  9. cimprofiles-0.1.0a2/src/cimprofiles/build_merged_profiles.py +261 -0
  10. cimprofiles-0.1.0a2/src/cimprofiles/cim16/cim16v33/__init__.py +789 -0
  11. cimprofiles-0.1.0a2/src/cimprofiles/cim16/cim16v33/cim16v33.py +39396 -0
  12. cimprofiles-0.1.0a2/src/cimprofiles/cim16/cim16v33/cim16v33.rdfs-t2b.md +26221 -0
  13. cimprofiles-0.1.0a2/src/cimprofiles/cim17/cgmes_3_0_0/__init__.py +2696 -0
  14. cimprofiles-0.1.0a2/src/cimprofiles/cim17/cgmes_3_0_0/core_equipment/__init__.py +250 -0
  15. cimprofiles-0.1.0a2/src/cimprofiles/cim17/cgmes_3_0_0/core_equipment/core_equipment.py +12615 -0
  16. cimprofiles-0.1.0a2/src/cimprofiles/cim17/cgmes_3_0_0/diagram/__init__.py +29 -0
  17. cimprofiles-0.1.0a2/src/cimprofiles/cim17/cgmes_3_0_0/diagram/diagram_layout.py +815 -0
  18. cimprofiles-0.1.0a2/src/cimprofiles/cim17/cgmes_3_0_0/dynamics/__init__.py +9 -0
  19. cimprofiles-0.1.0a2/src/cimprofiles/cim17/cgmes_3_0_0/dynamics/dynamics.py +18 -0
  20. cimprofiles-0.1.0a2/src/cimprofiles/cim17/cgmes_3_0_0/equipment_boundary/__init__.py +34 -0
  21. cimprofiles-0.1.0a2/src/cimprofiles/cim17/cgmes_3_0_0/equipment_boundary/equipment_boundary.py +1088 -0
  22. cimprofiles-0.1.0a2/src/cimprofiles/cim17/cgmes_3_0_0/geographical_location/__init__.py +22 -0
  23. cimprofiles-0.1.0a2/src/cimprofiles/cim17/cgmes_3_0_0/geographical_location/geographical_location.py +824 -0
  24. cimprofiles-0.1.0a2/src/cimprofiles/cim17/cgmes_3_0_0/operation/__init__.py +67 -0
  25. cimprofiles-0.1.0a2/src/cimprofiles/cim17/cgmes_3_0_0/operation/operation.py +2447 -0
  26. cimprofiles-0.1.0a2/src/cimprofiles/cim17/cgmes_3_0_0/short_circuit/__init__.py +65 -0
  27. cimprofiles-0.1.0a2/src/cimprofiles/cim17/cgmes_3_0_0/short_circuit/short_circuit.py +3769 -0
  28. cimprofiles-0.1.0a2/src/cimprofiles/cim17/cgmes_3_0_0/state_variables/__init__.py +42 -0
  29. cimprofiles-0.1.0a2/src/cimprofiles/cim17/cgmes_3_0_0/state_variables/state_variables.py +2286 -0
  30. cimprofiles-0.1.0a2/src/cimprofiles/cim17/cgmes_3_0_0/steady_state_hypothesis/__init__.py +111 -0
  31. cimprofiles-0.1.0a2/src/cimprofiles/cim17/cgmes_3_0_0/steady_state_hypothesis/steady_state_hypothesis.py +4112 -0
  32. cimprofiles-0.1.0a2/src/cimprofiles/cim17/cgmes_3_0_0/topology/__init__.py +32 -0
  33. cimprofiles-0.1.0a2/src/cimprofiles/cim17/cgmes_3_0_0/topology/topology.py +712 -0
  34. cimprofiles-0.1.0a2/src/cimprofiles/cim17/cim17v40/__init__.py +1719 -0
  35. cimprofiles-0.1.0a2/src/cimprofiles/cim17/cim17v40/cim17v40.py +177479 -0
  36. cimprofiles-0.1.0a2/src/cimprofiles/cim17/cimhub_2023/__init__.py +621 -0
  37. cimprofiles-0.1.0a2/src/cimprofiles/cim17/cimhub_2023/cimhub_2023.py +28616 -0
  38. cimprofiles-0.1.0a2/src/cimprofiles/cim17/cimhub_2023/cimhub_2023.rdfs-t2b.md +18888 -0
  39. cimprofiles-0.1.0a2/src/cimprofiles/cim17/gridappsd_rc4_2021/__init__.py +831 -0
  40. cimprofiles-0.1.0a2/src/cimprofiles/cim17/gridappsd_rc4_2021/rc4_2021.py +49017 -0
  41. cimprofiles-0.1.0a2/src/cimprofiles/cim18/cim18gad/__init__.py +2054 -0
  42. cimprofiles-0.1.0a2/src/cimprofiles/cim18/cim18gad/cim18v15.py +198592 -0
  43. cimprofiles-0.1.0a2/src/cimprofiles/cim18/cim18gmdm/__init__.py +1133 -0
  44. cimprofiles-0.1.0a2/src/cimprofiles/cim18/cim18gmdm/asset/Asset.rdfs-t2b.md +781 -0
  45. cimprofiles-0.1.0a2/src/cimprofiles/cim18/cim18gmdm/asset/__init__.py +41 -0
  46. cimprofiles-0.1.0a2/src/cimprofiles/cim18/cim18gmdm/asset/asset.py +1427 -0
  47. cimprofiles-0.1.0a2/src/cimprofiles/cim18/cim18gmdm/canonical/__init__.py +928 -0
  48. cimprofiles-0.1.0a2/src/cimprofiles/cim18/cim18gmdm/canonical/canonical.py +65313 -0
  49. cimprofiles-0.1.0a2/src/cimprofiles/cim18/cim18gmdm/connectivity/UnbalancedConnectivity.rdfs-t2b.md +2541 -0
  50. cimprofiles-0.1.0a2/src/cimprofiles/cim18/cim18gmdm/connectivity/__init__.py +76 -0
  51. cimprofiles-0.1.0a2/src/cimprofiles/cim18/cim18gmdm/connectivity/connectivity.py +2791 -0
  52. cimprofiles-0.1.0a2/src/cimprofiles/cim18/cim18gmdm/diagram/__init__.py +26 -0
  53. cimprofiles-0.1.0a2/src/cimprofiles/cim18/cim18gmdm/diagram/diagram.py +758 -0
  54. cimprofiles-0.1.0a2/src/cimprofiles/cim18/cim18gmdm/electrical/UnbalancedElectrical.rdfs-t2b.md +3044 -0
  55. cimprofiles-0.1.0a2/src/cimprofiles/cim18/cim18gmdm/electrical/__init__.py +140 -0
  56. cimprofiles-0.1.0a2/src/cimprofiles/cim18/cim18gmdm/electrical/electrical.py +4107 -0
  57. cimprofiles-0.1.0a2/src/cimprofiles/cim18/cim18gmdm/location/GeographicalLocation.rdfs-t2b.md +969 -0
  58. cimprofiles-0.1.0a2/src/cimprofiles/cim18/cim18gmdm/location/__init__.py +69 -0
  59. cimprofiles-0.1.0a2/src/cimprofiles/cim18/cim18gmdm/location/location.py +1103 -0
  60. cimprofiles-0.1.0a2/src/cimprofiles/cim18/cim18gmdm/marketnode/__init__.py +15 -0
  61. cimprofiles-0.1.0a2/src/cimprofiles/cim18/cim18gmdm/marketnode/marketnode.py +180 -0
  62. cimprofiles-0.1.0a2/src/cimprofiles/cim18/cimhub_2026/__init__.py +550 -0
  63. cimprofiles-0.1.0a2/src/cimprofiles/cim18/cimhub_2026/cimhub_2026.py +33382 -0
  64. cimprofiles-0.1.0a2/src/cimprofiles/dedupe_profile_fields.py +150 -0
  65. cimprofiles-0.1.0a2/src/cimprofiles/env_vars.py +48 -0
  66. cimprofiles-0.1.0a2/src/cimprofiles/identity.py +453 -0
  67. cimprofiles-0.1.0a2/src/cimprofiles/merge.py +472 -0
  68. cimprofiles-0.1.0a2/src/cimprofiles/merge_releases.yaml +33 -0
  69. cimprofiles-0.1.0a2/src/cimprofiles/units/__init__.py +2 -0
  70. cimprofiles-0.1.0a2/src/cimprofiles/units/cim_units/__init__.py +2 -0
  71. cimprofiles-0.1.0a2/src/cimprofiles/units/cim_units/unit_multiplier.py +113 -0
  72. cimprofiles-0.1.0a2/src/cimprofiles/units/cim_units/unit_symbol.py +660 -0
  73. cimprofiles-0.1.0a2/src/cimprofiles/units/cim_units/units.txt +95 -0
  74. cimprofiles-0.1.0a2/src/cimprofiles/units/units.py +67 -0
  75. cimprofiles-0.1.0a2/tests/test_cim_profile.py +30 -0
  76. cimprofiles-0.1.0a2/tests/test_merge_profiles.py +281 -0
  77. cimprofiles-0.1.0a2/tests/test_profile_fields.py +32 -0
  78. cimprofiles-0.1.0a2/tests/test_uuid.py +345 -0
@@ -0,0 +1,69 @@
1
+ .vscode/*
2
+ .metadata/*
3
+ # Compiled class file
4
+ *.class
5
+
6
+ # Log file
7
+ *.log
8
+
9
+ # BlueJ files
10
+ *.ctxt
11
+
12
+ # Mobile Tools for Java (J2ME)
13
+ .mtj.tmp/
14
+
15
+ # Package Files #
16
+ *.jar
17
+ *.war
18
+ *.nar
19
+ *.ear
20
+ *.zip
21
+ *.tar.gz
22
+ *.rar
23
+
24
+ # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
25
+ hs_err_pid*
26
+ replay_pid*
27
+
28
+ # Python bytecode and extensions
29
+ __pycache__/
30
+ *.py[cod]
31
+ *$py.class
32
+ *.so
33
+
34
+ # Python packaging and build output
35
+ build/
36
+ dist/
37
+ *.egg-info/
38
+ *.egg
39
+ .eggs/
40
+ wheels/
41
+ sdist/
42
+
43
+ # Virtual environments
44
+ .venv/
45
+ venv/
46
+ env/
47
+ .python-version
48
+
49
+ # Test, coverage and type-checker caches
50
+ .pytest_cache/
51
+ .coverage
52
+ .coverage.*
53
+ htmlcov/
54
+ coverage.xml
55
+ .tox/
56
+ .nox/
57
+ .mypy_cache/
58
+ .ruff_cache/
59
+ .pyright/
60
+ .hypothesis/
61
+
62
+ # Jupyter
63
+ .ipynb_checkpoints/
64
+
65
+ # Documentation site build (mkdocs)
66
+ site/
67
+
68
+ # Local environment files
69
+ .env
@@ -0,0 +1,29 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2024, Battelle Memorial Institute; All rights reserved.
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
7
+
8
+ 1. Redistributions of source code must retain the above copyright notice,
9
+ this list of conditions and the following disclaimer.
10
+
11
+ 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ this list of conditions and the following disclaimer in the documentation
13
+ and/or other materials provided with the distribution.
14
+
15
+ 3. Neither the name of the copyright holder nor the names of its contributors
16
+ may be used to endorse or promote products derived from this software without
17
+ specific prior written permission.
18
+
19
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
29
+ THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,29 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2024, Battelle Memorial Institute; All rights reserved.
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
7
+
8
+ 1. Redistributions of source code must retain the above copyright notice,
9
+ this list of conditions and the following disclaimer.
10
+
11
+ 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ this list of conditions and the following disclaimer in the documentation
13
+ and/or other materials provided with the distribution.
14
+
15
+ 3. Neither the name of the copyright holder nor the names of its contributors
16
+ may be used to endorse or promote products derived from this software without
17
+ specific prior written permission.
18
+
19
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
29
+ THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,128 @@
1
+ Metadata-Version: 2.5
2
+ Name: cimprofiles
3
+ Version: 0.1.0a2
4
+ Summary: CIM data profiles (Python dataclasses) and the Identity/units object model used by CIMantic Graphs
5
+ Project-URL: Homepage, https://github.com/PNNL-CIM-Tools/CIM-Profiles
6
+ Project-URL: Repository, https://github.com/PNNL-CIM-Tools/CIM-Profiles
7
+ Project-URL: Issues, https://github.com/PNNL-CIM-Tools/CIM-Profiles/issues
8
+ Author-email: "A. Anderson" <19935503+AAndersn@users.noreply.github.com>, "C. Allwardt" <3979063+craig8@users.noreply.github.com>
9
+ License-Expression: BSD-3-Clause
10
+ License-File: LICENSE
11
+ Keywords: cgmes,cim,iec-61968,iec-61970,power-systems
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Intended Audience :: Science/Research
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Requires-Python: <4.0,>=3.10
21
+ Requires-Dist: pint>=0.24.4
22
+ Description-Content-Type: text/markdown
23
+
24
+ # CIM-Profiles
25
+
26
+ CIMTool workspaces for the CIM 16–18 profiles, and the `cimprofiles` Python package built from
27
+ them. These files originally shipped as part of cim-graph 0.1.x through 0.5.x.
28
+
29
+ `cimprofiles` ships the CIM profiles as Python dataclasses, together with the object model they
30
+ are built on (`Identity`, `CIMUnit`, profile merging). It depends only on `pint`, and it is
31
+ released separately from [cim-graph](https://github.com/PNNL-CIM-Tools/CIM-Graph). Profile updates
32
+ (new classes from EA tickets, new profiles) therefore don't wait for a cim-graph release.
33
+
34
+ ```bash
35
+ pip install cimprofiles
36
+ ```
37
+
38
+ ```python
39
+ import cimprofiles.cim18.cimhub_2026 as cim
40
+
41
+ line = cim.ACLineSegment(name='line_1')
42
+ ```
43
+
44
+ cim-graph 0.6 and later depend on `cimprofiles`. The old `cimgraph.data_profile.*` import paths
45
+ still work there, with a `DeprecationWarning`.
46
+
47
+ ## Repository layout
48
+
49
+ | Path | Contents |
50
+ |---|---|
51
+ | `cim17v40/`, `cim18v15/` | CIMTool workspaces. The Sparx EA `.eap` models are stored with Git LFS. |
52
+ | `CIMTool_plugin/` | The cimantic-graphs XSLT builders and their documentation |
53
+ | `src/cimprofiles/` | The Python package, with profiles grouped by CIM version (`cim16/`, `cim17/`, `cim18/`). See [`src/cimprofiles/README.md`](src/cimprofiles/README.md) for the available profiles and how merging works. |
54
+ | `scripts/import_cimtool_output.sh` | Copies a profile generated by CIMTool into `src/cimprofiles/` and rewrites its imports |
55
+ | `tests/` | Tests for `Identity`, UUIDs, merging and the generated profiles |
56
+
57
+ ## Seeded UUIDs
58
+
59
+ Deterministic identifiers are what downstream converters (ArcGIS, OpenDSS, ...) rely on to give
60
+ the same equipment the same RDF ID on every run. `Identity.identifier` is a UUID (CIM 18):
61
+ either the one given, or a deterministic construct. There are two cases.
62
+
63
+ **Read from a file:** the `rdf:ID`/`rdf:about` *is* the UUID, in any serialization
64
+ (`urn:uuid:…`, `#_…`, `_…`, any case). The name is not used. An identifier that is not a UUID is
65
+ replaced, with a warning, by the UUID seeded from it (below), so reading the same file again
66
+ gives the same UUIDs. The original string is kept as the mRID, unless the file has an mRID.
67
+ Readers key their graphs with `cimprofiles.identity.read_identifier`, which gives the same UUID.
68
+
69
+ **Built** (converters, notebooks): a new object, deterministic only for the same model
70
+ authority, model, class, mRID and name. A renamed object (bus 300 to bus 301) is a different
71
+ object and gets a different UUID. A UUID given as the mRID is used directly.
72
+
73
+ The seeded UUID is version 5 (RFC 9562 §5.5):
74
+
75
+ ```python
76
+ namespace = uuid5(NAMESPACE_URL, model_authority)
77
+ uuid = uuid5(namespace, f'{model_name}+{ClassName}+{mRID}+{name}+{seed}')
78
+ ```
79
+
80
+ - `model_authority` is a URI (`CIMG_MODEL_AUTHORITY`, default
81
+ `https://github.com/PNNL-CIM-Tools/CIM-Graph`), as in `md:Model.modelingAuthoritySet`. The
82
+ namespace is also the identifier of the `cim:ModelAuthority` object cim-graph writes in file
83
+ headers, so each authority's UUIDs live in its own namespace.
84
+ - `model_name` comes from `CIMG_MODEL_NAME` (default empty).
85
+ - `mRID` is the object's mRID, or the non-UUID `rdf:ID`/`rdf:about` of an object read from a
86
+ file. It is normalized so every serialization of one object agrees: surrounding whitespace, a
87
+ `urn:uuid:` prefix, everything up to the last `#` and one leading `_` are removed.
88
+ `rdf:ID="_LINE1"`, `rdf:about="#_LINE1"` and `mRID="LINE1"` give the same UUID. Case is kept.
89
+ - `name` (whitespace-trimmed) and `seed` (passed to `obj.uuid(seed=...)`) are optional.
90
+ - Every component keeps its position even when empty, and `%` and `+` inside a component are
91
+ escaped as `%25` and `%2B`, so two different inputs never produce the same string.
92
+ - No identifying input at all (or only empty/blank values) gives a random version 4 UUID.
93
+
94
+ `obj.uri()` returns the bare UUID: lowercase, or uppercase if it was read uppercase (CIMHub and
95
+ GridAPPS-D data), so writing a file back reproduces its identifiers. Underscores and
96
+ `urn:uuid:` prefixes belong to the serialization style and are added by cim-graph's writers
97
+ and queries (`CIMG_IEC61970_552`: `552-NEW`, `552-LEGACY` or `CGMES`).
98
+
99
+ `cimprofiles.identity.seeded_uuid` and `model_authority_namespace` implement the seeded UUID, and any
100
+ language with a UUID library can reproduce it from this description.
101
+
102
+ ## Updating a profile
103
+
104
+ 1. Regenerate it in CIMTool with the cimantic-graphs builders (`CIMTool_plugin/builder.md`).
105
+ 2. Import it. This rewrites the `cimgraph.data_profile` imports emitted by CIMTool before 2.3.1:
106
+ ```bash
107
+ scripts/import_cimtool_output.sh cim17 <Profiles/name.py> <Profiles/name.__init__.py>
108
+ ```
109
+ The first argument is the CIM version directory. A fourth argument names the package
110
+ directory when it differs from the envelope name (`gridappsd_rc4_2021` for `rc4_2021`).
111
+ 3. Check for duplicate field definitions, and rebuild the pre-baked merged profiles if it is one
112
+ of their parts:
113
+ ```bash
114
+ uv run python -m cimprofiles.dedupe_profile_fields --check
115
+ uv run python -m cimprofiles.build_merged_profiles
116
+ ```
117
+ 4. Run the tests: `uv run pytest`.
118
+
119
+ ## Development
120
+
121
+ ```bash
122
+ uv sync
123
+ uv run pytest
124
+ ```
125
+
126
+ ## License
127
+
128
+ BSD 3-Clause. See [LICENSE](LICENSE).
@@ -0,0 +1,105 @@
1
+ # CIM-Profiles
2
+
3
+ CIMTool workspaces for the CIM 16–18 profiles, and the `cimprofiles` Python package built from
4
+ them. These files originally shipped as part of cim-graph 0.1.x through 0.5.x.
5
+
6
+ `cimprofiles` ships the CIM profiles as Python dataclasses, together with the object model they
7
+ are built on (`Identity`, `CIMUnit`, profile merging). It depends only on `pint`, and it is
8
+ released separately from [cim-graph](https://github.com/PNNL-CIM-Tools/CIM-Graph). Profile updates
9
+ (new classes from EA tickets, new profiles) therefore don't wait for a cim-graph release.
10
+
11
+ ```bash
12
+ pip install cimprofiles
13
+ ```
14
+
15
+ ```python
16
+ import cimprofiles.cim18.cimhub_2026 as cim
17
+
18
+ line = cim.ACLineSegment(name='line_1')
19
+ ```
20
+
21
+ cim-graph 0.6 and later depend on `cimprofiles`. The old `cimgraph.data_profile.*` import paths
22
+ still work there, with a `DeprecationWarning`.
23
+
24
+ ## Repository layout
25
+
26
+ | Path | Contents |
27
+ |---|---|
28
+ | `cim17v40/`, `cim18v15/` | CIMTool workspaces. The Sparx EA `.eap` models are stored with Git LFS. |
29
+ | `CIMTool_plugin/` | The cimantic-graphs XSLT builders and their documentation |
30
+ | `src/cimprofiles/` | The Python package, with profiles grouped by CIM version (`cim16/`, `cim17/`, `cim18/`). See [`src/cimprofiles/README.md`](src/cimprofiles/README.md) for the available profiles and how merging works. |
31
+ | `scripts/import_cimtool_output.sh` | Copies a profile generated by CIMTool into `src/cimprofiles/` and rewrites its imports |
32
+ | `tests/` | Tests for `Identity`, UUIDs, merging and the generated profiles |
33
+
34
+ ## Seeded UUIDs
35
+
36
+ Deterministic identifiers are what downstream converters (ArcGIS, OpenDSS, ...) rely on to give
37
+ the same equipment the same RDF ID on every run. `Identity.identifier` is a UUID (CIM 18):
38
+ either the one given, or a deterministic construct. There are two cases.
39
+
40
+ **Read from a file:** the `rdf:ID`/`rdf:about` *is* the UUID, in any serialization
41
+ (`urn:uuid:…`, `#_…`, `_…`, any case). The name is not used. An identifier that is not a UUID is
42
+ replaced, with a warning, by the UUID seeded from it (below), so reading the same file again
43
+ gives the same UUIDs. The original string is kept as the mRID, unless the file has an mRID.
44
+ Readers key their graphs with `cimprofiles.identity.read_identifier`, which gives the same UUID.
45
+
46
+ **Built** (converters, notebooks): a new object, deterministic only for the same model
47
+ authority, model, class, mRID and name. A renamed object (bus 300 to bus 301) is a different
48
+ object and gets a different UUID. A UUID given as the mRID is used directly.
49
+
50
+ The seeded UUID is version 5 (RFC 9562 §5.5):
51
+
52
+ ```python
53
+ namespace = uuid5(NAMESPACE_URL, model_authority)
54
+ uuid = uuid5(namespace, f'{model_name}+{ClassName}+{mRID}+{name}+{seed}')
55
+ ```
56
+
57
+ - `model_authority` is a URI (`CIMG_MODEL_AUTHORITY`, default
58
+ `https://github.com/PNNL-CIM-Tools/CIM-Graph`), as in `md:Model.modelingAuthoritySet`. The
59
+ namespace is also the identifier of the `cim:ModelAuthority` object cim-graph writes in file
60
+ headers, so each authority's UUIDs live in its own namespace.
61
+ - `model_name` comes from `CIMG_MODEL_NAME` (default empty).
62
+ - `mRID` is the object's mRID, or the non-UUID `rdf:ID`/`rdf:about` of an object read from a
63
+ file. It is normalized so every serialization of one object agrees: surrounding whitespace, a
64
+ `urn:uuid:` prefix, everything up to the last `#` and one leading `_` are removed.
65
+ `rdf:ID="_LINE1"`, `rdf:about="#_LINE1"` and `mRID="LINE1"` give the same UUID. Case is kept.
66
+ - `name` (whitespace-trimmed) and `seed` (passed to `obj.uuid(seed=...)`) are optional.
67
+ - Every component keeps its position even when empty, and `%` and `+` inside a component are
68
+ escaped as `%25` and `%2B`, so two different inputs never produce the same string.
69
+ - No identifying input at all (or only empty/blank values) gives a random version 4 UUID.
70
+
71
+ `obj.uri()` returns the bare UUID: lowercase, or uppercase if it was read uppercase (CIMHub and
72
+ GridAPPS-D data), so writing a file back reproduces its identifiers. Underscores and
73
+ `urn:uuid:` prefixes belong to the serialization style and are added by cim-graph's writers
74
+ and queries (`CIMG_IEC61970_552`: `552-NEW`, `552-LEGACY` or `CGMES`).
75
+
76
+ `cimprofiles.identity.seeded_uuid` and `model_authority_namespace` implement the seeded UUID, and any
77
+ language with a UUID library can reproduce it from this description.
78
+
79
+ ## Updating a profile
80
+
81
+ 1. Regenerate it in CIMTool with the cimantic-graphs builders (`CIMTool_plugin/builder.md`).
82
+ 2. Import it. This rewrites the `cimgraph.data_profile` imports emitted by CIMTool before 2.3.1:
83
+ ```bash
84
+ scripts/import_cimtool_output.sh cim17 <Profiles/name.py> <Profiles/name.__init__.py>
85
+ ```
86
+ The first argument is the CIM version directory. A fourth argument names the package
87
+ directory when it differs from the envelope name (`gridappsd_rc4_2021` for `rc4_2021`).
88
+ 3. Check for duplicate field definitions, and rebuild the pre-baked merged profiles if it is one
89
+ of their parts:
90
+ ```bash
91
+ uv run python -m cimprofiles.dedupe_profile_fields --check
92
+ uv run python -m cimprofiles.build_merged_profiles
93
+ ```
94
+ 4. Run the tests: `uv run pytest`.
95
+
96
+ ## Development
97
+
98
+ ```bash
99
+ uv sync
100
+ uv run pytest
101
+ ```
102
+
103
+ ## License
104
+
105
+ BSD 3-Clause. See [LICENSE](LICENSE).
@@ -0,0 +1,57 @@
1
+ [project]
2
+ name = "cimprofiles"
3
+ version = "0.1.0a2"
4
+ description = "CIM data profiles (Python dataclasses) and the Identity/units object model used by CIMantic Graphs"
5
+ authors = [
6
+ {name = "A. Anderson", email = "19935503+AAndersn@users.noreply.github.com"},
7
+ {name = "C. Allwardt", email = "3979063+craig8@users.noreply.github.com"}
8
+ ]
9
+ readme = "README.md"
10
+ requires-python = ">=3.10,<4.0"
11
+ license = "BSD-3-Clause"
12
+ license-files = ["LICENSE"]
13
+ keywords = ["cim", "power-systems", "iec-61970", "iec-61968", "cgmes"]
14
+ classifiers = [
15
+ "Development Status :: 3 - Alpha",
16
+ "Intended Audience :: Developers",
17
+ "Intended Audience :: Science/Research",
18
+ "Programming Language :: Python :: 3",
19
+ "Programming Language :: Python :: 3.10",
20
+ "Programming Language :: Python :: 3.11",
21
+ "Programming Language :: Python :: 3.12",
22
+ "Programming Language :: Python :: 3.13",
23
+ ]
24
+
25
+ dependencies = [
26
+ "pint>=0.24.4",
27
+ ]
28
+
29
+ [dependency-groups]
30
+ dev = [
31
+ "pytest>=8.3.5",
32
+ # build_merged_profiles reads merge_releases.yaml
33
+ "pyyaml>=6.0",
34
+ ]
35
+
36
+ [project.urls]
37
+ Homepage = "https://github.com/PNNL-CIM-Tools/CIM-Profiles"
38
+ Repository = "https://github.com/PNNL-CIM-Tools/CIM-Profiles"
39
+ Issues = "https://github.com/PNNL-CIM-Tools/CIM-Profiles/issues"
40
+
41
+ [build-system]
42
+ requires = ["hatchling>=1.27"]
43
+ build-backend = "hatchling.build"
44
+
45
+ [tool.hatch.build.targets.wheel]
46
+ packages = ["src/cimprofiles"]
47
+
48
+ [tool.hatch.build.targets.sdist]
49
+ include = [
50
+ "/src/cimprofiles",
51
+ "/tests",
52
+ "README.md",
53
+ "LICENSE",
54
+ ]
55
+
56
+ [tool.pytest.ini_options]
57
+ testpaths = ["tests"]