commonlib-reader 1.2.0__tar.gz → 1.3.0__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.
- commonlib_reader-1.3.0/PKG-INFO +85 -0
- commonlib_reader-1.3.0/README.md +72 -0
- commonlib_reader-1.3.0/pyproject.toml +31 -0
- commonlib_reader-1.2.0/pyproject.toml → commonlib_reader-1.3.0/pyproject.toml.orig +2 -2
- {commonlib_reader-1.2.0 → commonlib_reader-1.3.0}/src/commonlib_reader/__init__.py +7 -10
- commonlib_reader-1.3.0/src/commonlib_reader/code.py +170 -0
- {commonlib_reader-1.2.0 → commonlib_reader-1.3.0}/src/commonlib_reader/connector.py +1 -1
- {commonlib_reader-1.2.0 → commonlib_reader-1.3.0}/src/commonlib_reader/discipline.py +2 -2
- {commonlib_reader-1.2.0 → commonlib_reader-1.3.0}/src/commonlib_reader/facility.py +26 -5
- {commonlib_reader-1.2.0 → commonlib_reader-1.3.0}/src/commonlib_reader/ims.py +32 -24
- commonlib_reader-1.3.0/src/commonlib_reader/library.py +174 -0
- commonlib_reader-1.3.0/src/commonlib_reader/project.py +74 -0
- {commonlib_reader-1.2.0 → commonlib_reader-1.3.0}/src/commonlib_reader/tag.py +94 -42
- {commonlib_reader-1.2.0 → commonlib_reader-1.3.0}/src/commonlib_reader/unit.py +30 -14
- {commonlib_reader-1.2.0 → commonlib_reader-1.3.0}/src/commonlib_reader/utils.py +1 -38
- commonlib_reader-1.2.0/PKG-INFO +0 -39
- commonlib_reader-1.2.0/README.md +0 -26
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: commonlib-reader
|
|
3
|
+
Version: 1.3.0
|
|
4
|
+
Summary: Reader for Equinor commonlib api.
|
|
5
|
+
Author: Åsmund Våge Fannemel
|
|
6
|
+
Author-email: Åsmund Våge Fannemel <asmf@equinor.com>
|
|
7
|
+
License: MIT
|
|
8
|
+
Requires-Dist: pandas>=2.1.4
|
|
9
|
+
Requires-Dist: eq-api-connector>=1.1.0,<2.0.0
|
|
10
|
+
Requires-Python: >=3.10, <4.0.0
|
|
11
|
+
Project-URL: Repository, https://github.com/equinor/commonlib-reader.git
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
|
|
14
|
+
# commonlib-reader
|
|
15
|
+
Connector package for Equinor [Commonlib](https://commonlib.equinor.com/) [api](https://commonlibapi.equinor.com/swagger/index.html).
|
|
16
|
+
|
|
17
|
+
Current features:
|
|
18
|
+
- Reading any code table with the `Code` class
|
|
19
|
+
- Reading library definitions and attribute definitions with the `Library` and `AttributeDefinition` classes
|
|
20
|
+
- Getting facility data using the [Facility](commonlib_reader/facility.py) class
|
|
21
|
+
- [IMS source ](commonlib_reader/ims.py) lookup tables for facilities
|
|
22
|
+
- Getting Tag category, Tag type, Tag format, and Tag format element data. See [tag.py](commonlib_reader/tag.py)
|
|
23
|
+
- Getting [units of measure](commonlib_reader/ims.py) definitions.
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
## Use
|
|
27
|
+
Try it out by running the [demo](examples/demo.py).
|
|
28
|
+
|
|
29
|
+
### Libraries and codes
|
|
30
|
+
|
|
31
|
+
A `Library` defines a code table and its attribute schema; a `Code` is one entry
|
|
32
|
+
in that table. Use package-provided specialized readers when available, such as
|
|
33
|
+
`Facility`, `Discipline`, `Unit`, `TagType`, `TagCategory`, and `TagFormat`;
|
|
34
|
+
otherwise use the generic `Code` reader.
|
|
35
|
+
|
|
36
|
+
### Libraries
|
|
37
|
+
|
|
38
|
+
Use `Library` to discover available code tables and inspect their definitions.
|
|
39
|
+
|
|
40
|
+
```python
|
|
41
|
+
from commonlib_reader import Library
|
|
42
|
+
|
|
43
|
+
library_names = Library.get_names()
|
|
44
|
+
discipline_library = Library.get("Discipline")
|
|
45
|
+
attribute_definitions = discipline_library.attribute_definitions
|
|
46
|
+
is_scoped = discipline_library.is_scope_specific
|
|
47
|
+
scope_type = discipline_library.scope_type
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
`Library.get_all()` supports name and scope filters. Each `AttributeDefinition`
|
|
51
|
+
provides its name, description, required status, identity participation, validation
|
|
52
|
+
regular expression, and referenced library name.
|
|
53
|
+
|
|
54
|
+
Check `is_scope_specific` and `scope_type` before retrieving codes. For example,
|
|
55
|
+
when `scope_type` is `"Facility"` and `is_scope_specific` is `True`, pass the
|
|
56
|
+
facility installation code, such as `"TROC"`, as `scope`.
|
|
57
|
+
|
|
58
|
+
### Code tables
|
|
59
|
+
|
|
60
|
+
Use `Code.get_codes()` to retrieve entries from any CommonLib code table. Filter by
|
|
61
|
+
installation scope or code name when needed.
|
|
62
|
+
|
|
63
|
+
```python
|
|
64
|
+
from commonlib_reader import Code
|
|
65
|
+
|
|
66
|
+
disciplines = Code.get_codes("Discipline", scope="TROC")
|
|
67
|
+
administration = Code.get_codes("Discipline", scope="TROC", name="A")
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Each entry provides `name`, `description`, `identity`, `is_valid`, `attributes`, and
|
|
71
|
+
other CommonLib metadata. Use `Code.get_names()` or `Code.get_name_and_desc()` when
|
|
72
|
+
only dropdown-friendly names or name/description data is required.
|
|
73
|
+
|
|
74
|
+
## Installing
|
|
75
|
+
|
|
76
|
+
Install package from pypi using `pip install commonlib_reader`
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
## Developing / testing
|
|
80
|
+
|
|
81
|
+
uv is preferred for developers. Clone and install with required packages for testing and coverage:
|
|
82
|
+
`uv sync`
|
|
83
|
+
|
|
84
|
+
For testing with coverage run:
|
|
85
|
+
`uv run pytest --cov --cov-report=html`
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# commonlib-reader
|
|
2
|
+
Connector package for Equinor [Commonlib](https://commonlib.equinor.com/) [api](https://commonlibapi.equinor.com/swagger/index.html).
|
|
3
|
+
|
|
4
|
+
Current features:
|
|
5
|
+
- Reading any code table with the `Code` class
|
|
6
|
+
- Reading library definitions and attribute definitions with the `Library` and `AttributeDefinition` classes
|
|
7
|
+
- Getting facility data using the [Facility](commonlib_reader/facility.py) class
|
|
8
|
+
- [IMS source ](commonlib_reader/ims.py) lookup tables for facilities
|
|
9
|
+
- Getting Tag category, Tag type, Tag format, and Tag format element data. See [tag.py](commonlib_reader/tag.py)
|
|
10
|
+
- Getting [units of measure](commonlib_reader/ims.py) definitions.
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
## Use
|
|
14
|
+
Try it out by running the [demo](examples/demo.py).
|
|
15
|
+
|
|
16
|
+
### Libraries and codes
|
|
17
|
+
|
|
18
|
+
A `Library` defines a code table and its attribute schema; a `Code` is one entry
|
|
19
|
+
in that table. Use package-provided specialized readers when available, such as
|
|
20
|
+
`Facility`, `Discipline`, `Unit`, `TagType`, `TagCategory`, and `TagFormat`;
|
|
21
|
+
otherwise use the generic `Code` reader.
|
|
22
|
+
|
|
23
|
+
### Libraries
|
|
24
|
+
|
|
25
|
+
Use `Library` to discover available code tables and inspect their definitions.
|
|
26
|
+
|
|
27
|
+
```python
|
|
28
|
+
from commonlib_reader import Library
|
|
29
|
+
|
|
30
|
+
library_names = Library.get_names()
|
|
31
|
+
discipline_library = Library.get("Discipline")
|
|
32
|
+
attribute_definitions = discipline_library.attribute_definitions
|
|
33
|
+
is_scoped = discipline_library.is_scope_specific
|
|
34
|
+
scope_type = discipline_library.scope_type
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
`Library.get_all()` supports name and scope filters. Each `AttributeDefinition`
|
|
38
|
+
provides its name, description, required status, identity participation, validation
|
|
39
|
+
regular expression, and referenced library name.
|
|
40
|
+
|
|
41
|
+
Check `is_scope_specific` and `scope_type` before retrieving codes. For example,
|
|
42
|
+
when `scope_type` is `"Facility"` and `is_scope_specific` is `True`, pass the
|
|
43
|
+
facility installation code, such as `"TROC"`, as `scope`.
|
|
44
|
+
|
|
45
|
+
### Code tables
|
|
46
|
+
|
|
47
|
+
Use `Code.get_codes()` to retrieve entries from any CommonLib code table. Filter by
|
|
48
|
+
installation scope or code name when needed.
|
|
49
|
+
|
|
50
|
+
```python
|
|
51
|
+
from commonlib_reader import Code
|
|
52
|
+
|
|
53
|
+
disciplines = Code.get_codes("Discipline", scope="TROC")
|
|
54
|
+
administration = Code.get_codes("Discipline", scope="TROC", name="A")
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Each entry provides `name`, `description`, `identity`, `is_valid`, `attributes`, and
|
|
58
|
+
other CommonLib metadata. Use `Code.get_names()` or `Code.get_name_and_desc()` when
|
|
59
|
+
only dropdown-friendly names or name/description data is required.
|
|
60
|
+
|
|
61
|
+
## Installing
|
|
62
|
+
|
|
63
|
+
Install package from pypi using `pip install commonlib_reader`
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
## Developing / testing
|
|
67
|
+
|
|
68
|
+
uv is preferred for developers. Clone and install with required packages for testing and coverage:
|
|
69
|
+
`uv sync`
|
|
70
|
+
|
|
71
|
+
For testing with coverage run:
|
|
72
|
+
`uv run pytest --cov --cov-report=html`
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "commonlib-reader"
|
|
3
|
+
version = "1.3.0"
|
|
4
|
+
description = "Reader for Equinor commonlib api."
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.10,<4.0.0"
|
|
7
|
+
dependencies = [
|
|
8
|
+
"pandas>=2.1.4",
|
|
9
|
+
"eq-api-connector (>=1.1.0,<2.0.0)",
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
[[project.authors]]
|
|
13
|
+
name = "Åsmund Våge Fannemel"
|
|
14
|
+
email = "asmf@equinor.com"
|
|
15
|
+
|
|
16
|
+
[project.license]
|
|
17
|
+
text = "MIT"
|
|
18
|
+
|
|
19
|
+
[project.urls]
|
|
20
|
+
Repository = "https://github.com/equinor/commonlib-reader.git"
|
|
21
|
+
|
|
22
|
+
[dependency-groups]
|
|
23
|
+
dev = [
|
|
24
|
+
"pytest>=7.4.4,<10.0.0",
|
|
25
|
+
"pytest-cov>=7.0.0,<8.0.0",
|
|
26
|
+
"black>=24.1.1,<27.0.0",
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
[build-system]
|
|
30
|
+
requires = ["uv_build>=0.11.16,<0.13"]
|
|
31
|
+
build-backend = "uv_build"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "commonlib-reader"
|
|
3
|
-
version = "1.
|
|
3
|
+
version = "1.3.0"
|
|
4
4
|
description = "Reader for Equinor commonlib api."
|
|
5
5
|
authors = [
|
|
6
6
|
{ name = "Åsmund Våge Fannemel", email = "asmf@equinor.com" }
|
|
@@ -22,5 +22,5 @@ dev = [
|
|
|
22
22
|
]
|
|
23
23
|
|
|
24
24
|
[build-system]
|
|
25
|
-
requires = ["uv_build>=0.11.16,<0.
|
|
25
|
+
requires = ["uv_build>=0.11.16,<0.13"]
|
|
26
26
|
build-backend = "uv_build"
|
|
@@ -1,25 +1,22 @@
|
|
|
1
|
-
from commonlib_reader.utils import (
|
|
2
|
-
get_code,
|
|
3
|
-
get_code_param,
|
|
4
|
-
get_library_names,
|
|
5
|
-
)
|
|
6
|
-
|
|
7
|
-
|
|
8
1
|
from .discipline import Discipline
|
|
9
2
|
from .tag import TagType, TagCategory, TagFormat
|
|
10
3
|
from .ims import IMS
|
|
11
4
|
from .facility import Facility
|
|
12
5
|
from .unit import Unit
|
|
6
|
+
from .code import Code
|
|
7
|
+
from .library import Library, AttributeDefinition
|
|
8
|
+
from .project import Project
|
|
13
9
|
|
|
14
10
|
__all__ = [
|
|
11
|
+
"AttributeDefinition",
|
|
12
|
+
"Code",
|
|
15
13
|
"Discipline",
|
|
16
14
|
"Facility",
|
|
17
15
|
"IMS",
|
|
16
|
+
"Library",
|
|
17
|
+
"Project",
|
|
18
18
|
"TagType",
|
|
19
19
|
"TagCategory",
|
|
20
20
|
"TagFormat",
|
|
21
21
|
"Unit",
|
|
22
|
-
"get_code",
|
|
23
|
-
"get_code_param",
|
|
24
|
-
"get_library_names",
|
|
25
22
|
]
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
from typing import Dict, List, Optional
|
|
2
|
+
|
|
3
|
+
from commonlib_reader.connector import get_connector
|
|
4
|
+
from commonlib_reader.utils import attributes_list_to_dict
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Code:
|
|
8
|
+
"""A generic representation of one entry in a CommonLib library.
|
|
9
|
+
|
|
10
|
+
A Library defines the code table and its attribute schema; a Code stores one
|
|
11
|
+
value from that table. Use this class to read entries from libraries without
|
|
12
|
+
a dedicated domain class implemented in this package, such as Facility,
|
|
13
|
+
Discipline, Unit, TagType, TagCategory, or TagFormat.
|
|
14
|
+
|
|
15
|
+
Attributes:
|
|
16
|
+
library (str): Name of the library the code belongs to.
|
|
17
|
+
name (str): The code name (the code value).
|
|
18
|
+
description (str): Description of the code.
|
|
19
|
+
is_valid (bool): Whether the code can still be used with new data.
|
|
20
|
+
identity (str): Unique identity used to cross reference the code.
|
|
21
|
+
iri (str): CommonLib IRI of the code.
|
|
22
|
+
project (str): Project the code belongs to, if any.
|
|
23
|
+
attachment_key (str): Key used to download an attached file, if any.
|
|
24
|
+
attributes (Dict[str, str]): Library specific attributes keyed by definition name.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
def __init__(self, data: dict, library: str = ""):
|
|
28
|
+
if not isinstance(data, dict):
|
|
29
|
+
raise ValueError("Input data must be a dict from codetable")
|
|
30
|
+
self._data = data
|
|
31
|
+
self._library = library
|
|
32
|
+
self._attributes = attributes_list_to_dict(self._data.get("attributes", []))
|
|
33
|
+
|
|
34
|
+
def __eq__(self, other):
|
|
35
|
+
if isinstance(other, Code):
|
|
36
|
+
return self._data == other._data and self._library == other._library
|
|
37
|
+
return False
|
|
38
|
+
|
|
39
|
+
def __str__(self):
|
|
40
|
+
return f"{self.name} - {self.description}"
|
|
41
|
+
|
|
42
|
+
@property
|
|
43
|
+
def library(self) -> str:
|
|
44
|
+
return self._library
|
|
45
|
+
|
|
46
|
+
@property
|
|
47
|
+
def name(self) -> str:
|
|
48
|
+
return self._data.get("name", "")
|
|
49
|
+
|
|
50
|
+
@property
|
|
51
|
+
def description(self) -> str:
|
|
52
|
+
return self._data.get("description", "")
|
|
53
|
+
|
|
54
|
+
@property
|
|
55
|
+
def is_valid(self) -> bool:
|
|
56
|
+
return self._data.get("isValid", False)
|
|
57
|
+
|
|
58
|
+
@property
|
|
59
|
+
def identity(self) -> str:
|
|
60
|
+
return self._data.get("identity", "")
|
|
61
|
+
|
|
62
|
+
@property
|
|
63
|
+
def iri(self) -> str:
|
|
64
|
+
return self._data.get("iri", "") or ""
|
|
65
|
+
|
|
66
|
+
@property
|
|
67
|
+
def project(self) -> str:
|
|
68
|
+
return self._data.get("project", "") or ""
|
|
69
|
+
|
|
70
|
+
@property
|
|
71
|
+
def attachment_key(self) -> str:
|
|
72
|
+
return self._data.get("attachmentKey", "") or ""
|
|
73
|
+
|
|
74
|
+
@property
|
|
75
|
+
def attributes(self) -> Dict[str, str]:
|
|
76
|
+
return self._attributes
|
|
77
|
+
|
|
78
|
+
@staticmethod
|
|
79
|
+
def _get_code_data_param(code: str, params: Optional[dict] = None):
|
|
80
|
+
"""Retrieve raw code-table data using pre-built request parameters.
|
|
81
|
+
|
|
82
|
+
Args:
|
|
83
|
+
code (str): Name of the code library to read.
|
|
84
|
+
params (dict, optional): Query parameters to send to the API.
|
|
85
|
+
|
|
86
|
+
Returns:
|
|
87
|
+
list: Raw code entries returned by the API.
|
|
88
|
+
"""
|
|
89
|
+
return get_connector().get_json(f"/api/Code/{code}", params=params or {})
|
|
90
|
+
|
|
91
|
+
@classmethod
|
|
92
|
+
def _get_code_data(
|
|
93
|
+
cls,
|
|
94
|
+
library: str,
|
|
95
|
+
scope: Optional[str] = None,
|
|
96
|
+
name: Optional[str] = None,
|
|
97
|
+
):
|
|
98
|
+
"""Retrieve raw code-table data with optional scope and name filters.
|
|
99
|
+
|
|
100
|
+
Args:
|
|
101
|
+
library (str): Name of the code library to read.
|
|
102
|
+
scope (str, optional): Scope (installation code) to filter by.
|
|
103
|
+
name (str, optional): Criterion for code name (use % for wildcards).
|
|
104
|
+
|
|
105
|
+
Returns:
|
|
106
|
+
list: Raw code entries returned by the API.
|
|
107
|
+
"""
|
|
108
|
+
params = {}
|
|
109
|
+
if scope is not None:
|
|
110
|
+
params["scope"] = scope
|
|
111
|
+
if name is not None:
|
|
112
|
+
params["name"] = name
|
|
113
|
+
return cls._get_code_data_param(library, params=params)
|
|
114
|
+
|
|
115
|
+
@classmethod
|
|
116
|
+
def get_codes(
|
|
117
|
+
cls,
|
|
118
|
+
library: str,
|
|
119
|
+
scope: Optional[str] = None,
|
|
120
|
+
name: Optional[str] = None,
|
|
121
|
+
) -> List["Code"]:
|
|
122
|
+
"""Get all codes from a library as Code objects.
|
|
123
|
+
|
|
124
|
+
Args:
|
|
125
|
+
library (str): Name of the library to read.
|
|
126
|
+
scope (str, optional): Scope (installation code) to filter by.
|
|
127
|
+
name (str, optional): Criterion for code name (use % for wildcards).
|
|
128
|
+
|
|
129
|
+
Returns:
|
|
130
|
+
List[Code]: List of Code objects from the library.
|
|
131
|
+
"""
|
|
132
|
+
data = cls._get_code_data(library, scope=scope, name=name)
|
|
133
|
+
if not isinstance(data, list):
|
|
134
|
+
raise ValueError(f"Invalid data from api for library {library}")
|
|
135
|
+
|
|
136
|
+
return [cls(x, library=library) for x in data]
|
|
137
|
+
|
|
138
|
+
@staticmethod
|
|
139
|
+
def get_names(library: str, scope: Optional[str] = None) -> list:
|
|
140
|
+
"""Get code names of a library as a list of strings. For dropdowns etc.
|
|
141
|
+
|
|
142
|
+
Args:
|
|
143
|
+
library (str): Name of the library to read.
|
|
144
|
+
scope (str, optional): Scope (installation code) to filter by.
|
|
145
|
+
|
|
146
|
+
Returns:
|
|
147
|
+
list: List of code name strings.
|
|
148
|
+
"""
|
|
149
|
+
params = {}
|
|
150
|
+
if scope is not None:
|
|
151
|
+
params["scope"] = scope
|
|
152
|
+
return get_connector().get_json(f"/api/Code/NameList/{library}", params=params)
|
|
153
|
+
|
|
154
|
+
@staticmethod
|
|
155
|
+
def get_name_and_desc(library: str, scope: Optional[str] = None) -> list:
|
|
156
|
+
"""Get codes of a library as a list of name and description objects.
|
|
157
|
+
|
|
158
|
+
Args:
|
|
159
|
+
library (str): Name of the library to read.
|
|
160
|
+
scope (str, optional): Scope (installation code) to filter by.
|
|
161
|
+
|
|
162
|
+
Returns:
|
|
163
|
+
list: List of objects with name, description and isValid.
|
|
164
|
+
"""
|
|
165
|
+
params = {}
|
|
166
|
+
if scope is not None:
|
|
167
|
+
params["scope"] = scope
|
|
168
|
+
return get_connector().get_json(
|
|
169
|
+
f"/api/Code/NameAndDesc/{library}", params=params
|
|
170
|
+
)
|
|
@@ -14,7 +14,7 @@ def get_connector() -> APIConnector:
|
|
|
14
14
|
clientID = "728cfddd-b8e9-4ed7-b9a3-8f2fd5b8e79a"
|
|
15
15
|
scopes = ["37d598fc-da0f-46bd-949f-7107918d47a5/user_impersonation"]
|
|
16
16
|
connector = APIConnector(client_id=clientID, scope=scopes)
|
|
17
|
-
connector.
|
|
17
|
+
connector.url_prod = "https://commonlibapi.equinor.com/"
|
|
18
18
|
_connector = connector
|
|
19
19
|
|
|
20
20
|
return _connector
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from typing import List
|
|
2
2
|
|
|
3
|
-
from commonlib_reader.
|
|
3
|
+
from commonlib_reader.code import Code
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
class Discipline:
|
|
@@ -45,7 +45,7 @@ class Discipline:
|
|
|
45
45
|
Returns:
|
|
46
46
|
List["Discipline"]: List of discipline objects
|
|
47
47
|
"""
|
|
48
|
-
dis_data =
|
|
48
|
+
dis_data = Code._get_code_data("Discipline", scope=scope)
|
|
49
49
|
|
|
50
50
|
if not isinstance(dis_data, list) or not all(
|
|
51
51
|
isinstance(x, dict) for x in dis_data
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from typing import List, Union
|
|
2
2
|
|
|
3
|
-
from commonlib_reader.
|
|
3
|
+
from commonlib_reader.code import Code
|
|
4
|
+
from commonlib_reader.utils import attributes_list_to_dict
|
|
4
5
|
|
|
5
6
|
|
|
6
7
|
class Facility:
|
|
@@ -38,14 +39,25 @@ class Facility:
|
|
|
38
39
|
self._data = Facility._get_facility_data(code=code)
|
|
39
40
|
self._attributes = attributes_list_to_dict(self._data["attributes"])
|
|
40
41
|
|
|
42
|
+
# Backward compatibility aliases
|
|
41
43
|
if self.is_stid:
|
|
42
44
|
self.STID = self.identity
|
|
43
45
|
self.instCode = self.identity # Alias for identity
|
|
44
46
|
try:
|
|
45
|
-
self.SAP = int(
|
|
47
|
+
self.SAP = int(
|
|
48
|
+
self.sap
|
|
49
|
+
) # Backward compatibility alias for SAPPlant as integer
|
|
46
50
|
except (TypeError, ValueError):
|
|
47
51
|
pass
|
|
48
52
|
|
|
53
|
+
def __eq__(self, other):
|
|
54
|
+
if isinstance(other, Facility):
|
|
55
|
+
return self.identity == other.identity and self._data == other._data
|
|
56
|
+
return False
|
|
57
|
+
|
|
58
|
+
def __str__(self):
|
|
59
|
+
return f"Facility(identity={self.identity}, name={self.description})"
|
|
60
|
+
|
|
49
61
|
@property
|
|
50
62
|
def identity(self) -> str:
|
|
51
63
|
return self._data.get("identity", "")
|
|
@@ -96,7 +108,7 @@ class Facility:
|
|
|
96
108
|
def ioc_plant(self) -> str:
|
|
97
109
|
return self._attributes.get("IOCPlant", "")
|
|
98
110
|
|
|
99
|
-
def
|
|
111
|
+
def _check_is_stid(self) -> bool:
|
|
100
112
|
"""
|
|
101
113
|
Checks if the facility is marked for STID.
|
|
102
114
|
|
|
@@ -109,6 +121,15 @@ class Facility:
|
|
|
109
121
|
|
|
110
122
|
return False
|
|
111
123
|
|
|
124
|
+
def isSTID(self) -> bool:
|
|
125
|
+
"""
|
|
126
|
+
Backward compatibility method. Use is_stid property instead.
|
|
127
|
+
|
|
128
|
+
Returns:
|
|
129
|
+
bool: True if the facility is marked for STID, False otherwise.
|
|
130
|
+
"""
|
|
131
|
+
return self._check_is_stid()
|
|
132
|
+
|
|
112
133
|
def resolve_gov_facility_name(self) -> str:
|
|
113
134
|
"""
|
|
114
135
|
Retrieves the governmental facility name.
|
|
@@ -226,7 +247,7 @@ class Facility:
|
|
|
226
247
|
@classmethod
|
|
227
248
|
def get_sap_facilities(cls) -> List["Facility"]:
|
|
228
249
|
fac = cls.get_all_facilities()
|
|
229
|
-
return [f for f in fac if len(f.sap) > 0]
|
|
250
|
+
return [f for f in fac if len(f.sap) > 0 and f.sap.isdigit()]
|
|
230
251
|
|
|
231
252
|
@classmethod
|
|
232
253
|
def get_ioc_facilities(cls) -> List["Facility"]:
|
|
@@ -259,7 +280,7 @@ class Facility:
|
|
|
259
280
|
List[dict]: A list of dictionaries, each representing facility data.
|
|
260
281
|
"""
|
|
261
282
|
if cls._cache is None:
|
|
262
|
-
code =
|
|
283
|
+
code = Code._get_code_data("Facility")
|
|
263
284
|
if isinstance(code, list):
|
|
264
285
|
cls._cache = code
|
|
265
286
|
else:
|
|
@@ -1,20 +1,22 @@
|
|
|
1
1
|
from typing import List, Union
|
|
2
|
+
from commonlib_reader.code import Code
|
|
2
3
|
from commonlib_reader.facility import Facility
|
|
3
|
-
from commonlib_reader.utils import attributes_list_to_dict
|
|
4
|
+
from commonlib_reader.utils import attributes_list_to_dict
|
|
4
5
|
|
|
5
6
|
|
|
6
7
|
class IMS:
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
isValid (bool) - True if IMS is in operation
|
|
8
|
+
"""Class for IMS (Information Management System) objects.
|
|
9
|
+
|
|
10
|
+
Properties:
|
|
11
|
+
facility (str): Name of the facility associated with this IMS.
|
|
12
|
+
type (str): Type of the IMS system.
|
|
13
|
+
alias (str): Facility name alias used by the IMS.
|
|
14
|
+
is_valid (bool): True if the IMS is in operation, False otherwise.
|
|
15
|
+
seeq_datasource (str): The Seeq datasource identifier for this IMS.
|
|
16
16
|
"""
|
|
17
17
|
|
|
18
|
+
_ims_codes = None
|
|
19
|
+
|
|
18
20
|
def __init__(self, data: Union[str, dict]):
|
|
19
21
|
"""Instance constructor for IMS object. End-users should use static method IMS.from_facility()
|
|
20
22
|
|
|
@@ -33,7 +35,6 @@ class IMS:
|
|
|
33
35
|
self._data = data
|
|
34
36
|
self._attributes = attributes_list_to_dict(self._data["attributes"])
|
|
35
37
|
|
|
36
|
-
self.isValid = data["isValid"]
|
|
37
38
|
for attr in self._data["attributes"]:
|
|
38
39
|
self.__setattr__(attr["definitionName"], attr["displayValue"])
|
|
39
40
|
|
|
@@ -51,7 +52,12 @@ class IMS:
|
|
|
51
52
|
|
|
52
53
|
@property
|
|
53
54
|
def is_valid(self) -> bool:
|
|
54
|
-
return
|
|
55
|
+
return self._data.get("isValid", False)
|
|
56
|
+
|
|
57
|
+
@property
|
|
58
|
+
def isValid(self) -> bool:
|
|
59
|
+
"""Backward compatibility alias for is_valid."""
|
|
60
|
+
return self.is_valid
|
|
55
61
|
|
|
56
62
|
@property
|
|
57
63
|
def seeq_datasource(self) -> str:
|
|
@@ -60,9 +66,10 @@ class IMS:
|
|
|
60
66
|
@staticmethod
|
|
61
67
|
def from_facility(facility: Union[Facility, str, int]) -> "IMS":
|
|
62
68
|
"""Get IMS instance from STID code.
|
|
69
|
+
If no IMS instance is found for the input facility, will try to find IMS instance for parent facility recursively.
|
|
63
70
|
|
|
64
71
|
Args:
|
|
65
|
-
facility (str): Facility inst code (STID) or SAP code.
|
|
72
|
+
facility (Facility, str, int): Facility object, inst code (STID) or SAP code.
|
|
66
73
|
|
|
67
74
|
Raises:
|
|
68
75
|
ValueError: Not able to instantiate IMS object from input facility code.
|
|
@@ -70,18 +77,15 @@ class IMS:
|
|
|
70
77
|
Returns:
|
|
71
78
|
IMS: IMS instance
|
|
72
79
|
"""
|
|
73
|
-
if isinstance(facility,
|
|
80
|
+
if not isinstance(facility, Facility):
|
|
74
81
|
facility = Facility(facility)
|
|
75
82
|
|
|
76
|
-
if isinstance(facility, Facility):
|
|
77
|
-
facility = facility.identity
|
|
78
|
-
|
|
79
|
-
if not isinstance(facility, str) or len(facility) == 0:
|
|
80
|
-
raise ValueError("Not able to detect facility from input {facility}.")
|
|
81
|
-
|
|
82
83
|
ims = IMS.get_ims_list(facility=facility)
|
|
83
84
|
if len(ims) == 1:
|
|
84
85
|
return ims[0]
|
|
86
|
+
if len(ims) == 0:
|
|
87
|
+
if facility.parent_facility:
|
|
88
|
+
return IMS.from_facility(facility.parent_facility)
|
|
85
89
|
|
|
86
90
|
raise ValueError(f"Not able to get IMS object for facility {facility}")
|
|
87
91
|
|
|
@@ -90,15 +94,15 @@ class IMS:
|
|
|
90
94
|
"""Get list of IMS instance of entries in code library ApplicationIMS. Caches locally in memory.
|
|
91
95
|
|
|
92
96
|
Returns:
|
|
93
|
-
List[IMS]:
|
|
97
|
+
List[IMS]: List of IMS instances from entries in code library ApplicationIMS.
|
|
94
98
|
"""
|
|
95
|
-
if cls._ims_codes is None
|
|
96
|
-
cls._ims_codes =
|
|
99
|
+
if cls._ims_codes is None:
|
|
100
|
+
cls._ims_codes = Code._get_code_data("ApplicationIMS")
|
|
97
101
|
|
|
98
102
|
return [IMS(x) for x in cls._ims_codes]
|
|
99
103
|
|
|
100
104
|
@staticmethod
|
|
101
|
-
def get_ims_list(facility: str = "") -> List["IMS"]:
|
|
105
|
+
def get_ims_list(facility: Union[str, Facility] = "") -> List["IMS"]:
|
|
102
106
|
"""Get list of IMS objects.
|
|
103
107
|
|
|
104
108
|
Args:
|
|
@@ -107,6 +111,10 @@ class IMS:
|
|
|
107
111
|
Returns:
|
|
108
112
|
List[IMS]: list of IMS objects
|
|
109
113
|
"""
|
|
114
|
+
|
|
115
|
+
if isinstance(facility, Facility):
|
|
116
|
+
facility = facility.identity
|
|
117
|
+
|
|
110
118
|
i = IMS._get_ims_codes()
|
|
111
119
|
if len(facility) > 0:
|
|
112
120
|
return [x for x in i if x.facility == facility]
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
from typing import List, Optional
|
|
2
|
+
|
|
3
|
+
from commonlib_reader.connector import get_connector
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class AttributeDefinition:
|
|
7
|
+
"""Definition of an attribute belonging to a CommonLib library.
|
|
8
|
+
|
|
9
|
+
Attributes:
|
|
10
|
+
name (str): Name of the attribute.
|
|
11
|
+
description (str): Description of the attribute.
|
|
12
|
+
required (bool): Whether the attribute is required.
|
|
13
|
+
include_in_identity (bool): Whether the attribute is part of the code identity.
|
|
14
|
+
regex (str): Validation pattern for the attribute value, if any.
|
|
15
|
+
reference_library_name (str): Library referenced by this attribute, if any.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
def __init__(self, data: dict):
|
|
19
|
+
if not isinstance(data, dict):
|
|
20
|
+
raise ValueError("Input data must be a dict from api")
|
|
21
|
+
self._data = data
|
|
22
|
+
|
|
23
|
+
def __eq__(self, other):
|
|
24
|
+
if isinstance(other, AttributeDefinition):
|
|
25
|
+
return self._data == other._data
|
|
26
|
+
return False
|
|
27
|
+
|
|
28
|
+
def __str__(self):
|
|
29
|
+
return self.name
|
|
30
|
+
|
|
31
|
+
@property
|
|
32
|
+
def name(self) -> str:
|
|
33
|
+
return self._data.get("name", "")
|
|
34
|
+
|
|
35
|
+
@property
|
|
36
|
+
def description(self) -> str:
|
|
37
|
+
return self._data.get("description", "") or ""
|
|
38
|
+
|
|
39
|
+
@property
|
|
40
|
+
def required(self) -> bool:
|
|
41
|
+
return self._data.get("required", False)
|
|
42
|
+
|
|
43
|
+
@property
|
|
44
|
+
def include_in_identity(self) -> bool:
|
|
45
|
+
return self._data.get("includeInIdentity", False)
|
|
46
|
+
|
|
47
|
+
@property
|
|
48
|
+
def regex(self) -> str:
|
|
49
|
+
return self._data.get("regex", "") or ""
|
|
50
|
+
|
|
51
|
+
@property
|
|
52
|
+
def reference_library_name(self) -> str:
|
|
53
|
+
return self._data.get("referenceLibraryName", "") or ""
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class Library:
|
|
57
|
+
"""A CommonLib library (a code-table definition and attribute schema).
|
|
58
|
+
|
|
59
|
+
A Library defines a code table and the attributes available on its Code
|
|
60
|
+
entries. It is not a container of Code instances; retrieve entries with
|
|
61
|
+
Code.get_codes() using this library's name.
|
|
62
|
+
|
|
63
|
+
Attributes:
|
|
64
|
+
name (str): Name of the library.
|
|
65
|
+
description (str): Description of the library.
|
|
66
|
+
is_valid (bool): Whether the library can still be used with new data.
|
|
67
|
+
scope_type (str): The scope type of the library.
|
|
68
|
+
is_global (bool): Whether the library is global.
|
|
69
|
+
is_scope_specific (bool): Whether the library is scope specific.
|
|
70
|
+
attribute_definitions (List[AttributeDefinition]): Attribute definitions of the library.
|
|
71
|
+
"""
|
|
72
|
+
|
|
73
|
+
def __init__(self, data: dict):
|
|
74
|
+
if not isinstance(data, dict):
|
|
75
|
+
raise ValueError("Input data must be a dict from api")
|
|
76
|
+
self._data = data
|
|
77
|
+
|
|
78
|
+
def __eq__(self, other):
|
|
79
|
+
if isinstance(other, Library):
|
|
80
|
+
return self._data == other._data
|
|
81
|
+
return False
|
|
82
|
+
|
|
83
|
+
def __str__(self):
|
|
84
|
+
return f"{self.name} - {self.description}"
|
|
85
|
+
|
|
86
|
+
@property
|
|
87
|
+
def name(self) -> str:
|
|
88
|
+
return self._data.get("name", "")
|
|
89
|
+
|
|
90
|
+
@property
|
|
91
|
+
def description(self) -> str:
|
|
92
|
+
return self._data.get("description", "") or ""
|
|
93
|
+
|
|
94
|
+
@property
|
|
95
|
+
def is_valid(self) -> bool:
|
|
96
|
+
return self._data.get("isValid", False)
|
|
97
|
+
|
|
98
|
+
@property
|
|
99
|
+
def scope_type(self) -> str:
|
|
100
|
+
return self._data.get("scopeType", "") or ""
|
|
101
|
+
|
|
102
|
+
@property
|
|
103
|
+
def is_global(self) -> bool:
|
|
104
|
+
return self._data.get("isGlobal", False)
|
|
105
|
+
|
|
106
|
+
@property
|
|
107
|
+
def is_scope_specific(self) -> bool:
|
|
108
|
+
return self._data.get("isScopeSpecific", False)
|
|
109
|
+
|
|
110
|
+
@property
|
|
111
|
+
def attribute_definitions(self) -> List[AttributeDefinition]:
|
|
112
|
+
return [
|
|
113
|
+
AttributeDefinition(x)
|
|
114
|
+
for x in self._data.get("attributeDefinitions", []) or []
|
|
115
|
+
]
|
|
116
|
+
|
|
117
|
+
@classmethod
|
|
118
|
+
def get(cls, name: str) -> "Library":
|
|
119
|
+
"""Get a single library by name.
|
|
120
|
+
|
|
121
|
+
Args:
|
|
122
|
+
name (str): Name of the library to retrieve.
|
|
123
|
+
|
|
124
|
+
Returns:
|
|
125
|
+
Library: The requested library object.
|
|
126
|
+
|
|
127
|
+
Raises:
|
|
128
|
+
ValueError: If the library is not found.
|
|
129
|
+
"""
|
|
130
|
+
for lib in cls.get_all(name=name):
|
|
131
|
+
if lib.name.upper() == name.upper():
|
|
132
|
+
return lib
|
|
133
|
+
raise ValueError(f"Library {name} not found")
|
|
134
|
+
|
|
135
|
+
@classmethod
|
|
136
|
+
def get_all(
|
|
137
|
+
cls, name: Optional[str] = None, scope: Optional[str] = None
|
|
138
|
+
) -> List["Library"]:
|
|
139
|
+
"""Get libraries as a list of Library objects.
|
|
140
|
+
|
|
141
|
+
Args:
|
|
142
|
+
name (str, optional): Criterion for library name (use % for wildcards).
|
|
143
|
+
scope (str, optional): Return libraries for this scope only.
|
|
144
|
+
|
|
145
|
+
Returns:
|
|
146
|
+
List[Library]: List of Library objects.
|
|
147
|
+
"""
|
|
148
|
+
params = {}
|
|
149
|
+
if name is not None:
|
|
150
|
+
params["name"] = name
|
|
151
|
+
if scope is not None:
|
|
152
|
+
params["scope"] = scope
|
|
153
|
+
|
|
154
|
+
data = get_connector().get_json("/api/Library", params=params)
|
|
155
|
+
if not isinstance(data, list):
|
|
156
|
+
raise ValueError("Invalid library data from api")
|
|
157
|
+
|
|
158
|
+
return [cls(x) for x in data]
|
|
159
|
+
|
|
160
|
+
@staticmethod
|
|
161
|
+
def get_names() -> List[str]:
|
|
162
|
+
"""Get library names as a list of strings. For dropdowns etc.
|
|
163
|
+
|
|
164
|
+
Returns:
|
|
165
|
+
List[str]: Sorted list of library name strings.
|
|
166
|
+
"""
|
|
167
|
+
library_names = get_connector().get_json(url="/api/Library/NameList")
|
|
168
|
+
if isinstance(library_names, list) and all(
|
|
169
|
+
isinstance(name, str) for name in library_names
|
|
170
|
+
):
|
|
171
|
+
library_names.sort()
|
|
172
|
+
return library_names
|
|
173
|
+
|
|
174
|
+
raise ValueError("Wrong data from API when getting library names.")
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
from typing import List, Optional
|
|
2
|
+
|
|
3
|
+
from commonlib_reader.connector import get_connector
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Project:
|
|
7
|
+
"""A project.
|
|
8
|
+
|
|
9
|
+
Attributes:
|
|
10
|
+
name (str): Name of the project.
|
|
11
|
+
description (str): Description of the project.
|
|
12
|
+
abbreviation (str): Project abbreviation / alias.
|
|
13
|
+
is_valid (bool): Whether the project can still be used with new data.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
def __init__(self, data: dict):
|
|
17
|
+
if not isinstance(data, dict):
|
|
18
|
+
raise ValueError("Input data must be a dict from api")
|
|
19
|
+
self._data = data
|
|
20
|
+
|
|
21
|
+
def __eq__(self, other):
|
|
22
|
+
if isinstance(other, Project):
|
|
23
|
+
return self._data == other._data
|
|
24
|
+
return False
|
|
25
|
+
|
|
26
|
+
def __str__(self):
|
|
27
|
+
return f"{self.name} - {self.description}"
|
|
28
|
+
|
|
29
|
+
@property
|
|
30
|
+
def name(self) -> str:
|
|
31
|
+
return self._data.get("name", "")
|
|
32
|
+
|
|
33
|
+
@property
|
|
34
|
+
def description(self) -> str:
|
|
35
|
+
return self._data.get("description", "") or ""
|
|
36
|
+
|
|
37
|
+
@property
|
|
38
|
+
def is_valid(self) -> bool:
|
|
39
|
+
return self._data.get("isValid", False)
|
|
40
|
+
|
|
41
|
+
@property
|
|
42
|
+
def abbreviation(self) -> str:
|
|
43
|
+
return self._data.get("aliasName", "") or ""
|
|
44
|
+
|
|
45
|
+
@classmethod
|
|
46
|
+
def get_all(
|
|
47
|
+
cls,
|
|
48
|
+
name: Optional[str] = None,
|
|
49
|
+
abbreviation: Optional[str] = None,
|
|
50
|
+
only_valid: bool = True,
|
|
51
|
+
) -> List["Project"]:
|
|
52
|
+
"""Get projects as a list of Project objects.
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
name (str, optional): Criterion for project name (use % for wildcards).
|
|
56
|
+
abbreviation (str, optional): Criterion for project abbreviation (use % for wildcards).
|
|
57
|
+
only_valid (bool): If True, only return projects usable with new data. Defaults to True.
|
|
58
|
+
|
|
59
|
+
Returns:
|
|
60
|
+
List[Project]: List of Project objects.
|
|
61
|
+
"""
|
|
62
|
+
params = {}
|
|
63
|
+
if name is not None:
|
|
64
|
+
params["name"] = name
|
|
65
|
+
if abbreviation is not None:
|
|
66
|
+
params["abbreviation"] = abbreviation
|
|
67
|
+
if not only_valid:
|
|
68
|
+
params["isValid"] = "null"
|
|
69
|
+
|
|
70
|
+
data = get_connector().get_json("/api/Project", params=params)
|
|
71
|
+
if not isinstance(data, list):
|
|
72
|
+
raise ValueError("Invalid project data from api")
|
|
73
|
+
|
|
74
|
+
return [cls(x) for x in data]
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
from typing import List, Optional, Union
|
|
2
|
+
from commonlib_reader.code import Code
|
|
2
3
|
from commonlib_reader.utils import (
|
|
3
4
|
attributes_list_to_dict,
|
|
4
|
-
get_code,
|
|
5
|
-
get_code_param,
|
|
6
5
|
query_sql,
|
|
7
6
|
)
|
|
8
7
|
import re
|
|
@@ -19,11 +18,11 @@ class TagFormatElement:
|
|
|
19
18
|
"""A class representing the elements constructing a tag number.
|
|
20
19
|
|
|
21
20
|
Attributes:
|
|
22
|
-
description (str)
|
|
23
|
-
name (str)
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
21
|
+
description (str): Description of the tag format element.
|
|
22
|
+
name (str): Name of the tag format element.
|
|
23
|
+
is_valid (bool): Whether the tag format element is valid.
|
|
24
|
+
is_required (bool): Whether the tag format element is required.
|
|
25
|
+
is_selected (bool): Whether the tag format element is selected.
|
|
27
26
|
|
|
28
27
|
"""
|
|
29
28
|
|
|
@@ -35,10 +34,9 @@ class TagFormatElement:
|
|
|
35
34
|
data (dict): Data containing different properties of a tag format element.
|
|
36
35
|
"""
|
|
37
36
|
self._data = data
|
|
38
|
-
|
|
39
|
-
self.
|
|
40
|
-
self.
|
|
41
|
-
self.IsSelected = bool(data["SelectFlag"])
|
|
37
|
+
self._is_valid = bool(data["IsValid"])
|
|
38
|
+
self._is_required = bool(data["Required"])
|
|
39
|
+
self._is_selected = bool(data["SelectFlag"])
|
|
42
40
|
|
|
43
41
|
@property
|
|
44
42
|
def name(self) -> str:
|
|
@@ -50,15 +48,30 @@ class TagFormatElement:
|
|
|
50
48
|
|
|
51
49
|
@property
|
|
52
50
|
def is_valid(self) -> bool:
|
|
53
|
-
return self.
|
|
51
|
+
return self._is_valid
|
|
52
|
+
|
|
53
|
+
@property
|
|
54
|
+
def IsValid(self) -> bool:
|
|
55
|
+
"""Backward compatibility property for is_valid."""
|
|
56
|
+
return self.is_valid
|
|
54
57
|
|
|
55
58
|
@property
|
|
56
59
|
def is_required(self) -> bool:
|
|
57
|
-
return self.
|
|
60
|
+
return self._is_required
|
|
61
|
+
|
|
62
|
+
@property
|
|
63
|
+
def IsRequired(self) -> bool:
|
|
64
|
+
"""Backward compatibility property for is_required."""
|
|
65
|
+
return self.is_required
|
|
58
66
|
|
|
59
67
|
@property
|
|
60
68
|
def is_selected(self) -> bool:
|
|
61
|
-
return self.
|
|
69
|
+
return self._is_selected
|
|
70
|
+
|
|
71
|
+
@property
|
|
72
|
+
def IsSelected(self) -> bool:
|
|
73
|
+
"""Backward compatibility property for is_selected."""
|
|
74
|
+
return self.is_selected
|
|
62
75
|
|
|
63
76
|
def get_TagFormat(self) -> "TagFormat":
|
|
64
77
|
tag_format_id = self._data["TagFormat_ID"]
|
|
@@ -254,9 +267,9 @@ class TagType:
|
|
|
254
267
|
inst_code (str): The facility code the tag type is associated with.
|
|
255
268
|
name (str): The name of the tag type.
|
|
256
269
|
description (str): A description of the tag type.
|
|
257
|
-
is_valid (bool): A flag indicating whether the tag type is valid.
|
|
258
270
|
tag_category (str): The category under which this tag type falls.
|
|
259
|
-
|
|
271
|
+
is_valid (bool): A flag indicating whether the tag type is valid.
|
|
272
|
+
stid_tag_count (int): The number of STID tags associated with this tag type.
|
|
260
273
|
"""
|
|
261
274
|
|
|
262
275
|
def __init__(self, data: dict, inst_code: str):
|
|
@@ -270,10 +283,11 @@ class TagType:
|
|
|
270
283
|
self._data = data
|
|
271
284
|
self._attributes = attributes_list_to_dict(self._data["attributes"])
|
|
272
285
|
self._inst_code = inst_code
|
|
286
|
+
self._stid_tag_count = 0
|
|
273
287
|
|
|
274
288
|
for attr in self._data["attributes"]:
|
|
275
289
|
if attr["definitionName"] == "STIDTagCount":
|
|
276
|
-
self.
|
|
290
|
+
self._stid_tag_count = int(attr["displayValue"])
|
|
277
291
|
|
|
278
292
|
@property
|
|
279
293
|
def inst_code(self) -> str:
|
|
@@ -295,9 +309,19 @@ class TagType:
|
|
|
295
309
|
def is_valid(self) -> bool:
|
|
296
310
|
return self._data["isValid"]
|
|
297
311
|
|
|
312
|
+
@property
|
|
313
|
+
def isValid(self) -> bool:
|
|
314
|
+
"""Backward compatibility property for is_valid."""
|
|
315
|
+
return self.is_valid
|
|
316
|
+
|
|
298
317
|
@property
|
|
299
318
|
def stid_tag_count(self) -> int:
|
|
300
|
-
return self.
|
|
319
|
+
return self._stid_tag_count
|
|
320
|
+
|
|
321
|
+
@property
|
|
322
|
+
def STID_tag_Count(self) -> int:
|
|
323
|
+
"""Backward compatibility property for stid_tag_count."""
|
|
324
|
+
return self.stid_tag_count
|
|
301
325
|
|
|
302
326
|
def __str__(self):
|
|
303
327
|
return f"{self.name} - {self.description}"
|
|
@@ -336,13 +360,9 @@ class TagType:
|
|
|
336
360
|
List[TagType]: A list of TagType objects matching the criteria.
|
|
337
361
|
"""
|
|
338
362
|
|
|
339
|
-
params = {}
|
|
340
|
-
params["scope"] = inst_code
|
|
341
|
-
params["name"] = name
|
|
342
|
-
|
|
343
363
|
tag_types = [
|
|
344
364
|
TagType(x, inst_code=inst_code)
|
|
345
|
-
for x in
|
|
365
|
+
for x in Code._get_code_data("TagType", scope=inst_code, name=name)
|
|
346
366
|
]
|
|
347
367
|
|
|
348
368
|
if tag_category:
|
|
@@ -455,14 +475,14 @@ class TagCategory:
|
|
|
455
475
|
A class representing a Facility specific category of tag types.
|
|
456
476
|
|
|
457
477
|
Attributes:
|
|
458
|
-
inst_code (str): Installation code for the
|
|
478
|
+
inst_code (str): Installation code for the facility the TagCategory is associated with.
|
|
459
479
|
name (str): Name of the tag category.
|
|
460
480
|
description (str): Description of the tag category.
|
|
461
481
|
is_valid (bool): Flag indicating whether the tag category is considered valid.
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
482
|
+
tag_category_id (int): Unique identifier of the tag category.
|
|
483
|
+
tag_category_dlg (str): Additional dialog information associated with the tag category.
|
|
484
|
+
individ_flag (str): A flag indicating individual characteristics for the category.
|
|
485
|
+
sap_fl_category (str): Corresponding SAP functional location category.
|
|
466
486
|
"""
|
|
467
487
|
|
|
468
488
|
def __init__(self, data, inst_code):
|
|
@@ -476,16 +496,20 @@ class TagCategory:
|
|
|
476
496
|
self._data = data
|
|
477
497
|
self._inst_code = inst_code
|
|
478
498
|
self._attributes = attributes_list_to_dict(self._data["attributes"])
|
|
499
|
+
self._tag_category_id = 0
|
|
500
|
+
self._tag_category_dlg = ""
|
|
501
|
+
self._individ_flag = ""
|
|
502
|
+
self._sap_fl_category = ""
|
|
479
503
|
|
|
480
504
|
for attr in self._data["attributes"]:
|
|
481
505
|
if attr["definitionName"] == "TagCategoryId":
|
|
482
|
-
self.
|
|
506
|
+
self._tag_category_id = int(attr["displayValue"])
|
|
483
507
|
elif attr["definitionName"] == "TagCategoryDlg":
|
|
484
|
-
self.
|
|
508
|
+
self._tag_category_dlg = attr["displayValue"]
|
|
485
509
|
elif attr["definitionName"] == "IndividFlag":
|
|
486
|
-
self.
|
|
510
|
+
self._individ_flag = attr["displayValue"]
|
|
487
511
|
elif attr["definitionName"] == "SapFlCategory":
|
|
488
|
-
self.
|
|
512
|
+
self._sap_fl_category = attr["displayValue"]
|
|
489
513
|
|
|
490
514
|
self._types = []
|
|
491
515
|
self._formats = []
|
|
@@ -506,25 +530,49 @@ class TagCategory:
|
|
|
506
530
|
def is_valid(self) -> bool:
|
|
507
531
|
return self._data["isValid"]
|
|
508
532
|
|
|
533
|
+
@property
|
|
534
|
+
def isValid(self) -> bool:
|
|
535
|
+
"""Backward compatibility property for is_valid."""
|
|
536
|
+
return self.is_valid
|
|
537
|
+
|
|
509
538
|
@property
|
|
510
539
|
def tag_category_id(self) -> int:
|
|
511
|
-
id = self.
|
|
512
|
-
if id
|
|
540
|
+
id = self._tag_category_id
|
|
541
|
+
if id == 0:
|
|
513
542
|
raise ValueError("TagCategoryId attribute not found")
|
|
514
|
-
|
|
515
543
|
return int(id)
|
|
516
544
|
|
|
545
|
+
@property
|
|
546
|
+
def TagCategoryId(self) -> int:
|
|
547
|
+
"""Backward compatibility property for tag_category_id."""
|
|
548
|
+
return self.tag_category_id
|
|
549
|
+
|
|
517
550
|
@property
|
|
518
551
|
def tag_category_dlg(self) -> str:
|
|
519
|
-
return self.
|
|
552
|
+
return self._tag_category_dlg
|
|
553
|
+
|
|
554
|
+
@property
|
|
555
|
+
def TagCategoryDlg(self) -> str:
|
|
556
|
+
"""Backward compatibility property for tag_category_dlg."""
|
|
557
|
+
return self.tag_category_dlg
|
|
520
558
|
|
|
521
559
|
@property
|
|
522
560
|
def individ_flag(self) -> str:
|
|
523
|
-
return self.
|
|
561
|
+
return self._individ_flag
|
|
562
|
+
|
|
563
|
+
@property
|
|
564
|
+
def IndividFlag(self) -> str:
|
|
565
|
+
"""Backward compatibility property for individ_flag."""
|
|
566
|
+
return self.individ_flag
|
|
524
567
|
|
|
525
568
|
@property
|
|
526
569
|
def sap_fl_category(self) -> str:
|
|
527
|
-
return self.
|
|
570
|
+
return self._sap_fl_category
|
|
571
|
+
|
|
572
|
+
@property
|
|
573
|
+
def SapFlCategory(self) -> str:
|
|
574
|
+
"""Backward compatibility property for sap_fl_category."""
|
|
575
|
+
return self.sap_fl_category
|
|
528
576
|
|
|
529
577
|
def get_formats(self) -> List[TagFormat]:
|
|
530
578
|
"""Get tag formats for this specific tag category.
|
|
@@ -625,7 +673,9 @@ def _get_category_data(inst_code: str) -> List[dict]:
|
|
|
625
673
|
global _cache
|
|
626
674
|
|
|
627
675
|
if inst_code not in _cache["TagCategory"].keys():
|
|
628
|
-
_cache["TagCategory"][inst_code] =
|
|
676
|
+
_cache["TagCategory"][inst_code] = Code._get_code_data(
|
|
677
|
+
"TagCategory", scope=inst_code
|
|
678
|
+
)
|
|
629
679
|
|
|
630
680
|
return _cache["TagCategory"][inst_code]
|
|
631
681
|
|
|
@@ -642,7 +692,7 @@ def _get_type_data(inst_code: str) -> List[dict]:
|
|
|
642
692
|
global _cache
|
|
643
693
|
|
|
644
694
|
if inst_code not in _cache["TagType"].keys():
|
|
645
|
-
_cache["TagType"][inst_code] =
|
|
695
|
+
_cache["TagType"][inst_code] = Code._get_code_data("TagType", scope=inst_code)
|
|
646
696
|
|
|
647
697
|
return _cache["TagType"][inst_code]
|
|
648
698
|
|
|
@@ -656,7 +706,7 @@ def _get_master_type_data(scope="") -> List[dict]:
|
|
|
656
706
|
global _cache
|
|
657
707
|
|
|
658
708
|
if "MasterTagType" not in _cache.keys():
|
|
659
|
-
_cache["MasterTagType"] =
|
|
709
|
+
_cache["MasterTagType"] = Code._get_code_data("MasterTagType")
|
|
660
710
|
|
|
661
711
|
return _cache["MasterTagType"]
|
|
662
712
|
|
|
@@ -673,6 +723,8 @@ def _get_format_data(inst_code: str) -> List[dict]:
|
|
|
673
723
|
global _cache
|
|
674
724
|
|
|
675
725
|
if inst_code not in _cache["TagFormat"].keys():
|
|
676
|
-
_cache["TagFormat"][inst_code] =
|
|
726
|
+
_cache["TagFormat"][inst_code] = Code._get_code_data(
|
|
727
|
+
"TagFormat", scope=inst_code
|
|
728
|
+
)
|
|
677
729
|
|
|
678
730
|
return _cache["TagFormat"][inst_code]
|
|
@@ -1,10 +1,19 @@
|
|
|
1
|
-
from typing import Union
|
|
1
|
+
from typing import List, Union
|
|
2
2
|
|
|
3
|
-
from commonlib_reader.
|
|
3
|
+
from commonlib_reader.code import Code
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
class Unit:
|
|
7
|
-
|
|
7
|
+
"""A class representing a unit of measurement.
|
|
8
|
+
|
|
9
|
+
Properties:
|
|
10
|
+
name (str): The name of the unit.
|
|
11
|
+
description (str): A description of the unit.
|
|
12
|
+
identity (str): The unique identifier for the unit.
|
|
13
|
+
quantity (str): The quantity this unit measures.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
_units = None
|
|
8
17
|
|
|
9
18
|
def __init__(self, data: Union[dict, str]):
|
|
10
19
|
if isinstance(data, str):
|
|
@@ -26,41 +35,48 @@ class Unit:
|
|
|
26
35
|
raise ValueError("Input data must be a dict from codetable")
|
|
27
36
|
|
|
28
37
|
@property
|
|
29
|
-
def name(self):
|
|
38
|
+
def name(self) -> str:
|
|
39
|
+
"""Get the unit name."""
|
|
30
40
|
return getattr(self, "_name", "")
|
|
31
41
|
|
|
32
42
|
@name.setter
|
|
33
|
-
def name(self, value):
|
|
43
|
+
def name(self, value: str):
|
|
44
|
+
"""Set the unit name."""
|
|
34
45
|
self._name = value
|
|
35
46
|
|
|
36
47
|
@property
|
|
37
|
-
def description(self):
|
|
48
|
+
def description(self) -> str:
|
|
49
|
+
"""Get the unit description."""
|
|
38
50
|
return getattr(self, "_description", "")
|
|
39
51
|
|
|
40
52
|
@description.setter
|
|
41
|
-
def description(self, value):
|
|
53
|
+
def description(self, value: str):
|
|
54
|
+
"""Set the unit description."""
|
|
42
55
|
self._description = value
|
|
43
56
|
|
|
44
57
|
@property
|
|
45
|
-
def identity(self):
|
|
58
|
+
def identity(self) -> str:
|
|
59
|
+
"""Get the unit identity."""
|
|
46
60
|
return getattr(self, "_identity", "")
|
|
47
61
|
|
|
48
62
|
@identity.setter
|
|
49
|
-
def identity(self, value):
|
|
63
|
+
def identity(self, value: str):
|
|
64
|
+
"""Set the unit identity."""
|
|
50
65
|
self._identity = value
|
|
51
66
|
|
|
52
67
|
@property
|
|
53
|
-
def quantity(self):
|
|
68
|
+
def quantity(self) -> str:
|
|
69
|
+
"""Get the quantity measured by this unit."""
|
|
54
70
|
return getattr(self, "Quantity", "")
|
|
55
71
|
|
|
56
72
|
@classmethod
|
|
57
|
-
def get_units(cls):
|
|
73
|
+
def get_units(cls) -> List["Unit"]:
|
|
58
74
|
"""Get list of Unit objects of entries in code library. Caches locally in memory.
|
|
59
75
|
|
|
60
76
|
Returns:
|
|
61
|
-
List[
|
|
77
|
+
List[Unit]: List of Unit objects from entries in code library.
|
|
62
78
|
"""
|
|
63
|
-
if cls._units is None
|
|
64
|
-
cls._units =
|
|
79
|
+
if cls._units is None:
|
|
80
|
+
cls._units = Code._get_code_data("UnitOfMeasure")
|
|
65
81
|
|
|
66
82
|
return [Unit(x) for x in cls._units]
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import json
|
|
2
|
-
from typing import Dict, List
|
|
2
|
+
from typing import Dict, List
|
|
3
3
|
from urllib.parse import urljoin
|
|
4
4
|
|
|
5
5
|
import requests
|
|
@@ -7,43 +7,6 @@ import requests
|
|
|
7
7
|
from commonlib_reader.connector import get_connector
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
def get_library_names() -> list[str]:
|
|
11
|
-
library_names = get_connector().get_json(url="/api/Library/NameList")
|
|
12
|
-
if isinstance(library_names, list) and all(
|
|
13
|
-
[isinstance(x, str) for x in library_names]
|
|
14
|
-
):
|
|
15
|
-
library_names.sort() # type: ignore
|
|
16
|
-
return library_names # type: ignore
|
|
17
|
-
|
|
18
|
-
raise ValueError("Wrong data from API when getting library names.")
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
def get_code(code: str, scope: Optional[str] = None, name: Optional[str] = None):
|
|
22
|
-
params = {}
|
|
23
|
-
if scope is not None:
|
|
24
|
-
params["scope"] = scope
|
|
25
|
-
|
|
26
|
-
if name is not None:
|
|
27
|
-
params["name"] = name
|
|
28
|
-
return get_code_param(code=code, params=params)
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
def get_code_param(code, params=None):
|
|
32
|
-
"""_summary_
|
|
33
|
-
|
|
34
|
-
Args:
|
|
35
|
-
code (_type_): _description_
|
|
36
|
-
params (_type_, optional): _description_. Defaults to None.
|
|
37
|
-
|
|
38
|
-
Returns:
|
|
39
|
-
_type_: _description_
|
|
40
|
-
"""
|
|
41
|
-
if params is None:
|
|
42
|
-
params = {}
|
|
43
|
-
|
|
44
|
-
return get_connector().get_json(f"/api/Code/{code}", params=params)
|
|
45
|
-
|
|
46
|
-
|
|
47
10
|
def query_sql(sql: str):
|
|
48
11
|
return post_sql(sql=sql, take=0, skip=0)
|
|
49
12
|
|
commonlib_reader-1.2.0/PKG-INFO
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.3
|
|
2
|
-
Name: commonlib-reader
|
|
3
|
-
Version: 1.2.0
|
|
4
|
-
Summary: Reader for Equinor commonlib api.
|
|
5
|
-
Author: Åsmund Våge Fannemel
|
|
6
|
-
Author-email: Åsmund Våge Fannemel <asmf@equinor.com>
|
|
7
|
-
License: MIT
|
|
8
|
-
Requires-Dist: pandas>=2.1.4
|
|
9
|
-
Requires-Dist: eq-api-connector>=1.1.0,<2.0.0
|
|
10
|
-
Requires-Python: >=3.10, <4.0.0
|
|
11
|
-
Project-URL: Repository, https://github.com/equinor/commonlib-reader.git
|
|
12
|
-
Description-Content-Type: text/markdown
|
|
13
|
-
|
|
14
|
-
# commonlib-reader
|
|
15
|
-
Connector package for Equinor [Commonlib](https://commonlib.equinor.com/) [api](https://commonlibapi.equinor.com/swagger/index.html).
|
|
16
|
-
|
|
17
|
-
Current features:
|
|
18
|
-
- Reading code tables
|
|
19
|
-
- Getting facility data using the [Facility](commonlib_reader/facility.py) class
|
|
20
|
-
- [IMS source ](commonlib_reader/ims.py) lookup tables for facilities
|
|
21
|
-
- Getting Tag category, Tag type, Tag format, and Tag format element data. See [tag.py](commonlib_reader/tag.py)
|
|
22
|
-
- Getting [units of measure](commonlib_reader/ims.py) definitions.
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
## Use
|
|
26
|
-
Try it out by running the [demo](examples/demo.py).
|
|
27
|
-
|
|
28
|
-
## Installing
|
|
29
|
-
|
|
30
|
-
Install package from pypi using `pip install commonlib_reader`
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
## Developing / testing
|
|
34
|
-
|
|
35
|
-
uv is preferred for developers. Clone and install with required packages for testing and coverage:
|
|
36
|
-
`uv sync`
|
|
37
|
-
|
|
38
|
-
For testing with coverage run:
|
|
39
|
-
`uv run pytest --cov --cov-report=html`
|
commonlib_reader-1.2.0/README.md
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
# commonlib-reader
|
|
2
|
-
Connector package for Equinor [Commonlib](https://commonlib.equinor.com/) [api](https://commonlibapi.equinor.com/swagger/index.html).
|
|
3
|
-
|
|
4
|
-
Current features:
|
|
5
|
-
- Reading code tables
|
|
6
|
-
- Getting facility data using the [Facility](commonlib_reader/facility.py) class
|
|
7
|
-
- [IMS source ](commonlib_reader/ims.py) lookup tables for facilities
|
|
8
|
-
- Getting Tag category, Tag type, Tag format, and Tag format element data. See [tag.py](commonlib_reader/tag.py)
|
|
9
|
-
- Getting [units of measure](commonlib_reader/ims.py) definitions.
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
## Use
|
|
13
|
-
Try it out by running the [demo](examples/demo.py).
|
|
14
|
-
|
|
15
|
-
## Installing
|
|
16
|
-
|
|
17
|
-
Install package from pypi using `pip install commonlib_reader`
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
## Developing / testing
|
|
21
|
-
|
|
22
|
-
uv is preferred for developers. Clone and install with required packages for testing and coverage:
|
|
23
|
-
`uv sync`
|
|
24
|
-
|
|
25
|
-
For testing with coverage run:
|
|
26
|
-
`uv run pytest --cov --cov-report=html`
|