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.

Files changed (96) hide show
  1. teradataml/README.md +210 -0
  2. teradataml/__init__.py +1 -1
  3. teradataml/_version.py +1 -1
  4. teradataml/analytics/analytic_function_executor.py +162 -76
  5. teradataml/analytics/byom/__init__.py +1 -1
  6. teradataml/analytics/json_parser/__init__.py +2 -0
  7. teradataml/analytics/json_parser/analytic_functions_argument.py +95 -2
  8. teradataml/analytics/json_parser/metadata.py +22 -4
  9. teradataml/analytics/sqle/DecisionTreePredict.py +3 -2
  10. teradataml/analytics/sqle/NaiveBayesPredict.py +3 -2
  11. teradataml/analytics/sqle/__init__.py +3 -0
  12. teradataml/analytics/utils.py +4 -1
  13. teradataml/automl/__init__.py +2369 -464
  14. teradataml/automl/autodataprep/__init__.py +15 -0
  15. teradataml/automl/custom_json_utils.py +184 -112
  16. teradataml/automl/data_preparation.py +113 -58
  17. teradataml/automl/data_transformation.py +154 -53
  18. teradataml/automl/feature_engineering.py +113 -53
  19. teradataml/automl/feature_exploration.py +548 -25
  20. teradataml/automl/model_evaluation.py +260 -32
  21. teradataml/automl/model_training.py +399 -206
  22. teradataml/clients/auth_client.py +2 -2
  23. teradataml/common/aed_utils.py +11 -2
  24. teradataml/common/bulk_exposed_utils.py +4 -2
  25. teradataml/common/constants.py +62 -2
  26. teradataml/common/garbagecollector.py +50 -21
  27. teradataml/common/messagecodes.py +47 -2
  28. teradataml/common/messages.py +19 -1
  29. teradataml/common/sqlbundle.py +23 -6
  30. teradataml/common/utils.py +116 -10
  31. teradataml/context/aed_context.py +16 -10
  32. teradataml/data/Employee.csv +5 -0
  33. teradataml/data/Employee_Address.csv +4 -0
  34. teradataml/data/Employee_roles.csv +5 -0
  35. teradataml/data/JulesBelvezeDummyData.csv +100 -0
  36. teradataml/data/byom_example.json +5 -0
  37. teradataml/data/creditcard_data.csv +284618 -0
  38. teradataml/data/docs/byom/docs/ONNXSeq2Seq.py +255 -0
  39. teradataml/data/docs/sqle/docs_17_10/NGramSplitter.py +1 -1
  40. teradataml/data/docs/sqle/docs_17_20/NGramSplitter.py +1 -1
  41. teradataml/data/docs/sqle/docs_17_20/TextParser.py +1 -1
  42. teradataml/data/jsons/byom/ONNXSeq2Seq.json +287 -0
  43. teradataml/data/jsons/sqle/20.00/AI_AnalyzeSentiment.json +3 -7
  44. teradataml/data/jsons/sqle/20.00/AI_AskLLM.json +3 -7
  45. teradataml/data/jsons/sqle/20.00/AI_DetectLanguage.json +3 -7
  46. teradataml/data/jsons/sqle/20.00/AI_ExtractKeyPhrases.json +3 -7
  47. teradataml/data/jsons/sqle/20.00/AI_MaskPII.json +3 -7
  48. teradataml/data/jsons/sqle/20.00/AI_RecognizeEntities.json +3 -7
  49. teradataml/data/jsons/sqle/20.00/AI_RecognizePIIEntities.json +3 -7
  50. teradataml/data/jsons/sqle/20.00/AI_TextClassifier.json +3 -7
  51. teradataml/data/jsons/sqle/20.00/AI_TextEmbeddings.json +3 -7
  52. teradataml/data/jsons/sqle/20.00/AI_TextSummarize.json +3 -7
  53. teradataml/data/jsons/sqle/20.00/AI_TextTranslate.json +3 -7
  54. teradataml/data/jsons/sqle/20.00/TD_API_AzureML.json +151 -0
  55. teradataml/data/jsons/sqle/20.00/TD_API_Sagemaker.json +182 -0
  56. teradataml/data/jsons/sqle/20.00/TD_API_VertexAI.json +183 -0
  57. teradataml/data/load_example_data.py +29 -11
  58. teradataml/data/payment_fraud_dataset.csv +10001 -0
  59. teradataml/data/teradataml_example.json +67 -0
  60. teradataml/dataframe/copy_to.py +714 -54
  61. teradataml/dataframe/dataframe.py +1153 -33
  62. teradataml/dataframe/dataframe_utils.py +8 -3
  63. teradataml/dataframe/functions.py +168 -1
  64. teradataml/dataframe/setop.py +4 -1
  65. teradataml/dataframe/sql.py +141 -9
  66. teradataml/dbutils/dbutils.py +470 -35
  67. teradataml/dbutils/filemgr.py +1 -1
  68. teradataml/hyperparameter_tuner/optimizer.py +456 -142
  69. teradataml/lib/aed_0_1.dll +0 -0
  70. teradataml/lib/libaed_0_1.dylib +0 -0
  71. teradataml/lib/libaed_0_1.so +0 -0
  72. teradataml/lib/libaed_0_1_aarch64.so +0 -0
  73. teradataml/scriptmgmt/UserEnv.py +234 -34
  74. teradataml/scriptmgmt/lls_utils.py +43 -17
  75. teradataml/sdk/_json_parser.py +1 -1
  76. teradataml/sdk/api_client.py +9 -6
  77. teradataml/sdk/modelops/_client.py +3 -0
  78. teradataml/series/series.py +12 -7
  79. teradataml/store/feature_store/constants.py +601 -234
  80. teradataml/store/feature_store/feature_store.py +2886 -616
  81. teradataml/store/feature_store/mind_map.py +639 -0
  82. teradataml/store/feature_store/models.py +5831 -214
  83. teradataml/store/feature_store/utils.py +390 -0
  84. teradataml/table_operators/table_operator_util.py +1 -1
  85. teradataml/table_operators/templates/dataframe_register.template +6 -2
  86. teradataml/table_operators/templates/dataframe_udf.template +6 -2
  87. teradataml/utils/docstring.py +527 -0
  88. teradataml/utils/dtypes.py +93 -0
  89. teradataml/utils/internal_buffer.py +2 -2
  90. teradataml/utils/utils.py +41 -2
  91. teradataml/utils/validators.py +694 -17
  92. {teradataml-20.0.0.6.dist-info → teradataml-20.0.0.7.dist-info}/METADATA +213 -2
  93. {teradataml-20.0.0.6.dist-info → teradataml-20.0.0.7.dist-info}/RECORD +96 -81
  94. {teradataml-20.0.0.6.dist-info → teradataml-20.0.0.7.dist-info}/WHEEL +0 -0
  95. {teradataml-20.0.0.6.dist-info → teradataml-20.0.0.7.dist-info}/top_level.txt +0 -0
  96. {teradataml-20.0.0.6.dist-info → teradataml-20.0.0.7.dist-info}/zip-safe +0 -0
@@ -0,0 +1,390 @@
1
+ """
2
+ Copyright (c) 2025 by Teradata Corporation. All rights reserved.
3
+ TERADATA CORPORATION CONFIDENTIAL AND TRADE SECRET
4
+
5
+ Primary Owner: pradeep.garre@teradata.com
6
+ Secondary Owner: akhil.bhist@teradata.com
7
+
8
+ This file implements the utilities required for Teradata Enterprise Feature Store.
9
+ """
10
+ from teradataml.common.exceptions import TeradataMlException
11
+ from teradataml.common.messagecodes import MessageCodes
12
+ from teradataml.common.messages import Messages
13
+ from teradataml.store.feature_store.constants import EFS_DB_COMPONENTS
14
+ from teradataml.utils.utils import execute_sql
15
+ from collections import defaultdict
16
+
17
+
18
+ class _FSUtils:
19
+ """
20
+ Utility class for Feature Store operations.
21
+ """
22
+
23
+ @staticmethod
24
+ def _get_entities_from_entity_df(df):
25
+ """
26
+ DESCRIPTION:
27
+ Extracts entities from the entity DataFrame.
28
+
29
+ PARAMETERS:
30
+ df:
31
+ Required Argument.
32
+ Specifies the DataFrame containing entity information with
33
+ columns 'entity_name' and 'entity_column'.
34
+ Types: teradataml DataFrame.
35
+
36
+ Returns:
37
+ list: A list of entities.
38
+
39
+ EXAMPLE:
40
+ >>> from teradataml.store.feature_store.utils import _FSUtils
41
+ >>> from teradataml import FeatureStore
42
+ >>> fs = FeatureStore('my_repo')
43
+ >>> df = fs.list_entities()
44
+ >>> entities = _FSUtils._get_entities_from_entity_df(df)
45
+ >>> print(entities)
46
+ [Entity(name='customer', columns=['id', 'name'])]
47
+ """
48
+ from teradataml.store.feature_store.models import Entity
49
+ # Store Entity name vs Columns. One Entity can have multiple columns.
50
+ entity_columns = defaultdict(list)
51
+ for row in df.itertuples():
52
+ entity_columns[row.entity_name].append(row.entity_column)
53
+
54
+ return [Entity(name=name, columns=columns) for name, columns in entity_columns.items()]
55
+
56
+ @staticmethod
57
+ def _get_archived_features_from_catalog(repo, data_domain):
58
+ """
59
+ DESCRIPTION:
60
+ Retrieves archived features from the catalog.
61
+
62
+ PARAMETERS:
63
+ repo:
64
+ Required Argument.
65
+ Specifies the repository name.
66
+ Type: str.
67
+
68
+ data_domain:
69
+ Required Argument.
70
+ Specifies the data domain for which archived features are to be retrieved.
71
+ Type: str.
72
+
73
+ Returns:
74
+ set
75
+
76
+ EXAMPLE:
77
+ >>> from teradataml.store.feature_store.utils import _FSUtils
78
+ >>> archived_features = _FSUtils._get_archived_features_from_catalog('my_repo', 'finance')
79
+ >>> print(archived_features)
80
+ {'feature1', 'feature2', ...}
81
+ """
82
+ features_tbl = EFS_DB_COMPONENTS['feature']
83
+ catalog_tbl = EFS_DB_COMPONENTS['feature_metadata']
84
+
85
+ sql = """
86
+ select name
87
+ from "{repo}"."{feature_tbl}" b, "{repo}"."{catalog}" a
88
+ where a.feature_id = b.id
89
+ and a.data_domain = b.data_domain
90
+ and a.valid_end < current_timestamp
91
+ and a.data_domain = '{data_domain}'
92
+ """.format(
93
+ repo=repo,
94
+ feature_tbl=features_tbl,
95
+ catalog=catalog_tbl,
96
+ data_domain=data_domain
97
+ )
98
+
99
+ return {rec[0] for rec in execute_sql(sql)}
100
+
101
+ @staticmethod
102
+ def _get_open_feature_process(repo, data_domain, process_id):
103
+ """
104
+ DESCRIPTION:
105
+ Retrieves the open feature process for a process id
106
+ in a given repository and data domain.
107
+
108
+ PARAMETERS:
109
+ repo:
110
+ Required Argument.
111
+ Specifies the repository name.
112
+ Type: str.
113
+
114
+ data_domain:
115
+ Required Argument.
116
+ Specifies the data domain for which the open feature process is to be retrieved.
117
+ Type: str.
118
+
119
+ process_id:
120
+ Required Argument.
121
+ Specifies the process ID for which the open feature process is to be retrieved.
122
+ Type: str.
123
+
124
+ Returns:
125
+ dict: A dictionary containing the open feature process details.
126
+
127
+ EXAMPLE:
128
+ >>> from teradataml.store.feature_store.utils import _FSUtils
129
+ >>> open_process = _FSUtils._get_open_feature_process('my_repo', 'finance')
130
+ >>> print(open_process)
131
+ {'process_id': 123, ...}
132
+ """
133
+ sql = """
134
+ CURRENT VALIDTIME
135
+ SELECT PROCESS_TYPE, DATA_SOURCE, ENTITY_ID, FEATURE_NAMES FROM
136
+ "{}"."{}" WHERE
137
+ PROCESS_ID = '{}' AND DATA_DOMAIN = '{}'
138
+ """.format(repo,
139
+ EFS_DB_COMPONENTS['feature_process'],
140
+ process_id, data_domain
141
+ )
142
+
143
+ recs = execute_sql(sql).fetchone()
144
+
145
+ if not recs:
146
+ res = _FSUtils._get_data_domains(repo, process_id, 'feature_process')
147
+ if res:
148
+ msg_code = MessageCodes.EFS_OBJECT_IN_OTHER_DOMAIN
149
+ error_msg = Messages.get_message(msg_code, "Feature process", "id '{}'".\
150
+ format(process_id), data_domain, res)
151
+ else:
152
+ msg_code = MessageCodes.EFS_OBJECT_NOT_EXIST
153
+ error_msg = Messages.get_message(msg_code, "Feature process", "id '{}'".\
154
+ format(process_id), data_domain)
155
+ raise TeradataMlException(error_msg, msg_code)
156
+ return {
157
+ "process_id": process_id,
158
+ "process_type": recs[0],
159
+ "data_source": recs[1],
160
+ "entity_id": recs[2],
161
+ "feature_names": [f.strip() for f in recs[3].split(",")]
162
+ }
163
+
164
+ @staticmethod
165
+ def _is_entity_exists_in_fc(entity_name, repo, data_domain,
166
+ description, columns):
167
+ """
168
+ DESCRIPTION:
169
+ Checks if an entity exists in the Feature Catalog (feature_metadata table).
170
+
171
+ PARAMETERS:
172
+ entity_name:
173
+ Required Argument.
174
+ Specifies the entity name to check for existence.
175
+ Type: str.
176
+
177
+ repo:
178
+ Required Argument.
179
+ Specifies the repository name.
180
+ Type: str.
181
+
182
+ data_domain:
183
+ Required Argument.
184
+ Specifies the data domain for which the entity existence is to be checked.
185
+ Type: str.
186
+
187
+ description:
188
+ Required Argument.
189
+ Specifies the description of the entity.
190
+ Type: str.
191
+
192
+ columns:
193
+ Required Argument.
194
+ Specifies the column names of the entity.
195
+ Type: list of str.
196
+
197
+ Returns:
198
+ str: The existence status of the entity.
199
+
200
+
201
+ EXAMPLE:
202
+ >>> from teradataml.store.feature_store.utils import _FSUtils
203
+ >>> exists = _FSUtils._is_entity_exists_in_fc('e1', 'my_repo', 'finance', 'description', ['col1', 'col2'])
204
+ >>> print(exists)
205
+ "exists"
206
+ """
207
+ # Retrieve entity columns with description for entity name that exists in features_metadata.
208
+ query = """
209
+ SELECT
210
+ entxrf.entity_name,
211
+ entxrf.entity_column,
212
+ ent.description
213
+ FROM "{0}"._efs_entity_xref entxrf
214
+ JOIN "{0}"._efs_entity ent
215
+ ON entxrf.entity_name = ent.name
216
+ AND entxrf.data_domain = ent.data_domain
217
+ WHERE entxrf.data_domain = '{1}'
218
+ AND EXISTS (
219
+ SELECT 1
220
+ FROM "{0}"._efs_features_metadata fm
221
+ WHERE fm.data_domain = entxrf.data_domain
222
+ AND fm.entity_name = entxrf.entity_name
223
+ AND fm.entity_name = '{2}'
224
+ );
225
+ """.format(repo, data_domain, entity_name)
226
+
227
+ records = execute_sql(query).fetchall()
228
+
229
+ # If Records are not found, it means the entity is new and needs to be inserted.
230
+ if not records:
231
+ return "insert"
232
+
233
+ for rec in records:
234
+ # Check if the column or description is different than the existing record
235
+ # If either the column or description is different, return "modify"
236
+ if rec[1] not in columns or rec[2] != description:
237
+ return "modify"
238
+
239
+ # If no changes are found, return "exists"
240
+ return "exists"
241
+
242
+ # Check if an entity exists in the Feature Store (entity table)
243
+ _is_entity_exists_in_fs = staticmethod(
244
+ lambda entity_name, repo, data_domain: _FSUtils._get_count_from_table(
245
+ EFS_DB_COMPONENTS['entity'], repo, data_domain, f"name = '{entity_name}'") > 0
246
+ )
247
+
248
+ # Check if a feature group exists in the Feature Store (feature_group table)
249
+ _is_fg_exists_in_fs = staticmethod(
250
+ lambda fg_name, repo, data_domain: _FSUtils._get_count_from_table(
251
+ EFS_DB_COMPONENTS['feature_group'], repo, data_domain, f"name = '{fg_name}'") > 0
252
+ )
253
+
254
+ # Check if a feature group is referenced in any feature process (feature_process table)
255
+ _is_fg_exists_in_fp = staticmethod(
256
+ lambda fg_name, repo, data_domain: _FSUtils._get_count_from_table(
257
+ EFS_DB_COMPONENTS['feature_process'], repo, data_domain, f"data_source = '{fg_name}' AND process_type='feature group'") > 0
258
+ )
259
+
260
+ @staticmethod
261
+ def _get_count_from_table(table_name, repo, data_domain, condition=None):
262
+ """
263
+ DESCRIPTION:
264
+ Retrieves records count from a specified table in the repository.
265
+
266
+ PARAMETERS:
267
+ table_name:
268
+ Required Argument.
269
+ Specifies the name of the table to retrieve records from.
270
+ Type: str.
271
+
272
+ repo:
273
+ Required Argument.
274
+ Specifies the repository name.
275
+ Type: str.
276
+
277
+ data_domain:
278
+ Required Argument.
279
+ Specifies the data domain for filtering records.
280
+ Type: str.
281
+
282
+ condition:
283
+ Optional Argument.
284
+ Specifies additional conditions for filtering records.
285
+ Type: str.
286
+
287
+ Returns:
288
+ int: The count of records in the specified table.
289
+
290
+ EXAMPLE:
291
+ >>> from teradataml.store.feature_store.utils import _FSUtils
292
+ >>> _FSUtils._get_count_from_table(EFS_DB_COMPONENTS['feature'], 'my_table', 'my_repo')
293
+ 100
294
+ """
295
+ sql = f'SELECT * FROM "{repo}"."{table_name}" WHERE data_domain = \'{data_domain}\''
296
+ if condition:
297
+ sql += f' AND {condition}'
298
+ return execute_sql(sql).rowcount
299
+
300
+ @staticmethod
301
+ def _get_sql_query_for_type(type_):
302
+ """
303
+ DESCRIPTION:
304
+ Gets the SQL query template to retrieve data domains in which an object exists.
305
+
306
+ PARAMETERS:
307
+ type_:
308
+ Required Argument.
309
+ Specifies the type of object to query.
310
+ Permitted Values: 'feature', 'entity', 'data_source', 'feature_group',
311
+ 'group_features', 'feature_process', 'dataset', 'feature_version',
312
+ 'ds_entity'
313
+ Types: str
314
+
315
+ Returns:
316
+ str: SQL query template
317
+
318
+ EXAMPLE:
319
+ >>> from teradataml.store.feature_store.utils import _FSUtils
320
+ >>> sql_template = _FSUtils._get_sql_query_for_type('feature')
321
+ >>> print(sql_template)
322
+ 'SELECT * FROM "{repo}"._efs_features WHERE name = '{object}''
323
+ """
324
+ # Mapping of types to their table names and column names
325
+ table_column_mapping = {
326
+ 'feature': (EFS_DB_COMPONENTS['feature'], 'name'),
327
+ 'entity': (EFS_DB_COMPONENTS['entity'], 'name'),
328
+ 'data_source': (EFS_DB_COMPONENTS['data_source'], 'name'),
329
+ 'feature_group': (EFS_DB_COMPONENTS['feature_group'], 'name'),
330
+ 'group_features': (EFS_DB_COMPONENTS['group_features'], 'group_name'),
331
+ 'feature_process': (EFS_DB_COMPONENTS['feature_process'], 'process_id'),
332
+ 'dataset': (EFS_DB_COMPONENTS['dataset_catalog'], 'id'),
333
+ 'feature_version': (EFS_DB_COMPONENTS['feature_version'], 'feature_version'),
334
+ 'ds_entity': (EFS_DB_COMPONENTS['feature_version'], 'entity_id'),
335
+ }
336
+
337
+ table_name, column_name = table_column_mapping[type_]
338
+ # For group_features, use group_data_domain to fetch the data domain
339
+ domain_column = 'group_data_domain' if type_ == 'group_features' else 'data_domain'
340
+
341
+ return f'SELECT {domain_column} FROM "{{repo}}".{table_name} WHERE {column_name} = \'{{object}}\''
342
+
343
+ @staticmethod
344
+ def _get_data_domains(repo, name, type_):
345
+ """
346
+ DESCRIPTION:
347
+ Get the data domains where an object exists within the specified repository.
348
+
349
+ PARAMETERS:
350
+ repo:
351
+ Required Argument.
352
+ Specifies the repository name.
353
+ Types: str
354
+
355
+ name:
356
+ Required Argument.
357
+ Specifies the name of the object to retrieve information for.
358
+ Types: str
359
+
360
+ type_:
361
+ Required Argument.
362
+ Specifies the type of object to query.
363
+ Permitted Values: 'feature', 'entity', 'data_source', 'feature_group',
364
+ 'group_features', 'feature_process', 'dataset', 'feature_version',
365
+ 'ds_entity'
366
+ Types: str
367
+
368
+ Returns:
369
+ list: A list of data domains where the object exists.
370
+ If the object does not exist, an empty list is returned.
371
+
372
+ EXAMPLE:
373
+ >>> from teradataml.store.feature_store.utils import _FSUtils
374
+ >>> available_domains = _FSUtils._get_data_domains('my_repo', 'feature1', 'feature')
375
+ >>> print(available_domains)
376
+ ['finance', 'marketing']
377
+ """
378
+ # Get SQL query template for the specified type
379
+ sql_template = _FSUtils._get_sql_query_for_type(type_)
380
+
381
+ # Format the SQL query with repo and object
382
+ sql = sql_template.format(repo=repo, object=name)
383
+
384
+ res = execute_sql(sql).fetchall()
385
+ if not res: # Return empty list if no results found
386
+ return []
387
+
388
+ # Get the data domains from the result set.
389
+ available_domains = list(set(rec[0] for rec in res))
390
+ return available_domains
@@ -699,7 +699,7 @@ class _TableOperatorUtils:
699
699
  self.is_printed = True
700
700
  else:
701
701
  GarbageCollector._delete_object_entry(
702
- object_to_delete=self.script_entry,
702
+ objects_to_delete=self.script_entry,
703
703
  object_type=TeradataConstants.TERADATA_SCRIPT,
704
704
  remove_entry_from_gc_list=True
705
705
  )
@@ -2,6 +2,7 @@ import json
2
2
  import sys, csv
3
3
  import datetime
4
4
  import urllib.parse
5
+ import decimal
5
6
 
6
7
  td_buffer = {{}}
7
8
 
@@ -30,7 +31,10 @@ output_type_converters = script_data["output_type_converters"]
30
31
  for k,v in output_type_converters.items():
31
32
  if v == 'datetime.date' or v == 'datetime.time' or v == 'datetime.datetime':
32
33
  output_type_converters[k] = 'str'
33
- output_type_converters = {{k:getattr(__builtins__, v) for k,v in output_type_converters.items()}}
34
+ output_type_converters = {{
35
+ k: (decimal.Decimal if v == 'decimal.Decimal' else getattr(__builtins__, v))
36
+ for k, v in output_type_converters.items()
37
+ }}
34
38
 
35
39
 
36
40
 
@@ -57,7 +61,7 @@ if __name__ == "__main__":
57
61
  else:
58
62
  arg = output_type_converters.get(v)(record[v])
59
63
  else:
60
- arg = record[v]
64
+ arg = record[v] if c_type_.__name__ == 'str' else None
61
65
  else:
62
66
  arg = v
63
67
  f_args = f_args + (arg, )
@@ -1,5 +1,6 @@
1
1
  import sys, csv
2
2
  import datetime
3
+ import decimal
3
4
 
4
5
  td_buffer = {{}}
5
6
 
@@ -21,7 +22,10 @@ output_type_converters = {OUTPUT_TYPE_CONVERTERS}
21
22
  for k,v in output_type_converters.items():
22
23
  if v == 'datetime.date' or v == 'datetime.time' or v == 'datetime.datetime':
23
24
  output_type_converters[k] = 'str'
24
- output_type_converters = {{k:getattr(__builtins__, v) for k,v in output_type_converters.items()}}
25
+ output_type_converters = {{
26
+ k: (decimal.Decimal if v == 'decimal.Decimal' else getattr(__builtins__, v))
27
+ for k, v in output_type_converters.items()
28
+ }}
25
29
  # The quotechar to use.
26
30
  quotechar = "{QUOTECHAR}"
27
31
  if quotechar == "None":
@@ -51,7 +55,7 @@ if __name__ == "__main__":
51
55
  else:
52
56
  arg = output_type_converters.get(v)(record[v])
53
57
  else:
54
- arg = record[v]
58
+ arg = record[v] if c_type_.__name__ == 'str' else None
55
59
  else:
56
60
  arg = v
57
61
  f_args = f_args + (arg, )