commonlib-reader 1.0.0__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.
@@ -0,0 +1,25 @@
1
+ from commonlib_reader.utils import (
2
+ get_code,
3
+ get_code_param,
4
+ get_disciplines,
5
+ get_library_names,
6
+ )
7
+
8
+
9
+ from .tag import TagType, TagCategory, TagFormat
10
+ from .ims import IMS
11
+ from .facility import Facility
12
+ from .unit import Unit
13
+
14
+ __all__ = [
15
+ "Facility",
16
+ "IMS",
17
+ "TagType",
18
+ "TagCategory",
19
+ "TagFormat",
20
+ "Unit",
21
+ "get_code",
22
+ "get_code_param",
23
+ "get_disciplines",
24
+ "get_library_names",
25
+ ]
@@ -0,0 +1,105 @@
1
+ from typing import List
2
+
3
+ from commonlib_reader.utils import attributes_list_to_dict, get_code
4
+
5
+
6
+ class Facility:
7
+ """
8
+ Facility class to encapsulate information.
9
+
10
+ Attributes:
11
+ identity (str) : A unique identifier for the facility (read from the data source).
12
+ name (str) : The name of the facility (read from the data source).
13
+ description (str) : A description of the facility (read from the data source).
14
+ SAPPlant (str) : SAP Plant code (if available).
15
+ Field (str) : Field identifier associated with the facility (if available).
16
+ ParentFacility (str) : Parent facility identifier (if available).
17
+ NPDID (str) : NPD ID (if available).
18
+
19
+ _cache (list of dict, optional):
20
+ Class level cache to store facility data, to minimize data source access.
21
+
22
+ """
23
+
24
+ _cache = None
25
+
26
+ def __init__(self, code):
27
+ """
28
+ Initializes the Facility instance by retrieving data related to the given STID plant code.
29
+
30
+ Parameters:
31
+ code (str): The code used to retrieve facility data from the data source.
32
+
33
+ Raises:
34
+ ValueError: If no data is found for the provided code.
35
+ """
36
+ self._data = Facility._get_facility(code=code)
37
+ self._attributes = attributes_list_to_dict(self._data["attributes"])
38
+
39
+ self.identity = self._data["identity"]
40
+ self.name = self._data["name"]
41
+ self.description = self._data["description"]
42
+
43
+ common_attributes = ["SAPPlant", "Field", "ParentFacility", "NPDID"]
44
+ for attr in common_attributes:
45
+ self.__setattr__(attr, "")
46
+
47
+ for key, val in self._attributes.items():
48
+ if key in common_attributes:
49
+ self.__setattr__(key, val)
50
+
51
+ def isSTID(self):
52
+ """
53
+ Checks if the facility is marked for STID.
54
+
55
+ Returns:
56
+ bool: True if the facility is marked for STID, False otherwise.
57
+ """
58
+ if "IsForSTID" in self._attributes.keys():
59
+ if self._attributes["IsForSTID"] == "True":
60
+ return True
61
+
62
+ return False
63
+
64
+ @classmethod
65
+ def get_all_facilities(cls) -> List["Facility"]:
66
+ """
67
+ Retrieves and returns a list of Facility instances for all known facilities.
68
+
69
+ Returns:
70
+ List[Facility]: A list of Facility instances.
71
+ """
72
+ f = Facility._get_all_facilities()
73
+ return [Facility(x["identity"]) for x in f]
74
+
75
+ @classmethod
76
+ def _get_all_facilities(cls) -> List[dict]:
77
+ """
78
+ Retrieves all facility data, using a class level cache.
79
+
80
+ Returns:
81
+ List[dict]: A list of dictionaries, each representing facility data.
82
+ """
83
+ if cls._cache is None:
84
+ cls._cache = get_code("Facility")
85
+
86
+ return cls._cache
87
+
88
+ @classmethod
89
+ def _get_facility(cls, code) -> dict:
90
+ """
91
+ Retrieves the facility data for the given code.
92
+
93
+ Parameters:
94
+ code (str): The STID plant code corresponding to the facility.
95
+
96
+ Returns:
97
+ dict: A dictionary containing data related to the facility.
98
+
99
+ Raises:
100
+ ValueError: If no data is found for the provided code.
101
+ """
102
+ for f in cls._get_all_facilities():
103
+ if f["identity"] == code or f["name"] == code or f["description"] == code:
104
+ return f
105
+ raise ValueError(f"No data found for {code}")
@@ -0,0 +1,126 @@
1
+ from typing import List, Union
2
+ from commonlib_reader.utils import attributes_list_to_dict, get_code
3
+
4
+
5
+ class IMS:
6
+ _ims_codes = []
7
+
8
+ """Class for IMS objects.
9
+
10
+ properties:
11
+ Facility (str) - Name of facility
12
+ IMSType (str) - Type of IMS
13
+ Alias (str) - Facility name aliases
14
+ isValid (bool) - True if IMS is in operation
15
+ """
16
+
17
+ def __init__(self, data: Union[str, dict]):
18
+ """Instance constructor for IMS object. End-users should use static method IMS.from_facility()
19
+
20
+ Args:
21
+ data (str,dict): Facility name or data dictionary to populate instance data attributes.
22
+
23
+ Raises:
24
+ ValueError: If input data is not a dict.
25
+ """
26
+ if isinstance(data, str):
27
+ data = IMS.from_facility(data)._data
28
+
29
+ if not isinstance(data, dict):
30
+ raise ValueError("Input data must be a dict from codetable")
31
+
32
+ self._data = data
33
+ self._attributes = attributes_list_to_dict(self._data["attributes"])
34
+
35
+ self.isValid = data["isValid"]
36
+
37
+ self.Facility = ""
38
+ self.IMSType = ""
39
+ self.Alias = ""
40
+
41
+ for attr in self._data["attributes"]:
42
+ self.__setattr__(attr["definitionName"], attr["displayValue"])
43
+
44
+ @staticmethod
45
+ def from_facility(facility: str) -> "IMS":
46
+ """Get IMS instance from STID code.
47
+
48
+ Args:
49
+ facility (str): Facility code
50
+
51
+ Raises:
52
+ ValueError: Not able to instantiate IMS object from input facility code.
53
+
54
+ Returns:
55
+ IMS: IMS instance
56
+ """
57
+ if facility is None or len(facility) == 0:
58
+ raise ValueError(
59
+ "Facility must be provided. Empty strings are not allowed."
60
+ )
61
+ ims = IMS.get_ims_list(facility=facility)
62
+ if len(ims) == 1:
63
+ return ims[0]
64
+
65
+ raise ValueError(f"Not able to get IMS object for facility {facility}")
66
+
67
+ @classmethod
68
+ def _get_ims_codes(cls) -> List["IMS"]:
69
+ """Get list of IMS instance of entries in code library ApplicationIMS. Caches locally in memory.
70
+
71
+ Returns:
72
+ List[IMS]: list of IMS instance from entries in code library ApplicationIMS.
73
+ """
74
+ if cls._ims_codes is None or len(cls._ims_codes) == 0:
75
+ cls._ims_codes = get_code("ApplicationIMS")
76
+
77
+ return [IMS(x) for x in cls._ims_codes]
78
+
79
+ @staticmethod
80
+ def get_ims_list(facility: str = "") -> List["IMS"]:
81
+ """Get list of IMS objects.
82
+
83
+ Args:
84
+ facility (str, optional): Facility. Defaults to "", which will get list of all entries defined in lib.
85
+
86
+ Returns:
87
+ List[IMS]: list of IMS objects
88
+ """
89
+ i = IMS._get_ims_codes()
90
+ if len(facility) > 0:
91
+ return [x for x in i if x.Facility == facility]
92
+
93
+ return i
94
+
95
+ @staticmethod
96
+ def get_source(facility: str) -> str:
97
+ """Get IMS name for a facility.
98
+
99
+ Args:
100
+ facility (str): Name of facility.
101
+
102
+ Raises:
103
+ ValueError: If facility input is invalid, i.e., empty.
104
+
105
+ Returns:
106
+ str: Name of IMS
107
+ """
108
+
109
+ l_ims = IMS.from_facility(facility=facility)
110
+ return l_ims.Alias
111
+
112
+ @staticmethod
113
+ def get_type(facility: str) -> str:
114
+ """Get IMS type for a facility.
115
+
116
+ Args:
117
+ facility (str): Name of facility
118
+
119
+ Raises:
120
+ ValueError: If facility input is invalid, i.e., empty.
121
+
122
+ Returns:
123
+ str: Type of IMS
124
+ """
125
+ l_ims = IMS.from_facility(facility=facility)
126
+ return l_ims.IMSType
@@ -0,0 +1,439 @@
1
+ from typing import List, Union
2
+ from commonlib_reader.utils import get_code, get_code_param, query_sql
3
+
4
+ # from commonlib_reader.utils import attributes_list_to_dict
5
+
6
+ _cache = {}
7
+ _cache["TagType"] = {}
8
+ _cache["TagCategory"] = {}
9
+ _cache["TagFormat"] = {}
10
+
11
+
12
+ class TagFormat:
13
+ """
14
+ A class that represents the format of a tag within the context of a Facility.
15
+
16
+ Attributes:
17
+ inst_code (str): Installation code.
18
+ description (str): Description of the tag format.
19
+ tag_category (str): Tag category this format belongs to.
20
+ syntax (str): The syntax structure of the tag format.
21
+ regex (str): The regular expression pattern representing the tag format.
22
+ regex_grouped (str): Grouped regular expression pattern for the tag format.
23
+ """
24
+
25
+ def __init__(self, data: dict, inst_code: str):
26
+ """
27
+ Initializes a TagFormat object.
28
+
29
+ Parameters:
30
+ data (dict): Data containing different properties of a tag format.
31
+ inst_code (str): Installation code for this tag format.
32
+ """
33
+ self._data = data
34
+ # self._attributes = attributes_list_to_dict(self._data["attributes"])
35
+
36
+ self.inst_code = inst_code
37
+ self.description = data["description"]
38
+
39
+ self.tag_category = ""
40
+ self.syntax = ""
41
+ self.regex = ""
42
+ self.regex_grouped = ""
43
+
44
+ for attr in self._data["attributes"]:
45
+ if attr["definitionName"] == "TagCategory":
46
+ self.tag_category = attr["displayValue"]
47
+ elif attr["definitionName"] == "Syntax":
48
+ self.syntax = attr["displayValue"]
49
+ elif attr["definitionName"] == "Regex":
50
+ self.regex = attr["displayValue"]
51
+ elif attr["definitionName"] == "RegexGrouped":
52
+ self.regex_grouped = attr["displayValue"]
53
+
54
+ def __str__(self):
55
+ return f"{self.description} - {self.tag_category}"
56
+
57
+ @staticmethod
58
+ def get_tagformat(
59
+ description: str, inst_code: str, tag_category: str
60
+ ) -> "TagFormat":
61
+ """
62
+ Retrieve a tag format for a given description, installation code and tag category.
63
+
64
+ Parameters:
65
+ description (str): Description of the tag format to retrieve.
66
+ inst_code (str): Installation code of the requested tag format.
67
+ tag_category (str): Category of the requested tag format.
68
+
69
+ Returns:
70
+ TagFormat: The requested tag format object.
71
+ """
72
+ t = TagCategory.get_category(inst_code=inst_code, name=tag_category)
73
+ return t[0].get_format(description)
74
+
75
+
76
+ class TagType:
77
+ """
78
+ A class that represents a tag type, which is pertinent to a tag category and
79
+ associated with a particular facility.
80
+
81
+ Attributes:
82
+ inst_code (str): The facility code the tag type is associated with.
83
+ name (str): The name of the tag type.
84
+ description (str): A description of the tag type.
85
+ is_valid (bool): A flag indicating whether the tag type is valid.
86
+ tag_category (str): The category under which this tag type falls.
87
+ STID_tag_Count (int): The number of STID tags associated with this tag type.
88
+ """
89
+
90
+ def __init__(self, data: dict, inst_code: str):
91
+ """
92
+ Initializes a TagType object with provided data and installation code.
93
+
94
+ Parameters:
95
+ data (dict): Data containing different properties of a tag type.
96
+ inst_code (str): Installation code for which this tag type applies.
97
+ """
98
+ self._data = data
99
+ self.inst_code = inst_code
100
+
101
+ self.name = self._data["name"]
102
+ self.description = self._data["description"]
103
+ self.is_valid = self._data["isValid"]
104
+ self.tag_category = ""
105
+
106
+ for attr in self._data["attributes"]:
107
+ if attr["definitionName"] == "STIDTagCount":
108
+ self.STID_tag_Count = int(attr["displayValue"])
109
+ elif attr["definitionName"] == "TagCategory":
110
+ self.tag_category = attr["displayValue"]
111
+
112
+ def __str__(self):
113
+ return f"{self.name} - {self.description}"
114
+
115
+ @staticmethod
116
+ def get_tagtype(name: str, inst_code: str, tag_category: str) -> "TagType":
117
+ """
118
+ Retrieve a tag type object based on the name, installation code, and tag category.
119
+
120
+ Parameters:
121
+ name (str): Name of the tag type to retrieve.
122
+ inst_code (str): Installation code specific to the tag type.
123
+ tag_category (str): Category to which the tag type belongs.
124
+
125
+ Returns:
126
+ TagType: The TagType object matching the criteria.
127
+ """
128
+ t = TagCategory.get_category(inst_code=inst_code, name=tag_category)
129
+ return t[0].get_type(name)
130
+
131
+ @staticmethod
132
+ def get_tagtype_no_cache(
133
+ name: str, inst_code: str, tag_category: str = ""
134
+ ) -> "TagType":
135
+ """
136
+ Retrieve tag types for the given name and installation code without using the cache. Optionally filter by tag category.
137
+
138
+ Parameters:
139
+ name (str): The name of the tag type to retrieve.
140
+ inst_code (str): Installation code specific to the tag type.
141
+ tag_category (str, optional): Optional category to filter the tag types.
142
+
143
+ Returns:
144
+ List[TagType]: A list of TagType objects matching the criteria.
145
+ """
146
+
147
+ params = {}
148
+ params["scope"] = inst_code
149
+ params["name"] = name
150
+
151
+ tag_types = [
152
+ TagType(x, inst_code=inst_code)
153
+ for x in get_code_param("TagType", params=params)
154
+ ]
155
+
156
+ if tag_category:
157
+ tag_types = [x for x in tag_types if x.tag_category == tag_category]
158
+
159
+ return tag_types
160
+
161
+ @staticmethod
162
+ def get_master_tagtype(
163
+ name: str, tag_category: str = "", technology: str = "Oil&Gas"
164
+ ) -> "TagType":
165
+ """
166
+ Retrieve master tag types based on name, category, and technology. If name is empty,
167
+ sorts by name and returns all. If name is provided, filters by name.
168
+
169
+ Parameters:
170
+ name (str): The name of the master tag type to retrieve. Can be empty to retrieve all.
171
+ tag_category (str, optional): Category to filter the master tag types. Can be empty to not filter.
172
+ technology (str, optional): Technology to filter the master tag types, defaults to 'Oil&Gas'.
173
+
174
+ Returns:
175
+ List[TagType]: A list of TagType objects matching the criteria.
176
+ """
177
+ return_value = []
178
+ d = _get_master_type_data()
179
+ for k in range(0, len(d)):
180
+ for att in d[k]["attributes"]:
181
+ if att["definitionName"] == "Technology":
182
+ currTechnology = att["displayValue"]
183
+ break
184
+
185
+ include_technology = (
186
+ technology is None
187
+ or len(technology) == 0
188
+ or currTechnology == technology
189
+ )
190
+
191
+ include_category = tag_category is None or len(tag_category) == 0
192
+ if not include_category:
193
+ for att in d[k]["attributes"]:
194
+ if (
195
+ att["definitionName"] == "TagCategory"
196
+ and att["displayValue"] == tag_category
197
+ ):
198
+ include_category = True
199
+ break
200
+
201
+ if include_category and include_technology:
202
+ return_value.append(TagType(d[k], currTechnology))
203
+
204
+ if not name:
205
+ return_value.sort(key=lambda x: x.name)
206
+ else:
207
+ return_value = [x for x in return_value if x.name == name]
208
+
209
+ return return_value
210
+
211
+ @staticmethod
212
+ def get_master_tagtype_mappings(
213
+ name: str, tag_category: str = "", technology: str = "Oil&Gas"
214
+ ):
215
+ """
216
+ Retrieve mappings of the master tag types based on name, category,
217
+ and technology. Raises a ValueError if no relevant mappings are found
218
+ or if more than one master tag type is matching name, tag category and technology input.
219
+
220
+ Parameters:
221
+ name (str): The name of the master tag type to search for mappings.
222
+ tag_category (str, optional): Category to filter the tag type mappings. Can be empty to not filter.
223
+ technology (str, optional): Technology to filter the tag type mappings, defaults to 'Oil&Gas'.
224
+
225
+ Returns:
226
+ List: A list of mapped tag types.
227
+
228
+ Raises:
229
+ ValueError: If no master tag type is found, or if multiple master tag types are found.
230
+ """
231
+ mtt = TagType.get_master_tagtype(
232
+ name=name, tag_category=tag_category, technology=technology
233
+ )
234
+
235
+ if len(mtt) == 0:
236
+ raise ValueError("No master tag type found")
237
+
238
+ if len(mtt) > 1:
239
+ raise ValueError("Multiple master tag types found. Currently not supported")
240
+
241
+ sql = f"""SELECT tt.scope Facility,tt.Name LocalTagType, tt.tagcategory LocalTagCategory FROM MasterTagType mtt
242
+ inner join TagType tt on tt.MasterTagType_ID=mtt.id
243
+ where mtt.tagcategory='{mtt[0].tag_category}' and mtt.Name ='{mtt[0].name}' and mtt.Technology='{mtt[0].inst_code}' and tt.isValid='True'
244
+ order by tt.name, tt.scope"""
245
+
246
+ res = query_sql(sql=sql)
247
+ mapped_types = []
248
+ [
249
+ mapped_types.extend(
250
+ TagType.get_tagtype_no_cache(
251
+ x["LocalTagType"], x["Facility"], x["LocalTagCategory"]
252
+ )
253
+ )
254
+ for x in res
255
+ ]
256
+ return mapped_types
257
+
258
+
259
+ class TagCategory:
260
+ """
261
+ A class representing a Facility specific category of tag types.
262
+
263
+ Attributes:
264
+ inst_code (str): Installation code for the facilitye the TagCategory is associated with.
265
+ name (str): Name of the tag category.
266
+ description (str): Description of the tag category.
267
+ is_valid (bool): Flag indicating whether the tag category is considered valid.
268
+ TagCategoryId (int): Unique identifier of the tag category.
269
+ TagCategoryDlg (str): Additional dialog information associated with the tag category.
270
+ IndividFlag (str): A flag indicating individual characteristics for the category.
271
+ SapFlCategory (str): Corresponding SAP functional location category.
272
+ """
273
+
274
+ def __init__(self, data, inst_code):
275
+ """
276
+ Initializes a TagCategory object.
277
+
278
+ Parameters:
279
+ data (dict): Data containing different properties of a tag category.
280
+ inst_code (str): Installation code for which this tag category applies.
281
+ """
282
+ self._data = data
283
+ self.inst_code = inst_code
284
+
285
+ self.name = self._data["name"]
286
+ self.description = self._data["description"]
287
+ self.is_valid = self._data["isValid"]
288
+
289
+ for attr in self._data["attributes"]:
290
+ if attr["definitionName"] == "TagCategoryId":
291
+ self.TagCategoryId = int(attr["displayValue"])
292
+ elif attr["definitionName"] == "TagCategoryDlg":
293
+ self.TagCategoryDlg = attr["displayValue"]
294
+ elif attr["definitionName"] == "IndividFlag":
295
+ self.IndividFlag = attr["displayValue"]
296
+ elif attr["definitionName"] == "SapFlCategory":
297
+ self.SapFlCategory = attr["displayValue"]
298
+
299
+ self._types = []
300
+ self._formats = []
301
+
302
+ def get_formats(self) -> List[TagFormat]:
303
+ """Get tag formats for this specific tag category.
304
+
305
+ Returns:
306
+ List[TagType]: List of TagFormat objects belonging to this category.
307
+ """
308
+ if self._formats is None or len(self._formats) == 0:
309
+ tag_formats = [
310
+ TagFormat(x, self.inst_code) for x in _get_format_data(self.inst_code)
311
+ ]
312
+ self._formats = [x for x in tag_formats if x.tag_category == self.name]
313
+
314
+ return self._formats
315
+
316
+ def get_format(self, description: str) -> TagFormat:
317
+ """Get single tag format for this specific tag category.
318
+
319
+ Args:
320
+ format (str): Description (name) of tag format.
321
+
322
+ Returns:
323
+ TagFormat: Tag format object
324
+ """
325
+ for curr_type in self.get_formats():
326
+ if curr_type.description == description:
327
+ return curr_type
328
+
329
+ return None
330
+
331
+ def get_types(self) -> List[TagType]:
332
+ """Get tag types for this specific tag category.
333
+
334
+ Returns:
335
+ List[TagType]: List of TagType objects belonging to this category.
336
+ """
337
+ if self._types is None or len(self._types) == 0:
338
+ tag_types = [
339
+ TagType(x, self.inst_code) for x in _get_type_data(self.inst_code)
340
+ ]
341
+ self._types = [x for x in tag_types if x.tag_category == self.name]
342
+ self._types.sort(key=lambda x: x.name)
343
+
344
+ return self._types
345
+
346
+ def get_type(self, type: str) -> Union[TagType, None]:
347
+ """Get single type from this specific tag category.
348
+
349
+ Args:
350
+ type (str): Type name
351
+
352
+ Returns:
353
+ Union[TagType, None]: TagType if found, else None.
354
+ """
355
+ for curr_type in self.get_types():
356
+ if curr_type.name == type:
357
+ return curr_type
358
+
359
+ return None
360
+
361
+ def __str__(self):
362
+ return f"{self.TagCategoryId}:{self.name} - {self.description}"
363
+
364
+ @staticmethod
365
+ def get_category(inst_code, name="") -> List["TagCategory"]:
366
+ categories = _get_category_data(inst_code=inst_code)
367
+ tc = [TagCategory(x, inst_code=inst_code) for x in categories]
368
+ tc.sort(key=lambda x: x.TagCategoryId)
369
+ if name is None:
370
+ pass
371
+ elif isinstance(name, str) and len(name) > 0:
372
+ tc = [x for x in tc if x.name == name or x.description == name]
373
+
374
+ return tc
375
+
376
+
377
+ def _get_category_data(inst_code) -> List[dict]:
378
+ """Get code table of tag categories for a facility from commonlibapi.
379
+
380
+ Args:
381
+ inst_code (str): STID installation code.
382
+
383
+ Returns:
384
+ List[dict]: Data for each tag category.
385
+ """
386
+ global _cache
387
+
388
+ if inst_code not in _cache["TagCategory"].keys():
389
+ _cache["TagCategory"][inst_code] = get_code("TagCategory", scope=inst_code)
390
+
391
+ return _cache["TagCategory"][inst_code]
392
+
393
+
394
+ def _get_type_data(inst_code: str) -> List[dict]:
395
+ """Get code table of tag types for an installation from commonlibapi.
396
+
397
+ Args:
398
+ inst_code (str): STID installation code.
399
+
400
+ Returns:
401
+ List[dict]: Data for each tag type.
402
+ """
403
+ global _cache
404
+
405
+ if inst_code not in _cache["TagType"].keys():
406
+ _cache["TagType"][inst_code] = get_code("TagType", scope=inst_code)
407
+
408
+ return _cache["TagType"][inst_code]
409
+
410
+
411
+ def _get_master_type_data(scope="") -> List[dict]:
412
+ """Get code table of master tag types from commonlibapi.
413
+
414
+ Returns:
415
+ List[dict]: Data for each tag type.
416
+ """
417
+ global _cache
418
+
419
+ if "MasterTagType" not in _cache.keys():
420
+ _cache["MasterTagType"] = get_code("MasterTagType")
421
+
422
+ return _cache["MasterTagType"]
423
+
424
+
425
+ def _get_format_data(inst_code: str) -> List[dict]:
426
+ """Get code table of tag formats for an installation from commonlibapi.
427
+
428
+ Args:
429
+ inst_code (str): STID installation code.
430
+
431
+ Returns:
432
+ List[dict]: Data for each format.
433
+ """
434
+ global _cache
435
+
436
+ if inst_code not in _cache["TagFormat"].keys():
437
+ _cache["TagFormat"][inst_code] = get_code("TagFormat", scope=inst_code)
438
+
439
+ return _cache["TagFormat"][inst_code]
@@ -0,0 +1,44 @@
1
+ from commonlib_reader.utils import get_code
2
+
3
+ # from commonlib_reader.utils import attributes_list_to_dict
4
+
5
+
6
+ class Unit:
7
+ _units = []
8
+
9
+ def __init__(self, data):
10
+ self.name = ""
11
+ self.description = ""
12
+
13
+ self.identity = ""
14
+ self.quantity = ""
15
+
16
+ if isinstance(data, str):
17
+ s = [x for x in Unit.get_units() if x.name == data]
18
+ if len(s) > 0:
19
+ data = s[0]._data
20
+ else:
21
+ raise ValueError(f"No unit named {data} found.")
22
+
23
+ if isinstance(data, dict):
24
+ self._data = data
25
+ # self._attributes = attributes_list_to_dict(self._data["attributes"])
26
+
27
+ for key in data.keys():
28
+ if key == "attributes":
29
+ for attr in data["attributes"]:
30
+ self.__setattr__(attr["definitionName"], attr["displayValue"])
31
+ else:
32
+ self.__setattr__(key, data[key])
33
+
34
+ @classmethod
35
+ def get_units(cls):
36
+ """Get list of Unit objects of entries in code library. Caches locally in memory.
37
+
38
+ Returns:
39
+ List[IMS]: list of Unit objects from entries in code library.
40
+ """
41
+ if cls._units is None or len(cls._units) == 0:
42
+ cls._units = get_code("UnitOfMeasure")
43
+
44
+ return [Unit(x) for x in cls._units]
@@ -0,0 +1,139 @@
1
+ import json
2
+ from typing import Dict, List
3
+ from urllib.parse import urljoin
4
+
5
+ import requests
6
+ from msal_bearer.BearerAuth import BearerAuth, get_login_name
7
+
8
+
9
+ def get_library_names():
10
+ url = urljoin(get_api_url(), "api/Library/NameList")
11
+ library_names = get_json(url=url)
12
+ library_names.sort()
13
+ return library_names
14
+
15
+
16
+ def get_disciplines():
17
+ return get_code("Discipline")
18
+
19
+
20
+ def get_code(code: str, scope: str = None, name: str = None):
21
+ params = {}
22
+ if scope is not None:
23
+ params["scope"] = scope
24
+
25
+ if name is not None:
26
+ params["name"] = name
27
+ return get_code_param(code=code, params=params)
28
+
29
+
30
+ def get_code_param(code, params=None):
31
+ if params is None:
32
+ params = {}
33
+
34
+ url = urljoin(get_api_url(), f"api/Code/{code}")
35
+ return get_json(url, params=params)
36
+
37
+
38
+ def query_sql(sql: str):
39
+ return post_sql(sql=sql, take=0, skip=0)
40
+
41
+
42
+ def get_api_url() -> str:
43
+ """Get base url to api
44
+
45
+ Returns:
46
+ str: Base url to api
47
+ """
48
+ return "https://commonlibapi.equinor.com/"
49
+
50
+
51
+ def get_auth() -> BearerAuth:
52
+ """Get Bearerauth object including token for accessing api.
53
+
54
+ Returns:
55
+ BearerAuth: Object with access token for api.
56
+ """
57
+ tenantID = "3aa4a235-b6e2-48d5-9195-7fcf05b459b0"
58
+ clientID = "728cfddd-b8e9-4ed7-b9a3-8f2fd5b8e79a"
59
+ scopes = ["37d598fc-da0f-46bd-949f-7107918d47a5/user_impersonation"]
60
+ auth = BearerAuth.get_auth(
61
+ tenantID=tenantID,
62
+ clientID=clientID,
63
+ scopes=scopes,
64
+ username=f"{get_login_name()}@equinor.com",
65
+ )
66
+
67
+ return auth
68
+
69
+
70
+ def get_json(url: str, params=None) -> list:
71
+ """Get json from api endpoint
72
+
73
+ Args:
74
+ url (str): Url to api endpoint to get.
75
+ params (dict, optional): Dictionary of parameters to pass. Defaults to None.
76
+
77
+ Returns:
78
+ list: List of response from api
79
+ """
80
+ response = requests.get(url, auth=get_auth(), params=params)
81
+ # response.raise_for_status()
82
+ if response.status_code == 200:
83
+ try:
84
+ return response.json()
85
+ except json.JSONDecodeError:
86
+ print(
87
+ f"Warning: {str(url)} returned successfully, but not with a valid json response"
88
+ )
89
+ else:
90
+ print(f"Warning: {str(url)} returned status code {response.status_code}")
91
+
92
+ return []
93
+
94
+
95
+ def post_sql(sql: str, take: int = 100, skip: int = 0) -> list:
96
+ """Get json from api/sql endpoint accepting sql queries.
97
+
98
+ Args:
99
+ sql (str): SQL query to run
100
+ take (int, optional): Number of results to return. Defaults to 100.
101
+ skip (int, optional): Number of results to skip. Defaults to 0.
102
+
103
+ Returns:
104
+ list: List of response from api
105
+ """
106
+ url = urljoin(get_api_url(), "api/sql")
107
+ response = requests.post(
108
+ url=url, json={"query": sql, "take": take, "skip": skip}, auth=get_auth()
109
+ )
110
+ if response.status_code == 200:
111
+ try:
112
+ return response.json()
113
+ except json.JSONDecodeError:
114
+ print(
115
+ f"Warning: {str(url)} returned successfully, but not with a valid json response"
116
+ )
117
+ else:
118
+ print(f"Warning: {str(url)} returned status code {response.status_code}")
119
+
120
+ return []
121
+
122
+
123
+ def attributes_list_to_dict(attribute_list: List[Dict]) -> Dict:
124
+ """Convert list of attributes typically returned from commonlib to a normal dictionary.
125
+
126
+ Args:
127
+ attribute_list (List[Dict]): List of attributes
128
+
129
+ Returns:
130
+ Dict: Dictionary with attribute definitionName as keys.
131
+ """
132
+ d = {}
133
+ for r in attribute_list:
134
+ try:
135
+ d[r["definitionName"]] = r["displayValue"]
136
+ except:
137
+ pass
138
+
139
+ return d
@@ -0,0 +1,39 @@
1
+ Metadata-Version: 2.1
2
+ Name: commonlib-reader
3
+ Version: 1.0.0
4
+ Summary: Reader for Equinor commonlibapi.
5
+ Home-page: https://github.com/equinor/commonlib-reader.git
6
+ Author: Åsmund Våge Fannemel
7
+ Author-email: asmf@equinor.com
8
+ Requires-Python: >=3.9,<4.0
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Programming Language :: Python :: 3.9
11
+ Classifier: Programming Language :: Python :: 3.10
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Requires-Dist: msal_bearer (>0.2.1)
15
+ Requires-Dist: pandas (>=2.1.4,<3.0.0)
16
+ Requires-Dist: requests (>=2.31.0,<3.0.0)
17
+ Project-URL: Repository, https://github.com/equinor/commonlib-reader.git
18
+ Description-Content-Type: text/markdown
19
+
20
+ # commonlib-python
21
+ Connector package for Equinor Commonlib api. Used for getting code tables.
22
+
23
+ Some additional functionality for asset specific Tag categories and tag types is also included.
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
+ Poetry is preferred for developers. Clone and install with required packages for testing and coverage:
36
+ `poetry install`
37
+
38
+ For testing with coverage run:
39
+ `poetry run pytest --cov --cov-report=html`
@@ -0,0 +1,9 @@
1
+ commonlib_reader/__init__.py,sha256=tpUVIRqbBqlyWj8iqxnUCzrpLr63OKB89fcwCogCk20,434
2
+ commonlib_reader/facility.py,sha256=V2XCUi_2gfZSiiUtA3ll9_15NXrWJeDcUq0Ux3l5S6Y,3486
3
+ commonlib_reader/ims.py,sha256=qyHBS9ar-e-6IPoldE-almAOsBMamgkf86EGya7tK9Q,3600
4
+ commonlib_reader/tag.py,sha256=x8OEQJ0XpLiixCZOz_0zp6hh513byAzxNr5HQFjNzQc,15543
5
+ commonlib_reader/unit.py,sha256=NDIJA2A2m7ZzsKUmza5EQLZQQXhHW9p_DzYUrPhu3OY,1346
6
+ commonlib_reader/utils.py,sha256=sjYYI8HpmFCYyMQ1nEMsBMBsODdicdSZkxNDJ_VBdO8,3685
7
+ commonlib_reader-1.0.0.dist-info/METADATA,sha256=Yz7L0aH1XjV5Ifeug6-OVbMKALoVGAUYx-hh2f0Ea-w,1290
8
+ commonlib_reader-1.0.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
9
+ commonlib_reader-1.0.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: poetry-core 1.9.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any