Skip to content

Commit 9651de7

Browse files
authored
chore: update cryptography to >= 44.0.0 (#410)
* chore: support newer versions of msal_bearer * chore: python 3.9 to use cryptography > 44.0.0 * fix: aspen query_sql with parsing * fix: tests * chore: update README.md * fix: build * Update web_handlers.py * chore: poetry update * chore: mark obsolete functions * chore: update poetry.lock
1 parent 4c8f1bf commit 9651de7

8 files changed

Lines changed: 1085 additions & 1112 deletions

File tree

.github/workflows/build.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ jobs:
99
strategy:
1010
fail-fast: false
1111
matrix:
12-
python-version: ["3.8", "3.9", "3.10", "3.11"]
12+
python-version: ["3.9", "3.10", "3.11"]
1313
os: [windows-latest, ubuntu-latest, macos-latest]
1414
runs-on: ${{ matrix.os }}
1515
steps:
@@ -19,7 +19,7 @@ jobs:
1919
- name: Install required Linux library for pykerberos
2020
if: matrix.os == 'ubuntu-latest'
2121
run: |
22-
sudo apt-get install libkrb5-dev
22+
sudo apt-get update && sudo apt-get install libkrb5-dev
2323
2424
- name: Install Poetry
2525
run: |

README.md

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,25 +6,17 @@
66
[![Downloads](https://pepy.tech/badge/tagreader)](https://pepy.tech/project/tagreader)
77

88
Tagreader is a Python package for reading timeseries data from the OSIsoft PI and Aspen Infoplus.21
9-
Information Manufacturing Systems (IMS) systems. It is intended to be easy to use, and present as similar interfaces
10-
as possible to the backend historians.
9+
Information Management Systems (IMS). It is intended to be easy to use, and present as similar interfaces
10+
as possible to the backend plant historians.
1111

1212
## Installation
1313
You can install tagreader directly into your project from pypi by using pip
14-
or another package manager. The only requirement is Python version 3.8 or above.
14+
or another package manager. Supports Python version 3.9.2 and above.
1515

1616
```shell
1717
pip install tagreader
1818
```
1919

20-
The following are required and will be installed:
21-
22-
* pandas
23-
* requests
24-
* requests-kerberos
25-
* certifi
26-
* diskcache
27-
2820
## Usage
2921
Tagreader is easy to use for both Equinor internal IMS services, and non-internal usage. For non-internal usage
3022
you simply need to provide the corresponding IMS service URLs and IMSType.

poetry.lock

Lines changed: 1045 additions & 1071 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,19 +28,18 @@ classifiers=[
2828
]
2929

3030
[tool.poetry.dependencies]
31-
python = "^3.8"
31+
python = "^3.9.2"
3232
pandas = ">=1"
3333
certifi = "^2024.12.14"
3434
requests = "^2"
3535
requests-kerberos = "^0"
36-
msal-bearer = ">=0.2.1,<1.2.0"
36+
msal-bearer = "^1.3.0"
3737
notebook = { version = "^7.2.2", optional = true }
3838
matplotlib = { version = "^3.7.5", optional = true }
3939
diskcache = "^5.6.1"
4040
pycryptodome = "^3.20.0"
4141
requests-ntlm = ">=1.1,<=2.0"
4242

43-
4443
[tool.poetry.group.dev.dependencies]
4544
pre-commit = "^3"
4645
pytest = ">=7,<9"

tagreader/clients.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import os
2-
from datetime import datetime, timedelta, tzinfo
2+
from datetime import datetime, timedelta, timezone, tzinfo
33
from itertools import groupby
44
from operator import itemgetter
55
from typing import Any, Dict, List, Optional, Tuple, Union
@@ -128,6 +128,8 @@ def get_server_address_aspen(datasource: str) -> Optional[Tuple[str, int]]:
128128
host and port based on the path above and the UUID.
129129
"""
130130

131+
# todo: is obsolete after removing ODBC
132+
131133
if not is_windows():
132134
return None
133135
import winreg
@@ -168,6 +170,7 @@ def get_server_address_pi(datasource: str) -> Optional[Tuple[str, int]]:
168170
:return: host, port
169171
:type: tuple(string, int)
170172
"""
173+
# todo: is obsolete after removing ODBC
171174

172175
if not is_windows():
173176
return None
@@ -557,7 +560,7 @@ def read(
557560
except ValueError:
558561
start = convert_to_pydatetime(start)
559562
if end is None:
560-
end = datetime.utcnow()
563+
end = datetime.now(timezone.utc)
561564
elif isinstance(end, (str, pd.Timestamp)):
562565
end = convert_to_pydatetime(end)
563566

tagreader/web_handlers.py

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ def get_auth_aspen(use_internal: bool = True):
7272
if use_internal:
7373
return HTTPKerberosAuth(mutual_authentication=OPTIONAL)
7474

75-
from msal_bearer.BearerAuth import BearerAuth
75+
from msal_bearer import BearerAuth
7676

7777
tenantID = "3aa4a235-b6e2-48d5-9195-7fcf05b459b0"
7878
clientID = "7adaaa99-897f-428c-8a5f-4053db565b32"
@@ -260,6 +260,7 @@ def __init__(
260260

261261
@staticmethod
262262
def generate_connection_string(host, *_, **__):
263+
# todo: is obsolete after removing ODBC
263264
raise NotImplementedError
264265

265266
@staticmethod
@@ -670,11 +671,13 @@ def generate_sql_query(
670671
return connection_string
671672

672673
def initialize_connection_string(
674+
# todo: is obsolete after removing ODBC
673675
self,
674676
host: Optional[str] = None,
675677
port: int = 10014,
676678
connection_string: Optional[str] = None,
677679
):
680+
# todo: is obsolete after removing ODBC
678681
if connection_string:
679682
self._connection_string = connection_string
680683
else:
@@ -712,16 +715,17 @@ def query_sql(self, query: str, parse: bool = True) -> Union[str, pd.DataFrame]:
712715
parsed_dict = res.json()["data"][0]
713716

714717
cols = []
715-
for i in parsed_dict["cols"]:
716-
cols.append(i["n"])
718+
if "cols" in parsed_dict.keys():
719+
for i in parsed_dict["cols"]:
720+
cols.append(i["n"])
717721

718722
rows = []
719-
720-
for i in parsed_dict["rows"]:
721-
element = []
722-
for j in i["fld"]:
723-
element.append(j["v"])
724-
rows.append(element)
723+
if "rows" in parsed_dict.keys():
724+
for i in parsed_dict["rows"]:
725+
element = []
726+
for j in i["fld"]:
727+
element.append(j["v"])
728+
rows.append(element)
725729
return pd.DataFrame(data=rows, columns=cols)
726730
return res.text
727731

@@ -756,6 +760,7 @@ def _time_to_UTC_string(time: datetime) -> str:
756760

757761
@staticmethod
758762
def generate_connection_string(host, *_, **__):
763+
# todo: is obsolete after removing ODBC
759764
raise NotImplementedError
760765

761766
@staticmethod

tests/test_AspenHandlerREST.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,7 @@ def test_generate_sql_query(aspen_handler: AspenHandlerWeb) -> None:
235235

236236

237237
def test_initialize_connection_string(aspen_handler: AspenHandlerWeb) -> None:
238+
# todo: is obsolete after removing ODBC
238239
aspen_handler.initialize_connection_string(
239240
host="my_host", port=999, connection_string="my_connection_string"
240241
)

tests/test_AspenHandlerREST_connect.py

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
from datetime import datetime, timedelta
33
from typing import Generator
44

5+
import pandas as pd
56
import pytest
6-
from pytest import raises
77

88
from tagreader.clients import IMSClient, list_sources
99
from tagreader.utils import IMSType
@@ -137,18 +137,17 @@ def test_query_sql(client: IMSClient) -> None:
137137
# The % causes WC_E_SYNTAX error in result. Tried "everything" but no go.
138138
# Leaving it for now.
139139
# query = "SELECT name, ip_description FROM ip_analogdef WHERE name LIKE 'ATC%'"
140-
query = "Select name, ip_description from ip_analogdef where name = 'atcai'"
140+
query = "Select name, ip_description from ip_analogdef where name = 'atc'"
141141
res = client.query_sql(query=query, parse=False)
142-
print(res)
142+
# print(res)
143143
assert isinstance(res, str)
144-
with raises(NotImplementedError):
145-
res = client.query_sql(query=query, parse=True)
146-
assert isinstance(res, str)
147-
client.handler.initialize_connection_string()
148-
query = "Select name, ip_description from ip_analogdef where name = 'atcai'"
149-
res = client.query_sql(query=query, parse=False)
150-
print(res)
151-
assert isinstance(res, str)
152-
with raises(NotImplementedError):
153-
res = client.query_sql(query=query, parse=True)
154-
assert isinstance(res, str)
144+
145+
res = client.query_sql(query=query, parse=True)
146+
assert isinstance(res, pd.DataFrame)
147+
assert res.empty
148+
149+
query = "Select name, ip_description from ip_analogdef where name = 'AverageCPUTimeVals'"
150+
res = client.query_sql(query=query, parse=True)
151+
assert isinstance(res, pd.DataFrame)
152+
assert len(res.index.values) == 1
153+
assert res.index.values[0] == 0

0 commit comments

Comments
 (0)