teradataml 20.0.0.4__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 +182 -13
- teradataml/__init__.py +2 -1
- teradataml/_version.py +2 -2
- teradataml/analytics/analytic_function_executor.py +8 -13
- teradataml/analytics/json_parser/analytic_functions_argument.py +4 -0
- teradataml/analytics/sqle/__init__.py +16 -1
- teradataml/analytics/utils.py +60 -1
- teradataml/automl/__init__.py +290 -106
- teradataml/automl/autodataprep/__init__.py +471 -0
- teradataml/automl/data_preparation.py +29 -10
- teradataml/automl/data_transformation.py +11 -0
- teradataml/automl/feature_engineering.py +64 -4
- teradataml/automl/feature_exploration.py +639 -25
- teradataml/automl/model_training.py +1 -1
- teradataml/clients/auth_client.py +12 -8
- teradataml/clients/keycloak_client.py +165 -0
- teradataml/common/constants.py +71 -26
- teradataml/common/exceptions.py +32 -0
- teradataml/common/messagecodes.py +28 -0
- teradataml/common/messages.py +13 -4
- teradataml/common/sqlbundle.py +3 -2
- teradataml/common/utils.py +345 -45
- teradataml/context/context.py +259 -93
- teradataml/data/apriori_example.json +22 -0
- teradataml/data/docs/sqle/docs_17_20/Apriori.py +138 -0
- teradataml/data/docs/sqle/docs_17_20/NERExtractor.py +121 -0
- teradataml/data/docs/sqle/docs_17_20/NGramSplitter.py +3 -3
- teradataml/data/docs/sqle/docs_17_20/SMOTE.py +212 -0
- teradataml/data/docs/sqle/docs_17_20/TextMorph.py +119 -0
- teradataml/data/docs/sqle/docs_17_20/TextParser.py +54 -3
- teradataml/data/docs/uaf/docs_17_20/ACF.py +1 -1
- teradataml/data/docs/uaf/docs_17_20/ArimaEstimate.py +2 -2
- teradataml/data/docs/uaf/docs_17_20/ArimaXEstimate.py +2 -2
- teradataml/data/docs/uaf/docs_17_20/DFFT.py +1 -1
- teradataml/data/docs/uaf/docs_17_20/DFFT2.py +1 -1
- teradataml/data/docs/uaf/docs_17_20/DFFT2Conv.py +1 -1
- teradataml/data/docs/uaf/docs_17_20/DFFTConv.py +1 -1
- teradataml/data/docs/uaf/docs_17_20/FilterFactory1d.py +4 -4
- teradataml/data/docs/uaf/docs_17_20/GenseriesSinusoids.py +2 -2
- teradataml/data/docs/uaf/docs_17_20/GoldfeldQuandt.py +2 -2
- teradataml/data/docs/uaf/docs_17_20/HoltWintersForecaster.py +6 -6
- teradataml/data/docs/uaf/docs_17_20/LineSpec.py +1 -1
- teradataml/data/docs/uaf/docs_17_20/LinearRegr.py +1 -1
- teradataml/data/docs/uaf/docs_17_20/Matrix2Image.py +4 -4
- teradataml/data/docs/uaf/docs_17_20/MultivarRegr.py +1 -1
- teradataml/data/docs/uaf/docs_17_20/PACF.py +1 -1
- teradataml/data/docs/uaf/docs_17_20/PowerSpec.py +2 -2
- teradataml/data/docs/uaf/docs_17_20/PowerTransform.py +3 -3
- teradataml/data/docs/uaf/docs_17_20/Resample.py +5 -5
- teradataml/data/docs/uaf/docs_17_20/SAX.py +3 -3
- teradataml/data/docs/uaf/docs_17_20/SignifPeriodicities.py +1 -1
- teradataml/data/docs/uaf/docs_17_20/SimpleExp.py +1 -1
- teradataml/data/docs/uaf/docs_17_20/Smoothma.py +3 -3
- teradataml/data/docs/uaf/docs_17_20/UNDIFF.py +1 -1
- teradataml/data/jsons/byom/onnxembeddings.json +1 -0
- teradataml/data/jsons/sqle/17.20/NGramSplitter.json +6 -6
- teradataml/data/jsons/sqle/17.20/TD_Apriori.json +181 -0
- teradataml/data/jsons/sqle/17.20/TD_NERExtractor.json +145 -0
- teradataml/data/jsons/sqle/17.20/TD_SMOTE.json +267 -0
- teradataml/data/jsons/sqle/17.20/TD_TextMorph.json +134 -0
- teradataml/data/jsons/sqle/17.20/TD_TextParser.json +114 -9
- teradataml/data/jsons/sqle/20.00/AI_AnalyzeSentiment.json +328 -0
- teradataml/data/jsons/sqle/20.00/AI_AskLLM.json +420 -0
- teradataml/data/jsons/sqle/20.00/AI_DetectLanguage.json +343 -0
- teradataml/data/jsons/sqle/20.00/AI_ExtractKeyPhrases.json +328 -0
- teradataml/data/jsons/sqle/20.00/AI_MaskPII.json +328 -0
- teradataml/data/jsons/sqle/20.00/AI_RecognizeEntities.json +328 -0
- teradataml/data/jsons/sqle/20.00/AI_RecognizePIIEntities.json +328 -0
- teradataml/data/jsons/sqle/20.00/AI_TextClassifier.json +359 -0
- teradataml/data/jsons/sqle/20.00/AI_TextEmbeddings.json +360 -0
- teradataml/data/jsons/sqle/20.00/AI_TextSummarize.json +343 -0
- teradataml/data/jsons/sqle/20.00/AI_TextTranslate.json +343 -0
- teradataml/data/jsons/sqle/20.00/TD_SMOTE.json +2 -2
- teradataml/data/jsons/sqle/20.00/TD_VectorDistance.json +1 -1
- teradataml/data/ner_dict.csv +8 -0
- teradataml/data/ner_input_eng.csv +7 -0
- teradataml/data/ner_rule.csv +5 -0
- teradataml/data/pattern_matching_data.csv +11 -0
- teradataml/data/pos_input.csv +40 -0
- teradataml/data/sdk/modelops/modelops_spec.json +101737 -0
- teradataml/data/tdnerextractor_example.json +14 -0
- teradataml/data/teradataml_example.json +21 -1
- teradataml/data/textmorph_example.json +5 -0
- teradataml/data/to_num_data.csv +4 -0
- teradataml/data/tochar_data.csv +5 -0
- teradataml/data/trans_dense.csv +16 -0
- teradataml/data/trans_sparse.csv +55 -0
- teradataml/data/url_data.csv +10 -9
- teradataml/dataframe/copy_to.py +38 -27
- teradataml/dataframe/data_transfer.py +61 -45
- teradataml/dataframe/dataframe.py +1110 -132
- teradataml/dataframe/dataframe_utils.py +73 -27
- teradataml/dataframe/functions.py +1070 -9
- teradataml/dataframe/sql.py +750 -959
- teradataml/dbutils/dbutils.py +33 -13
- teradataml/dbutils/filemgr.py +14 -10
- teradataml/hyperparameter_tuner/utils.py +4 -2
- teradataml/lib/aed_0_1.dll +0 -0
- teradataml/opensource/_base.py +12 -157
- teradataml/options/configure.py +24 -9
- teradataml/scriptmgmt/UserEnv.py +317 -39
- teradataml/scriptmgmt/lls_utils.py +456 -135
- 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/store/__init__.py +1 -1
- teradataml/table_operators/Apply.py +16 -1
- teradataml/table_operators/Script.py +20 -1
- teradataml/table_operators/query_generator.py +4 -21
- teradataml/table_operators/table_operator_util.py +58 -9
- teradataml/utils/dtypes.py +4 -2
- teradataml/utils/internal_buffer.py +22 -2
- teradataml/utils/utils.py +0 -1
- teradataml/utils/validators.py +318 -58
- {teradataml-20.0.0.4.dist-info → teradataml-20.0.0.6.dist-info}/METADATA +188 -14
- {teradataml-20.0.0.4.dist-info → teradataml-20.0.0.6.dist-info}/RECORD +131 -84
- {teradataml-20.0.0.4.dist-info → teradataml-20.0.0.6.dist-info}/WHEEL +0 -0
- {teradataml-20.0.0.4.dist-info → teradataml-20.0.0.6.dist-info}/top_level.txt +0 -0
- {teradataml-20.0.0.4.dist-info → teradataml-20.0.0.6.dist-info}/zip-safe +0 -0
teradataml/sdk/README.md
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
## How to create Software Development Kit (SDK) using OpenAPI spec
|
|
2
|
+
|
|
3
|
+
All SDKs should be in module `teradataml.sdk`. If a module name `<module_name>` is to be created with OpenAPI JSON file,
|
|
4
|
+
- The json file (say `openapi_spec.json`) should be placed in the directory `teradataml/data/sdk/<module_name>"` after creating required folders to maintain the folder structure.
|
|
5
|
+
- Create a folder `<module_name>` in `teradataml/sdk/` and place `__init__.py` file.
|
|
6
|
+
- Copy and paste the code from `teradataml/sdk/modelops/__init__.py` to newly created `__init__.py` file.
|
|
7
|
+
- Update the constants `SdkNames` and `SdkPackagePaths` in `teradataml/sdk/constants.py` to name the module and locate to appropriate location of OpenAPI JSON spec.
|
|
8
|
+
- Update the values to the constants `SdkNames` and `SdkPackagePaths` in `__init__.py`.
|
|
9
|
+
- Create `teradataml/sdk/<module_name>/_constants.py`.
|
|
10
|
+
- Copy and paste the code from `teradataml/sdk/modelops/_constants.py`. Keep empty dictionaries if no change in class names and function names is required. Fill in the dictionary similar to `teradataml/sdk/modelops/_constants.py` with intended class and function names.
|
|
11
|
+
- If customization is needed in client object, copy and paste the file `teradataml/sdk/modelops/_client.py` to `teradataml/sdk/<module_name>/_client.py` and update corresponding imports (for new client) in `teradataml/sdk/<module_name>/__init__.py`. Otherwise, user can use `BaseClient` from `teradataml/sdk/api_client.py`.
|
|
12
|
+
- Generate Pydantic models for OpenAPI schema using below commands which will create `teradataml/sdk/<module_name>/models.py`. Add unit test cases similar to `teradataml/tests/unit/sdk/test_modelops_schema.py` which import models and use helper class to bulk test the classes.
|
|
13
|
+
```shell
|
|
14
|
+
pip install datamodel-code-generator==0.27.3
|
|
15
|
+
# Run below command from pyTeradata directory.
|
|
16
|
+
datamodel-codegen --input teradataml/data/sdk/<module_name>/openapi_spec.json --input-file-type openapi --output teradataml/sdk/<module_name>/models.py --output-model-type pydantic_v2.BaseModel --use-field-description --keep-model-order --target-python-version=3.8 --use-schema-description --field-constraints --allow-population-by-field-name --strict-types bool int float # From windows use datamodel-codegen.exe
|
|
17
|
+
```
|
|
18
|
+
- If there are not schema in OpenAPI spec, create empty file `teradataml/sdk/<module_name>/models.py`.
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
## What is created dynamically
|
|
22
|
+
|
|
23
|
+
When the user runs `from teradataml.sdk.<module_name> import *` or `from teradataml.sdk.<module_name> import AnyClass`, it creates classes and class methods dynamically.
|
|
24
|
+
|
|
25
|
+
How are these classes created?
|
|
26
|
+
- Tags from OpenAPI spec are converted to Camel case and used as classes.
|
|
27
|
+
- If any of the API endpoint methods does not have tags associated with them, such functions are kept in class name `DefaultApi`.
|
|
28
|
+
|
|
29
|
+
How are class methods created?
|
|
30
|
+
- All the API endpoint methods form each function of the class.
|
|
31
|
+
- The function names are taken from `OperationId` field of function in OpenAPI JSON spec. The value of `OperationId` is converted to Snake case along with replacing hyphens (`-`) with underscores (`_`). This new value is used as API function name for the user to call by passing parameters.
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
## Example - Vantage ModelOps SDK
|
|
35
|
+
|
|
36
|
+
Couple of the tags in ModelOps OpenAPI spec is `Alert rules`, `Models`. These tags are converted to classes `AlertRules` and `Models` respectively.
|
|
37
|
+
|
|
38
|
+
The API end point `/api/models` contains `get` method with `operationId` as `getCollectionResource-model-get`. The framework creates `get_collection_resource_model_get(...)` function in `Models` class.
|
|
39
|
+
|
|
40
|
+
Similarly, the API end point `/api/models/{id}/alertRules` contains `get` method with `operationId` as `getAlertRules`. The framework creates `get_alert_rules(...)` functions in `AlertRules` class.
|
|
41
|
+
|
|
42
|
+
So, these API endpoints can be accessed through SDK as follows:
|
|
43
|
+
```python
|
|
44
|
+
# Authenticate and connect to client.
|
|
45
|
+
from teradataml.sdk.modelops import ModelOpsClient
|
|
46
|
+
from teradataml.sdk import ClientCredentialsAuth # Three different authentication mechanisms are supported.
|
|
47
|
+
auth_obj = ClientCredentialsAuth(
|
|
48
|
+
auth_client_id="<client_id>",
|
|
49
|
+
auth_client_secret="<client_secret>",
|
|
50
|
+
auth_token_url="https://10.27.117.175/sso/realms/teradata/protocol/openid-connect/token"
|
|
51
|
+
)
|
|
52
|
+
client = ModelOpsCleint(
|
|
53
|
+
base_url="https://10.27.117.175/core",
|
|
54
|
+
auth=auth_obj,
|
|
55
|
+
ssl_verify=False
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
# Import required classes.
|
|
59
|
+
from teradataml.sdk.modelops import AlertRules, Models
|
|
60
|
+
|
|
61
|
+
# Some APIs are tied with Project ID which needs to be set to the client.
|
|
62
|
+
client.set_project_id("<uuid_project_id>")
|
|
63
|
+
|
|
64
|
+
# Create Models object and get all the models.
|
|
65
|
+
mod = Models(client=client)
|
|
66
|
+
models = mod.get_collection_resource_model_get()
|
|
67
|
+
|
|
68
|
+
# Get alert rules for any one of the model.
|
|
69
|
+
ar = AlertRules(client=client)
|
|
70
|
+
ar.get_alert_rules(id="<uuid_model_id>")
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Note:
|
|
74
|
+
- All the argument to the API functions are read as `**kwargs`. So, the user has to pass keyword arguments i.e., positional argument usage is not supported yet.
|
|
75
|
+
- The following validations are done for arguments which accepts basic data types:
|
|
76
|
+
- Missing required arguments.
|
|
77
|
+
- Invalid type passed to arguments.
|
|
78
|
+
- Invalid (non-permitted) value passed to arguments.
|
|
79
|
+
- Validations for dict type objects (like input for `requestBody`) are yet to be added.
|
|
@@ -0,0 +1,422 @@
|
|
|
1
|
+
# ################################################################################################
|
|
2
|
+
#
|
|
3
|
+
# Copyright 2025 Teradata. All rights reserved.
|
|
4
|
+
# TERADATA CONFIDENTIAL AND TRADE SECRET
|
|
5
|
+
#
|
|
6
|
+
# Primary Owner: Adithya Avvaru (adithya.avvaru@teradata.com)
|
|
7
|
+
# Secondary Owner: Pankaj Purandare (pankajvinod.purandare@teradata.com)
|
|
8
|
+
#
|
|
9
|
+
# Version: 1.0
|
|
10
|
+
# SDK Version: 1.0
|
|
11
|
+
#
|
|
12
|
+
# This file contains different authentication modes and corresponding classes for the OpenAPI SDK.
|
|
13
|
+
#
|
|
14
|
+
# ################################################################################################
|
|
15
|
+
|
|
16
|
+
import json
|
|
17
|
+
import logging
|
|
18
|
+
import os
|
|
19
|
+
import re
|
|
20
|
+
import time
|
|
21
|
+
from abc import ABC, abstractmethod
|
|
22
|
+
from enum import Enum
|
|
23
|
+
|
|
24
|
+
import requests
|
|
25
|
+
from oauthlib.oauth2 import BackendApplicationClient
|
|
26
|
+
from requests.auth import HTTPBasicAuth
|
|
27
|
+
from requests_oauthlib import OAuth2Session
|
|
28
|
+
|
|
29
|
+
from teradataml.common.exceptions import TeradataMlException
|
|
30
|
+
from teradataml.common.messages import MessageCodes, Messages
|
|
31
|
+
from teradataml.utils.validators import _Validators
|
|
32
|
+
|
|
33
|
+
from .spinner import spin_it
|
|
34
|
+
|
|
35
|
+
logger = logging.getLogger(__name__)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class AuthMode(Enum):
|
|
39
|
+
DEVICE_CODE = "device_code"
|
|
40
|
+
CLIENT_CREDENTIALS = "client_credentials"
|
|
41
|
+
BEARER = "bearer"
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class _BaseAuth(ABC):
|
|
45
|
+
AUTH_MODE = None
|
|
46
|
+
|
|
47
|
+
def __init__(self):
|
|
48
|
+
|
|
49
|
+
self.session = None
|
|
50
|
+
self._ssl_verify = None
|
|
51
|
+
self._base_url = None
|
|
52
|
+
|
|
53
|
+
@abstractmethod
|
|
54
|
+
def authenticate(self, **kwargs):
|
|
55
|
+
raise NotImplementedError("Subclasses must implement authenticate method")
|
|
56
|
+
|
|
57
|
+
def _set_session_tls(self):
|
|
58
|
+
self.session.verify = self._ssl_verify
|
|
59
|
+
if not self._ssl_verify:
|
|
60
|
+
import urllib3
|
|
61
|
+
from urllib3.exceptions import InsecureRequestWarning
|
|
62
|
+
|
|
63
|
+
logger.warning(
|
|
64
|
+
"Certificate validation disabled. Adding certificate verification is"
|
|
65
|
+
" strongly advised"
|
|
66
|
+
)
|
|
67
|
+
urllib3.disable_warnings(InsecureRequestWarning)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
class ClientCredentialsAuth(_BaseAuth):
|
|
71
|
+
"""
|
|
72
|
+
Class to handle authentication using client credentials.
|
|
73
|
+
"""
|
|
74
|
+
AUTH_MODE = AuthMode.CLIENT_CREDENTIALS
|
|
75
|
+
|
|
76
|
+
def __init__(self, auth_token_url, auth_client_id, auth_client_secret):
|
|
77
|
+
"""
|
|
78
|
+
DESCRIPTION:
|
|
79
|
+
Initializes the object to authenticate through client credentials authentication.
|
|
80
|
+
|
|
81
|
+
PARAMETERS:
|
|
82
|
+
auth_token_url:
|
|
83
|
+
Required Argument.
|
|
84
|
+
Specifies the token endpoint URL to fetch the access token.
|
|
85
|
+
Types: str
|
|
86
|
+
|
|
87
|
+
auth_client_id:
|
|
88
|
+
Required Argument.
|
|
89
|
+
Specifies the client ID for authentication.
|
|
90
|
+
Types: str
|
|
91
|
+
|
|
92
|
+
auth_client_secret:
|
|
93
|
+
Required Argument.
|
|
94
|
+
Specifies the client secret for authentication.
|
|
95
|
+
Types: str
|
|
96
|
+
|
|
97
|
+
RETURNS:
|
|
98
|
+
None
|
|
99
|
+
|
|
100
|
+
RAISES:
|
|
101
|
+
None
|
|
102
|
+
|
|
103
|
+
EXAMPLES:
|
|
104
|
+
>>> from teradataml.sdk import ClientCredentialsAuth
|
|
105
|
+
>>> auth = ClientCredentialsAuth(
|
|
106
|
+
auth_token_url="https://example.com/token",
|
|
107
|
+
auth_client_id="your_client_id",
|
|
108
|
+
auth_client_secret="your_client_secret"
|
|
109
|
+
)
|
|
110
|
+
"""
|
|
111
|
+
arg_info_matrix = []
|
|
112
|
+
arg_info_matrix.append(["auth_token_url", auth_token_url, False, (str,), True])
|
|
113
|
+
arg_info_matrix.append(["auth_client_id", auth_client_id, False, (str,), True])
|
|
114
|
+
arg_info_matrix.append(["auth_client_secret", auth_client_secret, False, (str,), True])
|
|
115
|
+
_Validators._validate_missing_required_arguments(arg_info_matrix)
|
|
116
|
+
_Validators._validate_function_arguments(arg_info_matrix)
|
|
117
|
+
|
|
118
|
+
self._auth_client_id = auth_client_id
|
|
119
|
+
self._auth_client_secret = auth_client_secret
|
|
120
|
+
self._auth_token_url = auth_token_url
|
|
121
|
+
|
|
122
|
+
def authenticate(self):
|
|
123
|
+
"""
|
|
124
|
+
DESCRIPTION:
|
|
125
|
+
Authenticates using client credentials and fetches the access token.
|
|
126
|
+
|
|
127
|
+
PARAMETERS:
|
|
128
|
+
None
|
|
129
|
+
|
|
130
|
+
RETURNS:
|
|
131
|
+
requests.Session: Authenticated session with the access token.
|
|
132
|
+
|
|
133
|
+
RAISES:
|
|
134
|
+
None
|
|
135
|
+
|
|
136
|
+
EXAMPLES:
|
|
137
|
+
>>> from teradataml.sdk import ClientCredentialsAuth
|
|
138
|
+
>>> auth = ClientCredentialsAuth(
|
|
139
|
+
auth_token_url="https://example.com/token",
|
|
140
|
+
auth_client_id="your_client_id",
|
|
141
|
+
auth_client_secret="your_client_secret"
|
|
142
|
+
)
|
|
143
|
+
>>> session = auth.authenticate()
|
|
144
|
+
"""
|
|
145
|
+
self.session = OAuth2Session(client=BackendApplicationClient(client_id=self._auth_client_id))
|
|
146
|
+
|
|
147
|
+
self._set_session_tls()
|
|
148
|
+
self.session.fetch_token(
|
|
149
|
+
token_url=self._auth_token_url,
|
|
150
|
+
auth=HTTPBasicAuth(self._auth_client_id, self._auth_client_secret),
|
|
151
|
+
verify=self._ssl_verify,
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
return self.session
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
class DeviceCodeAuth(_BaseAuth):
|
|
158
|
+
"""
|
|
159
|
+
Class to handle authentication using device code.
|
|
160
|
+
"""
|
|
161
|
+
AUTH_MODE = AuthMode.DEVICE_CODE
|
|
162
|
+
|
|
163
|
+
def __init__(self, auth_token_url, auth_device_auth_url, auth_client_id, auth_client_secret=None):
|
|
164
|
+
"""
|
|
165
|
+
DESCRIPTION:
|
|
166
|
+
Initializes the object to authenticate through device code authentication.
|
|
167
|
+
|
|
168
|
+
PARAMETERS:
|
|
169
|
+
auth_token_url:
|
|
170
|
+
Required Argument.
|
|
171
|
+
Specifies the token endpoint URL to fetch the access token.
|
|
172
|
+
Types: str
|
|
173
|
+
|
|
174
|
+
auth_device_auth_url:
|
|
175
|
+
Required Argument.
|
|
176
|
+
Specifies the device code endpoint URL to initiate device code flow.
|
|
177
|
+
Types: str
|
|
178
|
+
|
|
179
|
+
auth_client_id:
|
|
180
|
+
Required Argument.
|
|
181
|
+
Specifies the client ID for authentication.
|
|
182
|
+
Types: str
|
|
183
|
+
|
|
184
|
+
auth_client_secret:
|
|
185
|
+
Optional Argument.
|
|
186
|
+
Specifies the client secret for authentication.
|
|
187
|
+
Types: str or None
|
|
188
|
+
|
|
189
|
+
RETURNS:
|
|
190
|
+
None
|
|
191
|
+
|
|
192
|
+
RAISES:
|
|
193
|
+
None
|
|
194
|
+
|
|
195
|
+
EXAMPLES:
|
|
196
|
+
>>> from teradataml.sdk import DeviceCodeAuth
|
|
197
|
+
>>> auth = DeviceCodeAuth(
|
|
198
|
+
auth_token_url="https://example.com/token",
|
|
199
|
+
auth_device_auth_url="https://example.com/device_auth",
|
|
200
|
+
auth_client_id="your_client_id",
|
|
201
|
+
auth_client_secret="your_client_secret"
|
|
202
|
+
)
|
|
203
|
+
"""
|
|
204
|
+
arg_info_matrix = []
|
|
205
|
+
arg_info_matrix.append(["auth_token_url", auth_token_url, False, (str,), True])
|
|
206
|
+
arg_info_matrix.append(["auth_device_auth_url", auth_device_auth_url, False, (str,), True])
|
|
207
|
+
arg_info_matrix.append(["auth_client_id", auth_client_id, False, (str,), True])
|
|
208
|
+
arg_info_matrix.append(["auth_client_secret", auth_client_secret, True, (str,), True])
|
|
209
|
+
_Validators._validate_missing_required_arguments(arg_info_matrix)
|
|
210
|
+
_Validators._validate_function_arguments(arg_info_matrix)
|
|
211
|
+
|
|
212
|
+
self._auth_client_id = auth_client_id
|
|
213
|
+
self._auth_client_secret = auth_client_secret
|
|
214
|
+
self._auth_token_url = auth_token_url
|
|
215
|
+
self._auth_device_auth_url = auth_device_auth_url
|
|
216
|
+
|
|
217
|
+
def authenticate(self, token_cache_file_path=None):
|
|
218
|
+
"""
|
|
219
|
+
DESCRIPTION:
|
|
220
|
+
Authenticates using device code flow and fetches the access token.
|
|
221
|
+
|
|
222
|
+
PARAMETERS:
|
|
223
|
+
token_cache_file_path:
|
|
224
|
+
Optional Argument.
|
|
225
|
+
Specifies the file path to load and/or cache the token data.
|
|
226
|
+
Types: str
|
|
227
|
+
|
|
228
|
+
RETURNS:
|
|
229
|
+
requests.Session: Authenticated session with the access token.
|
|
230
|
+
|
|
231
|
+
RAISES:
|
|
232
|
+
None
|
|
233
|
+
|
|
234
|
+
EXAMPLES:
|
|
235
|
+
>>> from teradataml.sdk import DeviceCodeAuth
|
|
236
|
+
>>> auth = DeviceCodeAuth(
|
|
237
|
+
auth_token_url="https://example.com/token",
|
|
238
|
+
auth_device_auth_url="https://example.com/device_auth",
|
|
239
|
+
auth_client_id="your_client_id",
|
|
240
|
+
auth_client_secret="your_client_secret"
|
|
241
|
+
)
|
|
242
|
+
>>> session = auth.authenticate(token_cache_file_path="/path/to/token_cache.json")
|
|
243
|
+
"""
|
|
244
|
+
arg_info_matrix = []
|
|
245
|
+
arg_info_matrix.append(["token_cache_file_path", token_cache_file_path, True, (str,), True])
|
|
246
|
+
_Validators._validate_missing_required_arguments(arg_info_matrix)
|
|
247
|
+
_Validators._validate_function_arguments(arg_info_matrix)
|
|
248
|
+
|
|
249
|
+
token = None
|
|
250
|
+
if token_cache_file_path and os.path.exists(token_cache_file_path):
|
|
251
|
+
logger.debug(
|
|
252
|
+
f"Loading cached token data from {token_cache_file_path}"
|
|
253
|
+
)
|
|
254
|
+
with open(token_cache_file_path, "r") as f:
|
|
255
|
+
token = json.load(f)
|
|
256
|
+
|
|
257
|
+
if not token:
|
|
258
|
+
self.session = requests.session()
|
|
259
|
+
self._set_session_tls()
|
|
260
|
+
token = self._get_device_code()
|
|
261
|
+
|
|
262
|
+
if "access_token" in token:
|
|
263
|
+
logger.debug(f"Access token acquired successfully: {token}")
|
|
264
|
+
|
|
265
|
+
self.__prepare_session_for_token()
|
|
266
|
+
|
|
267
|
+
# Create session.
|
|
268
|
+
_bearer = BearerAuth(auth_bearer=token["access_token"])
|
|
269
|
+
_bearer._ssl_verify = self._ssl_verify
|
|
270
|
+
_bearer._base_url = self._base_url
|
|
271
|
+
self.session = _bearer.authenticate()
|
|
272
|
+
|
|
273
|
+
elif "refresh_token" in token:
|
|
274
|
+
logger.debug(f"Refresh token acquired successfully: {token}")
|
|
275
|
+
|
|
276
|
+
self.__prepare_session_for_token()
|
|
277
|
+
|
|
278
|
+
# Refresh token for the session.
|
|
279
|
+
self.session.refresh_token(
|
|
280
|
+
token_url=self._auth_token_url,
|
|
281
|
+
refresh_token=token["refresh_token"],
|
|
282
|
+
auth=HTTPBasicAuth(self._auth_client_id, self._auth_client_secret),
|
|
283
|
+
verify=self._ssl_verify,
|
|
284
|
+
)
|
|
285
|
+
|
|
286
|
+
else:
|
|
287
|
+
raise TeradataMlException(Messages.get_message(MessageCodes.REST_DEVICE_CODE_NO_BOTH, token),
|
|
288
|
+
MessageCodes.REST_DEVICE_CODE_NO_BOTH)
|
|
289
|
+
|
|
290
|
+
with open(token_cache_file_path, "w") as f:
|
|
291
|
+
json.dump(token, f)
|
|
292
|
+
|
|
293
|
+
return self.session
|
|
294
|
+
|
|
295
|
+
def __prepare_session_for_token(self):
|
|
296
|
+
session = OAuth2Session(client_id=self._auth_client_id)
|
|
297
|
+
|
|
298
|
+
# don't chase certs/print warning for TLS if already done for _get_device_code
|
|
299
|
+
if hasattr(self, "session"):
|
|
300
|
+
session.verify = self.session.verify
|
|
301
|
+
self.session = session
|
|
302
|
+
else:
|
|
303
|
+
self.session = session
|
|
304
|
+
self._set_session_tls()
|
|
305
|
+
|
|
306
|
+
def _get_device_code(self):
|
|
307
|
+
device_code_response = self.session.post(
|
|
308
|
+
self._auth_device_auth_url,
|
|
309
|
+
data={"client_id": self._auth_client_id, "scope": "openid profile"},
|
|
310
|
+
)
|
|
311
|
+
|
|
312
|
+
if device_code_response.status_code != 200:
|
|
313
|
+
raise TeradataMlException(Messages.get_message(MessageCodes.REST_DEVICE_CODE_GEN_FAILED,
|
|
314
|
+
device_code_response.status_code),
|
|
315
|
+
MessageCodes.REST_DEVICE_CODE_GEN_FAILED)
|
|
316
|
+
|
|
317
|
+
device_code_data = device_code_response.json()
|
|
318
|
+
print(
|
|
319
|
+
"1. On your computer or mobile device navigate to: ",
|
|
320
|
+
device_code_data["verification_uri_complete"],
|
|
321
|
+
)
|
|
322
|
+
print("2. Enter the following code: ", device_code_data["user_code"])
|
|
323
|
+
|
|
324
|
+
def authorize():
|
|
325
|
+
authenticated = False
|
|
326
|
+
token_data = None
|
|
327
|
+
|
|
328
|
+
while not authenticated:
|
|
329
|
+
token_response = self.session.post(
|
|
330
|
+
self._auth_token_url,
|
|
331
|
+
data={
|
|
332
|
+
"grant_type": "urn:ietf:params:oauth:grant-type:device_code",
|
|
333
|
+
"device_code": device_code_data["device_code"],
|
|
334
|
+
"client_id": self._auth_client_id,
|
|
335
|
+
},
|
|
336
|
+
)
|
|
337
|
+
|
|
338
|
+
token_data = token_response.json()
|
|
339
|
+
if token_response.status_code == 200:
|
|
340
|
+
authenticated = True
|
|
341
|
+
|
|
342
|
+
elif "error" in token_data:
|
|
343
|
+
if token_data["error"] in ("authorization_pending", "slow_down"):
|
|
344
|
+
time.sleep(device_code_data["interval"])
|
|
345
|
+
else:
|
|
346
|
+
raise TeradataMlException(Messages.get_message(MessageCodes.REST_DEVICE_CODE_AUTH_FAILED,
|
|
347
|
+
token_data["error_description"]),
|
|
348
|
+
MessageCodes.REST_DEVICE_CODE_AUTH_FAILED)
|
|
349
|
+
|
|
350
|
+
else:
|
|
351
|
+
raise TeradataMlException(Messages.get_message(MessageCodes.REST_DEVICE_CODE_AUTH_FAILED,
|
|
352
|
+
f"Bad response code: {token_response.status_code}"),
|
|
353
|
+
MessageCodes.REST_DEVICE_CODE_AUTH_FAILED)
|
|
354
|
+
|
|
355
|
+
return token_data
|
|
356
|
+
|
|
357
|
+
msg = "Waiting for device code to be authorized\n"
|
|
358
|
+
res = spin_it(authorize, msg, 3)
|
|
359
|
+
print(
|
|
360
|
+
"\033[32m\U0001f512 This device has been authorized successfully.\033[0m\n"
|
|
361
|
+
)
|
|
362
|
+
return res
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+
class BearerAuth(_BaseAuth):
|
|
366
|
+
"""
|
|
367
|
+
Class to handle authentication using bearer token.
|
|
368
|
+
"""
|
|
369
|
+
AUTH_MODE = AuthMode.BEARER
|
|
370
|
+
|
|
371
|
+
def __init__(self, auth_bearer):
|
|
372
|
+
"""
|
|
373
|
+
DESCRIPTION:
|
|
374
|
+
Initializes the object to authenticate through bearer token authentication.
|
|
375
|
+
|
|
376
|
+
PARAMETERS:
|
|
377
|
+
auth_bearer:
|
|
378
|
+
Required Argument.
|
|
379
|
+
Specifies the raw bearer token to be used for authentication.
|
|
380
|
+
Types: str
|
|
381
|
+
|
|
382
|
+
RETURNS:
|
|
383
|
+
None
|
|
384
|
+
|
|
385
|
+
RAISES:
|
|
386
|
+
None
|
|
387
|
+
|
|
388
|
+
EXAMPLES:
|
|
389
|
+
>>> from teradataml.sdk import BearerAuth
|
|
390
|
+
>>> auth = BearerAuth(auth_bearer="your_bearer_token")
|
|
391
|
+
"""
|
|
392
|
+
arg_info_matrix = [["auth_bearer", auth_bearer, False, (str,), True]]
|
|
393
|
+
_Validators._validate_missing_required_arguments(arg_info_matrix)
|
|
394
|
+
_Validators._validate_function_arguments(arg_info_matrix)
|
|
395
|
+
|
|
396
|
+
self._auth_bearer = f"Bearer {auth_bearer}"
|
|
397
|
+
|
|
398
|
+
def authenticate(self):
|
|
399
|
+
"""
|
|
400
|
+
DESCRIPTION:
|
|
401
|
+
Authenticates using the provided bearer token.
|
|
402
|
+
|
|
403
|
+
PARAMETERS:
|
|
404
|
+
None
|
|
405
|
+
|
|
406
|
+
RETURNS:
|
|
407
|
+
requests.Session: Authenticated session with the bearer token.
|
|
408
|
+
|
|
409
|
+
RAISES:
|
|
410
|
+
None
|
|
411
|
+
|
|
412
|
+
EXAMPLES:
|
|
413
|
+
>>> from teradataml.sdk import BearerAuth
|
|
414
|
+
>>> auth = BearerAuth(auth_bearer="your_bearer_token")
|
|
415
|
+
>>> session = auth.authenticate()
|
|
416
|
+
"""
|
|
417
|
+
self.session = requests.session()
|
|
418
|
+
self.session.headers.update({"Authorization": self._auth_bearer})
|
|
419
|
+
|
|
420
|
+
self._set_session_tls()
|
|
421
|
+
|
|
422
|
+
return self.session
|