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.

Files changed (53) hide show
  1. teradataml/LICENSE-3RD-PARTY.pdf +0 -0
  2. teradataml/README.md +96 -0
  3. teradataml/_version.py +1 -1
  4. teradataml/analytics/analytic_function_executor.py +1 -1
  5. teradataml/analytics/utils.py +56 -11
  6. teradataml/clients/auth_client.py +10 -6
  7. teradataml/clients/keycloak_client.py +165 -0
  8. teradataml/common/constants.py +10 -0
  9. teradataml/common/exceptions.py +32 -0
  10. teradataml/common/messagecodes.py +27 -0
  11. teradataml/common/messages.py +9 -1
  12. teradataml/common/sqlbundle.py +3 -2
  13. teradataml/common/utils.py +94 -12
  14. teradataml/context/context.py +37 -9
  15. teradataml/data/jsons/byom/onnxembeddings.json +1 -0
  16. teradataml/data/pattern_matching_data.csv +11 -0
  17. teradataml/data/sdk/modelops/modelops_spec.json +101737 -0
  18. teradataml/data/teradataml_example.json +8 -1
  19. teradataml/data/url_data.csv +10 -9
  20. teradataml/dataframe/copy_to.py +1 -1
  21. teradataml/dataframe/dataframe.py +980 -82
  22. teradataml/dataframe/dataframe_utils.py +58 -25
  23. teradataml/dataframe/functions.py +962 -1
  24. teradataml/dataframe/sql.py +570 -1031
  25. teradataml/hyperparameter_tuner/utils.py +4 -2
  26. teradataml/lib/aed_0_1.dll +0 -0
  27. teradataml/opensource/_base.py +7 -1
  28. teradataml/options/configure.py +20 -4
  29. teradataml/scriptmgmt/UserEnv.py +13 -2
  30. teradataml/scriptmgmt/lls_utils.py +99 -24
  31. teradataml/sdk/README.md +79 -0
  32. teradataml/sdk/__init__.py +4 -0
  33. teradataml/sdk/_auth_modes.py +422 -0
  34. teradataml/sdk/_func_params.py +487 -0
  35. teradataml/sdk/_json_parser.py +453 -0
  36. teradataml/sdk/_openapi_spec_constants.py +249 -0
  37. teradataml/sdk/_utils.py +236 -0
  38. teradataml/sdk/api_client.py +897 -0
  39. teradataml/sdk/constants.py +62 -0
  40. teradataml/sdk/modelops/__init__.py +98 -0
  41. teradataml/sdk/modelops/_client.py +406 -0
  42. teradataml/sdk/modelops/_constants.py +304 -0
  43. teradataml/sdk/modelops/models.py +2308 -0
  44. teradataml/sdk/spinner.py +107 -0
  45. teradataml/table_operators/query_generator.py +4 -21
  46. teradataml/utils/dtypes.py +2 -1
  47. teradataml/utils/utils.py +0 -1
  48. teradataml/utils/validators.py +5 -1
  49. {teradataml-20.0.0.5.dist-info → teradataml-20.0.0.6.dist-info}/METADATA +101 -2
  50. {teradataml-20.0.0.5.dist-info → teradataml-20.0.0.6.dist-info}/RECORD +53 -36
  51. {teradataml-20.0.0.5.dist-info → teradataml-20.0.0.6.dist-info}/WHEEL +0 -0
  52. {teradataml-20.0.0.5.dist-info → teradataml-20.0.0.6.dist-info}/top_level.txt +0 -0
  53. {teradataml-20.0.0.5.dist-info → teradataml-20.0.0.6.dist-info}/zip-safe +0 -0
@@ -276,6 +276,8 @@ class _ProgressBar:
276
276
  progress_precent=_progress_percent,
277
277
  completed_jobs=self.completed_jobs,
278
278
  total_jobs=self.total_jobs)
279
+ # Add padding to clear any leftover characters from the previous message.
280
+ padded_msg = _msg.ljust(self.blank_space_len)
279
281
  # Display the formatted bar.
280
- print(_msg, end='\r', file=self.STDOUT, flush=True)
281
- self.blank_space_len = len(_msg)
282
+ print(padded_msg, end='\r', file=self.STDOUT, flush=True)
283
+ self.blank_space_len = len(padded_msg)
Binary file
@@ -51,6 +51,7 @@ from teradataml.opensource._wrapper_utils import (_generate_new_name,
51
51
  _validate_df_query_type)
52
52
  from teradataml.options.configure import configure
53
53
  from teradataml.utils.validators import _Validators
54
+ from teradataml.utils.internal_buffer import _InternalBuffer
54
55
 
55
56
  logger = pylogger.getLogger()
56
57
 
@@ -88,9 +89,13 @@ class _GenericObjectWrapper:
88
89
  self._env = configure.openml_user_env
89
90
  else:
90
91
  self._env = UtilFuncs._create_or_get_env("open_source_ml.json")
92
+ else:
93
+ set_session_param("searchuifdbpath", self._db_name)
91
94
 
92
95
  # Check if the Python interpreter major versions are consistent between Vantage and local.
93
- UtilFuncs._check_python_version_diff(self._env)
96
+ _check_py_version = _InternalBuffer.get('_check_py_version')
97
+ if _check_py_version:
98
+ UtilFuncs._check_python_version_diff(self._env)
94
99
 
95
100
  # Raise warning when python package versions don't match between Vantage and local.
96
101
  # OPENSOURCE_PACKAGE_NAME is set for each opensource package, but not for the base class.
@@ -1257,6 +1262,7 @@ class _OpenSourceObjectWrapper(_GenericObjectWrapper):
1257
1262
 
1258
1263
  class _FunctionWrapper(_GenericObjectWrapper):
1259
1264
  def __init__(self, module_name, func_name, file_type, template_file):
1265
+
1260
1266
  super().__init__()
1261
1267
  self._module_name = module_name
1262
1268
  self._func_name = func_name
@@ -62,6 +62,7 @@ class _Configure(_ConfigureSuper):
62
62
  stored_procedure_install_location = _create_property('stored_procedure_install_location')
63
63
  table_operator = _create_property('table_operator')
64
64
  temp_object_type = _create_property('temp_object_type')
65
+ use_short_object_name = _create_property('use_short_object_name')
65
66
 
66
67
  def __init__(self, default_varchar_size=1024, column_casesensitive_handler=False,
67
68
  vantage_version="vantage1.1", val_install_location=None,
@@ -71,7 +72,7 @@ class _Configure(_ConfigureSuper):
71
72
  cran_repositories=None, inline_plot=True,
72
73
  indb_install_location=None,
73
74
  openml_user_env=None, local_storage=None, stored_procedure_install_location="SYSLIB",
74
- table_operator=None, temp_object_type=None):
75
+ table_operator=None, temp_object_type=None, use_short_object_name=False):
75
76
 
76
77
  """
77
78
  PARAMETERS:
@@ -140,8 +141,8 @@ class _Configure(_ConfigureSuper):
140
141
 
141
142
  indb_install_location:
142
143
  Specifies the installation location of In-DB Python package.
143
- Types: string
144
144
  Default Value: "/var/opt/teradata/languages/sles12sp3/Python/"
145
+ Types: string
145
146
  Example:
146
147
  # Set the installation location for older versions.
147
148
  teradataml.options.configure.indb_install_location = "/opt/teradata/languages/Python/"
@@ -182,9 +183,9 @@ class _Configure(_ConfigureSuper):
182
183
  Specifies the type of temporary database objects created internally by teradataml.
183
184
  Permitted Values:
184
185
  * "VT" - Volatile tables.
185
- Types: String
186
186
  Default Value: None
187
- Note:
187
+ Types: String
188
+ Notes:
188
189
  * If this option is set to "VT" and "persist" argument of analytic functions is
189
190
  set to True, then volatile tables are not created as volatile table can't be
190
191
  persisted and "persist" argument takes precedence.
@@ -193,6 +194,16 @@ class _Configure(_ConfigureSuper):
193
194
  # Set the type of temporary database objects to "VT" to create volatile internal
194
195
  # tables.
195
196
  teradataml.options.configure.temp_object_type = "VT"
197
+
198
+ use_short_object_name:
199
+ Specifies whether to use shorter names for temporary tables created internally by teradataml.
200
+ When set to True, teradataml generates internal temporary table names with a maximum length
201
+ of 20 characters. Otherwise, there is no restriction on the length of these table names.
202
+ Default Value: False
203
+ Types: bool
204
+ Example:
205
+ # Set the option to use short names for temporary tables.
206
+ teradataml.options.configure.use_short_object_name = True
196
207
  """
197
208
  super().__init__()
198
209
  super().__setattr__('default_varchar_size', default_varchar_size)
@@ -213,6 +224,7 @@ class _Configure(_ConfigureSuper):
213
224
  super().__setattr__('table_operator', table_operator)
214
225
  super().__setattr__('_indb_install_location', indb_install_location)
215
226
  super().__setattr__('temp_object_type', self.__get_temp_object_type(temp_object_type))
227
+ super().__setattr__('use_short_object_name', use_short_object_name)
216
228
 
217
229
  # internal configurations
218
230
  # These configurations are internal and should not be
@@ -447,6 +459,10 @@ class _Configure(_ConfigureSuper):
447
459
 
448
460
  value = self.__get_temp_object_type(value)
449
461
 
462
+ elif name == 'use_short_object_name':
463
+ if not isinstance(value, bool):
464
+ raise TypeError(Messages.get_message(MessageCodes.UNSUPPORTED_DATATYPE, name, 'bool'))
465
+
450
466
  super().__setattr__(name, value)
451
467
  else:
452
468
  raise AttributeError("'{}' object has no attribute '{}'".format(self.__class__.__name__, name))
@@ -20,11 +20,10 @@ import time
20
20
  from concurrent.futures import ThreadPoolExecutor, wait
21
21
  from json.decoder import JSONDecodeError
22
22
  from urllib.parse import urlparse
23
+
23
24
  import pandas as pd
24
- import requests
25
25
 
26
26
  from teradataml import configure
27
- from teradataml.clients.auth_client import _AuthWorkflow
28
27
  from teradataml.clients.pkce_client import _DAWorkflow
29
28
  from teradataml.common.constants import (AsyncOpStatus, CloudProvider,
30
29
  HTTPRequest)
@@ -4046,6 +4045,14 @@ class _AuthToken:
4046
4045
  def value(self):
4047
4046
  return self.__value
4048
4047
 
4048
+ @value.setter
4049
+ def value(self, token_value):
4050
+ """
4051
+ DESCRIPTION:
4052
+ Sets value of _AuthToken.
4053
+ """
4054
+ self.__value = token_value
4055
+
4049
4056
  @property
4050
4057
  def auth_type(self):
4051
4058
  return self.__auth_type
@@ -4060,3 +4067,7 @@ class _AuthToken:
4060
4067
  elif self.auth_type.lower() == "bearer":
4061
4068
  # Form the Authorization header value by prepending 'Bearer ' to the JWT token.
4062
4069
  return {"Authorization": "Bearer {}".format(self.value)}
4070
+ elif self.auth_type.lower() == "keycloak":
4071
+ # Get valid token value for current time.
4072
+ self.value = _InternalBuffer.get("keycloak_manager").get_token()
4073
+ return {"Authorization": "Bearer {}".format(self.value)}
@@ -24,27 +24,25 @@ from urllib.parse import urlparse
24
24
  import pandas as pd
25
25
 
26
26
  from teradataml import configure
27
- from teradataml.context.context import _get_user, get_connection
28
- from teradataml.common.constants import HTTPRequest, AsyncStatusColumns, AuthMechs
29
27
  from teradataml.clients.auth_client import _AuthWorkflow
28
+ from teradataml.clients.keycloak_client import _KeycloakManager
30
29
  from teradataml.clients.pkce_client import _DAWorkflow
31
30
  from teradataml.common.constants import (AsyncOpStatus, AsyncStatusColumns,
32
- HTTPRequest)
31
+ AuthMechs, HTTPRequest, TDServices)
33
32
  from teradataml.common.exceptions import TeradataMlException
34
33
  from teradataml.common.messagecodes import MessageCodes
35
34
  from teradataml.common.messages import Messages
36
35
  from teradataml.common.utils import UtilFuncs
37
36
  from teradataml.context.context import _get_user, get_connection
38
37
  from teradataml.scriptmgmt.UserEnv import (UserEnv, _AuthToken,
39
- _get_auth_token, _get_ues_url,
40
- _process_ues_response, _get_ccp_url)
38
+ _get_auth_token, _get_ccp_url,
39
+ _get_ues_url, _process_ues_response)
41
40
  from teradataml.telemetry_utils.queryband import collect_queryband
42
41
  from teradataml.utils.internal_buffer import _InternalBuffer
43
42
  from teradataml.utils.utils import _async_run_id_info
44
43
  from teradataml.utils.validators import _Validators
45
44
 
46
45
 
47
-
48
46
  @collect_queryband(queryband="LstBsEnv")
49
47
  def list_base_envs():
50
48
  """
@@ -1778,6 +1776,18 @@ def set_auth_token(base_url=None, client_id=None, pat_token=None, pem_file=None,
1778
1776
  Specifies the password for database user to be used for Basic authentication.
1779
1777
  Types: str
1780
1778
 
1779
+ auth_url:
1780
+ Optional Argument.
1781
+ Specifies the endpoint URL for a keycloak server.
1782
+ Types: str
1783
+
1784
+ rest_client:
1785
+ Optional Argument.
1786
+ Specifies the service for which keycloak token is to be generated.
1787
+ Permitted values: "VECTORSTORE"
1788
+ Default value: "VECTORSTORE"
1789
+ Types: str
1790
+
1781
1791
  auth_mech:
1782
1792
  Optional Argument.
1783
1793
  Specifies the mechanism to be used for generating authentication token.
@@ -1787,14 +1797,31 @@ def set_auth_token(base_url=None, client_id=None, pat_token=None, pem_file=None,
1787
1797
  * OAuth: Token generation is done through OAuth by using client id
1788
1798
  which can be sepcified by user in "client_id" argument or
1789
1799
  can be derived internally from "base_url".
1790
- * PAT : Token generation is done using "pat_token" and "pem_file".
1800
+ * PAT: Token generation is done using "pat_token" and "pem_file".
1791
1801
  * BASIC: Authentication is done via Basic authentication mechanism
1792
1802
  using user credentials passed in "username" and "password"
1793
1803
  arguments.
1794
- * JWT : Readily available token in "auth_token" argument is used.
1795
- Permitted Values: "OAuth", "PAT", "BASIC", "JWT".
1804
+ * JWT: Readily available token in "auth_token" argument is used.
1805
+ * KEYCLOAK: Token generation is done using keycloak.
1806
+ Permitted Values: "OAuth", "PAT", "BASIC", "JWT", "KEYCLOAK".
1796
1807
  Types: str
1797
1808
 
1809
+ validate_jwt:
1810
+ Optional Argument.
1811
+ Specifies whether to validate generated JWT token or not.
1812
+ Note:
1813
+ * Applicable only when "auth_mech" is "PAT".
1814
+ Default value: True
1815
+ Types: boolean
1816
+
1817
+ valid_from:
1818
+ Optional Argument.
1819
+ Specifies epoch seconds representing time from which JWT token will be valid.
1820
+ Note:
1821
+ * Applicable only when "auth_mech" is "PAT".
1822
+ Default value: None
1823
+ Types: int
1824
+
1798
1825
  RETURNS:
1799
1826
  True, if the operation is successful.
1800
1827
 
@@ -1861,6 +1888,16 @@ def set_auth_token(base_url=None, client_id=None, pat_token=None, pem_file=None,
1861
1888
  Authentication token is generated and set for the session.
1862
1889
  True
1863
1890
 
1891
+ # Example 8: Set the authentication token for by specifying "base_url", "auth_url"
1892
+ # "password" and "rest_client" and generating keycloak token internally.
1893
+ >>> import getpass
1894
+ >>> set_auth_token(base_url=getpass.getpass("base_url : "),
1895
+ ... auth_url=getpass.getpass("auth_url : "),
1896
+ ... password=getpass.getpass("password : "),
1897
+ ... rest_client=getpass.getpass("rest_client : "))
1898
+ Authentication token is generated and set for the session.
1899
+ True
1900
+
1864
1901
  """
1865
1902
 
1866
1903
  # Deriving global connection using get_connection().
@@ -1886,22 +1923,34 @@ def set_auth_token(base_url=None, client_id=None, pat_token=None, pem_file=None,
1886
1923
  __arg_info_matrix.append(["ues_url", ues_url, True, (str), True])
1887
1924
 
1888
1925
  username = kwargs.get("username", _get_user())
1889
- __arg_info_matrix.append((["username", username, True, (str), True]))
1926
+ __arg_info_matrix.append(["username", username, True, (str), True])
1890
1927
 
1891
1928
  password = kwargs.get("password", None)
1892
1929
  __arg_info_matrix.append(["password", password, True, (str), True])
1893
1930
 
1894
1931
  auth_token = kwargs.get("auth_token")
1895
- __arg_info_matrix.append((["auth_token", auth_token, True, (str), True]))
1932
+ __arg_info_matrix.append(["auth_token", auth_token, True, (str), True])
1896
1933
 
1897
- expiration_time = kwargs.get("expiration_time", 31536000)
1898
- __arg_info_matrix.append((["expiration_time", expiration_time, True, (int), True]))
1934
+ expiration_time = kwargs.get("expiration_time", 31536000) # 31536000 seconds meaning 365 days.
1935
+ __arg_info_matrix.append(["expiration_time", expiration_time, True, (int), True])
1899
1936
 
1900
1937
  kid = kwargs.get("kid")
1901
- __arg_info_matrix.append((["kid", kid, True, (str), True]))
1938
+ __arg_info_matrix.append(["kid", kid, True, (str), True])
1939
+
1940
+ auth_url = kwargs.get("auth_url", None)
1941
+ __arg_info_matrix.append(["auth_url", auth_url, True, (str), True])
1942
+
1943
+ rest_client = kwargs.get("rest_client", "VECTORSTORE")
1944
+ __arg_info_matrix.append(["rest_client", rest_client, True, (str), True, [svc.name for svc in TDServices]])
1902
1945
 
1903
1946
  auth_mech = kwargs.get("auth_mech", None)
1904
- __arg_info_matrix.append((["auth_mech", auth_mech, True, (str), True, [mech.value for mech in AuthMechs]]))
1947
+ __arg_info_matrix.append(["auth_mech", auth_mech, True, (str), True, [mech.name for mech in AuthMechs]])
1948
+
1949
+ validate_jwt = kwargs.get("validate_jwt", True)
1950
+ __arg_info_matrix.append(["validate_jwt", validate_jwt, True, (bool)])
1951
+
1952
+ valid_from = kwargs.get("valid_from", None)
1953
+ __arg_info_matrix.append(["valid_from", valid_from, True, int])
1905
1954
 
1906
1955
  # Validate arguments.
1907
1956
  _Validators._validate_function_arguments(__arg_info_matrix)
@@ -1950,13 +1999,15 @@ def set_auth_token(base_url=None, client_id=None, pat_token=None, pem_file=None,
1950
1999
  if auth_mech:
1951
2000
  auth_mech = auth_mech.lower()
1952
2001
  if auth_mech == 'oauth':
1953
- pat_token = pem_file = password = auth_token = None
2002
+ pat_token = pem_file = password = auth_token = auth_url = None
1954
2003
  elif auth_mech == 'jwt':
1955
- pat_token = pem_file = password = client_id = None
2004
+ pat_token = pem_file = password = client_id = auth_url = None
1956
2005
  elif auth_mech == 'basic':
1957
- pat_token = pem_file = auth_token = client_id = None
2006
+ pat_token = pem_file = auth_token = client_id = auth_url = None
1958
2007
  elif auth_mech == 'pat':
1959
- password = client_id = auth_token = None
2008
+ password = client_id = auth_token = auth_url = None
2009
+ elif auth_mech == 'keycloak':
2010
+ pat_token = pem_file = auth_token = client_id = None
1960
2011
 
1961
2012
  # Validate arguments for mutual exclusiveness.
1962
2013
  all_groups_none = \
@@ -1964,7 +2015,8 @@ def set_auth_token(base_url=None, client_id=None, pat_token=None, pem_file=None,
1964
2015
  {"auth_token": auth_token},
1965
2016
  {"pat_token": pat_token,
1966
2017
  "pem_file": pem_file},
1967
- {"password": password},
2018
+ {"password": password} if not auth_url else
2019
+ {"password": password, "auth_url": auth_url},
1968
2020
  return_all_falsy_status=True)
1969
2021
 
1970
2022
  # Determine authentication mechanism from availability of supportive arguments.
@@ -1973,6 +2025,8 @@ def set_auth_token(base_url=None, client_id=None, pat_token=None, pem_file=None,
1973
2025
  auth_mech = 'jwt'
1974
2026
  elif any([pat_token, pem_file]):
1975
2027
  auth_mech = 'pat'
2028
+ elif auth_url:
2029
+ auth_mech = 'keycloak'
1976
2030
  elif password:
1977
2031
  # Authentication is done via Basic authentication mechanism
1978
2032
  # by passing 'basic' field in header.
@@ -1995,7 +2049,6 @@ def set_auth_token(base_url=None, client_id=None, pat_token=None, pem_file=None,
1995
2049
  _InternalBuffer.add(auth_token=_AuthToken(token=auth_token,
1996
2050
  auth_type='bearer'))
1997
2051
  elif auth_mech == 'oauth':
1998
- # TODO: Finalize need to set this flag to False in other scenarios.
1999
2052
  configure._oauth = True
2000
2053
  client_id = "{}-oaf-device".format(org_id) if client_id is None else client_id
2001
2054
  da_wf = _DAWorkflow(parsed_base_url, client_id)
@@ -2028,11 +2081,13 @@ def set_auth_token(base_url=None, client_id=None, pat_token=None, pem_file=None,
2028
2081
  "pem_file": pem_file,
2029
2082
  "username": username,
2030
2083
  "expiration_time": expiration_time,
2031
- "kid": kid})
2084
+ "kid": kid,
2085
+ "valid_from": valid_from})
2032
2086
  token_data = auth_wf._proxy_jwt()
2033
2087
 
2034
- # Validate generated JWT token.
2035
- token_validated = _validate_jwt_token(base_url, token_data)
2088
+ if validate_jwt:
2089
+ # Validate generated JWT token.
2090
+ token_validated = _validate_jwt_token(base_url, token_data)
2036
2091
 
2037
2092
  # Store the jwt token in internal class attribute.
2038
2093
  _InternalBuffer.add(auth_token=_AuthToken(token=token_data,
@@ -2047,6 +2102,26 @@ def set_auth_token(base_url=None, client_id=None, pat_token=None, pem_file=None,
2047
2102
  # Store the header data in internal class attribute.
2048
2103
  _InternalBuffer.add(auth_token=_AuthToken(token=encoded_credentials,
2049
2104
  auth_type='basic'))
2105
+ elif auth_mech == 'keycloak':
2106
+ _Validators._validate_missing_required_arguments([["password", password, False, (str), True],
2107
+ ["auth_url", auth_url, False, (str), True]
2108
+ ])
2109
+ token_generator = _KeycloakManager(auth_url=auth_url,
2110
+ client_id=TDServices[rest_client].value)
2111
+
2112
+ # Store manager object in _InternalBuffer in order to generate token after expiry time.
2113
+ _InternalBuffer.add(keycloak_manager=token_generator)
2114
+ try:
2115
+ token_data = token_generator.generate_token(username=username,
2116
+ password=password)
2117
+ except:
2118
+ raise TeradataMlException(Messages.get_message(MessageCodes.FUNC_EXECUTION_FAILED,
2119
+ "set_auth_token",
2120
+ "Failed to generate keycloak token."),
2121
+ MessageCodes.FUNC_EXECUTION_FAILED)
2122
+
2123
+ _InternalBuffer.add(auth_token=_AuthToken(token=token_data,
2124
+ auth_type='keycloak'))
2050
2125
 
2051
2126
  if token_validated:
2052
2127
  print("Authentication token is generated, authenticated and set for the session.")
@@ -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,4 @@
1
+ from teradataml.sdk._auth_modes import (BearerAuth, ClientCredentialsAuth,
2
+ DeviceCodeAuth)
3
+ from teradataml.sdk.api_client import Client
4
+ from teradataml.sdk.constants import SdkPackagePaths