tagreader 6.0.4__tar.gz → 6.2.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.
- {tagreader-6.0.4 → tagreader-6.2.0}/PKG-INFO +12 -16
- {tagreader-6.0.4 → tagreader-6.2.0}/pyproject.toml +29 -25
- {tagreader-6.0.4 → tagreader-6.2.0}/tagreader/__init__.py +9 -2
- {tagreader-6.0.4 → tagreader-6.2.0}/tagreader/clients.py +11 -11
- {tagreader-6.0.4 → tagreader-6.2.0}/tagreader/utils.py +75 -25
- {tagreader-6.0.4 → tagreader-6.2.0}/tagreader/web_handlers.py +20 -21
- {tagreader-6.0.4 → tagreader-6.2.0}/LICENSE +0 -0
- {tagreader-6.0.4 → tagreader-6.2.0}/README.md +0 -0
- {tagreader-6.0.4 → tagreader-6.2.0}/tagreader/__version__.py +0 -0
- {tagreader-6.0.4 → tagreader-6.2.0}/tagreader/cache.py +0 -0
- {tagreader-6.0.4 → tagreader-6.2.0}/tagreader/logger.py +0 -0
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: tagreader
|
|
3
|
-
Version: 6.0
|
|
3
|
+
Version: 6.2.0
|
|
4
4
|
Summary: Tagreader is a Python package for reading trend data from the OSIsoft PI and Aspen Infoplus.21 IMS systems.
|
|
5
|
-
License: MIT
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
License-File: LICENSE
|
|
6
7
|
Keywords: Aspen InfoPlus.21,OSIsoft PI
|
|
7
8
|
Author: Einar S. Idsø
|
|
8
9
|
Author-email: eiids@equinor.com
|
|
@@ -15,28 +16,23 @@ Classifier: Natural Language :: English
|
|
|
15
16
|
Classifier: Operating System :: MacOS
|
|
16
17
|
Classifier: Operating System :: Microsoft :: Windows
|
|
17
18
|
Classifier: Operating System :: POSIX :: Linux
|
|
18
|
-
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
19
20
|
Classifier: Programming Language :: Python :: 3.10
|
|
20
21
|
Classifier: Programming Language :: Python :: 3.11
|
|
21
22
|
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
-
Classifier: Programming Language :: Python :: 3.13
|
|
23
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
24
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
25
23
|
Classifier: Topic :: Scientific/Engineering :: Interface Engine/Protocol Translator
|
|
26
24
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
27
25
|
Classifier: Topic :: Utilities
|
|
28
|
-
Provides-Extra: notebooks
|
|
29
26
|
Requires-Dist: certifi (>=2024.12.14,<2026.0.0)
|
|
30
|
-
Requires-Dist: diskcache (>=5.6.1
|
|
31
|
-
Requires-Dist:
|
|
32
|
-
Requires-Dist: msal-bearer (>=1.3.0,<2.0.0)
|
|
33
|
-
Requires-Dist: notebook (>=7.2.2,<8.0.0) ; extra == "notebooks"
|
|
27
|
+
Requires-Dist: diskcache (>=5.6.1)
|
|
28
|
+
Requires-Dist: msal-bearer (>=1.3.3)
|
|
34
29
|
Requires-Dist: pandas (>=1)
|
|
35
|
-
Requires-Dist: platformdirs (>=4.3.7
|
|
36
|
-
Requires-Dist: pycryptodome (>=3.20.0
|
|
37
|
-
Requires-Dist: requests (>=2
|
|
38
|
-
Requires-Dist: requests-kerberos (>=0
|
|
30
|
+
Requires-Dist: platformdirs (>=4.3.7)
|
|
31
|
+
Requires-Dist: pycryptodome (>=3.20.0)
|
|
32
|
+
Requires-Dist: requests (>=2.32.5)
|
|
33
|
+
Requires-Dist: requests-kerberos (>=0)
|
|
39
34
|
Requires-Dist: requests-ntlm (>=1.1,<=2.0)
|
|
35
|
+
Requires-Dist: urllib3 (>=2.5.0)
|
|
40
36
|
Project-URL: Homepage, https://github.com/equinor/tagreader-python
|
|
41
37
|
Project-URL: Repository, https://github.com/equinor/tagreader-python
|
|
42
38
|
Description-Content-Type: text/markdown
|
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
[
|
|
1
|
+
[project]
|
|
2
2
|
name = "tagreader"
|
|
3
|
-
version = "6.0
|
|
3
|
+
version = "6.2.0"
|
|
4
4
|
description = "Tagreader is a Python package for reading trend data from the OSIsoft PI and Aspen Infoplus.21 IMS systems."
|
|
5
|
-
authors = [
|
|
5
|
+
authors = [
|
|
6
|
+
{ name = "Einar S. Idsø", email = "eiids@equinor.com" },
|
|
7
|
+
{ name = "Morten Dæhli Aslesen", email = "masl@equinor.com" }
|
|
8
|
+
]
|
|
6
9
|
license = "MIT"
|
|
7
10
|
readme = "README.md"
|
|
8
|
-
packages = [{include = "tagreader"}]
|
|
9
11
|
keywords=["Aspen InfoPlus.21", "OSIsoft PI"]
|
|
10
|
-
|
|
11
|
-
repository = "https://github.com/equinor/tagreader-python"
|
|
12
|
+
requires-python = ">=3.9.2,<4.0.0"
|
|
12
13
|
classifiers=[
|
|
13
14
|
"Development Status :: 5 - Production/Stable",
|
|
14
15
|
"Intended Audience :: Developers",
|
|
@@ -18,36 +19,39 @@ classifiers=[
|
|
|
18
19
|
"Operating System :: MacOS",
|
|
19
20
|
"Operating System :: Microsoft :: Windows",
|
|
20
21
|
"Operating System :: POSIX :: Linux",
|
|
21
|
-
"Programming Language :: Python :: 3.8",
|
|
22
22
|
"Programming Language :: Python :: 3.9",
|
|
23
23
|
"Programming Language :: Python :: 3.10",
|
|
24
24
|
"Programming Language :: Python :: 3.11",
|
|
25
|
+
"Programming Language :: Python :: 3.12",
|
|
25
26
|
"Topic :: Scientific/Engineering :: Interface Engine/Protocol Translator",
|
|
26
27
|
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
27
28
|
"Topic :: Utilities",
|
|
28
29
|
]
|
|
30
|
+
dependencies = [
|
|
31
|
+
"pandas>=1",
|
|
32
|
+
"certifi>=2024.12.14,<2026.0.0",
|
|
33
|
+
"requests>=2.32.5",
|
|
34
|
+
"requests-kerberos>=0",
|
|
35
|
+
"msal-bearer>=1.3.3",
|
|
36
|
+
"diskcache>=5.6.1",
|
|
37
|
+
"pycryptodome>=3.20.0",
|
|
38
|
+
"requests-ntlm>=1.1,<=2.0",
|
|
39
|
+
"platformdirs>=4.3.7",
|
|
40
|
+
"urllib3>=2.5.0" # To avoid security issue https://www.cve.org/CVERecord?id=CVE-2025-50182
|
|
41
|
+
]
|
|
29
42
|
|
|
30
|
-
[tool.poetry.dependencies]
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
certifi = ">=2024.12.14,<2026.0.0"
|
|
34
|
-
requests = "^2"
|
|
35
|
-
requests-kerberos = "^0"
|
|
36
|
-
msal-bearer = "^1.3.0"
|
|
37
|
-
notebook = { version = "^7.2.2", optional = true }
|
|
38
|
-
matplotlib = { version = "^3.7.5", optional = true }
|
|
39
|
-
diskcache = "^5.6.1"
|
|
40
|
-
pycryptodome = "^3.20.0"
|
|
41
|
-
requests-ntlm = ">=1.1,<=2.0"
|
|
42
|
-
platformdirs = "^4.3.7"
|
|
43
|
+
[tool.poetry.group.test.dependencies]
|
|
44
|
+
pytest = ">=7,<9"
|
|
45
|
+
# pytest-cov = ">=6.0.0"
|
|
43
46
|
|
|
44
47
|
[tool.poetry.group.dev.dependencies]
|
|
45
|
-
|
|
46
|
-
|
|
48
|
+
# "black>=24.1.1",
|
|
49
|
+
pre-commit = ">=3.0"
|
|
47
50
|
|
|
48
|
-
[
|
|
49
|
-
|
|
51
|
+
[project.urls]
|
|
52
|
+
homepage = "https://github.com/equinor/tagreader-python"
|
|
53
|
+
repository = "https://github.com/equinor/tagreader-python"
|
|
50
54
|
|
|
51
55
|
[build-system]
|
|
52
|
-
requires = ["poetry-core"]
|
|
56
|
+
requires = ["poetry-core>=2.0.0,<3.0.0"]
|
|
53
57
|
build-backend = "poetry.core.masonry.api"
|
|
@@ -4,11 +4,18 @@ from tagreader.utils import (
|
|
|
4
4
|
ReaderType,
|
|
5
5
|
add_equinor_root_certificate,
|
|
6
6
|
is_equinor,
|
|
7
|
-
is_mac,
|
|
8
|
-
is_windows,
|
|
9
7
|
)
|
|
10
8
|
|
|
11
9
|
if is_equinor():
|
|
12
10
|
add_equinor_root_certificate()
|
|
13
11
|
|
|
14
12
|
from tagreader.__version__ import version as __version__
|
|
13
|
+
|
|
14
|
+
__all__ = [
|
|
15
|
+
"IMSClient",
|
|
16
|
+
"list_sources",
|
|
17
|
+
"IMSType",
|
|
18
|
+
"ReaderType",
|
|
19
|
+
"add_equinor_root_certificate",
|
|
20
|
+
"__version__",
|
|
21
|
+
]
|
|
@@ -32,7 +32,7 @@ def list_sources(
|
|
|
32
32
|
imstype: Union[IMSType, str],
|
|
33
33
|
url: Optional[str] = None,
|
|
34
34
|
auth: Optional[Any] = None,
|
|
35
|
-
|
|
35
|
+
verify_ssl: Optional[Union[bool, str]] = True,
|
|
36
36
|
) -> List[str]:
|
|
37
37
|
if isinstance(imstype, str):
|
|
38
38
|
try:
|
|
@@ -47,11 +47,11 @@ def list_sources(
|
|
|
47
47
|
if imstype == IMSType.PIWEBAPI:
|
|
48
48
|
if auth is None:
|
|
49
49
|
auth = get_auth_pi()
|
|
50
|
-
return list_piwebapi_sources(url=url, auth=auth, verify_ssl=
|
|
50
|
+
return list_piwebapi_sources(url=url, auth=auth, verify_ssl=verify_ssl)
|
|
51
51
|
elif imstype == IMSType.ASPENONE:
|
|
52
52
|
if auth is None:
|
|
53
53
|
auth = get_auth_aspen()
|
|
54
|
-
return list_aspenone_sources(url=url, auth=auth, verify_ssl=
|
|
54
|
+
return list_aspenone_sources(url=url, auth=auth, verify_ssl=verify_ssl)
|
|
55
55
|
elif imstype in [IMSType.PI, IMSType.ASPEN, IMSType.IP21]:
|
|
56
56
|
raise ValueError(
|
|
57
57
|
f"ODBC clients are no longer supported. Given ims client type: {imstype}."
|
|
@@ -120,14 +120,14 @@ def get_handler(
|
|
|
120
120
|
datasource: str,
|
|
121
121
|
url: Optional[str],
|
|
122
122
|
options: Dict[str, Union[int, float, str]],
|
|
123
|
-
|
|
123
|
+
verify_ssl: Optional[Union[bool, str]],
|
|
124
124
|
auth: Optional[Any],
|
|
125
125
|
cache: Optional[Union[SmartCache, BucketCache]] = None,
|
|
126
126
|
):
|
|
127
127
|
if imstype is None:
|
|
128
128
|
try:
|
|
129
129
|
if datasource in list_aspenone_sources(
|
|
130
|
-
url=None, auth=None, verify_ssl=
|
|
130
|
+
url=None, auth=None, verify_ssl=verify_ssl
|
|
131
131
|
):
|
|
132
132
|
imstype = IMSType.ASPENONE
|
|
133
133
|
except HTTPError as e:
|
|
@@ -135,7 +135,7 @@ def get_handler(
|
|
|
135
135
|
if imstype is None:
|
|
136
136
|
try:
|
|
137
137
|
if datasource in list_piwebapi_sources(
|
|
138
|
-
url=None, auth=None, verify_ssl=
|
|
138
|
+
url=None, auth=None, verify_ssl=verify_ssl
|
|
139
139
|
):
|
|
140
140
|
imstype = IMSType.PIWEBAPI
|
|
141
141
|
except HTTPError as e:
|
|
@@ -146,7 +146,7 @@ def get_handler(
|
|
|
146
146
|
url=url,
|
|
147
147
|
datasource=datasource,
|
|
148
148
|
options=options,
|
|
149
|
-
verify_ssl=
|
|
149
|
+
verify_ssl=verify_ssl,
|
|
150
150
|
auth=auth,
|
|
151
151
|
cache=cache,
|
|
152
152
|
)
|
|
@@ -156,7 +156,7 @@ def get_handler(
|
|
|
156
156
|
datasource=datasource,
|
|
157
157
|
url=url,
|
|
158
158
|
options=options,
|
|
159
|
-
verify_ssl=
|
|
159
|
+
verify_ssl=verify_ssl,
|
|
160
160
|
auth=auth,
|
|
161
161
|
)
|
|
162
162
|
elif imstype in [IMSType.PI, IMSType.ASPEN, IMSType.IP21]:
|
|
@@ -178,7 +178,7 @@ class IMSClient:
|
|
|
178
178
|
tz: Union[tzinfo, str] = pytz.timezone("Europe/Oslo"),
|
|
179
179
|
url: Optional[str] = None,
|
|
180
180
|
handler_options: Dict[str, Union[int, float, str]] = {}, # noqa:
|
|
181
|
-
|
|
181
|
+
verify_ssl: Optional[Union[bool, str]] = True,
|
|
182
182
|
auth: Optional[Any] = None,
|
|
183
183
|
cache: Optional[Union[SmartCache, BucketCache]] = None,
|
|
184
184
|
):
|
|
@@ -209,7 +209,7 @@ class IMSClient:
|
|
|
209
209
|
datasource=datasource,
|
|
210
210
|
url=url,
|
|
211
211
|
options=handler_options,
|
|
212
|
-
|
|
212
|
+
verify_ssl=verify_ssl,
|
|
213
213
|
auth=auth,
|
|
214
214
|
cache=self.cache,
|
|
215
215
|
)
|
|
@@ -412,7 +412,7 @@ class IMSClient:
|
|
|
412
412
|
):
|
|
413
413
|
start = start_time
|
|
414
414
|
end = stop_time
|
|
415
|
-
logger.
|
|
415
|
+
logger.warning(
|
|
416
416
|
(
|
|
417
417
|
"This function has been renamed to read() and is deprecated. "
|
|
418
418
|
"Please call 'read()' instead"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import enum
|
|
2
2
|
import hashlib
|
|
3
|
-
import logging
|
|
4
3
|
import platform
|
|
4
|
+
import socket
|
|
5
5
|
import ssl
|
|
6
6
|
from datetime import datetime, tzinfo
|
|
7
7
|
from enum import Enum
|
|
@@ -33,7 +33,6 @@ if is_windows():
|
|
|
33
33
|
import winreg
|
|
34
34
|
|
|
35
35
|
if is_mac():
|
|
36
|
-
import socket
|
|
37
36
|
import subprocess
|
|
38
37
|
|
|
39
38
|
|
|
@@ -118,7 +117,7 @@ def add_equinor_root_certificate() -> bool:
|
|
|
118
117
|
logger.debug(
|
|
119
118
|
"Unable to locate Equinor Root CA certificate on this host. Downloading from Equinor server."
|
|
120
119
|
)
|
|
121
|
-
response = requests.get("http://pki.equinor.com/aia/ecpr.crt")
|
|
120
|
+
response = requests.get("http://pki.equinor.com/aia/ecpr.crt", timeout=20)
|
|
122
121
|
|
|
123
122
|
if response.status_code != 200:
|
|
124
123
|
logger.error(
|
|
@@ -145,6 +144,7 @@ def add_equinor_root_certificate() -> bool:
|
|
|
145
144
|
with open(ca_file, "ab") as f:
|
|
146
145
|
f.write(bytes(certificate, "ascii"))
|
|
147
146
|
logger.debug("Equinor Root Certificate added to certifi store")
|
|
147
|
+
return True
|
|
148
148
|
|
|
149
149
|
|
|
150
150
|
def find_local_equinor_root_certificate() -> str:
|
|
@@ -153,7 +153,7 @@ def find_local_equinor_root_certificate() -> str:
|
|
|
153
153
|
|
|
154
154
|
if is_windows():
|
|
155
155
|
logger.debug("Checking for Equinor Root CA in Windows certificate store")
|
|
156
|
-
for cert in ssl.enum_certificates("CA"):
|
|
156
|
+
for cert in ssl.enum_certificates("CA"): # type: ignore
|
|
157
157
|
found_cert = cert[0]
|
|
158
158
|
# deepcode ignore InsecureHash: <Only hashes to compare with known hash>
|
|
159
159
|
if hashlib.sha1(found_cert).hexdigest().upper() == equinor_root_pem_hash:
|
|
@@ -189,6 +189,9 @@ def get_macos_equinor_certificates():
|
|
|
189
189
|
import ssl
|
|
190
190
|
import tempfile
|
|
191
191
|
|
|
192
|
+
if not is_mac():
|
|
193
|
+
raise OSError("Function only works on MacOS")
|
|
194
|
+
|
|
192
195
|
ca_search = "Equinor Root CA"
|
|
193
196
|
|
|
194
197
|
ctx = ssl.create_default_context()
|
|
@@ -210,37 +213,84 @@ def is_equinor() -> bool:
|
|
|
210
213
|
If Windows host:
|
|
211
214
|
Finds host's domain in Windows Registry at
|
|
212
215
|
HKLM\\SYSTEM\\ControlSet001\\Services\\Tcpip\\Parameters\\Domain
|
|
216
|
+
or check if hostname starts with eqdev or eqpc
|
|
213
217
|
If mac os host:
|
|
214
|
-
Finds statoil.net as AD hostname in certificates
|
|
218
|
+
Finds statoil.net as AD hostname in certificates or
|
|
219
|
+
Finds statoil.net, client.statoil.net or equinor.com in dns search domains
|
|
215
220
|
If Linux host:
|
|
216
|
-
Checks whether statoil.no is search
|
|
221
|
+
Checks whether statoil.no is dns search domains
|
|
217
222
|
|
|
218
223
|
Returns:
|
|
219
224
|
bool: True if Equinor
|
|
220
225
|
"""
|
|
221
|
-
if is_windows():
|
|
222
|
-
with winreg.OpenKey(
|
|
223
|
-
winreg.HKEY_LOCAL_MACHINE, r"SYSTEM\ControlSet001\Services\Tcpip\Parameters"
|
|
224
|
-
) as key:
|
|
225
|
-
domain = winreg.QueryValueEx(key, "Domain")
|
|
226
|
-
if "statoil" in domain[0]:
|
|
227
|
-
return True
|
|
228
|
-
elif is_mac():
|
|
229
|
-
s = subprocess.run(
|
|
230
|
-
["security", "find-certificate", "-a", "-c" "client.statoil.net"],
|
|
231
|
-
stdout=subprocess.PIPE,
|
|
232
|
-
).stdout
|
|
233
226
|
|
|
234
|
-
|
|
227
|
+
hostname = socket.gethostname()
|
|
235
228
|
|
|
236
|
-
|
|
237
|
-
if
|
|
238
|
-
return True
|
|
239
|
-
elif "client.statoil.net" in host and host in str(s):
|
|
229
|
+
if is_windows():
|
|
230
|
+
if hostname.lower().startswith("eqdev") or hostname.lower().startswith("eqpc"):
|
|
240
231
|
return True
|
|
241
|
-
|
|
232
|
+
with winreg.OpenKey( # type: ignore
|
|
233
|
+
winreg.HKEY_LOCAL_MACHINE,
|
|
234
|
+
r"SYSTEM\ControlSet001\Services\Tcpip\Parameters", # type: ignore
|
|
235
|
+
) as key:
|
|
236
|
+
domain = winreg.QueryValueEx(key, "Domain") # type: ignore
|
|
237
|
+
if "statoil" in domain[0] or "equinor" in domain[0]:
|
|
238
|
+
return True
|
|
239
|
+
elif is_linux() or is_mac():
|
|
242
240
|
with open("/etc/resolv.conf", "r") as f:
|
|
243
|
-
if
|
|
241
|
+
if any(
|
|
242
|
+
domain in f.read()
|
|
243
|
+
for domain in ["client.statoil.net", "statoil.net", "equinor.com"]
|
|
244
|
+
):
|
|
245
|
+
return True
|
|
246
|
+
|
|
247
|
+
if is_mac():
|
|
248
|
+
|
|
249
|
+
def get_mac_dns_search_list():
|
|
250
|
+
"""
|
|
251
|
+
Retrieves the DNS search list configured on macOS.
|
|
252
|
+
"""
|
|
253
|
+
try:
|
|
254
|
+
# Execute the scutil command to get DNS configuration
|
|
255
|
+
result = subprocess.run(
|
|
256
|
+
["scutil", "--dns"], capture_output=True, text=True, check=True
|
|
257
|
+
)
|
|
258
|
+
output = result.stdout
|
|
259
|
+
|
|
260
|
+
search_list = []
|
|
261
|
+
# Parse the output to find the search domains
|
|
262
|
+
for line in output.splitlines():
|
|
263
|
+
if "search domain" in line:
|
|
264
|
+
# Extract the domain from the line
|
|
265
|
+
parts = line.split(":")
|
|
266
|
+
if len(parts) > 1:
|
|
267
|
+
domain = parts[1].strip()
|
|
268
|
+
# Remove any leading/trailing quotes if present
|
|
269
|
+
domain = domain.strip('"')
|
|
270
|
+
search_list.append(domain)
|
|
271
|
+
return search_list
|
|
272
|
+
except subprocess.CalledProcessError as e:
|
|
273
|
+
print(f"Error executing scutil: {e}")
|
|
274
|
+
return []
|
|
275
|
+
except Exception as e:
|
|
276
|
+
print(f"An unexpected error occurred: {e}")
|
|
277
|
+
return []
|
|
278
|
+
|
|
279
|
+
if any(
|
|
280
|
+
domain in get_mac_dns_search_list()
|
|
281
|
+
for domain in ["client.statoil.net", "statoil.net", "equinor.com"]
|
|
282
|
+
):
|
|
283
|
+
return True
|
|
284
|
+
|
|
285
|
+
s = subprocess.run(
|
|
286
|
+
["security", "find-certificate", "-a", "-cclient.statoil.net"],
|
|
287
|
+
stdout=subprocess.PIPE,
|
|
288
|
+
).stdout
|
|
289
|
+
|
|
290
|
+
# deepcode ignore IdenticalBranches: Not an error. First test is just more precise.
|
|
291
|
+
if hostname + ".client.statoil.net" in str(s):
|
|
292
|
+
return True
|
|
293
|
+
elif "client.statoil.net" in hostname and hostname in str(s):
|
|
244
294
|
return True
|
|
245
295
|
else:
|
|
246
296
|
raise OSError(
|
|
@@ -42,12 +42,7 @@ def patched_hashlib_new(name, data=b"", usedforsecurity=True):
|
|
|
42
42
|
if name.lower() == "md4":
|
|
43
43
|
return MD4(data)
|
|
44
44
|
else:
|
|
45
|
-
|
|
46
|
-
try:
|
|
47
|
-
return hashlib_new_method(name, data=data, usedforsecurity=usedforsecurity)
|
|
48
|
-
except TypeError:
|
|
49
|
-
# Required for python 3.8
|
|
50
|
-
return hashlib_new_method(name, data=data)
|
|
45
|
+
return hashlib_new_method(name, data=data, usedforsecurity=usedforsecurity)
|
|
51
46
|
|
|
52
47
|
|
|
53
48
|
# Monkey-patch md4 in hashlib.new due to missing support for md4 in later releases of Python:
|
|
@@ -95,7 +90,7 @@ def get_url_aspen(use_internal: bool = True) -> str:
|
|
|
95
90
|
def list_aspenone_sources(
|
|
96
91
|
url: Optional[str] = None,
|
|
97
92
|
auth: Optional[Any] = None,
|
|
98
|
-
verify_ssl: Optional[bool] = True,
|
|
93
|
+
verify_ssl: Optional[Union[bool, str]] = True,
|
|
99
94
|
) -> List[str]:
|
|
100
95
|
if url is None:
|
|
101
96
|
url = get_url_aspen()
|
|
@@ -112,7 +107,7 @@ def list_aspenone_sources(
|
|
|
112
107
|
url_ = urljoin(url, "DataSources")
|
|
113
108
|
params = {"service": "ProcessData", "allQuotes": 1}
|
|
114
109
|
|
|
115
|
-
res = requests.get(url_, params=params, auth=auth, verify=verify_ssl)
|
|
110
|
+
res = requests.get(url_, params=params, auth=auth, verify=verify_ssl, timeout=300)
|
|
116
111
|
res.raise_for_status()
|
|
117
112
|
try:
|
|
118
113
|
source_list = [r["n"] for r in res.json()["data"] if r["t"] == "IP21"]
|
|
@@ -124,7 +119,7 @@ def list_aspenone_sources(
|
|
|
124
119
|
def list_piwebapi_sources(
|
|
125
120
|
url: Optional[str] = None,
|
|
126
121
|
auth: Optional[Any] = None,
|
|
127
|
-
verify_ssl: Optional[bool] = True,
|
|
122
|
+
verify_ssl: Optional[Union[bool, str]] = True,
|
|
128
123
|
) -> List[str]:
|
|
129
124
|
if url is None:
|
|
130
125
|
url = get_url_pi()
|
|
@@ -139,7 +134,7 @@ def list_piwebapi_sources(
|
|
|
139
134
|
urllib3.disable_warnings(InsecureRequestWarning)
|
|
140
135
|
|
|
141
136
|
url_ = urljoin(url, "dataservers")
|
|
142
|
-
res = requests.get(url_, auth=auth, verify=verify_ssl)
|
|
137
|
+
res = requests.get(url_, auth=auth, verify=verify_ssl, timeout=300)
|
|
143
138
|
|
|
144
139
|
res.raise_for_status()
|
|
145
140
|
try:
|
|
@@ -152,7 +147,7 @@ def list_piwebapi_sources(
|
|
|
152
147
|
def get_piwebapi_source_to_webid_dict(
|
|
153
148
|
url: Optional[str] = None,
|
|
154
149
|
auth: Optional[Any] = None,
|
|
155
|
-
verify_ssl: Optional[bool] = True,
|
|
150
|
+
verify_ssl: Optional[Union[bool, str]] = True,
|
|
156
151
|
) -> List[str]:
|
|
157
152
|
if url is None:
|
|
158
153
|
url = get_url_pi()
|
|
@@ -167,7 +162,7 @@ def get_piwebapi_source_to_webid_dict(
|
|
|
167
162
|
urllib3.disable_warnings(InsecureRequestWarning)
|
|
168
163
|
|
|
169
164
|
url_ = urljoin(url, "dataservers")
|
|
170
|
-
res = requests.get(url_, auth=auth, verify=verify_ssl)
|
|
165
|
+
res = requests.get(url_, auth=auth, verify=verify_ssl, timeout=300)
|
|
171
166
|
|
|
172
167
|
res.raise_for_status()
|
|
173
168
|
try:
|
|
@@ -182,7 +177,7 @@ class BaseHandlerWeb(ABC):
|
|
|
182
177
|
datasource: Optional[str],
|
|
183
178
|
url: Optional[str],
|
|
184
179
|
auth: Optional[Any],
|
|
185
|
-
verify_ssl: Optional[bool],
|
|
180
|
+
verify_ssl: Optional[Union[bool, str]],
|
|
186
181
|
):
|
|
187
182
|
self.datasource = datasource
|
|
188
183
|
self.base_url = url
|
|
@@ -213,6 +208,10 @@ class BaseHandlerWeb(ABC):
|
|
|
213
208
|
logger.warning(f"No data found for {url} {params}")
|
|
214
209
|
return {}
|
|
215
210
|
|
|
211
|
+
if res.text.startswith("XML Error"):
|
|
212
|
+
logger.warning(f"Invalid data returned for {url} {params}")
|
|
213
|
+
return {}
|
|
214
|
+
|
|
216
215
|
try:
|
|
217
216
|
return res.json()
|
|
218
217
|
except JSONDecodeError:
|
|
@@ -241,7 +240,7 @@ class AspenHandlerWeb(BaseHandlerWeb):
|
|
|
241
240
|
datasource: Optional[str],
|
|
242
241
|
url: Optional[str] = None,
|
|
243
242
|
auth: Optional[Any] = None,
|
|
244
|
-
verify_ssl: Optional[bool] = True,
|
|
243
|
+
verify_ssl: Optional[Union[bool, str]] = True,
|
|
245
244
|
options: Dict[str, Any] = dict(),
|
|
246
245
|
):
|
|
247
246
|
if url is None:
|
|
@@ -317,12 +316,12 @@ class AspenHandlerWeb(BaseHandlerWeb):
|
|
|
317
316
|
else:
|
|
318
317
|
query = '<Q f="d" allQuotes="1">'
|
|
319
318
|
|
|
320
|
-
query += "<Tag
|
|
319
|
+
query += f"<Tag><N><![CDATA[{tagname}]]></N>"
|
|
321
320
|
|
|
322
321
|
if mapname:
|
|
323
322
|
query += f"<M><![CDATA[{mapname}]]></M>"
|
|
324
323
|
|
|
325
|
-
query += f"<D><![CDATA[{self.datasource}]]></D
|
|
324
|
+
query += f"<D><![CDATA[{self.datasource}]]></D><F><![CDATA[VAL]]></F>"
|
|
326
325
|
|
|
327
326
|
if read_type == ReaderType.SNAPSHOT:
|
|
328
327
|
query += "<VS>1</VS>"
|
|
@@ -710,7 +709,7 @@ class PIHandlerWeb(BaseHandlerWeb):
|
|
|
710
709
|
url: Optional[str],
|
|
711
710
|
datasource: Optional[str],
|
|
712
711
|
auth: Optional[Any],
|
|
713
|
-
verify_ssl: bool,
|
|
712
|
+
verify_ssl: Optional[Union[bool, str]],
|
|
714
713
|
options: Dict[str, Union[int, float, str]],
|
|
715
714
|
cache: Optional[Union[SmartCache, BucketCache]],
|
|
716
715
|
):
|
|
@@ -844,10 +843,10 @@ class PIHandlerWeb(BaseHandlerWeb):
|
|
|
844
843
|
if self._is_summary(read_type):
|
|
845
844
|
params["selectedFields"] = "Links;Items.Value.Timestamp;Items.Value.Value"
|
|
846
845
|
if get_status:
|
|
847
|
-
params[
|
|
848
|
-
"
|
|
849
|
-
|
|
850
|
-
";Items.Value.Substituted"
|
|
846
|
+
params[
|
|
847
|
+
"selectedFields"
|
|
848
|
+
] += (
|
|
849
|
+
";Items.Value.Good;Items.Value.Questionable;Items.Value.Substituted"
|
|
851
850
|
)
|
|
852
851
|
elif read_type in [ReaderType.INT, ReaderType.RAW, ReaderType.SHAPEPRESERVING]:
|
|
853
852
|
params["selectedFields"] = "Links;Items.Timestamp;Items.Value"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|