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.

Files changed (131) hide show
  1. teradataml/LICENSE-3RD-PARTY.pdf +0 -0
  2. teradataml/README.md +182 -13
  3. teradataml/__init__.py +2 -1
  4. teradataml/_version.py +2 -2
  5. teradataml/analytics/analytic_function_executor.py +8 -13
  6. teradataml/analytics/json_parser/analytic_functions_argument.py +4 -0
  7. teradataml/analytics/sqle/__init__.py +16 -1
  8. teradataml/analytics/utils.py +60 -1
  9. teradataml/automl/__init__.py +290 -106
  10. teradataml/automl/autodataprep/__init__.py +471 -0
  11. teradataml/automl/data_preparation.py +29 -10
  12. teradataml/automl/data_transformation.py +11 -0
  13. teradataml/automl/feature_engineering.py +64 -4
  14. teradataml/automl/feature_exploration.py +639 -25
  15. teradataml/automl/model_training.py +1 -1
  16. teradataml/clients/auth_client.py +12 -8
  17. teradataml/clients/keycloak_client.py +165 -0
  18. teradataml/common/constants.py +71 -26
  19. teradataml/common/exceptions.py +32 -0
  20. teradataml/common/messagecodes.py +28 -0
  21. teradataml/common/messages.py +13 -4
  22. teradataml/common/sqlbundle.py +3 -2
  23. teradataml/common/utils.py +345 -45
  24. teradataml/context/context.py +259 -93
  25. teradataml/data/apriori_example.json +22 -0
  26. teradataml/data/docs/sqle/docs_17_20/Apriori.py +138 -0
  27. teradataml/data/docs/sqle/docs_17_20/NERExtractor.py +121 -0
  28. teradataml/data/docs/sqle/docs_17_20/NGramSplitter.py +3 -3
  29. teradataml/data/docs/sqle/docs_17_20/SMOTE.py +212 -0
  30. teradataml/data/docs/sqle/docs_17_20/TextMorph.py +119 -0
  31. teradataml/data/docs/sqle/docs_17_20/TextParser.py +54 -3
  32. teradataml/data/docs/uaf/docs_17_20/ACF.py +1 -1
  33. teradataml/data/docs/uaf/docs_17_20/ArimaEstimate.py +2 -2
  34. teradataml/data/docs/uaf/docs_17_20/ArimaXEstimate.py +2 -2
  35. teradataml/data/docs/uaf/docs_17_20/DFFT.py +1 -1
  36. teradataml/data/docs/uaf/docs_17_20/DFFT2.py +1 -1
  37. teradataml/data/docs/uaf/docs_17_20/DFFT2Conv.py +1 -1
  38. teradataml/data/docs/uaf/docs_17_20/DFFTConv.py +1 -1
  39. teradataml/data/docs/uaf/docs_17_20/FilterFactory1d.py +4 -4
  40. teradataml/data/docs/uaf/docs_17_20/GenseriesSinusoids.py +2 -2
  41. teradataml/data/docs/uaf/docs_17_20/GoldfeldQuandt.py +2 -2
  42. teradataml/data/docs/uaf/docs_17_20/HoltWintersForecaster.py +6 -6
  43. teradataml/data/docs/uaf/docs_17_20/LineSpec.py +1 -1
  44. teradataml/data/docs/uaf/docs_17_20/LinearRegr.py +1 -1
  45. teradataml/data/docs/uaf/docs_17_20/Matrix2Image.py +4 -4
  46. teradataml/data/docs/uaf/docs_17_20/MultivarRegr.py +1 -1
  47. teradataml/data/docs/uaf/docs_17_20/PACF.py +1 -1
  48. teradataml/data/docs/uaf/docs_17_20/PowerSpec.py +2 -2
  49. teradataml/data/docs/uaf/docs_17_20/PowerTransform.py +3 -3
  50. teradataml/data/docs/uaf/docs_17_20/Resample.py +5 -5
  51. teradataml/data/docs/uaf/docs_17_20/SAX.py +3 -3
  52. teradataml/data/docs/uaf/docs_17_20/SignifPeriodicities.py +1 -1
  53. teradataml/data/docs/uaf/docs_17_20/SimpleExp.py +1 -1
  54. teradataml/data/docs/uaf/docs_17_20/Smoothma.py +3 -3
  55. teradataml/data/docs/uaf/docs_17_20/UNDIFF.py +1 -1
  56. teradataml/data/jsons/byom/onnxembeddings.json +1 -0
  57. teradataml/data/jsons/sqle/17.20/NGramSplitter.json +6 -6
  58. teradataml/data/jsons/sqle/17.20/TD_Apriori.json +181 -0
  59. teradataml/data/jsons/sqle/17.20/TD_NERExtractor.json +145 -0
  60. teradataml/data/jsons/sqle/17.20/TD_SMOTE.json +267 -0
  61. teradataml/data/jsons/sqle/17.20/TD_TextMorph.json +134 -0
  62. teradataml/data/jsons/sqle/17.20/TD_TextParser.json +114 -9
  63. teradataml/data/jsons/sqle/20.00/AI_AnalyzeSentiment.json +328 -0
  64. teradataml/data/jsons/sqle/20.00/AI_AskLLM.json +420 -0
  65. teradataml/data/jsons/sqle/20.00/AI_DetectLanguage.json +343 -0
  66. teradataml/data/jsons/sqle/20.00/AI_ExtractKeyPhrases.json +328 -0
  67. teradataml/data/jsons/sqle/20.00/AI_MaskPII.json +328 -0
  68. teradataml/data/jsons/sqle/20.00/AI_RecognizeEntities.json +328 -0
  69. teradataml/data/jsons/sqle/20.00/AI_RecognizePIIEntities.json +328 -0
  70. teradataml/data/jsons/sqle/20.00/AI_TextClassifier.json +359 -0
  71. teradataml/data/jsons/sqle/20.00/AI_TextEmbeddings.json +360 -0
  72. teradataml/data/jsons/sqle/20.00/AI_TextSummarize.json +343 -0
  73. teradataml/data/jsons/sqle/20.00/AI_TextTranslate.json +343 -0
  74. teradataml/data/jsons/sqle/20.00/TD_SMOTE.json +2 -2
  75. teradataml/data/jsons/sqle/20.00/TD_VectorDistance.json +1 -1
  76. teradataml/data/ner_dict.csv +8 -0
  77. teradataml/data/ner_input_eng.csv +7 -0
  78. teradataml/data/ner_rule.csv +5 -0
  79. teradataml/data/pattern_matching_data.csv +11 -0
  80. teradataml/data/pos_input.csv +40 -0
  81. teradataml/data/sdk/modelops/modelops_spec.json +101737 -0
  82. teradataml/data/tdnerextractor_example.json +14 -0
  83. teradataml/data/teradataml_example.json +21 -1
  84. teradataml/data/textmorph_example.json +5 -0
  85. teradataml/data/to_num_data.csv +4 -0
  86. teradataml/data/tochar_data.csv +5 -0
  87. teradataml/data/trans_dense.csv +16 -0
  88. teradataml/data/trans_sparse.csv +55 -0
  89. teradataml/data/url_data.csv +10 -9
  90. teradataml/dataframe/copy_to.py +38 -27
  91. teradataml/dataframe/data_transfer.py +61 -45
  92. teradataml/dataframe/dataframe.py +1110 -132
  93. teradataml/dataframe/dataframe_utils.py +73 -27
  94. teradataml/dataframe/functions.py +1070 -9
  95. teradataml/dataframe/sql.py +750 -959
  96. teradataml/dbutils/dbutils.py +33 -13
  97. teradataml/dbutils/filemgr.py +14 -10
  98. teradataml/hyperparameter_tuner/utils.py +4 -2
  99. teradataml/lib/aed_0_1.dll +0 -0
  100. teradataml/opensource/_base.py +12 -157
  101. teradataml/options/configure.py +24 -9
  102. teradataml/scriptmgmt/UserEnv.py +317 -39
  103. teradataml/scriptmgmt/lls_utils.py +456 -135
  104. teradataml/sdk/README.md +79 -0
  105. teradataml/sdk/__init__.py +4 -0
  106. teradataml/sdk/_auth_modes.py +422 -0
  107. teradataml/sdk/_func_params.py +487 -0
  108. teradataml/sdk/_json_parser.py +453 -0
  109. teradataml/sdk/_openapi_spec_constants.py +249 -0
  110. teradataml/sdk/_utils.py +236 -0
  111. teradataml/sdk/api_client.py +897 -0
  112. teradataml/sdk/constants.py +62 -0
  113. teradataml/sdk/modelops/__init__.py +98 -0
  114. teradataml/sdk/modelops/_client.py +406 -0
  115. teradataml/sdk/modelops/_constants.py +304 -0
  116. teradataml/sdk/modelops/models.py +2308 -0
  117. teradataml/sdk/spinner.py +107 -0
  118. teradataml/store/__init__.py +1 -1
  119. teradataml/table_operators/Apply.py +16 -1
  120. teradataml/table_operators/Script.py +20 -1
  121. teradataml/table_operators/query_generator.py +4 -21
  122. teradataml/table_operators/table_operator_util.py +58 -9
  123. teradataml/utils/dtypes.py +4 -2
  124. teradataml/utils/internal_buffer.py +22 -2
  125. teradataml/utils/utils.py +0 -1
  126. teradataml/utils/validators.py +318 -58
  127. {teradataml-20.0.0.4.dist-info → teradataml-20.0.0.6.dist-info}/METADATA +188 -14
  128. {teradataml-20.0.0.4.dist-info → teradataml-20.0.0.6.dist-info}/RECORD +131 -84
  129. {teradataml-20.0.0.4.dist-info → teradataml-20.0.0.6.dist-info}/WHEEL +0 -0
  130. {teradataml-20.0.0.4.dist-info → teradataml-20.0.0.6.dist-info}/top_level.txt +0 -0
  131. {teradataml-20.0.0.4.dist-info → teradataml-20.0.0.6.dist-info}/zip-safe +0 -0
@@ -28,13 +28,16 @@ def skip_validation():
28
28
  def validation_func(): ...
29
29
 
30
30
  """
31
+
31
32
  def decorator(func):
32
33
  def wrapper(*args, **kwargs):
33
34
  # If "skip_all" flag is set to False,
34
35
  # skip all validation execution.
35
36
  if not _Validators.skip_all:
36
37
  return func(*args, **kwargs)
38
+
37
39
  return wraps(func)(wrapper)
40
+
38
41
  return decorator
39
42
 
40
43
 
@@ -90,13 +93,17 @@ class _Validators:
90
93
  type_as_str.append(typ1.__name__)
91
94
  elif isinstance(typ, (_ListOf, _TupleOf)):
92
95
  type_as_str.append(str(typ))
96
+ elif typ is pd.DataFrame:
97
+ type_as_str.append("pandas DataFrame")
93
98
  elif typ.__name__ == "DataFrame":
94
99
  type_as_str.append("teradataml DataFrame")
95
100
  else:
96
101
  type_as_str.append(typ.__name__)
97
102
 
98
103
  if isinstance(type_list, type):
99
- if type_list.__name__ == "DataFrame":
104
+ if type_list is pd.DataFrame:
105
+ type_as_str.append("pandas DataFrame")
106
+ elif type_list.__name__ == "DataFrame":
100
107
  type_as_str.append("teradataml DataFrame")
101
108
  else:
102
109
  type_as_str.append(type_list.__name__)
@@ -286,7 +293,7 @@ class _Validators:
286
293
 
287
294
  @staticmethod
288
295
  @skip_validation()
289
- def _validate_dataframe_has_argument_columns(columns, column_arg, data, data_arg, is_partition_arg=False,
296
+ def _validate_dataframe_has_argument_columns(columns, column_arg, data, data_arg, is_partition_arg=False,
290
297
  case_insensitive=False):
291
298
  """
292
299
  Function to check whether column names in columns are present in given dataframe or not.
@@ -346,7 +353,7 @@ class _Validators:
346
353
  columns = [columns]
347
354
 
348
355
  total_columns = []
349
-
356
+
350
357
  for column in columns:
351
358
  for separator in TeradataConstants.RANGE_SEPARATORS.value:
352
359
  if column is None:
@@ -365,33 +372,33 @@ class _Validators:
365
372
  # ':' specifies all columns in the table.
366
373
 
367
374
  try:
368
- # Check if its a sinlge column with one separator. For e.g. column:A.
375
+ # Check if it's a single column with one separator. For e.g. column:A.
369
376
  # If yes, just continue.
370
- _Validators._validate_column_exists_in_dataframe(column, data._metaexpr, case_insensitive=case_insensitive)
377
+ _Validators._validate_column_exists_in_dataframe(column, data._metaexpr,
378
+ case_insensitive=case_insensitive)
371
379
  continue
372
380
  except:
373
381
  # User has provided range value.
374
382
  column_names = column.split(separator)
375
383
  if (len(column_names) == 2 and
376
- any([column_names[0].isdigit(), column_names[1].isdigit()]) and
377
- not all([column_names[0].isdigit(), column_names[1].isdigit()]) and
378
- not "" in column_names):
379
- # Raises Exception if column range has mixed types. For e.g. "4:XYZ".
380
- err_msg = Messages.get_message(MessageCodes.MIXED_TYPES_IN_COLUMN_RANGE)
381
- raise ValueError(err_msg.format(column_arg))
382
-
384
+ any([column_names[0].isdigit(), column_names[1].isdigit()]) and
385
+ not all([column_names[0].isdigit(), column_names[1].isdigit()]) and
386
+ not "" in column_names):
387
+ # Raises Exception if column range has mixed types. For e.g. "4:XYZ".
388
+ err_msg = Messages.get_message(MessageCodes.MIXED_TYPES_IN_COLUMN_RANGE)
389
+ raise ValueError(err_msg.format(column_arg))
390
+
383
391
  for col in column_names:
384
392
  if not col.isdigit() and col != "":
385
393
  total_columns.append(col)
386
394
 
387
395
  elif column.count(separator) > 1:
388
- continue
396
+ continue
389
397
  else:
390
398
  total_columns.append(column)
391
399
 
392
400
  return _Validators._validate_column_exists_in_dataframe(total_columns, data._metaexpr, column_arg=column_arg,
393
401
  data_arg=data_arg, case_insensitive=case_insensitive)
394
-
395
402
 
396
403
  @staticmethod
397
404
  @skip_validation()
@@ -455,9 +462,9 @@ class _Validators:
455
462
  if isinstance(columns, str):
456
463
  columns = [columns]
457
464
 
458
- # Constructing New unquotted column names for selected columns ONLY using Parent _metaexpr
465
+ # Constructing New unquoted column names for selected columns ONLY using Parent _metaexpr
459
466
  if case_insensitive:
460
- # If lookup has to be a case insensitive then convert the
467
+ # If lookup has to be a case-insensitive then convert the
461
468
  # metaexpr columns name to lower case.
462
469
  unquoted_df_columns = [c.name.replace('"', "").lower() for c in metaexpr.c]
463
470
  else:
@@ -468,13 +475,10 @@ class _Validators:
468
475
  if column_name is None:
469
476
  column_name = str(column_name)
470
477
 
471
- if case_insensitive:
472
- # If lookup has to be a case insensitive then convert the
473
- # column name to lower case.
474
- column_name = column_name.lower()
478
+ case_based_column_name = column_name.lower() if case_insensitive else column_name
475
479
 
476
480
  # If column name does not exist in metaexpr, raise the exception
477
- if not column_name.replace('"', "") in unquoted_df_columns:
481
+ if not case_based_column_name.replace('"', "") in unquoted_df_columns:
478
482
  if column_arg and data_arg:
479
483
  raise ValueError(Messages.get_message(MessageCodes.TDMLDF_COLUMN_IN_ARG_NOT_FOUND,
480
484
  column_name,
@@ -483,7 +487,8 @@ class _Validators:
483
487
  "Table" if for_table else "DataFrame"))
484
488
  else:
485
489
  raise ValueError(Messages.get_message(MessageCodes.TDMLDF_DROP_INVALID_COL,
486
- column_name, sorted(unquoted_df_columns)))
490
+ column_name,
491
+ sorted([c.name.replace('"', "") for c in metaexpr.c])))
487
492
 
488
493
  return True
489
494
 
@@ -518,7 +523,7 @@ class _Validators:
518
523
 
519
524
  @staticmethod
520
525
  @skip_validation()
521
- def _validate_function_arguments(arg_list, skip_empty_check = None):
526
+ def _validate_function_arguments(arg_list, skip_empty_check=None):
522
527
  """
523
528
  Method to verify that the input arguments are of valid data type except for
524
529
  argument of DataFrameType.
@@ -543,10 +548,29 @@ class _Validators:
543
548
  EXAMPLES:
544
549
  _Validators._validate_function_arguments(arg_list)
545
550
  """
551
+ # arg_list is list of list, where each inner list can have maximum 6 elements
552
+ # and must have minimum (first) 4 elements:
553
+ # Consider following inner list.
554
+ # [element1, element2, element3, element4, element5, element6]
555
+ # Corresponds to:
556
+ # [<1_arg_name>, <2_arg_value>, <3_is_optional>, <4_tuple_of_accepted_types>,
557
+ # <5_empty_not_allowed>, <6_list_of_permitted_values>]
558
+ # e.g.
559
+ # arg_list = [["join", join, True, (str), True, concat_join_permitted_values]]
560
+ # 1. element1 --> Argument Name, a string. ["join" in above example.]
561
+ # 2. element2 --> Argument itself. [join]
562
+ # 3. element3 --> Specifies a flag that mentions if argument is optional or not.
563
+ # False means required argument and True means optional argument.
564
+ # 4. element4 --> Tuple of accepted types. (str) in above example.
565
+ # 5. element5 --> True, means validate for empty value. Error will be raised, if empty values are passed.
566
+ # If not specified, argument value will not be validated for empty value.
567
+ # 6. element6 --> A list of permitted values, an argument can accept.
568
+ # If not specified, argument value will not be validated against any permitted values.
569
+ # If a list is passed, validation will be performed for permitted values.
546
570
  invalid_arg_names = []
547
571
  invalid_arg_types = []
548
572
 
549
- typeCheckFailed = False
573
+ type_check_failed = False
550
574
 
551
575
  for args in arg_list:
552
576
  num_args = len(args)
@@ -569,7 +593,7 @@ class _Validators:
569
593
  # Let's validate argument types.
570
594
  #
571
595
  # Verify datatypes for arguments which are required or the optional arguments are not None
572
- if ((args[2] == True and args[1] is not None) or (args[2] == False)):
596
+ if (args[2] == True and args[1] is not None) or (args[2] == False):
573
597
  # Validate the types of argument, if expected types are instance of tuple or type
574
598
  dtype_list = _Validators.__getTypeAsStr(args[3])
575
599
 
@@ -586,13 +610,13 @@ class _Validators:
586
610
  if not _Validators._check_isinstance(value, args[3]):
587
611
  invalid_arg_names.append(args[0])
588
612
  invalid_arg_types.append(valid_types_str)
589
- typeCheckFailed = True
613
+ type_check_failed = True
590
614
  break
591
615
  elif not _Validators._check_isinstance(args[1], args[3]):
592
616
  # Argument is not of type list.
593
617
  invalid_arg_names.append(args[0])
594
618
  invalid_arg_types.append(valid_types_str)
595
- typeCheckFailed = True
619
+ type_check_failed = True
596
620
 
597
621
  elif isinstance(args[3], tuple):
598
622
  # Argument can accept values of multiple types, but not list.
@@ -600,30 +624,30 @@ class _Validators:
600
624
  if not _Validators._check_isinstance(args[1], args[3]):
601
625
  invalid_arg_names.append(args[0])
602
626
  invalid_arg_types.append(valid_types_str)
603
- typeCheckFailed = True
627
+ type_check_failed = True
604
628
  else:
605
629
  # Argument can accept values of single type.
606
630
  valid_types_str = " or ".join(dtype_list)
607
631
  if not _Validators._check_isinstance(args[1], args[3]):
608
632
  invalid_arg_names.append(args[0])
609
633
  invalid_arg_types.append(valid_types_str)
610
- typeCheckFailed = True
634
+ type_check_failed = True
611
635
 
612
636
  #
613
637
  # Validate the arguments for empty value
614
638
  #
615
- if not typeCheckFailed and len(args) >= 5:
639
+ if not type_check_failed and len(args) >= 5:
616
640
  if args[4]:
617
641
  _Validators._validate_input_columns_not_empty(args[1], args[0], skip_empty_check)
618
642
 
619
643
  #
620
644
  # Validate the arguments for permitted values
621
645
  #
622
- if not typeCheckFailed and len(args) >= 6:
646
+ if not type_check_failed and len(args) >= 6:
623
647
  if args[5] is not None:
624
648
  _Validators._validate_permitted_values(args[1], args[5], args[0], supported_types=args[3])
625
649
 
626
- if typeCheckFailed:
650
+ if type_check_failed:
627
651
  if len(invalid_arg_names) != 0:
628
652
  raise TypeError(Messages.get_message(MessageCodes.UNSUPPORTED_DATATYPE,
629
653
  invalid_arg_names, invalid_arg_types))
@@ -632,7 +656,7 @@ class _Validators:
632
656
 
633
657
  @staticmethod
634
658
  @skip_validation()
635
- def _validate_input_columns_not_empty(arg, arg_name, skip_empty_check = None):
659
+ def _validate_input_columns_not_empty(arg, arg_name, skip_empty_check=None):
636
660
  """
637
661
  Function to check whether argument is empty string or not.
638
662
 
@@ -664,7 +688,7 @@ class _Validators:
664
688
  for col in arg:
665
689
  if not (skip_empty_check and arg_name in skip_empty_check.keys() and col in skip_empty_check[arg_name]):
666
690
  if isinstance(col, str):
667
- if (not (col is None) and ((len(col.strip()) == 0))):
691
+ if (not (col is None)) and (len(col.strip()) == 0):
668
692
  raise ValueError(Messages.get_message(MessageCodes.ARG_EMPTY, arg_name))
669
693
  return True
670
694
 
@@ -704,8 +728,8 @@ class _Validators:
704
728
  if args[2] == False and args[1] is None:
705
729
  miss_args.append(args[0])
706
730
 
707
- if (len(miss_args)>0):
708
- raise TeradataMlException(Messages.get_message(MessageCodes.MISSING_ARGS,miss_args),
731
+ if len(miss_args) > 0:
732
+ raise TeradataMlException(Messages.get_message(MessageCodes.MISSING_ARGS, miss_args),
709
733
  MessageCodes.MISSING_ARGS)
710
734
  return True
711
735
 
@@ -813,7 +837,7 @@ class _Validators:
813
837
  invalid_values.sort()
814
838
 
815
839
  # Concatenate the message for datatypes not present in datatypes of permitted_values.
816
- if len(add_types) > 0 :
840
+ if len(add_types) > 0:
817
841
  add_types = _Validators.__getTypeAsStr(add_types)
818
842
  add_types = " or ".join(add_types)
819
843
  permitted_values = "{} {}".format(permitted_values, "or any values of type {}".format(add_types))
@@ -978,7 +1002,7 @@ class _Validators:
978
1002
  return True
979
1003
 
980
1004
  is_arg_in_lower_bound, is_arg_in_upper_bound = True, True
981
- lbound_msg, ubound_msg = "", ""
1005
+ lbound_msg, ubound_msg = "", ""
982
1006
 
983
1007
  # Check for lower bound.
984
1008
  if lbound is not None:
@@ -1071,7 +1095,7 @@ class _Validators:
1071
1095
  if timebucket_duration is None:
1072
1096
  return True
1073
1097
 
1074
- # Check if notation if formal or shorthand (beginning with a digit)
1098
+ # Check if notation is formal or shorthand (beginning with a digit)
1075
1099
  if timebucket_duration[0].isdigit():
1076
1100
  valid_timebucket_durations = PTITableConstants.VALID_TIMEBUCKET_DURATIONS_SHORTHAND.value
1077
1101
  pattern_to_use = PTITableConstants.PATTERN_TIMEBUCKET_DURATION_SHORT.value
@@ -1099,7 +1123,7 @@ class _Validators:
1099
1123
 
1100
1124
  @staticmethod
1101
1125
  @skip_validation()
1102
- def _validate_column_type(df, col, col_arg, expected_types, raiseError = True):
1126
+ def _validate_column_type(df, col, col_arg, expected_types, raiseError=True):
1103
1127
  """
1104
1128
  Internal function to validate the type of an input DataFrame column against
1105
1129
  a list of expected types.
@@ -1123,7 +1147,7 @@ class _Validators:
1123
1147
 
1124
1148
  expected_types:
1125
1149
  Required Argument.
1126
- Specifies a list of teradatasqlachemy datatypes that the column is
1150
+ Specifies a list of teradatasqlalchemy datatypes that the column is
1127
1151
  expected to be of type.
1128
1152
  Types: list of teradatasqlalchemy types
1129
1153
 
@@ -1134,10 +1158,10 @@ class _Validators:
1134
1158
  Types: bool
1135
1159
 
1136
1160
  RETURNS:
1137
- True, when the columns is of an expected type.
1161
+ True, when the column is of an expected type.
1138
1162
 
1139
1163
  RAISES:
1140
- TeradataMlException, when the columns is not one of the expected types.
1164
+ TeradataMlException, when the column is not one of the expected types.
1141
1165
 
1142
1166
  EXAMPLES:
1143
1167
  _Validators._validate_column_type(df, timecode_column, 'timecode_column', PTITableConstants.VALID_TIMECODE_DATATYPES)
@@ -1405,6 +1429,155 @@ class _Validators:
1405
1429
  err_disp_arg2_name), MessageCodes.EITHER_THIS_OR_THAT_ARGUMENT)
1406
1430
  return True
1407
1431
 
1432
+ @staticmethod
1433
+ @skip_validation()
1434
+ def _validate_mutually_exclusive_argument_groups(*arg_groups, all_falsy_check=False,
1435
+ return_all_falsy_status=False):
1436
+ """
1437
+ DESCRIPTION:
1438
+ Function to validate mutual exclusiveness of group of arguments.
1439
+
1440
+ PARAMETERS:
1441
+ *arg_groups:
1442
+ Specifies variable length argument list where each argument in list is a dictionary
1443
+ representing one group of arguments which should be mutually exclusive from
1444
+ other groups of arguments. Each dictionary contains key-value pairs for argument
1445
+ name and its value.
1446
+
1447
+ all_falsy_check:
1448
+ Optional Argument.
1449
+ Specifies whether to throw Teradataml Exception when all arguments in all argument
1450
+ groups hold Falsy/null values.
1451
+ Types: bool
1452
+
1453
+ return_all_falsy_status:
1454
+ Optional Argument.
1455
+ Specifies whether to return the boolean flag which states if all arguments in all argument
1456
+ groups hold Falsy/null values.
1457
+ Types: bool
1458
+
1459
+ RETURNS:
1460
+ * When "return_all_falsy_status" is True:
1461
+ * True: If all arguments in all argument groups hold Falsy/null values.
1462
+ * False: If all arguments in all argument groups do not hold Falsy/null values.
1463
+ * When "return_all_falsy_status" is False:
1464
+ None
1465
+ RAISES:
1466
+ TeradataMLException
1467
+
1468
+ EXAMPLES:
1469
+ # Example 1: When groups of arguments are not mutually exclusive.
1470
+ >>> _Validators._validate_mutually_exclusive_argument_groups({"arg1": "arg1"},
1471
+ ... {"arg2": "arg2"},
1472
+ ... {"arg3": "arg3", "arg4": "arg4"})
1473
+ [Teradata][teradataml](TDML_2061) Provide either '['arg1']' argument(s) or '['arg2']' argument(s) or '['arg3', 'arg4']' argument(s).
1474
+
1475
+ # Example 2: When groups of arguments are mutually exclusive.
1476
+ >>> _Validators._validate_mutually_exclusive_argument_groups({"arg1": None},
1477
+ ... {"arg2": ""},
1478
+ ... {"arg3": "arg3", "arg4": "arg4"})
1479
+
1480
+ # Example 3: When all groups of arguments hold falsy values
1481
+ # and "all_falsy_check" is set to True.
1482
+ >>> _Validators._validate_mutually_exclusive_argument_groups({"arg1": None},
1483
+ ... {"arg2": None},
1484
+ ... {"arg3": None, "arg4": None},
1485
+ ... all_falsy_check=True)
1486
+ [Teradata][teradataml](TDML_2061) Provide either '['arg1']' argument(s) or '['arg2']' argument(s) or '['arg3', 'arg4']' argument(s).
1487
+
1488
+ # Example 4: When all groups of arguments hold falsy values
1489
+ # and "all_falsy_check" is set to False.
1490
+ >>> _Validators._validate_mutually_exclusive_argument_groups({"arg1": None},
1491
+ ... {"arg2": None},
1492
+ ... {"arg3": None, "arg4": None})
1493
+
1494
+ # Example 5: When all groups of arguments hold falsy values
1495
+ # and "all_falsy_check" is set to False and
1496
+ # "return_all_falsy_status" is set to True.
1497
+ >>> _Validators._validate_mutually_exclusive_argument_groups({"arg1": None},
1498
+ ... {"arg2": None},
1499
+ ... {"arg3": None, "arg4": None},
1500
+ ... return_all_falsy_status=True)
1501
+ True
1502
+ """
1503
+ all_groups_falsy = True
1504
+ mutually_exclusive_groups = True
1505
+ non_falsy_groups = []
1506
+ for arg_grp in arg_groups:
1507
+ # TODO: Handling of falsy values can be done in more appropriate way by
1508
+ # differentiating None/empty string/empty list.
1509
+ is_group_falsy = not any(value for value in arg_grp.values())
1510
+ if not is_group_falsy:
1511
+ non_falsy_groups.append(arg_grp)
1512
+
1513
+ # Current group is having non-falsy values and already traversed
1514
+ # group(s) also has(have) non-falsy values. So set "mutually_exclusive_groups" to False.
1515
+ if not all_groups_falsy:
1516
+ mutually_exclusive_groups = False
1517
+
1518
+ all_groups_falsy = all_groups_falsy and is_group_falsy
1519
+
1520
+ # Raise error if any one of the below-mentioned conditions is True:
1521
+ # More than one group has non-falsy values.
1522
+ # All groups have all falsy values and "all_falsy_check" is True.
1523
+ if not mutually_exclusive_groups or (all_falsy_check and all_groups_falsy):
1524
+ if not non_falsy_groups:
1525
+ non_falsy_groups = [str(list(arg_grp.keys())) for arg_grp in arg_groups]
1526
+ else:
1527
+ non_falsy_groups = [str(list(non_falsy_group.keys())) for non_falsy_group in non_falsy_groups]
1528
+ error_msg = Messages.get_message(
1529
+ MessageCodes.EITHER_THIS_OR_THAT_ARGUMENT, str(non_falsy_groups[0]),
1530
+ "' argument(s) or \'".join(non_falsy_groups[1:]))
1531
+
1532
+ raise TeradataMlException(error_msg, MessageCodes.EITHER_THIS_OR_THAT_ARGUMENT)
1533
+
1534
+ if return_all_falsy_status:
1535
+ return all_groups_falsy
1536
+
1537
+ @staticmethod
1538
+ @skip_validation()
1539
+ def _validate_mutually_inclusive_n_arguments(**kwargs):
1540
+ """
1541
+ DESCRIPTION:
1542
+ Function to validate mutual inclusiveness of group of arguments.
1543
+
1544
+ PARAMETERS:
1545
+ **kwargs:
1546
+ Specifies variable number of keyword arguments which are to be
1547
+ validated for mutual inclusiveness.
1548
+
1549
+ RETURNS:
1550
+ True, if arguments are mutually inclusive.
1551
+
1552
+ RAISES:
1553
+ TeradataMLException
1554
+
1555
+ EXAMPLES:
1556
+ Example 1: When all arguments have non-None values.
1557
+ >>> _Validators._validate_mutually_inclusive_n_arguments(arg1="arg1", arg2="arg2",
1558
+ ... arg3="arg3", arg4="arg4")
1559
+ True
1560
+
1561
+ Example 2: When one of the arguments is empty string.
1562
+ >>> _Validators._validate_mutually_inclusive_n_arguments(arg1="arg1", arg2="arg2",
1563
+ ... arg3="arg3", arg4="")
1564
+ TeradataMlException
1565
+
1566
+ Example 3: When one of the arguments is None.
1567
+ >>> _Validators._validate_mutually_inclusive_n_arguments(arg1="arg1", arg2=None,
1568
+ ... arg3="arg3", arg4="arg4")
1569
+ TeradataMlException
1570
+ """
1571
+ # TODO: Handling of falsy values can be done in more appropriate way by
1572
+ # differentiating None/empty string/empty list.
1573
+ if all(arg_value for arg, arg_value in kwargs.items()):
1574
+ return True
1575
+ else:
1576
+ arg_list = list(kwargs.keys())
1577
+ message = Messages.get_message(MessageCodes.MUST_PASS_ARGUMENT,
1578
+ arg_list[0], " and ".join(arg_list[1:]))
1579
+ raise TeradataMlException(message, MessageCodes.MUST_PASS_ARGUMENT)
1580
+
1408
1581
  @staticmethod
1409
1582
  @skip_validation()
1410
1583
  def _validate_unexpected_column_type(df, col, col_arg, unexpected_types, check_exist=True, raise_error=True,
@@ -1557,6 +1730,60 @@ class _Validators:
1557
1730
  raise TeradataMlException(error_msg.replace("(not None)", "as '{}'".format(msg_arg_value)),
1558
1731
  MessageCodes.DEPENDENT_ARGUMENT)
1559
1732
  return True
1733
+
1734
+ @staticmethod
1735
+ @skip_validation()
1736
+ def _validate_dependent_method(dependent_mtd, independent_mtd, independent_mtd_calls):
1737
+ """
1738
+ DESCRIPTION:
1739
+ Function validates if an independent method has been called before a dependent method.
1740
+ Raises an error if the independent method is not called before the dependent method is called,
1741
+ otherwise, returns True.
1742
+
1743
+ PARAMETERS:
1744
+ dependent_mtd:
1745
+ Required Argument.
1746
+ Specifies the name of dependent method.
1747
+ Types: String
1748
+
1749
+ independent_mtd:
1750
+ Required Argument.
1751
+ Specifies the name of independent method.
1752
+ Types: String or List of Strings
1753
+
1754
+ independent_mtd_calls:
1755
+ Required Argument.
1756
+ Specifies the flag to check whether independent method is called or not.
1757
+ Types: bool or List of bool
1758
+
1759
+ RETURNS:
1760
+ True, when the independent method is called before the dependent method.
1761
+
1762
+ RAISES:
1763
+ TeradataMlException, when independent method is not called before the
1764
+ dependent method.
1765
+
1766
+ EXAMPLES:
1767
+ _Validators._validate_dependent_method("dependent_method", "independent_method", False)
1768
+ _Validators._validate_dependent_method("dependent_method", "independent_method", True)
1769
+ _Validators._validate_dependent_method("dependent_method", ["independent_method1", "independent_method2"], [False, False])
1770
+ """
1771
+ # Check if all independent method calls are False
1772
+ independent_mtd_calls = [independent_mtd_calls] \
1773
+ if not isinstance(independent_mtd_calls, list) else independent_mtd_calls
1774
+ all_false = all(not value for value in independent_mtd_calls)
1775
+
1776
+ # Check if any of the independent method is called before dependent method
1777
+ if dependent_mtd and all_false:
1778
+ error_code = MessageCodes.DEPENDENT_METHOD
1779
+
1780
+ if isinstance(independent_mtd, str):
1781
+ independent_mtd = [independent_mtd]
1782
+ independent_mtd = ' or '.join(f"'{item}'" for item in independent_mtd)
1783
+
1784
+ error_msg = Messages.get_message(error_code, independent_mtd, dependent_mtd)
1785
+ raise TeradataMlException(error_msg, error_code)
1786
+ return True
1560
1787
 
1561
1788
  @staticmethod
1562
1789
  @skip_validation()
@@ -1765,7 +1992,7 @@ class _Validators:
1765
1992
  arg2 = True if arg2 == 0 else bool(arg2)
1766
1993
 
1767
1994
  # Either both the arguments are specified or both are None.
1768
- if not(all([arg1, arg2]) or both_args_none):
1995
+ if not (all([arg1, arg2]) or both_args_none):
1769
1996
  arg_order = [err_disp_arg1_name, err_disp_arg2_name] if arg1 \
1770
1997
  else [err_disp_arg2_name, err_disp_arg1_name]
1771
1998
  raise TeradataMlException(Messages.get_message(
@@ -1802,7 +2029,7 @@ class _Validators:
1802
2029
  _Validators._validate_file_extension("/data/mapper.py",".py")
1803
2030
  _Validators._validate_file_extension("ml__demoenv_requirements_1605727131624097.txt",".txt")
1804
2031
  """
1805
- extension = extension if isinstance(extension, list) else[extension]
2032
+ extension = extension if isinstance(extension, list) else [extension]
1806
2033
  file_extension = file_path.lower().split('.')[-1]
1807
2034
  if file_extension not in extension:
1808
2035
  raise TeradataMlException(
@@ -1811,7 +2038,6 @@ class _Validators:
1811
2038
 
1812
2039
  return True
1813
2040
 
1814
-
1815
2041
  @staticmethod
1816
2042
  @skip_validation()
1817
2043
  def _validate_argument_is_not_None(arg, arg_name, additional_error="", reverse=False):
@@ -1867,7 +2093,6 @@ class _Validators:
1867
2093
  "provided {}".format(additional_error), ""))
1868
2094
  return True
1869
2095
 
1870
-
1871
2096
  @staticmethod
1872
2097
  @skip_validation()
1873
2098
  def _validate_dataframe(df, raise_error=True):
@@ -1912,7 +2137,6 @@ class _Validators:
1912
2137
  raise TeradataMlException(Messages.get_message(MessageCodes.IS_NOT_VALID_DF),
1913
2138
  MessageCodes.IS_NOT_VALID_DF)
1914
2139
 
1915
-
1916
2140
  @staticmethod
1917
2141
  @skip_validation()
1918
2142
  def _validate_column_value_length(argument_name, argument_value, allowed_length,
@@ -1961,11 +2185,10 @@ class _Validators:
1961
2185
  error_msg = Messages.get_message(
1962
2186
  error_code, operation,
1963
2187
  'Length of argument {0} ({1}) is more than the allowed length ({2}).'
1964
- .format(argument_name, len(argument_value), allowed_length))
2188
+ .format(argument_name, len(argument_value), allowed_length))
1965
2189
  raise TeradataMlException(error_msg, error_code)
1966
2190
  return True
1967
2191
 
1968
-
1969
2192
  @staticmethod
1970
2193
  @skip_validation()
1971
2194
  def _validate_list_lengths_equal(list1, arg_name1, list2, arg_name2):
@@ -2149,15 +2372,15 @@ class _Validators:
2149
2372
  err_val = key
2150
2373
  raise ValueError(
2151
2374
  Messages.get_message(MessageCodes.INVALID_DICT_ARG_VALUE, err_val,
2152
- err_str, arg_name, permitted_values))
2153
-
2375
+ err_str, arg_name, permitted_values))
2376
+
2154
2377
  # Catch ValueError raised by '_validate_function_arguments'
2155
2378
  # for empty string value.
2156
2379
  elif "TDML_2004" in str(ve):
2157
2380
  err_str = "Key" if "<dict_key>" in str(ve) else "Value"
2158
2381
  raise ValueError(
2159
2382
  Messages.get_message(MessageCodes.DICT_ARG_KEY_VALUE_EMPTY,
2160
- err_str, arg_name))
2383
+ err_str, arg_name))
2161
2384
 
2162
2385
  except TypeError as te:
2163
2386
  # Catch TypeError raised by '_validate_function_arguments' to
@@ -2173,7 +2396,7 @@ class _Validators:
2173
2396
  kv_type.__name__ for kv_type in permitted_types]
2174
2397
 
2175
2398
  raise TypeError(
2176
- Messages.get_message(MessageCodes.UNSUPPORTED_DICT_KEY_VALUE_DTYPE, err_str,
2399
+ Messages.get_message(MessageCodes.UNSUPPORTED_DICT_KEY_VALUE_DTYPE, err_str,
2177
2400
  arg_name, permitted_types))
2178
2401
 
2179
2402
  return True
@@ -2259,7 +2482,6 @@ class _Validators:
2259
2482
  MessageCodes.IMPORT_PYTHON_PACKAGE)
2260
2483
  return True
2261
2484
 
2262
-
2263
2485
  @staticmethod
2264
2486
  @skip_validation()
2265
2487
  def _validate_ipaddress(ip_address):
@@ -2288,7 +2510,6 @@ class _Validators:
2288
2510
  'of four numbers (each between 0 and 255) separated by periods'))
2289
2511
 
2290
2512
  return True
2291
-
2292
2513
 
2293
2514
  @staticmethod
2294
2515
  @skip_validation()
@@ -2313,11 +2534,11 @@ class _Validators:
2313
2534
  >>> _Validators._check_auth_token("udf")
2314
2535
  """
2315
2536
  if _InternalBuffer.get("auth_token") is None:
2316
- raise TeradataMlException(Messages.get_message(MessageCodes.SET_REQUIRED_PARAMS,\
2537
+ raise TeradataMlException(Messages.get_message(MessageCodes.SET_REQUIRED_PARAMS, \
2317
2538
  'Auth Token', func_name,
2318
2539
  'set_auth_token'),
2319
2540
  MessageCodes.SET_REQUIRED_PARAMS)
2320
-
2541
+
2321
2542
  return True
2322
2543
 
2323
2544
  @staticmethod
@@ -2366,3 +2587,42 @@ class _Validators:
2366
2587
  target_func_name),
2367
2588
  MessageCodes.SET_REQUIRED_PARAMS)
2368
2589
  return True
2590
+
2591
+ @staticmethod
2592
+ def _valid_list_length(arg_value, arg_name, required_length):
2593
+ """
2594
+ DESCRIPTION:
2595
+ Check if the argument has length matching the required length.
2596
+
2597
+ PARAMETERS:
2598
+ arg_value:
2599
+ Required Argument.
2600
+ Specifies the argument value.
2601
+ Types: _ListOf
2602
+
2603
+ arg_name:
2604
+ Required Argument.
2605
+ Specifies the argument name.
2606
+ Types: str
2607
+
2608
+ required_length:
2609
+ Required Argument.
2610
+ Specifies the required list length.
2611
+ Types: int
2612
+
2613
+ RAISES:
2614
+ TeradataMlException
2615
+
2616
+ RETURNS:
2617
+ True.
2618
+
2619
+ EXAMPLES:
2620
+ >>> _Validators._valid_list_length(["udf", "udf1"], "arg_name", 2)
2621
+ """
2622
+ if (isinstance(arg_value, list) and len(arg_value) != required_length) or \
2623
+ (not isinstance(arg_value, list)):
2624
+ raise TeradataMlException(Messages.get_message(
2625
+ MessageCodes.INVALID_LIST_LENGTH).format(arg_name,
2626
+ required_length),
2627
+ MessageCodes.INVALID_LIST_LENGTH)
2628
+ return True