wedata-pre-code 1.0.8__py3-none-any.whl → 1.0.11__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.
- wedata_pre_code/wedata3/client.py +11 -4
- wedata_pre_code/wedata3/experiment.py +187 -0
- {wedata_pre_code-1.0.8.dist-info → wedata_pre_code-1.0.11.dist-info}/METADATA +1 -1
- {wedata_pre_code-1.0.8.dist-info → wedata_pre_code-1.0.11.dist-info}/RECORD +5 -4
- {wedata_pre_code-1.0.8.dist-info → wedata_pre_code-1.0.11.dist-info}/WHEEL +1 -1
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
from typing import Optional
|
|
2
2
|
|
|
3
3
|
from wedata_pre_code.common.base_client import BaseClient
|
|
4
|
+
from wedata_pre_code.wedata3.experiment import (
|
|
5
|
+
_create_experiment,
|
|
6
|
+
_delete_experiment,
|
|
7
|
+
_rename_experiment,
|
|
8
|
+
_restore_experiment
|
|
9
|
+
)
|
|
10
|
+
|
|
4
11
|
|
|
5
12
|
__doc__ = """
|
|
6
13
|
Wedata3预执行代码客户端
|
|
@@ -337,7 +344,7 @@ class Wedata3PreCodeClient(BaseClient):
|
|
|
337
344
|
return wrapper
|
|
338
345
|
|
|
339
346
|
# 应用装饰器
|
|
340
|
-
MlflowClient.create_experiment = inject_workspace_tag(
|
|
347
|
+
MlflowClient.create_experiment = inject_workspace_tag(_create_experiment)
|
|
341
348
|
MlflowClient.create_registered_model = inject_workspace_tag(MlflowClient.create_registered_model)
|
|
342
349
|
MlflowClient.create_model_version = inject_workspace_tag(MlflowClient.create_model_version)
|
|
343
350
|
MlflowClient.get_experiment = validate_wedata_tag(MlflowClient.get_experiment)
|
|
@@ -345,9 +352,9 @@ class Wedata3PreCodeClient(BaseClient):
|
|
|
345
352
|
MlflowClient.get_run = validate_wedata_tag(MlflowClient.get_run)
|
|
346
353
|
MlflowClient.get_parent_run = validate_wedata_tag(MlflowClient.get_parent_run)
|
|
347
354
|
MlflowClient.get_registered_model = validate_wedata_tag(MlflowClient.get_registered_model)
|
|
348
|
-
MlflowClient.delete_experiment =
|
|
349
|
-
MlflowClient.restore_experiment =
|
|
350
|
-
MlflowClient.rename_experiment = validate_wedata_before_operation(
|
|
355
|
+
MlflowClient.delete_experiment = _delete_experiment
|
|
356
|
+
MlflowClient.restore_experiment = _restore_experiment
|
|
357
|
+
MlflowClient.rename_experiment = validate_wedata_before_operation(_rename_experiment)
|
|
351
358
|
MlflowClient.set_experiment_tag = validate_wedata_before_operation(MlflowClient.set_experiment_tag)
|
|
352
359
|
MlflowClient.set_tag = validate_wedata_before_operation(MlflowClient.set_tag)
|
|
353
360
|
MlflowClient.delete_tag = validate_wedata_before_operation(MlflowClient.delete_tag)
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import http
|
|
2
|
+
import os
|
|
3
|
+
import hashlib
|
|
4
|
+
import hmac
|
|
5
|
+
import json
|
|
6
|
+
import time
|
|
7
|
+
from datetime import datetime, timezone
|
|
8
|
+
from typing import Optional, Dict, Any
|
|
9
|
+
from http.client import HTTPSConnection, HTTPException
|
|
10
|
+
from mlflow.protos.databricks_pb2 import ABORTED, BAD_REQUEST
|
|
11
|
+
from mlflow import MlflowException
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
__doc__ = """
|
|
15
|
+
实验相关云API接口
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _set_request_header(headers: Optional[Dict[str, str]]) -> Dict[str, str]:
|
|
20
|
+
if headers is None:
|
|
21
|
+
headers = {}
|
|
22
|
+
|
|
23
|
+
if "IS_WEDATA_TEST" in os.environ.keys():
|
|
24
|
+
headers["X-Qcloud-User-Id"] = os.environ["TEST_USER_ID"]
|
|
25
|
+
|
|
26
|
+
return headers
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _get_endpoint() -> str:
|
|
30
|
+
endpoint = os.getenv("TENCENTCLOUD_ENDPOINT")
|
|
31
|
+
if endpoint is None:
|
|
32
|
+
endpoint = "wedata.internal.tencentcloudapi.com"
|
|
33
|
+
|
|
34
|
+
return endpoint
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class _DataScienceApi(object):
|
|
38
|
+
_version = "2025-10-10"
|
|
39
|
+
_service = "wedata"
|
|
40
|
+
|
|
41
|
+
def __init__(self, region: str, secret_id: str, secret_key: str, token: Optional[str] = None) -> None:
|
|
42
|
+
self._host = _get_endpoint()
|
|
43
|
+
self._region = region
|
|
44
|
+
self._secret_id = secret_id
|
|
45
|
+
self._secret_key = secret_key
|
|
46
|
+
self._token = token
|
|
47
|
+
|
|
48
|
+
def _sign(self, action: str, body: str, timestamp: int) -> str:
|
|
49
|
+
"""http请求签名"""
|
|
50
|
+
algorithm = "TC3-HMAC-SHA256"
|
|
51
|
+
date = datetime.fromtimestamp(timestamp, timezone.utc).strftime("%Y-%m-%d")
|
|
52
|
+
|
|
53
|
+
# ************* 步骤 1:拼接规范请求串 *************
|
|
54
|
+
http_request_method = "POST"
|
|
55
|
+
canonical_uri = "/"
|
|
56
|
+
canonical_querystring = ""
|
|
57
|
+
ct = "application/json; charset=utf-8"
|
|
58
|
+
canonical_headers = "content-type:%s\nhost:%s\nx-tc-action:%s\n" % (ct, self._host, action.lower())
|
|
59
|
+
signed_headers = "content-type;host;x-tc-action"
|
|
60
|
+
hashed_request_payload = hashlib.sha256(body.encode("utf-8")).hexdigest()
|
|
61
|
+
canonical_request = (http_request_method + "\n" +
|
|
62
|
+
canonical_uri + "\n" +
|
|
63
|
+
canonical_querystring + "\n" +
|
|
64
|
+
canonical_headers + "\n" +
|
|
65
|
+
signed_headers + "\n" +
|
|
66
|
+
hashed_request_payload)
|
|
67
|
+
|
|
68
|
+
# ************* 步骤 2:拼接待签名字符串 *************
|
|
69
|
+
credential_scope = date + "/" + self._service + "/" + "tc3_request"
|
|
70
|
+
hashed_canonical_request = hashlib.sha256(canonical_request.encode("utf-8")).hexdigest()
|
|
71
|
+
string_to_sign = (algorithm + "\n" +
|
|
72
|
+
str(timestamp) + "\n" +
|
|
73
|
+
credential_scope + "\n" +
|
|
74
|
+
hashed_canonical_request)
|
|
75
|
+
|
|
76
|
+
# ************* 步骤 3:计算签名 *************
|
|
77
|
+
secret_date = hmac.new(("TC3" + self._secret_key).encode("utf-8"), date.encode("utf-8"), hashlib.sha256).digest()
|
|
78
|
+
secret_service = hmac.new(secret_date, self._service.encode("utf-8"), hashlib.sha256).digest()
|
|
79
|
+
secret_signing = hmac.new(secret_service, "tc3_request".encode("utf-8"), hashlib.sha256).digest()
|
|
80
|
+
signature = hmac.new(secret_signing, string_to_sign.encode("utf-8"), hashlib.sha256).hexdigest()
|
|
81
|
+
|
|
82
|
+
# ************* 步骤 4:拼接 Authorization *************
|
|
83
|
+
authorization = (algorithm + " " +
|
|
84
|
+
"Credential=" + self._secret_id + "/" + credential_scope + ", " +
|
|
85
|
+
"SignedHeaders=" + signed_headers + ", " +
|
|
86
|
+
"Signature=" + signature)
|
|
87
|
+
|
|
88
|
+
return authorization
|
|
89
|
+
|
|
90
|
+
def _request(self, action: str, payload: Dict[str, Any], headers: Dict[str, str]):
|
|
91
|
+
body = json.dumps(payload)
|
|
92
|
+
timestamp = int(time.time())
|
|
93
|
+
authorization = self._sign(action, body, timestamp)
|
|
94
|
+
|
|
95
|
+
headers.update({
|
|
96
|
+
"Authorization": authorization,
|
|
97
|
+
"Content-Type": "application/json; charset=utf-8",
|
|
98
|
+
"Host": self._host,
|
|
99
|
+
"X-TC-Action": action,
|
|
100
|
+
"X-TC-Timestamp": str(timestamp),
|
|
101
|
+
"X-TC-Version": self._version,
|
|
102
|
+
})
|
|
103
|
+
if self._region:
|
|
104
|
+
headers["X-TC-Region"] = self._region
|
|
105
|
+
if self._token:
|
|
106
|
+
headers["X-TC-Token"] = self._token
|
|
107
|
+
|
|
108
|
+
req = HTTPSConnection(self._host, timeout=30)
|
|
109
|
+
try:
|
|
110
|
+
req.request("POST", "/", headers=headers, body=body.encode("utf-8"))
|
|
111
|
+
resp = req.getresponse()
|
|
112
|
+
finally:
|
|
113
|
+
req.close()
|
|
114
|
+
content = resp.read().decode("utf-8")
|
|
115
|
+
|
|
116
|
+
# check http status
|
|
117
|
+
if resp.status != http.HTTPStatus.OK:
|
|
118
|
+
raise HTTPException(f"ServerNetworkError, message: {content}")
|
|
119
|
+
try:
|
|
120
|
+
data = json.loads(content)
|
|
121
|
+
except json.JSONDecodeError:
|
|
122
|
+
raise HTTPException(f"ServerNetworkError, message: {content}")
|
|
123
|
+
|
|
124
|
+
# check error
|
|
125
|
+
if "Error" in data["Response"]:
|
|
126
|
+
code = data["Response"]["Error"]["Code"]
|
|
127
|
+
message = data["Response"]["Error"]["Message"]
|
|
128
|
+
req_id = data["Response"]["RequestId"]
|
|
129
|
+
raise HTTPException(f"code:{code} message:{message} requestId:{req_id}")
|
|
130
|
+
|
|
131
|
+
return data
|
|
132
|
+
|
|
133
|
+
def create_experiment(self, body: Dict[str, Any], headers: Optional[Dict[str, str]] = None) -> Dict[str, Any]:
|
|
134
|
+
headers = _set_request_header(headers)
|
|
135
|
+
resp = self._request("CreateExperiment", body, headers)
|
|
136
|
+
|
|
137
|
+
return resp
|
|
138
|
+
|
|
139
|
+
def rename_experiment(self, body: Dict[str, Any], headers: Optional[Dict[str, str]] = None) -> Dict[str, Any]:
|
|
140
|
+
headers = _set_request_header(headers)
|
|
141
|
+
resp = self._request("UpdateExperimentName", body, headers)
|
|
142
|
+
|
|
143
|
+
return resp
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def _get_client() -> _DataScienceApi:
|
|
147
|
+
region = os.environ["KERNEL_WEDATA_REGION"]
|
|
148
|
+
secret_id = os.environ["KERNEL_WEDATA_CLOUD_SDK_SECRET_ID"]
|
|
149
|
+
secret_key = os.environ["KERNEL_WEDATA_CLOUD_SDK_SECRET_KEY"]
|
|
150
|
+
token = os.environ["KERNEL_WEDATA_CLOUD_SDK_SECRET_TOKEN"]
|
|
151
|
+
_client = _DataScienceApi(region, secret_id, secret_key, token)
|
|
152
|
+
return _client
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def _create_experiment(
|
|
156
|
+
self, name: str,
|
|
157
|
+
artifact_location: Optional[str] = None,
|
|
158
|
+
tags: Optional[dict[str, Any]] = None,
|
|
159
|
+
) -> str:
|
|
160
|
+
req_body = {
|
|
161
|
+
"WorkspaceId": os.environ["WEDATA_WORKSPACE_ID"],
|
|
162
|
+
"Name": name,
|
|
163
|
+
"Type": "MACHINE_LEARNING",
|
|
164
|
+
"Tags": [{"Key": key, "Value": value} for key, value in (tags or {}).items()]
|
|
165
|
+
}
|
|
166
|
+
_client = _get_client()
|
|
167
|
+
resp = _client.create_experiment(req_body)
|
|
168
|
+
return resp["Response"]["Data"]["ExperimentId"]
|
|
169
|
+
|
|
170
|
+
def _rename_experiment(self, experiment_id: str, new_name: str) -> None:
|
|
171
|
+
req_body = {
|
|
172
|
+
"NewName": new_name,
|
|
173
|
+
"ExperimentId": experiment_id,
|
|
174
|
+
"WorkspaceId": os.environ["WEDATA_WORKSPACE_ID"],
|
|
175
|
+
}
|
|
176
|
+
_client = _get_client()
|
|
177
|
+
resp = _client.rename_experiment(req_body)
|
|
178
|
+
if not resp["Response"]["Data"]["Status"]:
|
|
179
|
+
raise MlflowException("Failed to rename the experiment", BAD_REQUEST)
|
|
180
|
+
|
|
181
|
+
def _restore_experiment(self, experiment_id: str) -> None:
|
|
182
|
+
raise MlflowException("Please go to the WeData console to restore the experiment; "
|
|
183
|
+
"this operation is prohibited in scripts.", ABORTED)
|
|
184
|
+
|
|
185
|
+
def _delete_experiment(self, experiment_id: str) -> None:
|
|
186
|
+
raise MlflowException("Please go to the WeData console to delete the experiment; "
|
|
187
|
+
"this operation is prohibited in scripts.", ABORTED)
|
|
@@ -5,7 +5,8 @@ wedata_pre_code/common/base_client.py,sha256=Y9lQBOYaDOB7Zy3MR_bPvHSQjN5Onsn8TPO
|
|
|
5
5
|
wedata_pre_code/wedata2/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
6
|
wedata_pre_code/wedata2/client.py,sha256=ScAQRrT-alc2CqatiwLCNAymYfEtWKWTnrCsLTbYEoM,19535
|
|
7
7
|
wedata_pre_code/wedata3/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
|
-
wedata_pre_code/wedata3/client.py,sha256=
|
|
9
|
-
wedata_pre_code
|
|
10
|
-
wedata_pre_code-1.0.
|
|
11
|
-
wedata_pre_code-1.0.
|
|
8
|
+
wedata_pre_code/wedata3/client.py,sha256=H0RB7JXeHka29xcQkyQekLR8VgSUy-9iMYRlPbRcJRg,21260
|
|
9
|
+
wedata_pre_code/wedata3/experiment.py,sha256=iVWmeiM-dgZrR7Cn2C0LHNMxR1BF-GAGqojHp5WrI0w,7314
|
|
10
|
+
wedata_pre_code-1.0.11.dist-info/WHEEL,sha256=XjEbIc5-wIORjWaafhI6vBtlxDBp7S9KiujWF1EM7Ak,79
|
|
11
|
+
wedata_pre_code-1.0.11.dist-info/METADATA,sha256=qCJNkdqlRxEpaYyMBK4QBUplT7sIsE3S8rDFKkZuCoU,7372
|
|
12
|
+
wedata_pre_code-1.0.11.dist-info/RECORD,,
|