erioon 0.1.0__py3-none-any.whl → 0.1.2__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.
- erioon/client.py +36 -79
- {erioon-0.1.0.dist-info → erioon-0.1.2.dist-info}/METADATA +1 -1
- {erioon-0.1.0.dist-info → erioon-0.1.2.dist-info}/RECORD +6 -6
- {erioon-0.1.0.dist-info → erioon-0.1.2.dist-info}/LICENSE +0 -0
- {erioon-0.1.0.dist-info → erioon-0.1.2.dist-info}/WHEEL +0 -0
- {erioon-0.1.0.dist-info → erioon-0.1.2.dist-info}/top_level.txt +0 -0
erioon/client.py
CHANGED
@@ -5,23 +5,12 @@ from datetime import datetime, timezone
|
|
5
5
|
from erioon.database import Database
|
6
6
|
|
7
7
|
class ErioonClient:
|
8
|
-
"""
|
9
|
-
Client SDK for interacting with the Erioon API.
|
10
|
-
|
11
|
-
Handles:
|
12
|
-
- User authentication with email/password and API key
|
13
|
-
- Token caching to avoid re-authenticating every time
|
14
|
-
- SAS token expiration detection and auto-renewal
|
15
|
-
- Access to user-specific databases
|
16
|
-
"""
|
17
|
-
|
18
8
|
def __init__(self, api, email, password, base_url="https://sdk.erioon.com"):
|
19
9
|
self.api = api
|
20
10
|
self.email = email
|
21
11
|
self.password = password
|
22
12
|
self.base_url = base_url
|
23
13
|
self.user_id = None
|
24
|
-
self.error = None
|
25
14
|
self.token_path = os.path.expanduser(f"~/.erioon_token_{self._safe_filename(email)}")
|
26
15
|
self.login_metadata = None
|
27
16
|
|
@@ -29,42 +18,28 @@ class ErioonClient:
|
|
29
18
|
self.login_metadata = self._load_or_login()
|
30
19
|
self._update_metadata_fields()
|
31
20
|
except Exception as e:
|
32
|
-
|
21
|
+
print(f"[ErioonClient] Initialization error: {e}")
|
33
22
|
|
34
23
|
def _safe_filename(self, text):
|
35
|
-
"""
|
36
|
-
Converts unsafe filename characters to underscores for cache file naming.
|
37
|
-
"""
|
38
24
|
return "".join(c if c.isalnum() else "_" for c in text)
|
39
25
|
|
40
26
|
def _do_login_and_cache(self):
|
41
|
-
"""
|
42
|
-
Logs in to the API and writes the returned metadata (e.g. SAS token, user ID) to a local file.
|
43
|
-
"""
|
44
27
|
metadata = self._login()
|
45
28
|
with open(self.token_path, "w") as f:
|
46
29
|
json.dump(metadata, f)
|
47
30
|
return metadata
|
48
31
|
|
49
32
|
def _load_or_login(self):
|
50
|
-
"""
|
51
|
-
Tries to load the cached login metadata.
|
52
|
-
If token is expired or file does not exist, performs a fresh login.
|
53
|
-
"""
|
54
33
|
if os.path.exists(self.token_path):
|
55
34
|
with open(self.token_path, "r") as f:
|
56
35
|
metadata = json.load(f)
|
57
36
|
if self._is_sas_expired(metadata):
|
58
|
-
|
37
|
+
return self._do_login_and_cache()
|
59
38
|
return metadata
|
60
39
|
else:
|
61
40
|
return self._do_login_and_cache()
|
62
41
|
|
63
42
|
def _login(self):
|
64
|
-
"""
|
65
|
-
Sends login request to Erioon API using API key, email, and password.
|
66
|
-
Returns authentication metadata including SAS token.
|
67
|
-
"""
|
68
43
|
url = f"{self.base_url}/login_with_credentials"
|
69
44
|
payload = {"api_key": self.api, "email": self.email, "password": self.password}
|
70
45
|
headers = {"Content-Type": "application/json"}
|
@@ -76,37 +51,30 @@ class ErioonClient:
|
|
76
51
|
self._update_metadata_fields()
|
77
52
|
return data
|
78
53
|
else:
|
79
|
-
|
54
|
+
try:
|
55
|
+
msg = response.json().get("error", "Login failed")
|
56
|
+
except Exception:
|
57
|
+
msg = response.text
|
58
|
+
print(f"[ErioonClient] Login failed: {msg}")
|
59
|
+
raise RuntimeError(msg)
|
80
60
|
|
81
61
|
def _update_metadata_fields(self):
|
82
|
-
"""
|
83
|
-
Updates internal fields like user_id, database name, and cluster info
|
84
|
-
from login metadata.
|
85
|
-
"""
|
86
62
|
if self.login_metadata:
|
87
63
|
self.user_id = self.login_metadata.get("_id")
|
88
|
-
self.database = self.login_metadata.get("database")
|
89
64
|
self.cluster = self.login_metadata.get("cluster")
|
65
|
+
self.database = self.login_metadata.get("database")
|
66
|
+
self.sas_tokens = self.login_metadata.get("sas_tokens", {})
|
90
67
|
|
91
68
|
def _clear_cached_token(self):
|
92
|
-
"""
|
93
|
-
Clears the locally cached authentication token and resets internal state.
|
94
|
-
"""
|
95
69
|
if os.path.exists(self.token_path):
|
96
70
|
os.remove(self.token_path)
|
97
71
|
self.user_id = None
|
98
72
|
self.login_metadata = None
|
99
73
|
|
100
74
|
def _is_sas_expired(self, metadata):
|
101
|
-
"""
|
102
|
-
Determines whether the SAS token has expired by comparing the 'sas_token_expiry'
|
103
|
-
or 'expiry' field with the current UTC time.
|
104
|
-
"""
|
105
75
|
expiry_str = metadata.get("sas_token_expiry") or metadata.get("expiry")
|
106
|
-
|
107
76
|
if not expiry_str:
|
108
77
|
return True
|
109
|
-
|
110
78
|
try:
|
111
79
|
expiry_dt = datetime.fromisoformat(expiry_str.replace("Z", "+00:00"))
|
112
80
|
now = datetime.now(timezone.utc)
|
@@ -115,50 +83,45 @@ class ErioonClient:
|
|
115
83
|
return True
|
116
84
|
|
117
85
|
def __getitem__(self, db_id):
|
118
|
-
"""
|
119
|
-
Allows syntax like `client["my_database_id"]` to access a database.
|
120
|
-
If the token is expired or invalid, it attempts reauthentication.
|
121
|
-
"""
|
122
86
|
if not self.user_id:
|
123
|
-
|
87
|
+
print(f"[ErioonClient] Not authenticated. Cannot access database {db_id}.")
|
88
|
+
raise ValueError("Client not authenticated.")
|
124
89
|
|
125
90
|
try:
|
126
91
|
return self._get_database_info(db_id)
|
127
92
|
except Exception as e:
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
raise
|
93
|
+
print(f"[ErioonClient] Access failed for DB {db_id}, retrying login... ({e})")
|
94
|
+
self._clear_cached_token()
|
95
|
+
|
96
|
+
try:
|
97
|
+
self.login_metadata = self._do_login_and_cache()
|
98
|
+
self._update_metadata_fields()
|
99
|
+
except Exception as login_error:
|
100
|
+
print(f"[ErioonClient] Re-login failed: {login_error}")
|
101
|
+
raise RuntimeError(login_error)
|
102
|
+
|
103
|
+
try:
|
104
|
+
return self._get_database_info(db_id)
|
105
|
+
except Exception as second_error:
|
106
|
+
print(f"[ErioonClient] DB fetch after re-auth failed: {second_error}")
|
107
|
+
raise RuntimeError(second_error)
|
143
108
|
|
144
109
|
def _get_database_info(self, db_id):
|
145
|
-
"""
|
146
|
-
Sends a POST request to fetch metadata for a given database ID.
|
147
|
-
Returns a `Database` instance initialized with SAS URL and metadata.
|
148
|
-
"""
|
149
110
|
payload = {"user_id": self.user_id, "db_id": db_id}
|
150
111
|
headers = {"Content-Type": "application/json"}
|
151
|
-
|
152
112
|
response = requests.post(f"{self.base_url}/db_info", json=payload, headers=headers)
|
153
113
|
|
154
114
|
if response.status_code == 200:
|
155
115
|
db_info = response.json()
|
116
|
+
sas_info = self.sas_tokens.get(db_id)
|
117
|
+
if not sas_info:
|
118
|
+
raise Exception(f"No SAS token info for database id {db_id}")
|
156
119
|
|
157
|
-
container_url =
|
158
|
-
sas_token =
|
120
|
+
container_url = sas_info.get("container_url")
|
121
|
+
sas_token = sas_info.get("sas_token")
|
159
122
|
|
160
123
|
if not container_url or not sas_token:
|
161
|
-
raise Exception("Missing SAS URL components
|
124
|
+
raise Exception("Missing SAS URL components")
|
162
125
|
|
163
126
|
if not sas_token.startswith("?"):
|
164
127
|
sas_token = "?" + sas_token
|
@@ -178,16 +141,10 @@ class ErioonClient:
|
|
178
141
|
error_msg = error_json.get("error", response.text)
|
179
142
|
except Exception:
|
180
143
|
error_msg = response.text
|
181
|
-
raise Exception(error_msg)
|
144
|
+
raise Exception(f"Failed to fetch database info: {error_msg}")
|
182
145
|
|
183
146
|
def __str__(self):
|
184
|
-
""
|
185
|
-
Returns user_id or error string when printed.
|
186
|
-
"""
|
187
|
-
return self.user_id if self.user_id else self.error
|
147
|
+
return self.user_id if self.user_id else "[ErioonClient] Unauthenticated"
|
188
148
|
|
189
149
|
def __repr__(self):
|
190
|
-
"""
|
191
|
-
Developer-friendly representation of the client.
|
192
|
-
"""
|
193
|
-
return f"<ErioonClient user_id={self.user_id}>" if self.user_id else f"<ErioonClient error='{self.error}'>"
|
150
|
+
return f"<ErioonClient user_id={self.user_id}>" if self.user_id else "<ErioonClient unauthenticated>"
|
@@ -1,5 +1,5 @@
|
|
1
1
|
erioon/auth.py,sha256=McktLrdxsWVyxhiFuk0qFokx63RI1yB8_qP3Mo7uZCI,724
|
2
|
-
erioon/client.py,sha256=
|
2
|
+
erioon/client.py,sha256=5Sd-s95UQokJLByA15ViYCxjAHennnb1vITj-nNtBKE,5714
|
3
3
|
erioon/collection.py,sha256=EyNHpoOEBBMH29gMy51zzR338z2uI79kl0_ZB7laHpM,9700
|
4
4
|
erioon/create.py,sha256=ilx0e3urK0lfYiaM3CSUe3Bf3l7GhHuwZyz0Z6ij0ok,10202
|
5
5
|
erioon/database.py,sha256=hj5sgaEDXmItg4aeZlO3MP6_hV3jeS-d9qycEnw7xHQ,2449
|
@@ -8,8 +8,8 @@ erioon/functions.py,sha256=LWrqslAok-l9QlMEynT-Pvksy5hwkogWoeK5rJf464A,12479
|
|
8
8
|
erioon/ping.py,sha256=BC0vZiane5YgCc07syZA5dKFcqbq1_Z8BUTmvIGRPcs,1829
|
9
9
|
erioon/read.py,sha256=kzzqqRuLtYmlniAnkd2xeWNZm4AwMQ2oAMcpKt6JhcQ,10580
|
10
10
|
erioon/update.py,sha256=E3d-dYJWh12bcAHx_vT9NFTscF__hViY3K9ZssN7At4,6060
|
11
|
-
erioon-0.1.
|
12
|
-
erioon-0.1.
|
13
|
-
erioon-0.1.
|
14
|
-
erioon-0.1.
|
15
|
-
erioon-0.1.
|
11
|
+
erioon-0.1.2.dist-info/LICENSE,sha256=xwnq3DNlZpQyteOK9HvtHRhMdYviXTTaCDljEodFRnQ,569
|
12
|
+
erioon-0.1.2.dist-info/METADATA,sha256=IZzuMRl69uhU0QqDGhwa-iaLPALcwbhBlR7Pke0HlGU,715
|
13
|
+
erioon-0.1.2.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
14
|
+
erioon-0.1.2.dist-info/top_level.txt,sha256=yjKEg85X5Q5ot46IMML_xukvIGG5YfdrLWcemjalItc,7
|
15
|
+
erioon-0.1.2.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|