teradataml 20.0.0.5__py3-none-any.whl → 20.0.0.6__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.
Potentially problematic release.
This version of teradataml might be problematic. Click here for more details.
- teradataml/LICENSE-3RD-PARTY.pdf +0 -0
- teradataml/README.md +96 -0
- teradataml/_version.py +1 -1
- teradataml/analytics/analytic_function_executor.py +1 -1
- teradataml/analytics/utils.py +56 -11
- teradataml/clients/auth_client.py +10 -6
- teradataml/clients/keycloak_client.py +165 -0
- teradataml/common/constants.py +10 -0
- teradataml/common/exceptions.py +32 -0
- teradataml/common/messagecodes.py +27 -0
- teradataml/common/messages.py +9 -1
- teradataml/common/sqlbundle.py +3 -2
- teradataml/common/utils.py +94 -12
- teradataml/context/context.py +37 -9
- teradataml/data/jsons/byom/onnxembeddings.json +1 -0
- teradataml/data/pattern_matching_data.csv +11 -0
- teradataml/data/sdk/modelops/modelops_spec.json +101737 -0
- teradataml/data/teradataml_example.json +8 -1
- teradataml/data/url_data.csv +10 -9
- teradataml/dataframe/copy_to.py +1 -1
- teradataml/dataframe/dataframe.py +980 -82
- teradataml/dataframe/dataframe_utils.py +58 -25
- teradataml/dataframe/functions.py +962 -1
- teradataml/dataframe/sql.py +570 -1031
- teradataml/hyperparameter_tuner/utils.py +4 -2
- teradataml/lib/aed_0_1.dll +0 -0
- teradataml/opensource/_base.py +7 -1
- teradataml/options/configure.py +20 -4
- teradataml/scriptmgmt/UserEnv.py +13 -2
- teradataml/scriptmgmt/lls_utils.py +99 -24
- teradataml/sdk/README.md +79 -0
- teradataml/sdk/__init__.py +4 -0
- teradataml/sdk/_auth_modes.py +422 -0
- teradataml/sdk/_func_params.py +487 -0
- teradataml/sdk/_json_parser.py +453 -0
- teradataml/sdk/_openapi_spec_constants.py +249 -0
- teradataml/sdk/_utils.py +236 -0
- teradataml/sdk/api_client.py +897 -0
- teradataml/sdk/constants.py +62 -0
- teradataml/sdk/modelops/__init__.py +98 -0
- teradataml/sdk/modelops/_client.py +406 -0
- teradataml/sdk/modelops/_constants.py +304 -0
- teradataml/sdk/modelops/models.py +2308 -0
- teradataml/sdk/spinner.py +107 -0
- teradataml/table_operators/query_generator.py +4 -21
- teradataml/utils/dtypes.py +2 -1
- teradataml/utils/utils.py +0 -1
- teradataml/utils/validators.py +5 -1
- {teradataml-20.0.0.5.dist-info → teradataml-20.0.0.6.dist-info}/METADATA +101 -2
- {teradataml-20.0.0.5.dist-info → teradataml-20.0.0.6.dist-info}/RECORD +53 -36
- {teradataml-20.0.0.5.dist-info → teradataml-20.0.0.6.dist-info}/WHEEL +0 -0
- {teradataml-20.0.0.5.dist-info → teradataml-20.0.0.6.dist-info}/top_level.txt +0 -0
- {teradataml-20.0.0.5.dist-info → teradataml-20.0.0.6.dist-info}/zip-safe +0 -0
teradataml/LICENSE-3RD-PARTY.pdf
CHANGED
|
Binary file
|
teradataml/README.md
CHANGED
|
@@ -17,6 +17,102 @@ Copyright 2025, Teradata. All Rights Reserved.
|
|
|
17
17
|
|
|
18
18
|
## Release Notes:
|
|
19
19
|
|
|
20
|
+
#### teradataml 20.00.00.06
|
|
21
|
+
* ##### New Features/Functionality
|
|
22
|
+
* ###### teradataml: SDK
|
|
23
|
+
* Added new client `teradataml.sdk.Client` which can be used by user to make REST calls through SDK.
|
|
24
|
+
* New exception added in `teradataml`, specifically for REST APIs `TeradatamlRestException` that has attribute `json_resonse` providing proper printable json.
|
|
25
|
+
* Exposed three different ways of authentication through `Client`.
|
|
26
|
+
* Client credentials Authentication through `ClientCredentialsAuth` class.
|
|
27
|
+
* Device code Authentication through `DeviceCodeAuth` class.
|
|
28
|
+
* Bearer Authentication through `BearerAuth` class.
|
|
29
|
+
|
|
30
|
+
* ###### teradataml: ModelOps SDK
|
|
31
|
+
* `teradataml` exposes Python interfaces for all the REST APIs provided by Teradata Vantage ModelOps.
|
|
32
|
+
* Added support for `blueprint()` method which prints available classes in `modelops` module.
|
|
33
|
+
* Added new client `ModelOpsClient` with some additional function compared to `teradataml.sdk.Client`.
|
|
34
|
+
* teradataml classes are added for the schema in ModelOps OpenAPI specification.
|
|
35
|
+
```python
|
|
36
|
+
>>> from teradataml.sdk.modelops import ModelOpsClient, Projects
|
|
37
|
+
>>> from teradataml.common.exceptions import TeradatamlRestException
|
|
38
|
+
>>> from teradataml.sdk import DeviceCodeAuth, BearerAuth, ClientCredentialsAuth # Authentication related classes.
|
|
39
|
+
>>> from teradataml.sdk.modelops import models # All classes related to OpenAPI schema are present in this module.
|
|
40
|
+
|
|
41
|
+
# Print available classes in modelops module.
|
|
42
|
+
>>> from teradataml.sdk.modelops import blueprint
|
|
43
|
+
>>> blueprint()
|
|
44
|
+
|
|
45
|
+
# Create ClientCredentialsAuth object and create ModelOpsClient object.
|
|
46
|
+
>>> cc_obj = ClientCredentialsAuth(auth_client_id="<client_id>",
|
|
47
|
+
auth_client_secret="<client_secret>",
|
|
48
|
+
auth_token_url="https://<example.com>/token")
|
|
49
|
+
>>> client = ModelOpsClient(base_url="<base_url>", auth=cc_obj, ssl_verify=False)
|
|
50
|
+
|
|
51
|
+
# Create Projects object.
|
|
52
|
+
>>> p = Projects(client=client)
|
|
53
|
+
|
|
54
|
+
# Create project using `body` argument taking object of ProjectRequestBody.
|
|
55
|
+
>>> project_paylod = {
|
|
56
|
+
"name": "dummy_project",
|
|
57
|
+
"description": "dummy_project created for testing",
|
|
58
|
+
"groupId": "<group_ID>",
|
|
59
|
+
"gitRepositoryUrl": "/app/built-in/empty",
|
|
60
|
+
"branch": "<branch>"
|
|
61
|
+
}
|
|
62
|
+
>>> p.create_project(body=models.ProjectRequestBody(**project_payload))
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
* ###### teradataml: Functions
|
|
66
|
+
* `get_formatters()` - Get the formatters for NUMERIC, DATE and CHAR types.
|
|
67
|
+
|
|
68
|
+
* ###### teradataml: DataFrame Methods
|
|
69
|
+
* `get_snapshot()` - Gets the snapshot data of a teradataml DataFrame created on OTF table for a given snapshot id or timestamp.
|
|
70
|
+
* `from_pandas()`: Creates a teradataml DataFrame from a pandas DataFrame.
|
|
71
|
+
* `from_records()`: Creates a teradataml DataFrame from a list.
|
|
72
|
+
* `from_dict()`: Creates a teradataml DataFrame from a dictionary.
|
|
73
|
+
|
|
74
|
+
* ###### teradataml: DataFrame Property
|
|
75
|
+
* `history` - Returns snapshot history for a DataFrame created on OTF table.
|
|
76
|
+
* `manifests` - Returns manifest information for a DataFrame created on OTF table.
|
|
77
|
+
* `partitions` - Returns partition information for a DataFrame created on OTF table.
|
|
78
|
+
* `snapshots` - Returns snapshot information for a DataFrame created on OTF table.
|
|
79
|
+
|
|
80
|
+
* ###### teradataml DataFrameColumn a.k.a. ColumnExpression
|
|
81
|
+
* `DataFrameColumn.rlike()` - Function to match a string against a regular expression pattern.
|
|
82
|
+
* `DataFrameColumn.substring_index()` - Function to return the substring from a column before a specified
|
|
83
|
+
delimiter, up to a given occurrence count.
|
|
84
|
+
* `DataFrameColumn.count_delimiters()` - Function to count the total number of occurrences of a specified delimiter.
|
|
85
|
+
|
|
86
|
+
* ##### Updates
|
|
87
|
+
* ###### teradataml DataFrameColumn a.k.a. ColumnExpression
|
|
88
|
+
* `DataFrameColumn.like()`
|
|
89
|
+
* Added argument `escape_char` to specify the escape character for the LIKE pattern.
|
|
90
|
+
* Argument `pattern` now accepts DataFrameColumn as input.
|
|
91
|
+
* `DataFrameColumn.ilike()`
|
|
92
|
+
* Added argument `escape_char` to specify the escape character for the ILIKE pattern.
|
|
93
|
+
* Argument `pattern` now accepts DataFrameColumn as input.
|
|
94
|
+
* `DataFrameColumn.parse_url()` - Added argument `key` to extract a specific query parameter when `url_part` is set to "QUERY".
|
|
95
|
+
|
|
96
|
+
* ###### teradataml: DataFrame function
|
|
97
|
+
* `groupby()`, `cube()` and `rollup()`
|
|
98
|
+
* Added argument `include_grouping_columns` to include aggregations on the grouping column(s).
|
|
99
|
+
* `DataFrame()`: New argument `data`, that accepts input data to create a teradataml DataFrame, is added.
|
|
100
|
+
|
|
101
|
+
* ###### General functions
|
|
102
|
+
* `set_auth_token()`
|
|
103
|
+
* New keyword argument `auth_url` accepts the endpoint URL for a keycloak server.
|
|
104
|
+
* New keyword argument `rest_client` accepts name of the service for which keycloak token is to be generated.
|
|
105
|
+
* New keyword argument `validate_jwt` accepts the boolean flag to decide whether to validate generated JWT token or not.
|
|
106
|
+
* New keyword argument `valid_from` accepts the epoch seconds representing time from which JWT token will be valid.
|
|
107
|
+
|
|
108
|
+
* ###### teradataml Options
|
|
109
|
+
* Configuration Options
|
|
110
|
+
* `configure.use_short_object_name`
|
|
111
|
+
Specifies whether to use a shorter name for temporary database objects which are created by teradataml internally.
|
|
112
|
+
|
|
113
|
+
* ###### BYOM Function
|
|
114
|
+
* Supports special characters.
|
|
115
|
+
|
|
20
116
|
#### teradataml 20.00.00.05
|
|
21
117
|
* ##### New Features/Functionality
|
|
22
118
|
* ##### teradataml: AutoML
|
teradataml/_version.py
CHANGED
|
@@ -490,7 +490,7 @@ class _AnlyticFunctionExecutor:
|
|
|
490
490
|
arg_value = self._spl_func_obj._add_square_bracket(arg_value)
|
|
491
491
|
|
|
492
492
|
# Check if there are columns with non-ASCII characters.
|
|
493
|
-
if UtilFuncs.
|
|
493
|
+
if UtilFuncs._is_non_ascii(arg_value):
|
|
494
494
|
arg_value = UtilFuncs._teradata_quote_arg(arg_value, "\"", False)
|
|
495
495
|
# Handling special case for Teradata reserved keywords or column names with spaces.
|
|
496
496
|
# If argument is a string or list of strings, then add quotes to the string.
|
teradataml/analytics/utils.py
CHANGED
|
@@ -459,19 +459,64 @@ class FuncSpecialCaseHandler():
|
|
|
459
459
|
"Matrix2Image": {"type": self._single_quote_arg,
|
|
460
460
|
"colormap": self._single_quote_arg
|
|
461
461
|
},
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
462
|
+
"AIAnalyzeSentiment": {"authorization": self._remove_quotes},
|
|
463
|
+
"AITextTranslate": {"authorization": self._remove_quotes},
|
|
464
|
+
"AITextSummarize": {"authorization": self._remove_quotes},
|
|
465
|
+
"AI_TextEmbeddings": {"authorization": self._remove_quotes},
|
|
466
|
+
"AITextClassifier": {"authorization": self._remove_quotes},
|
|
467
|
+
"AIRecognizePIIEntities": {"authorization": self._remove_quotes},
|
|
468
|
+
"AIRecognizeEntities": {"authorization": self._remove_quotes},
|
|
469
|
+
"AIMaskPII:": {"authorization": self._remove_quotes},
|
|
470
|
+
"AIExtractKeyPhrases": {"authorization": self._remove_quotes},
|
|
471
|
+
"AIDetectLanguage": {"authorization": self._remove_quotes},
|
|
472
|
+
"AIAskLLM": {"authorization": self._remove_quotes},
|
|
473
|
+
"DataikuPredict": {"accumulate": self._handle_byom_args},
|
|
474
|
+
"DataRobotPredict": {"accumulate": self._handle_byom_args},
|
|
475
|
+
"H2OPredict": {"accumulate": self._handle_byom_args},
|
|
476
|
+
"ONNXEmbeddings": {"accumulate": self._handle_byom_args},
|
|
477
|
+
"ONNXPredict": {"accumulate": self._handle_byom_args},
|
|
478
|
+
"PMMLPredict": {"accumulate": self._handle_byom_args}
|
|
473
479
|
}
|
|
474
480
|
|
|
481
|
+
def _handle_byom_args(self, arg_value, *args, **kwargs):
|
|
482
|
+
"""
|
|
483
|
+
DESCRIPTION:
|
|
484
|
+
Function to handle the special function arguments for BYOM functions.
|
|
485
|
+
Special character(s) are required to be in single quote for BYOM
|
|
486
|
+
functions. For other SQLE functions, special character(s) to be in double
|
|
487
|
+
quote. Hence removing double quotes and adding single quotes for
|
|
488
|
+
special character(s) in the argument value.
|
|
489
|
+
|
|
490
|
+
PARAMETERS:
|
|
491
|
+
arg_value
|
|
492
|
+
Required Argument.
|
|
493
|
+
Specifies the argument value to handle special function arguments.
|
|
494
|
+
Types: str or list of str(s)
|
|
495
|
+
|
|
496
|
+
RETURNS:
|
|
497
|
+
str
|
|
498
|
+
|
|
499
|
+
RAISES:
|
|
500
|
+
None
|
|
501
|
+
|
|
502
|
+
EXAMPLES:
|
|
503
|
+
# Example 1: Handle the special function arguments for BYOM functions.
|
|
504
|
+
>>> self._handle_byom_args('"alice.deauth"')
|
|
505
|
+
# result: 'alice.deauth'
|
|
506
|
+
"""
|
|
507
|
+
arg_values = []
|
|
508
|
+
if isinstance(arg_value, list):
|
|
509
|
+
arg_values = (val.strip('"') for val in arg_value)
|
|
510
|
+
return ", ".join(["'{}'".format(val) for val in arg_values])
|
|
511
|
+
|
|
512
|
+
if isinstance(arg_value, str):
|
|
513
|
+
# If argument value is a string, remove quotes.
|
|
514
|
+
arg_value = arg_value.strip('"')
|
|
515
|
+
return "'{}'".format(arg_value)
|
|
516
|
+
|
|
517
|
+
return arg_value
|
|
518
|
+
|
|
519
|
+
|
|
475
520
|
# Setter method for argument.
|
|
476
521
|
def set_arg_name(self, argument):
|
|
477
522
|
"""
|
|
@@ -33,6 +33,8 @@ class _AuthWorkflow:
|
|
|
33
33
|
5. "username" which is the DB user.
|
|
34
34
|
5. "expiration_time" which is the expiration time for the token and has a default value of
|
|
35
35
|
31536000 seconds.
|
|
36
|
+
6. "valid_from" which states epoch seconds representing time from which JWT token will be valid
|
|
37
|
+
and same is used as iat claim in payload.
|
|
36
38
|
Types: dict
|
|
37
39
|
|
|
38
40
|
RETURNS:
|
|
@@ -52,7 +54,7 @@ class _AuthWorkflow:
|
|
|
52
54
|
Generate expiry epoch time.
|
|
53
55
|
|
|
54
56
|
RETURNS:
|
|
55
|
-
|
|
57
|
+
tuple
|
|
56
58
|
"""
|
|
57
59
|
current_epoch_time = int(time.time())
|
|
58
60
|
expiry_epoch_time = current_epoch_time + self.state.get('expiration_time')
|
|
@@ -83,12 +85,11 @@ class _AuthWorkflow:
|
|
|
83
85
|
RETURNS:
|
|
84
86
|
A dictionary with the JWT payload.
|
|
85
87
|
"""
|
|
86
|
-
|
|
88
|
+
_, exp = self._get_epoch_time()
|
|
87
89
|
payload = {
|
|
88
90
|
"aud": [
|
|
89
91
|
"td:service:authentication"
|
|
90
92
|
],
|
|
91
|
-
"iat": iat,
|
|
92
93
|
"exp": exp,
|
|
93
94
|
"iss": "teradataml",
|
|
94
95
|
"multi-use": True,
|
|
@@ -96,6 +97,9 @@ class _AuthWorkflow:
|
|
|
96
97
|
"pat": self.state['pat_token'],
|
|
97
98
|
"sub": self.state['username']
|
|
98
99
|
}
|
|
100
|
+
# Add iat if required.
|
|
101
|
+
if self.state['valid_from']:
|
|
102
|
+
payload.update({"iat": self.state['valid_from']})
|
|
99
103
|
return payload
|
|
100
104
|
|
|
101
105
|
def _sign_jwt(self, payload, header):
|
|
@@ -128,6 +132,6 @@ class _AuthWorkflow:
|
|
|
128
132
|
RETURNS:
|
|
129
133
|
str
|
|
130
134
|
"""
|
|
131
|
-
|
|
132
|
-
self.state['jwt'] =
|
|
133
|
-
return
|
|
135
|
+
jwt_token = self._sign_jwt(self._generate_payload(), self._generate_header())
|
|
136
|
+
self.state['jwt'] = jwt_token
|
|
137
|
+
return jwt_token
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Unpublished work.
|
|
3
|
+
Copyright (c) 2025 by Teradata Corporation. All rights reserved.
|
|
4
|
+
TERADATA CORPORATION CONFIDENTIAL AND TRADE SECRET
|
|
5
|
+
Primary Owner: shivani.kondewar@teradata.com
|
|
6
|
+
Secondary Owner: aanchal.kavedia@teradata.com
|
|
7
|
+
This file implements _KeycloakManager class used to store data for keycloak token generation.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import time
|
|
11
|
+
from enum import Enum
|
|
12
|
+
|
|
13
|
+
from teradataml import TeradataMlException, MessageCodes
|
|
14
|
+
from teradataml.common.constants import HTTPRequest
|
|
15
|
+
from teradataml.context.context import _get_user
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class GrantType(Enum):
|
|
19
|
+
PASS = "password"
|
|
20
|
+
REFRESH = "refresh_token"
|
|
21
|
+
CLIENT = "client_credentials"
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class _KeycloakManager():
|
|
25
|
+
|
|
26
|
+
def __init__(self, auth_url, client_id):
|
|
27
|
+
"""
|
|
28
|
+
DESCRIPTION:
|
|
29
|
+
Constructor to initiate keycloak manager.
|
|
30
|
+
|
|
31
|
+
PARAMETERS:
|
|
32
|
+
auth_url:
|
|
33
|
+
Required Argument.
|
|
34
|
+
Specifies the endpoint URL for a keycloak server.
|
|
35
|
+
Types: str
|
|
36
|
+
|
|
37
|
+
client_id:
|
|
38
|
+
Required Argument.
|
|
39
|
+
Specifies the client/service for which keycloak server avails a token.
|
|
40
|
+
Types: str
|
|
41
|
+
|
|
42
|
+
RETURNS:
|
|
43
|
+
Instance of _KeycloakManager.
|
|
44
|
+
|
|
45
|
+
RAISES:
|
|
46
|
+
None
|
|
47
|
+
|
|
48
|
+
EXAMPLES:
|
|
49
|
+
>>> token_generator = _KeycloakManager(auth_url=auth_url,
|
|
50
|
+
... username=username,
|
|
51
|
+
... client_id=client_id)
|
|
52
|
+
"""
|
|
53
|
+
self._auth_url = auth_url
|
|
54
|
+
self._client_id = client_id
|
|
55
|
+
self._header = {"Content-Type": "application/x-www-form-urlencoded"}
|
|
56
|
+
self._expires_at = None
|
|
57
|
+
self._refresh_expires_at = None
|
|
58
|
+
|
|
59
|
+
def generate_token(self, username=None, password=None, refresh=False):
|
|
60
|
+
"""
|
|
61
|
+
DESCRIPTION:
|
|
62
|
+
Method generates keycloak token.
|
|
63
|
+
Token can be generated using any one of the following information:
|
|
64
|
+
* Username and password
|
|
65
|
+
* Refresh token
|
|
66
|
+
|
|
67
|
+
PARAMETERS:
|
|
68
|
+
username:
|
|
69
|
+
Optional Argument.
|
|
70
|
+
Specifies the username for database user for which keycloak token is
|
|
71
|
+
to be generated. If not specified, then user associated with current
|
|
72
|
+
connection is used.
|
|
73
|
+
Types: str
|
|
74
|
+
|
|
75
|
+
password:
|
|
76
|
+
Optional Argument.
|
|
77
|
+
Specifies the password for database user.
|
|
78
|
+
Types: str
|
|
79
|
+
|
|
80
|
+
refresh:
|
|
81
|
+
Optional Argument.
|
|
82
|
+
Specifies the boolean flag to indicate if token needs to be generated
|
|
83
|
+
using existing refresh token or not.
|
|
84
|
+
Default value: False
|
|
85
|
+
Types: Boolean
|
|
86
|
+
|
|
87
|
+
RETURNS:
|
|
88
|
+
Keycloak token
|
|
89
|
+
|
|
90
|
+
RAISES:
|
|
91
|
+
RuntimeError.
|
|
92
|
+
|
|
93
|
+
EXAMPLES:
|
|
94
|
+
# Example 1: Generate the authentication token using username and password.
|
|
95
|
+
>>> keycloak_obj.generate_token(username="username", password="password")
|
|
96
|
+
|
|
97
|
+
# Example 2: Generate the authentication token using default username for
|
|
98
|
+
# current session and provided password.
|
|
99
|
+
>>> keycloak_obj.generate_token(password="password")
|
|
100
|
+
|
|
101
|
+
# Example 3: Generate the authentication token using refresh token which is
|
|
102
|
+
# already available.
|
|
103
|
+
>>> keycloak_obj.generate_token(refresh=True)
|
|
104
|
+
"""
|
|
105
|
+
# Define the payload.
|
|
106
|
+
if password:
|
|
107
|
+
payload = {
|
|
108
|
+
"grant_type": GrantType.PASS.value,
|
|
109
|
+
"client_id": self._client_id,
|
|
110
|
+
"username": username if username else _get_user(),
|
|
111
|
+
"password": password
|
|
112
|
+
}
|
|
113
|
+
if refresh:
|
|
114
|
+
payload = {
|
|
115
|
+
"grant_type": GrantType.REFRESH.value,
|
|
116
|
+
"client_id": self._client_id,
|
|
117
|
+
"refresh_token": self._refresh_token
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
# Make the POST request.
|
|
121
|
+
# Importing locally to avoid circular import.
|
|
122
|
+
from teradataml import UtilFuncs
|
|
123
|
+
response = UtilFuncs._http_request(self._auth_url, HTTPRequest.POST,
|
|
124
|
+
headers=self._header, data=payload)
|
|
125
|
+
|
|
126
|
+
# Check the response.
|
|
127
|
+
if 200 <= response.status_code < 300:
|
|
128
|
+
response_data = response.json()
|
|
129
|
+
self._auth_token = response_data['access_token']
|
|
130
|
+
self._refresh_token = response_data['refresh_token']
|
|
131
|
+
# 30 is buffer time to assume delay in processing of response_data.
|
|
132
|
+
self._expires_at = time.time() + response_data['expires_in'] - 30
|
|
133
|
+
self._refresh_expires_at = time.time() + response_data['refresh_expires_in'] - 30
|
|
134
|
+
else:
|
|
135
|
+
raise
|
|
136
|
+
|
|
137
|
+
return self._auth_token
|
|
138
|
+
|
|
139
|
+
def get_token(self):
|
|
140
|
+
"""
|
|
141
|
+
DESCRIPTION:
|
|
142
|
+
Function to get keycloak token.
|
|
143
|
+
If access token is not expired, existing token is returned.
|
|
144
|
+
If access token is expired, and refresh token is alive, new access token is generated.
|
|
145
|
+
If both access token and refresh token are expired, TeradataMlException is raised
|
|
146
|
+
|
|
147
|
+
RETURNS:
|
|
148
|
+
Keycloak token
|
|
149
|
+
|
|
150
|
+
RAISES:
|
|
151
|
+
TeradataMlException.
|
|
152
|
+
|
|
153
|
+
"""
|
|
154
|
+
# If existing auth_token is expired, regenerate using refresh token.
|
|
155
|
+
if self._expires_at and time.time() > self._expires_at:
|
|
156
|
+
# If refresh token is expired, raise error.
|
|
157
|
+
if self._refresh_expires_at and time.time() > self._refresh_expires_at:
|
|
158
|
+
raise TeradataMlException("Refresh token for keycloak is expired."
|
|
159
|
+
" Execute set_auth_token() to set fresh authentication token.",
|
|
160
|
+
MessageCodes.FUNC_EXECUTION_FAILED)
|
|
161
|
+
else:
|
|
162
|
+
# Regenerate fresh access token using refresh token.
|
|
163
|
+
self.generate_token(refresh=True)
|
|
164
|
+
|
|
165
|
+
return self._auth_token
|
teradataml/common/constants.py
CHANGED
|
@@ -65,6 +65,8 @@ class SQLConstants(Enum):
|
|
|
65
65
|
SQL_HELP_DATALAKE = 34
|
|
66
66
|
CONSTRAINT = ["check_constraint", "primary_key_constraint",
|
|
67
67
|
"foreign_key_constraint", "unique_key_constraint"]
|
|
68
|
+
SQL_TD_OTF_METADATA = 35
|
|
69
|
+
SQL_TD_OTF_SNAPSHOT = 36
|
|
68
70
|
|
|
69
71
|
|
|
70
72
|
class TeradataConstants(Enum):
|
|
@@ -1567,3 +1569,11 @@ class AuthMechs(Enum):
|
|
|
1567
1569
|
JWT = "JWT"
|
|
1568
1570
|
PAT = "PAT"
|
|
1569
1571
|
BASIC = "BASIC"
|
|
1572
|
+
KEYCLOAK = "KEYCLOAK"
|
|
1573
|
+
|
|
1574
|
+
class TDServices(Enum):
|
|
1575
|
+
"""
|
|
1576
|
+
Enum to hold permitted values for types for services availed on Teradata vantage.
|
|
1577
|
+
"""
|
|
1578
|
+
VECTORSTORE = "vectorstore"
|
|
1579
|
+
MOPS = "MODELOPS" # For future reference
|
teradataml/common/exceptions.py
CHANGED
|
@@ -12,6 +12,12 @@ teradataml.common.exceptions
|
|
|
12
12
|
An Error class for the teradataml python module
|
|
13
13
|
"""
|
|
14
14
|
|
|
15
|
+
|
|
16
|
+
import warnings
|
|
17
|
+
import json
|
|
18
|
+
import pprint
|
|
19
|
+
|
|
20
|
+
|
|
15
21
|
class TeradataMlException(Exception):
|
|
16
22
|
"""
|
|
17
23
|
Teradata Ml Exception class.
|
|
@@ -71,3 +77,29 @@ class TeradataMlException(Exception):
|
|
|
71
77
|
"""
|
|
72
78
|
super(TeradataMlException, self).__init__(msg)
|
|
73
79
|
self.code = code
|
|
80
|
+
|
|
81
|
+
class TeradatamlRestException(TeradataMlException):
|
|
82
|
+
def __init__(self, msg, code, raw_message=None):
|
|
83
|
+
super().__init__(msg, code)
|
|
84
|
+
|
|
85
|
+
self._msg = msg
|
|
86
|
+
self._raw_message = raw_message
|
|
87
|
+
|
|
88
|
+
@property
|
|
89
|
+
def json_response(self):
|
|
90
|
+
"""
|
|
91
|
+
Returns the JSON response from the server.
|
|
92
|
+
"""
|
|
93
|
+
if self._raw_message is not None and self._raw_message.startswith("Error message: "):
|
|
94
|
+
failure_msg = f"Could not convert msg to json. Message is \n{self._raw_message}"
|
|
95
|
+
try:
|
|
96
|
+
json_resp = self._msg.split("Error message: ")[1]
|
|
97
|
+
json_resp = json.loads(json_resp)
|
|
98
|
+
return pprint.pformat(json_resp)
|
|
99
|
+
except json.JSONDecodeError as _:
|
|
100
|
+
warnings.warn(failure_msg)
|
|
101
|
+
elif self._raw_message is None:
|
|
102
|
+
return None
|
|
103
|
+
else:
|
|
104
|
+
warnings.warn(failure_msg)
|
|
105
|
+
|
|
@@ -228,6 +228,21 @@ class ErrorInfoCodes(Enum):
|
|
|
228
228
|
# OpenAF Error codes starting from 2551 - Reserved till 2560.
|
|
229
229
|
SET_REQUIRED_PARAMS = 'TDML_2551'
|
|
230
230
|
|
|
231
|
+
# Error codes for OTF. Reserved till 2570.
|
|
232
|
+
OTF_TABLE_REQUIRED = 'TDML_2561'
|
|
233
|
+
|
|
234
|
+
# Rest Excceptions. Reserved for 2570 - 2580
|
|
235
|
+
REST_HTTP_ERROR = 'TDML_2570'
|
|
236
|
+
REST_AUTH_MISSING_ARG = 'TDML_2571'
|
|
237
|
+
REST_NOT_CONFIGURED = 'TDML_2572'
|
|
238
|
+
REST_DEVICE_CODE_NO_BOTH = 'TDML_2573'
|
|
239
|
+
REST_DEVICE_CODE_GEN_FAILED = 'TDML_2574'
|
|
240
|
+
REST_DEVICE_CODE_AUTH_FAILED = 'TDML_2575'
|
|
241
|
+
|
|
242
|
+
# Python SDK Error codes starting from 2580 - Reserved till 2590.
|
|
243
|
+
INFO_NOT_PROVIDED_USE_DEFAULT = 'TDML_W_2580' # Logger warning.
|
|
244
|
+
|
|
245
|
+
|
|
231
246
|
class MessageCodes(Enum):
|
|
232
247
|
"""
|
|
233
248
|
MessageCodes contains all the messages that are displayed to the user which are informational
|
|
@@ -442,3 +457,15 @@ class MessageCodes(Enum):
|
|
|
442
457
|
"explicitly passed to function or specified using a configuration file, or setting up " \
|
|
443
458
|
"the environment variables."
|
|
444
459
|
DEPENDENT_METHOD = "Method(s) {} must be called before calling '{}'."
|
|
460
|
+
REST_HTTP_ERROR = "Failed to run rest API:\n{}"
|
|
461
|
+
REST_AUTH_MISSING_ARG = "For '{}' authentication, '{}' is/are not provided in config file or "\
|
|
462
|
+
"environment variable or through constructor argument 'auth'."
|
|
463
|
+
REST_NOT_CONFIGURED = "The argument '{}' is not set. {} endpoint not configured.\n" \
|
|
464
|
+
"Try (re)copy the CLI configuration from {} UI -> Session Details -> CLI Config."
|
|
465
|
+
REST_DEVICE_CODE_NO_BOTH = "Token does not contain access_token or refresh_token. Received token: {}"
|
|
466
|
+
REST_DEVICE_CODE_GEN_FAILED = "Error generating the device code. Received code: {}."
|
|
467
|
+
REST_DEVICE_CODE_AUTH_FAILED = "Error authenticating the device code.\n{}."
|
|
468
|
+
|
|
469
|
+
INFO_NOT_PROVIDED_USE_DEFAULT = "{} is not provided in path '{}' method '{}' for operationID '{}' using default {}."
|
|
470
|
+
OTF_TABLE_REQUIRED = "{} is supported only with OTF table."
|
|
471
|
+
|
teradataml/common/messages.py
CHANGED
|
@@ -196,7 +196,15 @@ class Messages():
|
|
|
196
196
|
[ErrorInfoCodes.TARGET_COL_NOT_FOUND_FOR_EVALUATE, MessageCodes.TARGET_COL_NOT_FOUND_FOR_EVALUATE],
|
|
197
197
|
[ErrorInfoCodes.SET_REQUIRED_PARAMS, MessageCodes.SET_REQUIRED_PARAMS],
|
|
198
198
|
[ErrorInfoCodes.MISSING_ARGS, MessageCodes.CONNECTION_PARAMS],
|
|
199
|
-
[ErrorInfoCodes.DEPENDENT_METHOD, MessageCodes.DEPENDENT_METHOD]
|
|
199
|
+
[ErrorInfoCodes.DEPENDENT_METHOD, MessageCodes.DEPENDENT_METHOD],
|
|
200
|
+
[ErrorInfoCodes.REST_HTTP_ERROR, MessageCodes.REST_HTTP_ERROR],
|
|
201
|
+
[ErrorInfoCodes.REST_AUTH_MISSING_ARG, MessageCodes.REST_AUTH_MISSING_ARG],
|
|
202
|
+
[ErrorInfoCodes.REST_NOT_CONFIGURED, MessageCodes.REST_NOT_CONFIGURED],
|
|
203
|
+
[ErrorInfoCodes.REST_DEVICE_CODE_NO_BOTH, MessageCodes.REST_DEVICE_CODE_NO_BOTH],
|
|
204
|
+
[ErrorInfoCodes.REST_DEVICE_CODE_GEN_FAILED, MessageCodes.REST_DEVICE_CODE_GEN_FAILED],
|
|
205
|
+
[ErrorInfoCodes.REST_DEVICE_CODE_AUTH_FAILED, MessageCodes.REST_DEVICE_CODE_AUTH_FAILED],
|
|
206
|
+
[ErrorInfoCodes.INFO_NOT_PROVIDED_USE_DEFAULT, MessageCodes.INFO_NOT_PROVIDED_USE_DEFAULT],
|
|
207
|
+
[ErrorInfoCodes.OTF_TABLE_REQUIRED, MessageCodes.OTF_TABLE_REQUIRED]
|
|
200
208
|
]
|
|
201
209
|
|
|
202
210
|
@staticmethod
|
teradataml/common/sqlbundle.py
CHANGED
|
@@ -70,8 +70,9 @@ class SQLBundle:
|
|
|
70
70
|
[SQLConstants.SQL_EXEC_STORED_PROCEDURE, "call {0}"],
|
|
71
71
|
[SQLConstants.SQL_SELECT_COLUMNNAMES_WITH_WHERE, "sel {0} from {1} where {2}"],
|
|
72
72
|
[SQLConstants.SQL_HELP_DATABASE, "HELP DATABASE {0}"],
|
|
73
|
-
[SQLConstants.SQL_HELP_DATALAKE, "HELP DATALAKE {0}"]
|
|
74
|
-
|
|
73
|
+
[SQLConstants.SQL_HELP_DATALAKE, "HELP DATALAKE {0}"],
|
|
74
|
+
[SQLConstants.SQL_TD_OTF_METADATA, "SELECT * FROM {0}(ON ({1})) D;"],
|
|
75
|
+
[SQLConstants.SQL_TD_OTF_SNAPSHOT, "SELECT * FROM {0} FOR SNAPSHOT AS OF {1};"]
|
|
75
76
|
]
|
|
76
77
|
self._add_sql_version()
|
|
77
78
|
|