teradataml 20.0.0.6__py3-none-any.whl → 20.0.0.7__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/README.md +210 -0
- teradataml/__init__.py +1 -1
- teradataml/_version.py +1 -1
- teradataml/analytics/analytic_function_executor.py +162 -76
- teradataml/analytics/byom/__init__.py +1 -1
- teradataml/analytics/json_parser/__init__.py +2 -0
- teradataml/analytics/json_parser/analytic_functions_argument.py +95 -2
- teradataml/analytics/json_parser/metadata.py +22 -4
- teradataml/analytics/sqle/DecisionTreePredict.py +3 -2
- teradataml/analytics/sqle/NaiveBayesPredict.py +3 -2
- teradataml/analytics/sqle/__init__.py +3 -0
- teradataml/analytics/utils.py +4 -1
- teradataml/automl/__init__.py +2369 -464
- teradataml/automl/autodataprep/__init__.py +15 -0
- teradataml/automl/custom_json_utils.py +184 -112
- teradataml/automl/data_preparation.py +113 -58
- teradataml/automl/data_transformation.py +154 -53
- teradataml/automl/feature_engineering.py +113 -53
- teradataml/automl/feature_exploration.py +548 -25
- teradataml/automl/model_evaluation.py +260 -32
- teradataml/automl/model_training.py +399 -206
- teradataml/clients/auth_client.py +2 -2
- teradataml/common/aed_utils.py +11 -2
- teradataml/common/bulk_exposed_utils.py +4 -2
- teradataml/common/constants.py +62 -2
- teradataml/common/garbagecollector.py +50 -21
- teradataml/common/messagecodes.py +47 -2
- teradataml/common/messages.py +19 -1
- teradataml/common/sqlbundle.py +23 -6
- teradataml/common/utils.py +116 -10
- teradataml/context/aed_context.py +16 -10
- teradataml/data/Employee.csv +5 -0
- teradataml/data/Employee_Address.csv +4 -0
- teradataml/data/Employee_roles.csv +5 -0
- teradataml/data/JulesBelvezeDummyData.csv +100 -0
- teradataml/data/byom_example.json +5 -0
- teradataml/data/creditcard_data.csv +284618 -0
- teradataml/data/docs/byom/docs/ONNXSeq2Seq.py +255 -0
- teradataml/data/docs/sqle/docs_17_10/NGramSplitter.py +1 -1
- teradataml/data/docs/sqle/docs_17_20/NGramSplitter.py +1 -1
- teradataml/data/docs/sqle/docs_17_20/TextParser.py +1 -1
- teradataml/data/jsons/byom/ONNXSeq2Seq.json +287 -0
- teradataml/data/jsons/sqle/20.00/AI_AnalyzeSentiment.json +3 -7
- teradataml/data/jsons/sqle/20.00/AI_AskLLM.json +3 -7
- teradataml/data/jsons/sqle/20.00/AI_DetectLanguage.json +3 -7
- teradataml/data/jsons/sqle/20.00/AI_ExtractKeyPhrases.json +3 -7
- teradataml/data/jsons/sqle/20.00/AI_MaskPII.json +3 -7
- teradataml/data/jsons/sqle/20.00/AI_RecognizeEntities.json +3 -7
- teradataml/data/jsons/sqle/20.00/AI_RecognizePIIEntities.json +3 -7
- teradataml/data/jsons/sqle/20.00/AI_TextClassifier.json +3 -7
- teradataml/data/jsons/sqle/20.00/AI_TextEmbeddings.json +3 -7
- teradataml/data/jsons/sqle/20.00/AI_TextSummarize.json +3 -7
- teradataml/data/jsons/sqle/20.00/AI_TextTranslate.json +3 -7
- teradataml/data/jsons/sqle/20.00/TD_API_AzureML.json +151 -0
- teradataml/data/jsons/sqle/20.00/TD_API_Sagemaker.json +182 -0
- teradataml/data/jsons/sqle/20.00/TD_API_VertexAI.json +183 -0
- teradataml/data/load_example_data.py +29 -11
- teradataml/data/payment_fraud_dataset.csv +10001 -0
- teradataml/data/teradataml_example.json +67 -0
- teradataml/dataframe/copy_to.py +714 -54
- teradataml/dataframe/dataframe.py +1153 -33
- teradataml/dataframe/dataframe_utils.py +8 -3
- teradataml/dataframe/functions.py +168 -1
- teradataml/dataframe/setop.py +4 -1
- teradataml/dataframe/sql.py +141 -9
- teradataml/dbutils/dbutils.py +470 -35
- teradataml/dbutils/filemgr.py +1 -1
- teradataml/hyperparameter_tuner/optimizer.py +456 -142
- teradataml/lib/aed_0_1.dll +0 -0
- teradataml/lib/libaed_0_1.dylib +0 -0
- teradataml/lib/libaed_0_1.so +0 -0
- teradataml/lib/libaed_0_1_aarch64.so +0 -0
- teradataml/scriptmgmt/UserEnv.py +234 -34
- teradataml/scriptmgmt/lls_utils.py +43 -17
- teradataml/sdk/_json_parser.py +1 -1
- teradataml/sdk/api_client.py +9 -6
- teradataml/sdk/modelops/_client.py +3 -0
- teradataml/series/series.py +12 -7
- teradataml/store/feature_store/constants.py +601 -234
- teradataml/store/feature_store/feature_store.py +2886 -616
- teradataml/store/feature_store/mind_map.py +639 -0
- teradataml/store/feature_store/models.py +5831 -214
- teradataml/store/feature_store/utils.py +390 -0
- teradataml/table_operators/table_operator_util.py +1 -1
- teradataml/table_operators/templates/dataframe_register.template +6 -2
- teradataml/table_operators/templates/dataframe_udf.template +6 -2
- teradataml/utils/docstring.py +527 -0
- teradataml/utils/dtypes.py +93 -0
- teradataml/utils/internal_buffer.py +2 -2
- teradataml/utils/utils.py +41 -2
- teradataml/utils/validators.py +694 -17
- {teradataml-20.0.0.6.dist-info → teradataml-20.0.0.7.dist-info}/METADATA +213 -2
- {teradataml-20.0.0.6.dist-info → teradataml-20.0.0.7.dist-info}/RECORD +96 -81
- {teradataml-20.0.0.6.dist-info → teradataml-20.0.0.7.dist-info}/WHEEL +0 -0
- {teradataml-20.0.0.6.dist-info → teradataml-20.0.0.7.dist-info}/top_level.txt +0 -0
- {teradataml-20.0.0.6.dist-info → teradataml-20.0.0.7.dist-info}/zip-safe +0 -0
|
@@ -0,0 +1,527 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Unpublished work.
|
|
3
|
+
Copyright (c) 2025 by Teradata Corporation. All rights reserved.
|
|
4
|
+
TERADATA CORPORATION CONFIDENTIAL AND TRADE SECRET
|
|
5
|
+
|
|
6
|
+
Primary Owner: Sushant.Mhambrey@Teradata.com
|
|
7
|
+
PankajVinod.Purandare@Teradata.com
|
|
8
|
+
|
|
9
|
+
This file implements the decorator to inherit docstring from parent method,
|
|
10
|
+
override specified sections, append shared parameters, and remove excluded parameters.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
import inspect
|
|
14
|
+
import re
|
|
15
|
+
import textwrap
|
|
16
|
+
from functools import wraps
|
|
17
|
+
from typing import (
|
|
18
|
+
Any,
|
|
19
|
+
Callable,
|
|
20
|
+
Dict,
|
|
21
|
+
List,
|
|
22
|
+
Optional,
|
|
23
|
+
Sequence,
|
|
24
|
+
Tuple,
|
|
25
|
+
Type,
|
|
26
|
+
Union,
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
# -------------------------------------------------------------------
|
|
30
|
+
# Helpers for emitting structured parameter blocks & notes
|
|
31
|
+
# -------------------------------------------------------------------
|
|
32
|
+
|
|
33
|
+
_LIST_MARKER_RE = re.compile(r"^(\*|\+|\-|\d+\.|[a-zA-Z]\.)\s")
|
|
34
|
+
_SECTION_HEADER_RE = re.compile(r"^\s*([A-Z][A-Z _]+?)\s*:?\s*$", re.MULTILINE)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def _emit_structured_block(
|
|
38
|
+
label: str,
|
|
39
|
+
content: Any,
|
|
40
|
+
description_indent: str,
|
|
41
|
+
) -> List[str]:
|
|
42
|
+
"""
|
|
43
|
+
DESCRIPTION:
|
|
44
|
+
Internal function to build a properly indented block in the docstring
|
|
45
|
+
for any "Label:" section where the content maybe a single value,
|
|
46
|
+
multiline string, or a list of items.
|
|
47
|
+
|
|
48
|
+
PARAMETERS:
|
|
49
|
+
label:
|
|
50
|
+
Required Argument.
|
|
51
|
+
The label for the block (e.g., 'Default Value').
|
|
52
|
+
Types: str
|
|
53
|
+
|
|
54
|
+
content:
|
|
55
|
+
Required Argument.
|
|
56
|
+
The value or list to be formatted as a block.
|
|
57
|
+
Types: Any
|
|
58
|
+
|
|
59
|
+
description_indent:
|
|
60
|
+
Required Argument.
|
|
61
|
+
The indentation to use for the block's description lines.
|
|
62
|
+
Types: str
|
|
63
|
+
|
|
64
|
+
RETURNS:
|
|
65
|
+
List of formatted lines for the docstring block.
|
|
66
|
+
Types: List[str]
|
|
67
|
+
|
|
68
|
+
RAISES:
|
|
69
|
+
None.
|
|
70
|
+
|
|
71
|
+
EXAMPLES:
|
|
72
|
+
lines = _emit_structured_block('Default Value', '512', ' ')
|
|
73
|
+
"""
|
|
74
|
+
lines: List[str] = []
|
|
75
|
+
if not content:
|
|
76
|
+
return lines
|
|
77
|
+
|
|
78
|
+
# Normalize into list of lines
|
|
79
|
+
if isinstance(content, (list, tuple, set)):
|
|
80
|
+
raw_lines = [f"* {item}" for item in content]
|
|
81
|
+
else:
|
|
82
|
+
raw_lines = [ln for ln in str(content).splitlines() if ln.strip()]
|
|
83
|
+
|
|
84
|
+
# Single-line simple content
|
|
85
|
+
if len(raw_lines) == 1 and not _LIST_MARKER_RE.match(raw_lines[0]):
|
|
86
|
+
lines.append(f"{description_indent}{label}: {raw_lines[0]}")
|
|
87
|
+
return lines
|
|
88
|
+
|
|
89
|
+
# Multi-line block
|
|
90
|
+
lines.append(f"{description_indent}{label}:")
|
|
91
|
+
block_indent = description_indent + " " * 4
|
|
92
|
+
sub_indent = description_indent + " " * 8
|
|
93
|
+
|
|
94
|
+
# Process each line, indenting bullets and preserving structure
|
|
95
|
+
# for multiline content
|
|
96
|
+
i = 0
|
|
97
|
+
while i < len(raw_lines):
|
|
98
|
+
raw = raw_lines[i].strip()
|
|
99
|
+
is_bullet = bool(_LIST_MARKER_RE.match(raw))
|
|
100
|
+
content = raw[2:].strip() if is_bullet else raw
|
|
101
|
+
if ( not is_bullet and ":" in raw) or content.endswith(":"):
|
|
102
|
+
lines.append(f"{block_indent}{content}") # Group headers at 4 spaces
|
|
103
|
+
i += 1
|
|
104
|
+
elif is_bullet:
|
|
105
|
+
bullet_indent = description_indent + " " * 8 # Keep bullets at 8 spaces
|
|
106
|
+
lines.append(f"{bullet_indent}* {content}")
|
|
107
|
+
i += 1
|
|
108
|
+
else:
|
|
109
|
+
# Not a bullet, just a regular line
|
|
110
|
+
lines.append(f"{sub_indent}{content}")
|
|
111
|
+
i += 1
|
|
112
|
+
|
|
113
|
+
return lines
|
|
114
|
+
|
|
115
|
+
def _emit_notes_block(notes: str, description_indent: str) -> List[str]:
|
|
116
|
+
"""
|
|
117
|
+
DESCRIPTION:
|
|
118
|
+
Internal function that emits a free-form notes string into a
|
|
119
|
+
'Note:' or 'Notes:' section with proper indentation and bullet
|
|
120
|
+
formatting for docstrings.
|
|
121
|
+
Detects whether to use singular or plural header and preserves
|
|
122
|
+
nested paragraphs.
|
|
123
|
+
|
|
124
|
+
PARAMETERS:
|
|
125
|
+
notes:
|
|
126
|
+
Required Argument.
|
|
127
|
+
The notes string to be formatted.
|
|
128
|
+
Types: str
|
|
129
|
+
|
|
130
|
+
description_indent:
|
|
131
|
+
Required Argument.
|
|
132
|
+
The indentation to use for the block's description lines.
|
|
133
|
+
Types: str
|
|
134
|
+
|
|
135
|
+
RETURNS:
|
|
136
|
+
List of formatted lines for the notes block.
|
|
137
|
+
Types: List[str]
|
|
138
|
+
|
|
139
|
+
RAISES:
|
|
140
|
+
None.
|
|
141
|
+
|
|
142
|
+
EXAMPLES:
|
|
143
|
+
lines = _emit_notes_block('Applicable only for file-based stores.', ' ')
|
|
144
|
+
"""
|
|
145
|
+
lines: List[str] = []
|
|
146
|
+
in_bullet_section = False
|
|
147
|
+
|
|
148
|
+
# Split and filter out blank lines
|
|
149
|
+
raw = [ln.rstrip() for ln in notes.splitlines() if ln.strip()]
|
|
150
|
+
if not raw:
|
|
151
|
+
return lines
|
|
152
|
+
|
|
153
|
+
# Determine if we need singular or plural header
|
|
154
|
+
bullet_lines = [ln for ln in raw if _LIST_MARKER_RE.match(ln.lstrip())]
|
|
155
|
+
header = "Notes:" if len(bullet_lines) > 1 else "Note:"
|
|
156
|
+
|
|
157
|
+
# Build lines with header
|
|
158
|
+
lines.append(f"{description_indent}{header}")
|
|
159
|
+
|
|
160
|
+
# For each line in raw, indent as bullet
|
|
161
|
+
# or paragraph line under last bullet
|
|
162
|
+
# depending on whether it starts with a bullet marker
|
|
163
|
+
for ln in raw:
|
|
164
|
+
stripped = ln.lstrip()
|
|
165
|
+
if _LIST_MARKER_RE.match(stripped):
|
|
166
|
+
# This is a bullet point or numbered item
|
|
167
|
+
lines.append(f"{description_indent} {stripped}")
|
|
168
|
+
in_bullet_section = True
|
|
169
|
+
else:
|
|
170
|
+
# This is a continuation line or regular text
|
|
171
|
+
# Give extra indent if we're in a bullet section (for continuation)
|
|
172
|
+
extra = " " if in_bullet_section else " "
|
|
173
|
+
lines.append(f"{description_indent}{extra}{stripped}")
|
|
174
|
+
|
|
175
|
+
return lines
|
|
176
|
+
#-------------------------------------------------------------------
|
|
177
|
+
# Section parsing & parameter-removal helpers
|
|
178
|
+
# -------------------------------------------------------------------
|
|
179
|
+
|
|
180
|
+
def _split_sections(docstring: str) -> List[Tuple[str, List[str]]]:
|
|
181
|
+
"""
|
|
182
|
+
DESCRIPTION:
|
|
183
|
+
Internal function to split a docstring into named sections based
|
|
184
|
+
on headers like 'DESCRIPTION:', 'PARAMETERS:', etc.
|
|
185
|
+
Leading text before the first recognized header is considered 'BODY'.
|
|
186
|
+
|
|
187
|
+
PARAMETERS:
|
|
188
|
+
docstring:
|
|
189
|
+
Required Argument.
|
|
190
|
+
The docstring to split into sections.
|
|
191
|
+
Types: str
|
|
192
|
+
|
|
193
|
+
RETURNS:
|
|
194
|
+
List of (header, lines) tuples representing docstring sections.
|
|
195
|
+
Types: List[Tuple[str, List[str]]]
|
|
196
|
+
|
|
197
|
+
RAISES:
|
|
198
|
+
None.
|
|
199
|
+
|
|
200
|
+
EXAMPLES:
|
|
201
|
+
sections = _split_sections('''DESCRIPTION:...PARAMETERS:...''')
|
|
202
|
+
"""
|
|
203
|
+
if not docstring:
|
|
204
|
+
return []
|
|
205
|
+
|
|
206
|
+
sections: List[Tuple[str, List[str]]] = []
|
|
207
|
+
last_header = "BODY"
|
|
208
|
+
last_index = 0
|
|
209
|
+
|
|
210
|
+
# Find all section headers
|
|
211
|
+
# and split the docstring into blocks
|
|
212
|
+
for match in _SECTION_HEADER_RE.finditer(docstring):
|
|
213
|
+
header = match.group(1).strip().upper()
|
|
214
|
+
block_text = docstring[last_index : match.start()].rstrip("\n")
|
|
215
|
+
|
|
216
|
+
# split into lines and strip out any leading/trailing blank lines
|
|
217
|
+
lines = block_text.splitlines()
|
|
218
|
+
while lines and not lines[0].strip():
|
|
219
|
+
lines.pop(0)
|
|
220
|
+
while lines and not lines[-1].strip():
|
|
221
|
+
lines.pop()
|
|
222
|
+
sections.append((last_header, lines))
|
|
223
|
+
|
|
224
|
+
#sections.append((last_header, block_text.splitlines()))
|
|
225
|
+
# update for next section with last header and last index
|
|
226
|
+
last_header = header
|
|
227
|
+
last_index = match.end()
|
|
228
|
+
|
|
229
|
+
# final block
|
|
230
|
+
final_block = docstring[last_index:].rstrip("\n")
|
|
231
|
+
|
|
232
|
+
lines = final_block.splitlines()
|
|
233
|
+
while lines and not lines[0].strip():
|
|
234
|
+
lines.pop(0)
|
|
235
|
+
while lines and not lines[-1].strip():
|
|
236
|
+
lines.pop()
|
|
237
|
+
sections.append((last_header, lines))
|
|
238
|
+
|
|
239
|
+
# drop the very first BODY if empty
|
|
240
|
+
if sections and not any(line.strip() for line in sections[0][1]):
|
|
241
|
+
sections.pop(0)
|
|
242
|
+
|
|
243
|
+
return sections
|
|
244
|
+
|
|
245
|
+
def _remove_excluded_parameters(
|
|
246
|
+
parameter_lines: List[str],
|
|
247
|
+
excluded_argument_names: set[str],
|
|
248
|
+
) -> List[str]:
|
|
249
|
+
"""
|
|
250
|
+
DESCRIPTION:
|
|
251
|
+
Removes parameter entry blocks from a PARAMETERS section whose name is
|
|
252
|
+
in excluded_argument_names.
|
|
253
|
+
|
|
254
|
+
PARAMETERS:
|
|
255
|
+
parameter_lines:
|
|
256
|
+
Required Argument.
|
|
257
|
+
The lines of the PARAMETERS section to filter.
|
|
258
|
+
Types: List[str]
|
|
259
|
+
|
|
260
|
+
excluded_argument_names:
|
|
261
|
+
Required Argument.
|
|
262
|
+
Set of parameter names to exclude from the PARAMETERS section.
|
|
263
|
+
Types: set[str]
|
|
264
|
+
|
|
265
|
+
RETURNS:
|
|
266
|
+
Filtered list of parameter lines.
|
|
267
|
+
Types: List[str]
|
|
268
|
+
|
|
269
|
+
RAISES:
|
|
270
|
+
None.
|
|
271
|
+
|
|
272
|
+
EXAMPLES:
|
|
273
|
+
param_lines = [
|
|
274
|
+
" chunk_size:",
|
|
275
|
+
" Optional Argument.",
|
|
276
|
+
" nv_ingestor:",
|
|
277
|
+
" Optional Argument."
|
|
278
|
+
]
|
|
279
|
+
filtered = _remove_excluded_parameters(param_lines , {"nv_ingestor"})
|
|
280
|
+
"""
|
|
281
|
+
cleaned_lines: List[str] = []
|
|
282
|
+
skipping = False
|
|
283
|
+
param_indent_level = None
|
|
284
|
+
|
|
285
|
+
# Iterate through all lines under PARAMETERS
|
|
286
|
+
# and remove blocks for excluded parameters
|
|
287
|
+
for line in parameter_lines:
|
|
288
|
+
# Detect start of each param block
|
|
289
|
+
name_match = re.match(r"^(\s*)(\w+):\s*$", line)
|
|
290
|
+
if name_match:
|
|
291
|
+
indent, param_name = name_match.groups()
|
|
292
|
+
if param_name in excluded_argument_names:
|
|
293
|
+
skipping = True
|
|
294
|
+
param_indent_level = len(indent)
|
|
295
|
+
continue
|
|
296
|
+
else:
|
|
297
|
+
skipping = False
|
|
298
|
+
|
|
299
|
+
if skipping:
|
|
300
|
+
# if we encounter a line that's at or above the original param indent,
|
|
301
|
+
# it means the block ended
|
|
302
|
+
current_indent = len(line) - len(line.lstrip())
|
|
303
|
+
if current_indent <= (param_indent_level or 0):
|
|
304
|
+
skipping = False
|
|
305
|
+
else:
|
|
306
|
+
continue
|
|
307
|
+
|
|
308
|
+
else:
|
|
309
|
+
cleaned_lines.append(line)
|
|
310
|
+
|
|
311
|
+
return cleaned_lines
|
|
312
|
+
|
|
313
|
+
# -------------------------------------------------------------------
|
|
314
|
+
# The unified decorator
|
|
315
|
+
# -------------------------------------------------------------------
|
|
316
|
+
|
|
317
|
+
def docstring_handler(
|
|
318
|
+
inherit_from: Optional[Union[Type, Callable]] = None,
|
|
319
|
+
replace_sections: Sequence[str] = ("EXAMPLES",),
|
|
320
|
+
common_params: Optional[Dict[str, Dict[str, Any]]] = None,
|
|
321
|
+
exclude_params: Optional[List[str]] = None,
|
|
322
|
+
) -> Callable[[Callable], Callable]:
|
|
323
|
+
"""
|
|
324
|
+
DESCRIPTION:
|
|
325
|
+
Decorator to inherit parent method's docstring, override specified sections,
|
|
326
|
+
append shared parameters, and remove excluded parameters.
|
|
327
|
+
|
|
328
|
+
PARAMETERS:
|
|
329
|
+
inherit_from:
|
|
330
|
+
Optional Argument.
|
|
331
|
+
Class or function to inherit the parent method's docstring from.
|
|
332
|
+
Types: class or function
|
|
333
|
+
|
|
334
|
+
replace_sections:
|
|
335
|
+
Optional Argument.
|
|
336
|
+
Sequence of section headers the child should override in the docstring.
|
|
337
|
+
Types: sequence of str
|
|
338
|
+
|
|
339
|
+
common_params:
|
|
340
|
+
Optional Argument.
|
|
341
|
+
Mapping of parameter-key to spec-dict to append into PARAMETERS.
|
|
342
|
+
Types: dict
|
|
343
|
+
|
|
344
|
+
exclude_params:
|
|
345
|
+
Optional Argument.
|
|
346
|
+
List of parameter keys (or argument_names) to remove from both inherited PARAMETERS and injected common_params.
|
|
347
|
+
Types: list of str
|
|
348
|
+
|
|
349
|
+
RETURNS:
|
|
350
|
+
Decorated function with updated docstring.
|
|
351
|
+
Types: Callable[[Callable], Callable]
|
|
352
|
+
|
|
353
|
+
RAISES:
|
|
354
|
+
None.
|
|
355
|
+
|
|
356
|
+
EXAMPLES:
|
|
357
|
+
@docstring_handler(inherit_from=BaseClass, common_params=PARAMS)
|
|
358
|
+
def my_func(...):
|
|
359
|
+
...
|
|
360
|
+
"""
|
|
361
|
+
excluded_keys = set(exclude_params or [])
|
|
362
|
+
|
|
363
|
+
if isinstance(replace_sections, str):
|
|
364
|
+
headers_to_replace = {replace_sections.upper()}
|
|
365
|
+
else:
|
|
366
|
+
headers_to_replace = {h.upper() for h in replace_sections}
|
|
367
|
+
|
|
368
|
+
def decorator(method: Callable) -> Callable:
|
|
369
|
+
# 1) Fetch and split parent doc if requested
|
|
370
|
+
parent_sections: List[Tuple[str, List[str]]] = []
|
|
371
|
+
if inherit_from:
|
|
372
|
+
parent_method = getattr(inherit_from, method.__name__)
|
|
373
|
+
raw_parent_doc = inspect.getdoc(parent_method) or ""
|
|
374
|
+
parent_sections = _split_sections(raw_parent_doc)
|
|
375
|
+
|
|
376
|
+
# 2) Split the child’s own doc
|
|
377
|
+
raw_child_doc = inspect.getdoc(method) or ""
|
|
378
|
+
child_sections = dict(_split_sections(raw_child_doc))
|
|
379
|
+
|
|
380
|
+
# 3) Merge sections
|
|
381
|
+
if inherit_from:
|
|
382
|
+
merged_sections: List[Tuple[str, List[str]]] = []
|
|
383
|
+
parent_headers = [hdr for hdr, _ in parent_sections]
|
|
384
|
+
|
|
385
|
+
for header, block_lines in parent_sections:
|
|
386
|
+
if header in headers_to_replace and header in child_sections:
|
|
387
|
+
merged_sections.append((header, child_sections[header]))
|
|
388
|
+
else:
|
|
389
|
+
merged_sections.append((header, block_lines))
|
|
390
|
+
|
|
391
|
+
# Append any child-only sections
|
|
392
|
+
for header, block_lines in _split_sections(raw_child_doc):
|
|
393
|
+
if header not in parent_headers and header != "BODY":
|
|
394
|
+
merged_sections.append((header, block_lines))
|
|
395
|
+
|
|
396
|
+
else:
|
|
397
|
+
# No inheritance: start with child's sections only
|
|
398
|
+
merged_sections = _split_sections(raw_child_doc)
|
|
399
|
+
|
|
400
|
+
# Ensure each section exists
|
|
401
|
+
section_canonical_names = ["DESCRIPTION", "PARAMETERS", "RETURNS", "RAISES", "EXAMPLES"]
|
|
402
|
+
existing = [hdr for hdr, _ in merged_sections ]
|
|
403
|
+
block_indent_auto = " " * 4
|
|
404
|
+
|
|
405
|
+
for section in section_canonical_names:
|
|
406
|
+
if section not in existing:
|
|
407
|
+
# DESCRIPTION gets a default line, others can just say "None"
|
|
408
|
+
|
|
409
|
+
if section == "DESCRIPTION":
|
|
410
|
+
default_block = [f"{block_indent_auto}Auto generated description."]
|
|
411
|
+
|
|
412
|
+
elif section == "PARAMETERS" and common_params:
|
|
413
|
+
default_block = []
|
|
414
|
+
else:
|
|
415
|
+
default_block = [f"{block_indent_auto}None"]
|
|
416
|
+
|
|
417
|
+
# Figure out what to insert next so order stays as section_canonical_names
|
|
418
|
+
insert_at = next(
|
|
419
|
+
(i for i, (hdr, _) in enumerate(merged_sections)
|
|
420
|
+
if hdr in section_canonical_names
|
|
421
|
+
and section_canonical_names.index(hdr) > section_canonical_names.index(section)),
|
|
422
|
+
len(merged_sections),
|
|
423
|
+
)
|
|
424
|
+
merged_sections.insert(insert_at, (section, default_block))
|
|
425
|
+
|
|
426
|
+
# 4) Inject or update PARAMETERS block
|
|
427
|
+
if common_params:
|
|
428
|
+
# find or create PARAMETERS section
|
|
429
|
+
param_index = next(
|
|
430
|
+
(i for i, (hdr, _) in enumerate(merged_sections) if hdr == "PARAMETERS"),
|
|
431
|
+
None,
|
|
432
|
+
)
|
|
433
|
+
header, existing_param_lines = merged_sections[param_index]
|
|
434
|
+
|
|
435
|
+
# remove excluded params
|
|
436
|
+
# also map keys → argument_name for exclusion
|
|
437
|
+
excluded_argument_names = {
|
|
438
|
+
common_params[key].get("argument_name", key)
|
|
439
|
+
for key in excluded_keys
|
|
440
|
+
if key in common_params
|
|
441
|
+
}
|
|
442
|
+
excluded_argument_names |= excluded_keys
|
|
443
|
+
|
|
444
|
+
cleaned_param_lines = _remove_excluded_parameters(
|
|
445
|
+
existing_param_lines,
|
|
446
|
+
excluded_argument_names,
|
|
447
|
+
)
|
|
448
|
+
|
|
449
|
+
# Which args are already present
|
|
450
|
+
existing_param_names = {
|
|
451
|
+
m.group(1)
|
|
452
|
+
for line in cleaned_param_lines
|
|
453
|
+
if (m := re.match(r"^\s*(\w+):\s*$", line))
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
# build new param lines
|
|
457
|
+
base_indent = " " * 4
|
|
458
|
+
description_indent = base_indent + " " * 4
|
|
459
|
+
injected_lines: List[str] = []
|
|
460
|
+
for param_key, spec in common_params.items():
|
|
461
|
+
# Only exclude by excluded keys in the injection loop, not by argument_name.
|
|
462
|
+
if param_key in excluded_keys:
|
|
463
|
+
continue
|
|
464
|
+
|
|
465
|
+
argument_name = spec.get("argument_name", param_key)
|
|
466
|
+
|
|
467
|
+
if argument_name in existing_param_names:
|
|
468
|
+
# If already exists, skip adding it again
|
|
469
|
+
continue
|
|
470
|
+
|
|
471
|
+
# name:
|
|
472
|
+
injected_lines.append(f"{base_indent}{argument_name}:")
|
|
473
|
+
# required
|
|
474
|
+
if spec.get("required"):
|
|
475
|
+
injected_lines.append(f"{description_indent}{spec['required']}")
|
|
476
|
+
# description
|
|
477
|
+
if spec.get("description"):
|
|
478
|
+
for i, desc_line in enumerate(spec["description"].splitlines()):
|
|
479
|
+
indent = description_indent if i else description_indent
|
|
480
|
+
injected_lines.append(f"{indent}{desc_line.strip()}")
|
|
481
|
+
# notes, default, permitted, types
|
|
482
|
+
injected_lines += _emit_notes_block(
|
|
483
|
+
spec.get("notes", ""), description_indent
|
|
484
|
+
)
|
|
485
|
+
injected_lines += _emit_structured_block(
|
|
486
|
+
"Default Value", spec.get("default_values"), description_indent
|
|
487
|
+
)
|
|
488
|
+
injected_lines += _emit_structured_block(
|
|
489
|
+
"Permitted Values", spec.get("permitted_values"), description_indent
|
|
490
|
+
)
|
|
491
|
+
if spec.get("types"):
|
|
492
|
+
injected_lines.append(
|
|
493
|
+
f"{description_indent}Types: {spec['types']}"
|
|
494
|
+
)
|
|
495
|
+
injected_lines.append("") # blank line
|
|
496
|
+
|
|
497
|
+
# merge old + blank separator + new
|
|
498
|
+
if cleaned_param_lines and injected_lines:
|
|
499
|
+
if cleaned_param_lines[-1].strip():
|
|
500
|
+
cleaned_param_lines.append("")
|
|
501
|
+
merged_param_block = cleaned_param_lines + injected_lines
|
|
502
|
+
|
|
503
|
+
# replace in merged_sections
|
|
504
|
+
merged_sections[param_index] = (header, merged_param_block)
|
|
505
|
+
|
|
506
|
+
# 5) Reconstruct final docstring
|
|
507
|
+
final_blocks: List[str] = []
|
|
508
|
+
for header, block_lines in merged_sections:
|
|
509
|
+
if header == "BODY":
|
|
510
|
+
if block_lines:
|
|
511
|
+
final_blocks.append("\n".join(block_lines).rstrip())
|
|
512
|
+
else:
|
|
513
|
+
# final_blocks.append(f"{header}:")
|
|
514
|
+
# if block_lines:
|
|
515
|
+
# final_blocks.append("\n".join(block_lines).rstrip())
|
|
516
|
+
if block_lines:
|
|
517
|
+
block = f"{header}:\n" + "\n".join(block_lines).rstrip()
|
|
518
|
+
else:
|
|
519
|
+
block = f"{header}:"
|
|
520
|
+
final_blocks.append(block)
|
|
521
|
+
|
|
522
|
+
final_doc = "\n\n".join(final_blocks).rstrip() + "\n"
|
|
523
|
+
method.__doc__ = textwrap.dedent(final_doc)
|
|
524
|
+
|
|
525
|
+
return method
|
|
526
|
+
|
|
527
|
+
return decorator
|
teradataml/utils/dtypes.py
CHANGED
|
@@ -733,3 +733,96 @@ class _Dtypes:
|
|
|
733
733
|
"""
|
|
734
734
|
return _DtypesMappers.DATETIME_PERIOD_TYPES
|
|
735
735
|
|
|
736
|
+
@staticmethod
|
|
737
|
+
def _get_normalized_type(td_type):
|
|
738
|
+
"""
|
|
739
|
+
DESCRIPTION:
|
|
740
|
+
Get the normalized types for DataFrame Types.
|
|
741
|
+
|
|
742
|
+
PARAMETERS:
|
|
743
|
+
None
|
|
744
|
+
|
|
745
|
+
RETURNS:
|
|
746
|
+
tuple
|
|
747
|
+
|
|
748
|
+
RAISES:
|
|
749
|
+
None
|
|
750
|
+
|
|
751
|
+
EXAMPLES:
|
|
752
|
+
>>> _Dtypes._get_normalized_types()
|
|
753
|
+
"""
|
|
754
|
+
# Storing the details of the normalized types.
|
|
755
|
+
|
|
756
|
+
# Decimal type with any precision and scale, normalie it to DECIMAL(38, 19).
|
|
757
|
+
decimal_precision = 38
|
|
758
|
+
decimal_scale = 19
|
|
759
|
+
|
|
760
|
+
# Byte type with any length, normalize it to BYTE(64000).
|
|
761
|
+
byte_length = 64000
|
|
762
|
+
|
|
763
|
+
# Number type with any precision and scale, normalize it to NUMBER(38, 10).
|
|
764
|
+
number_precision = 38
|
|
765
|
+
number_scale = 10
|
|
766
|
+
|
|
767
|
+
# Time and Timestamp with any precision, normalize it to TIME(6) and TIMESTAMP(6).
|
|
768
|
+
time_precision = 6
|
|
769
|
+
|
|
770
|
+
# Interval types with any precision and fractional precision, normalize it
|
|
771
|
+
# to store maximum precision and fractional precision.
|
|
772
|
+
interval_precision = 4
|
|
773
|
+
frac_precision = 6
|
|
774
|
+
|
|
775
|
+
# Character types with any length, normalize it to CHAR(2000) and VARCHAR(2000).
|
|
776
|
+
char_length = 2000
|
|
777
|
+
|
|
778
|
+
type_ = td_type.__class__
|
|
779
|
+
|
|
780
|
+
types_ = {
|
|
781
|
+
INTEGER: BIGINT(),
|
|
782
|
+
SMALLINT: BIGINT(),
|
|
783
|
+
BIGINT: BIGINT(),
|
|
784
|
+
DECIMAL: DECIMAL(precision=decimal_precision, scale=decimal_scale),
|
|
785
|
+
BYTEINT: BYTEINT(),
|
|
786
|
+
BYTE: BYTE(length=byte_length),
|
|
787
|
+
VARBYTE: VARBYTE(length=byte_length),
|
|
788
|
+
FLOAT: FLOAT(),
|
|
789
|
+
NUMBER: NUMBER(precision=number_precision, scale=number_scale),
|
|
790
|
+
DATE: DATE(),
|
|
791
|
+
INTERVAL_YEAR: INTERVAL_YEAR(precision=interval_precision),
|
|
792
|
+
INTERVAL_YEAR_TO_MONTH: INTERVAL_YEAR_TO_MONTH(precision=interval_precision),
|
|
793
|
+
INTERVAL_MONTH: INTERVAL_MONTH(precision=interval_precision),
|
|
794
|
+
INTERVAL_DAY: INTERVAL_DAY(precision=interval_precision),
|
|
795
|
+
INTERVAL_DAY_TO_HOUR: INTERVAL_DAY_TO_HOUR(precision=interval_precision),
|
|
796
|
+
INTERVAL_DAY_TO_MINUTE: INTERVAL_DAY_TO_MINUTE(precision=interval_precision),
|
|
797
|
+
INTERVAL_DAY_TO_SECOND: INTERVAL_DAY_TO_SECOND(
|
|
798
|
+
precision=interval_precision, frac_precision=frac_precision),
|
|
799
|
+
INTERVAL_HOUR: INTERVAL_HOUR(precision=interval_precision),
|
|
800
|
+
INTERVAL_HOUR_TO_MINUTE: INTERVAL_HOUR_TO_MINUTE(precision=interval_precision),
|
|
801
|
+
INTERVAL_HOUR_TO_SECOND: INTERVAL_HOUR_TO_SECOND(
|
|
802
|
+
precision=interval_precision, frac_precision=frac_precision),
|
|
803
|
+
INTERVAL_MINUTE: INTERVAL_MINUTE(precision=interval_precision),
|
|
804
|
+
INTERVAL_MINUTE_TO_SECOND: INTERVAL_MINUTE_TO_SECOND(
|
|
805
|
+
precision=interval_precision, frac_precision=frac_precision),
|
|
806
|
+
INTERVAL_SECOND: INTERVAL_SECOND(
|
|
807
|
+
precision=interval_precision, frac_precision=frac_precision),
|
|
808
|
+
PERIOD_DATE: PERIOD_DATE(),
|
|
809
|
+
DATE: DATE()
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
type_ = types_.get(type_)
|
|
813
|
+
if type_:
|
|
814
|
+
return type_, type_.__class__.__name__
|
|
815
|
+
elif isinstance(td_type, TIME):
|
|
816
|
+
type_ = TIME(precision=time_precision, timezone=td_type.timezone)
|
|
817
|
+
return type_, "TIME_{}".format(type_.timezone)
|
|
818
|
+
elif isinstance(td_type, TIMESTAMP):
|
|
819
|
+
type_ = TIMESTAMP(precision=time_precision, timezone=td_type.timezone)
|
|
820
|
+
return type_, "TIMESTAMP_{}".format(type_.timezone)
|
|
821
|
+
elif isinstance(td_type, (PERIOD_TIME, PERIOD_TIMESTAMP)):
|
|
822
|
+
type_ = td_type.__class__(frac_precision=frac_precision, timezone=td_type.timezone)
|
|
823
|
+
return type_, "{}_{}".format(type_.__class__.__name__, type_.timezone)
|
|
824
|
+
elif isinstance(td_type, (CHAR, VARCHAR)):
|
|
825
|
+
type_ = td_type.__class__(length=char_length, charset=td_type.charset)
|
|
826
|
+
return type_, "{}_{}".format(type_.__class__.__name__, type_.charset)
|
|
827
|
+
else:
|
|
828
|
+
return None, repr(None)
|
|
@@ -114,8 +114,8 @@ class _InternalBuffer:
|
|
|
114
114
|
None
|
|
115
115
|
|
|
116
116
|
EXAMPLES:
|
|
117
|
-
# Remove keys "list_base_envs" and "
|
|
118
|
-
>>> _InternalBuffer.remove_keys(['list_base_envs', '
|
|
117
|
+
# Remove keys "list_base_envs" and "default_base_env_python" from _InternalBuffer.
|
|
118
|
+
>>> _InternalBuffer.remove_keys(['list_base_envs', 'default_base_env_python'])
|
|
119
119
|
"""
|
|
120
120
|
for key in keys:
|
|
121
121
|
if cls.__data.get(key) is not None:
|