sdv 2.0.0.dev0__tar.gz → 2.0.1.dev0__tar.gz
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.
- {sdv-2.0.0.dev0/sdv.egg-info → sdv-2.0.1.dev0}/PKG-INFO +6 -7
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/pyproject.toml +5 -7
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/__init__.py +1 -1
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/cag/base.py +7 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/cag/programmable_constraint.py +4 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/multi_table/base.py +112 -34
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/sequential/par.py +15 -7
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/single_table/base.py +38 -18
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0/sdv.egg-info}/PKG-INFO +6 -7
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv.egg-info/requires.txt +7 -8
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/LICENSE +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/README.md +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/_utils.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/cag/__init__.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/cag/_errors.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/cag/_utils.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/cag/fixed_combinations.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/cag/fixed_increments.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/cag/inequality.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/cag/one_hot_encoding.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/cag/range.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/data_processing/__init__.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/data_processing/data_processor.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/data_processing/datetime_formatter.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/data_processing/errors.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/data_processing/numerical_formatter.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/data_processing/utils.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/datasets/__init__.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/datasets/_utils.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/datasets/demo.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/datasets/local.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/errors.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/evaluation/__init__.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/evaluation/_visualization.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/evaluation/evaluation.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/evaluation/utils.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/io/__init__.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/io/local/__init__.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/io/local/local.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/logging/__init__.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/logging/logger.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/logging/sdv_logger_config.yml +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/logging/utils.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/metadata/__init__.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/metadata/_single_table.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/metadata/errors.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/metadata/metadata.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/metadata/metadata_upgrader.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/metadata/utils.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/metadata/visualization.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/metrics/__init__.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/metrics/demos.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/metrics/relational.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/metrics/tabular.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/metrics/timeseries.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/multi_table/__init__.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/multi_table/dayz.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/multi_table/hma.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/multi_table/utils.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/sampling/__init__.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/sampling/hierarchical_sampler.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/sampling/independent_sampler.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/sampling/tabular.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/sequential/__init__.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/single_table/__init__.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/single_table/copulagan.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/single_table/copulas.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/single_table/ctgan.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/single_table/dayz.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/single_table/mixins.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/single_table/utils.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/utils/__init__.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/utils/utils.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv/version/__init__.py +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv.egg-info/SOURCES.txt +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv.egg-info/dependency_links.txt +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv.egg-info/entry_points.txt +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/sdv.egg-info/top_level.txt +0 -0
- {sdv-2.0.0.dev0 → sdv-2.0.1.dev0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sdv
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.1.dev0
|
|
4
4
|
Summary: Generate synthetic data for single table, multi table and sequential data
|
|
5
5
|
Author-email: "DataCebo, Inc." <info@sdv.dev>
|
|
6
6
|
License-Expression: BUSL-1.1
|
|
@@ -14,14 +14,13 @@ Classifier: Development Status :: 5 - Production/Stable
|
|
|
14
14
|
Classifier: Intended Audience :: Developers
|
|
15
15
|
Classifier: Natural Language :: English
|
|
16
16
|
Classifier: Programming Language :: Python :: 3
|
|
17
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
18
17
|
Classifier: Programming Language :: Python :: 3.10
|
|
19
18
|
Classifier: Programming Language :: Python :: 3.11
|
|
20
19
|
Classifier: Programming Language :: Python :: 3.12
|
|
21
20
|
Classifier: Programming Language :: Python :: 3.13
|
|
22
21
|
Classifier: Programming Language :: Python :: 3.14
|
|
23
22
|
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
24
|
-
Requires-Python: <3.15,>=3.
|
|
23
|
+
Requires-Python: <3.15,>=3.10
|
|
25
24
|
Description-Content-Type: text/markdown
|
|
26
25
|
License-File: LICENSE
|
|
27
26
|
Requires-Dist: boto3<2.0.0,>=1.28
|
|
@@ -29,8 +28,7 @@ Requires-Dist: botocore<2.0.0,>=1.31
|
|
|
29
28
|
Requires-Dist: cloudpickle>=2.1.0; python_version < "3.14"
|
|
30
29
|
Requires-Dist: cloudpickle>=3.1.1; python_version >= "3.14"
|
|
31
30
|
Requires-Dist: graphviz>=0.13.2
|
|
32
|
-
Requires-Dist: numpy>=1.
|
|
33
|
-
Requires-Dist: numpy>=1.24.0; python_version >= "3.10" and python_version < "3.12"
|
|
31
|
+
Requires-Dist: numpy>=1.24.0; python_version < "3.12"
|
|
34
32
|
Requires-Dist: numpy>=1.26.0; python_version >= "3.12" and python_version < "3.13"
|
|
35
33
|
Requires-Dist: numpy>=2.1.0; python_version >= "3.13" and python_version < "3.14"
|
|
36
34
|
Requires-Dist: numpy>=2.3.2; python_version >= "3.14"
|
|
@@ -46,7 +44,7 @@ Requires-Dist: ctgan>=0.11.1; python_version < "3.14"
|
|
|
46
44
|
Requires-Dist: ctgan>=0.12.0; python_version >= "3.14"
|
|
47
45
|
Requires-Dist: deepecho>=0.7.0; python_version < "3.14"
|
|
48
46
|
Requires-Dist: deepecho>=0.8.0; python_version >= "3.14"
|
|
49
|
-
Requires-Dist: rdt>=2.0.0
|
|
47
|
+
Requires-Dist: rdt>=2.0.0
|
|
50
48
|
Requires-Dist: sdmetrics>=0.32.0
|
|
51
49
|
Requires-Dist: platformdirs>=4.0
|
|
52
50
|
Requires-Dist: pyyaml>=6.0.1
|
|
@@ -64,7 +62,6 @@ Requires-Dist: google-api-python-client; extra == "test"
|
|
|
64
62
|
Requires-Dist: google-auth; extra == "test"
|
|
65
63
|
Requires-Dist: google-auth-oauthlib; extra == "test"
|
|
66
64
|
Requires-Dist: requests; extra == "test"
|
|
67
|
-
Requires-Dist: pyarrow; extra == "test"
|
|
68
65
|
Requires-Dist: gitpython; extra == "test"
|
|
69
66
|
Requires-Dist: slack-sdk<4.0,>=3.23; extra == "test"
|
|
70
67
|
Provides-Extra: pomegranate
|
|
@@ -91,6 +88,8 @@ Requires-Dist: coverage<8,>=4.5.12; extra == "dev"
|
|
|
91
88
|
Requires-Dist: invoke; extra == "dev"
|
|
92
89
|
Provides-Extra: readme
|
|
93
90
|
Requires-Dist: rundoc<0.5,>=0.4.3; extra == "readme"
|
|
91
|
+
Provides-Extra: benchmark
|
|
92
|
+
Requires-Dist: pyarrow; extra == "benchmark"
|
|
94
93
|
Dynamic: license-file
|
|
95
94
|
|
|
96
95
|
<div align="center">
|
|
@@ -7,7 +7,6 @@ classifiers = [
|
|
|
7
7
|
'Intended Audience :: Developers',
|
|
8
8
|
'Natural Language :: English',
|
|
9
9
|
'Programming Language :: Python :: 3',
|
|
10
|
-
'Programming Language :: Python :: 3.9',
|
|
11
10
|
'Programming Language :: Python :: 3.10',
|
|
12
11
|
'Programming Language :: Python :: 3.11',
|
|
13
12
|
'Programming Language :: Python :: 3.12',
|
|
@@ -19,7 +18,7 @@ keywords = ['sdv', 'synthetic-data', 'synthetic-data-generation', 'timeseries',
|
|
|
19
18
|
dynamic = ['version']
|
|
20
19
|
license = 'BUSL-1.1'
|
|
21
20
|
license-files = ['LICENSE']
|
|
22
|
-
requires-python = '>=3.
|
|
21
|
+
requires-python = '>=3.10,<3.15'
|
|
23
22
|
readme = 'README.md'
|
|
24
23
|
dependencies = [
|
|
25
24
|
'boto3>=1.28,<2.0.0',
|
|
@@ -27,8 +26,7 @@ dependencies = [
|
|
|
27
26
|
"cloudpickle>=2.1.0;python_version<'3.14'",
|
|
28
27
|
"cloudpickle>=3.1.1;python_version>='3.14'",
|
|
29
28
|
'graphviz>=0.13.2',
|
|
30
|
-
"numpy>=1.
|
|
31
|
-
"numpy>=1.24.0;python_version>='3.10' and python_version<'3.12'",
|
|
29
|
+
"numpy>=1.24.0;python_version<'3.12'",
|
|
32
30
|
"numpy>=1.26.0;python_version>='3.12' and python_version<'3.13'",
|
|
33
31
|
"numpy>=2.1.0;python_version>='3.13' and python_version<'3.14'",
|
|
34
32
|
"numpy>=2.3.2;python_version>='3.14'",
|
|
@@ -44,7 +42,7 @@ dependencies = [
|
|
|
44
42
|
"ctgan>=0.12.0;python_version>='3.14'",
|
|
45
43
|
"deepecho>=0.7.0;python_version<'3.14'",
|
|
46
44
|
"deepecho>=0.8.0;python_version>='3.14'",
|
|
47
|
-
"rdt>=2.0.0
|
|
45
|
+
"rdt>=2.0.0",
|
|
48
46
|
"sdmetrics>=0.32.0",
|
|
49
47
|
'platformdirs>=4.0',
|
|
50
48
|
'pyyaml>=6.0.1',
|
|
@@ -74,7 +72,6 @@ test = [
|
|
|
74
72
|
'google-auth',
|
|
75
73
|
'google-auth-oauthlib',
|
|
76
74
|
'requests',
|
|
77
|
-
'pyarrow',
|
|
78
75
|
'gitpython',
|
|
79
76
|
'slack-sdk>=3.23,<4.0',
|
|
80
77
|
]
|
|
@@ -113,6 +110,7 @@ dev = [
|
|
|
113
110
|
'invoke'
|
|
114
111
|
]
|
|
115
112
|
readme = ['rundoc>=0.4.3,<0.5',]
|
|
113
|
+
benchmark = ['pyarrow']
|
|
116
114
|
|
|
117
115
|
[tool.setuptools]
|
|
118
116
|
include-package-data = true
|
|
@@ -148,7 +146,7 @@ namespaces = false
|
|
|
148
146
|
version = {attr = 'sdv.__version__'}
|
|
149
147
|
|
|
150
148
|
[tool.bumpversion]
|
|
151
|
-
current_version = "2.0.
|
|
149
|
+
current_version = "2.0.1.dev0"
|
|
152
150
|
parse = '(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)(\.(?P<release>[a-z]+)(?P<candidate>\d+))?'
|
|
153
151
|
serialize = [
|
|
154
152
|
'{major}.{minor}.{patch}.{release}{candidate}',
|
|
@@ -90,8 +90,15 @@ class BaseConstraint:
|
|
|
90
90
|
f'{missing_attrs} are not saved as attributes on the constraint.'
|
|
91
91
|
)
|
|
92
92
|
|
|
93
|
+
if self._is_single_table and getattr(self, '_table_name', None) is not None:
|
|
94
|
+
instanced['table_name'] = self._table_name
|
|
95
|
+
|
|
93
96
|
return {'class_name': self.__class__.__name__, 'parameters': instanced}
|
|
94
97
|
|
|
98
|
+
def to_dict(self):
|
|
99
|
+
"""Return the constraint as a serializable dictionary."""
|
|
100
|
+
return self.get_constraint_dict()
|
|
101
|
+
|
|
95
102
|
@classmethod
|
|
96
103
|
def load_constraint_from_dict(cls, parameters):
|
|
97
104
|
"""Uses the given parameters to recreate an instance of the constraint."""
|
|
@@ -41,6 +41,10 @@ class ProgrammableConstraint:
|
|
|
41
41
|
'parameters': instanced,
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
+
def to_dict(self):
|
|
45
|
+
"""Return the constraint as a serializable dictionary."""
|
|
46
|
+
return self.get_constraint_dict()
|
|
47
|
+
|
|
44
48
|
@classmethod
|
|
45
49
|
def load_constraint_from_dict(cls, parameters):
|
|
46
50
|
"""Uses the given parameters to recreate an instance of the constraint."""
|
|
@@ -574,7 +574,7 @@ class BaseMultiTableSynthesizer:
|
|
|
574
574
|
If ``table_name`` is not present in the metadata.
|
|
575
575
|
"""
|
|
576
576
|
self._validate_table_name(table_name)
|
|
577
|
-
return self._table_synthesizers[table_name].get_transformers()
|
|
577
|
+
return self._table_synthesizers[table_name].get_transformers(table_name=table_name)
|
|
578
578
|
|
|
579
579
|
def update_transformers(self, table_name, column_name_to_transformer):
|
|
580
580
|
"""Update any of the transformers assigned to each of the column names.
|
|
@@ -590,7 +590,9 @@ class BaseMultiTableSynthesizer:
|
|
|
590
590
|
If ``table_name`` is not present in the metadata.
|
|
591
591
|
"""
|
|
592
592
|
self._validate_table_name(table_name)
|
|
593
|
-
self._table_synthesizers[table_name].update_transformers(
|
|
593
|
+
self._table_synthesizers[table_name].update_transformers(
|
|
594
|
+
column_name_to_transformer, table_name=table_name
|
|
595
|
+
)
|
|
594
596
|
|
|
595
597
|
def _store_and_convert_original_cols(self, data):
|
|
596
598
|
list_of_changed_tables = []
|
|
@@ -756,8 +758,8 @@ class BaseMultiTableSynthesizer:
|
|
|
756
758
|
|
|
757
759
|
def _validate_sample_input(
|
|
758
760
|
self,
|
|
759
|
-
table_name,
|
|
760
761
|
num_rows,
|
|
762
|
+
main_table_name,
|
|
761
763
|
batch_size,
|
|
762
764
|
max_tries_per_batch,
|
|
763
765
|
output_folder_path,
|
|
@@ -769,9 +771,17 @@ class BaseMultiTableSynthesizer:
|
|
|
769
771
|
'sampling synthetic data.'
|
|
770
772
|
)
|
|
771
773
|
|
|
774
|
+
if main_table_name is None:
|
|
775
|
+
raise SynthesizerInputError(
|
|
776
|
+
'`main_table_name` cannot be None for multi-table sampling. '
|
|
777
|
+
'Please provide a table name.'
|
|
778
|
+
)
|
|
779
|
+
|
|
772
780
|
table_names = list(self.get_metadata().tables)
|
|
773
|
-
if
|
|
774
|
-
raise SynthesizerInputError(
|
|
781
|
+
if main_table_name not in table_names:
|
|
782
|
+
raise SynthesizerInputError(
|
|
783
|
+
f"Table '{main_table_name}' does not exist in the metadata."
|
|
784
|
+
)
|
|
775
785
|
|
|
776
786
|
_validate_positive_integer('num_rows', num_rows)
|
|
777
787
|
_validate_positive_integer('max_tries_per_batch', max_tries_per_batch)
|
|
@@ -818,35 +828,7 @@ class BaseMultiTableSynthesizer:
|
|
|
818
828
|
|
|
819
829
|
return pd.concat(sampled, ignore_index=True)
|
|
820
830
|
|
|
821
|
-
def
|
|
822
|
-
self,
|
|
823
|
-
table_name,
|
|
824
|
-
num_rows,
|
|
825
|
-
batch_size=None,
|
|
826
|
-
max_tries_per_batch=100,
|
|
827
|
-
output_folder_path=None,
|
|
828
|
-
):
|
|
829
|
-
"""Generate synthetic data for the entire dataset.
|
|
830
|
-
|
|
831
|
-
Args:
|
|
832
|
-
table_name (str):
|
|
833
|
-
The name of the main table to sample.
|
|
834
|
-
num_rows (int):
|
|
835
|
-
The number of rows to sample.
|
|
836
|
-
batch_size (int, optional):
|
|
837
|
-
The batch size for sampling. Defaults to None.
|
|
838
|
-
max_tries_per_batch (int, optional):
|
|
839
|
-
The maximum number of tries per batch. Defaults to 100.
|
|
840
|
-
output_folder_path (str, optional):
|
|
841
|
-
The folder path to save the sampled data. Defaults to None.
|
|
842
|
-
|
|
843
|
-
Returns:
|
|
844
|
-
dict: A dictionary containing the sampled data for each table.
|
|
845
|
-
"""
|
|
846
|
-
self._validate_sample_input(
|
|
847
|
-
table_name, num_rows, batch_size, max_tries_per_batch, output_folder_path
|
|
848
|
-
)
|
|
849
|
-
scale = self._resolve_scale(table_name, num_rows)
|
|
831
|
+
def _sample_from_scale(self, scale, batch_size, max_tries_per_batch, output_folder_path):
|
|
850
832
|
with self._set_temp_numpy_seed(), disable_single_table_logger():
|
|
851
833
|
sampled_data = self._sample(
|
|
852
834
|
scale=scale,
|
|
@@ -878,6 +860,102 @@ class BaseMultiTableSynthesizer:
|
|
|
878
860
|
if output_folder_path is not None:
|
|
879
861
|
self._save_sampled_data(sampled_data, output_folder_path)
|
|
880
862
|
|
|
863
|
+
return sampled_data, total_rows, total_columns
|
|
864
|
+
|
|
865
|
+
def sample_scale(
|
|
866
|
+
self,
|
|
867
|
+
scale=1.0,
|
|
868
|
+
batch_size=None,
|
|
869
|
+
max_tries_per_batch=100,
|
|
870
|
+
output_folder_path=None,
|
|
871
|
+
):
|
|
872
|
+
"""Generate synthetic data for the entire dataset.
|
|
873
|
+
|
|
874
|
+
Args:
|
|
875
|
+
scale (float):
|
|
876
|
+
A float representing how much to scale the data by. If scale is set to ``1.0``,
|
|
877
|
+
this does not scale the sizes of the tables. If ``scale`` is greater than ``1.0``
|
|
878
|
+
create more rows than the original data by a factor of ``scale``.
|
|
879
|
+
If ``scale`` is lower than ``1.0`` create fewer rows by the factor of ``scale``
|
|
880
|
+
than the original tables. Defaults to ``1.0``.
|
|
881
|
+
batch_size (int, optional):
|
|
882
|
+
The batch size for sampling. Defaults to None.
|
|
883
|
+
max_tries_per_batch (int, optional):
|
|
884
|
+
The maximum number of tries per batch. Defaults to 100.
|
|
885
|
+
output_folder_path (str, optional):
|
|
886
|
+
The folder path to save the sampled data. Defaults to None.
|
|
887
|
+
|
|
888
|
+
Returns:
|
|
889
|
+
dict: A dictionary containing the sampled data for each table.
|
|
890
|
+
"""
|
|
891
|
+
if not self._fitted:
|
|
892
|
+
raise SamplingError(
|
|
893
|
+
'This synthesizer has not been fitted. Please fit your synthesizer first before '
|
|
894
|
+
'sampling synthetic data.'
|
|
895
|
+
)
|
|
896
|
+
|
|
897
|
+
if type(scale) not in (float, int) or not scale > 0:
|
|
898
|
+
raise SynthesizerInputError(
|
|
899
|
+
f"Invalid parameter for 'scale' ({scale}). Please provide a number that is >0.0."
|
|
900
|
+
)
|
|
901
|
+
self._validate_sample_input(
|
|
902
|
+
num_rows=1,
|
|
903
|
+
main_table_name=list(self.metadata.tables)[0],
|
|
904
|
+
batch_size=batch_size,
|
|
905
|
+
max_tries_per_batch=max_tries_per_batch,
|
|
906
|
+
output_folder_path=output_folder_path,
|
|
907
|
+
)
|
|
908
|
+
|
|
909
|
+
sampled_data, total_rows, total_columns = self._sample_from_scale(
|
|
910
|
+
scale, batch_size, max_tries_per_batch, output_folder_path
|
|
911
|
+
)
|
|
912
|
+
|
|
913
|
+
SYNTHESIZER_LOGGER.info({
|
|
914
|
+
'EVENT': 'Sample',
|
|
915
|
+
'TIMESTAMP': datetime.datetime.now(),
|
|
916
|
+
'SYNTHESIZER CLASS NAME': self.__class__.__name__,
|
|
917
|
+
'SYNTHESIZER ID': self._synthesizer_id,
|
|
918
|
+
'TOTAL NUMBER OF TABLES': len(sampled_data),
|
|
919
|
+
'TOTAL NUMBER OF ROWS': total_rows,
|
|
920
|
+
'TOTAL NUMBER OF COLUMNS': total_columns,
|
|
921
|
+
})
|
|
922
|
+
|
|
923
|
+
return sampled_data
|
|
924
|
+
|
|
925
|
+
def sample(
|
|
926
|
+
self,
|
|
927
|
+
num_rows,
|
|
928
|
+
main_table_name=None,
|
|
929
|
+
batch_size=None,
|
|
930
|
+
max_tries_per_batch=100,
|
|
931
|
+
output_folder_path=None,
|
|
932
|
+
):
|
|
933
|
+
"""Generate synthetic data for the entire dataset.
|
|
934
|
+
|
|
935
|
+
Args:
|
|
936
|
+
num_rows (int):
|
|
937
|
+
The number of rows to sample.
|
|
938
|
+
main_table_name (str):
|
|
939
|
+
The name of the main table to sample.
|
|
940
|
+
batch_size (int, optional):
|
|
941
|
+
The batch size for sampling. Defaults to None.
|
|
942
|
+
max_tries_per_batch (int, optional):
|
|
943
|
+
The maximum number of tries per batch. Defaults to 100.
|
|
944
|
+
output_folder_path (str, optional):
|
|
945
|
+
The folder path to save the sampled data. Defaults to None.
|
|
946
|
+
|
|
947
|
+
Returns:
|
|
948
|
+
dict: A dictionary containing the sampled data for each table.
|
|
949
|
+
"""
|
|
950
|
+
self._validate_sample_input(
|
|
951
|
+
num_rows, main_table_name, batch_size, max_tries_per_batch, output_folder_path
|
|
952
|
+
)
|
|
953
|
+
scale = self._resolve_scale(main_table_name, num_rows)
|
|
954
|
+
|
|
955
|
+
sampled_data, total_rows, total_columns = self._sample_from_scale(
|
|
956
|
+
scale, batch_size, max_tries_per_batch, output_folder_path
|
|
957
|
+
)
|
|
958
|
+
|
|
881
959
|
SYNTHESIZER_LOGGER.info({
|
|
882
960
|
'EVENT': 'Sample',
|
|
883
961
|
'TIMESTAMP': datetime.datetime.now(),
|
|
@@ -427,17 +427,25 @@ class PARSynthesizer(LossValuesMixin, MissingModuleMixin, BaseSynthesizer):
|
|
|
427
427
|
|
|
428
428
|
return processed_table_data
|
|
429
429
|
|
|
430
|
-
def update_transformers(self, column_name_to_transformer):
|
|
430
|
+
def update_transformers(self, column_name_to_transformer, table_name=None):
|
|
431
431
|
"""Update any of the transformers assigned to each of the column names.
|
|
432
432
|
|
|
433
433
|
Args:
|
|
434
434
|
column_name_to_transformer (dict):
|
|
435
435
|
Dict mapping column names to transformers to be used for that column.
|
|
436
|
+
table_name (str, optional):
|
|
437
|
+
The name of the table for which to update the transformers. If not provided,
|
|
438
|
+
will use the default table name associated with the synthesizer.
|
|
436
439
|
|
|
437
440
|
Raises:
|
|
438
441
|
ValueError:
|
|
439
442
|
Raise when the transformer of a context column is passed.
|
|
440
443
|
"""
|
|
444
|
+
if table_name is not None:
|
|
445
|
+
self._validate_table_name(table_name)
|
|
446
|
+
else:
|
|
447
|
+
table_name = self._table_name
|
|
448
|
+
|
|
441
449
|
forbidden_updates = []
|
|
442
450
|
for column in set(column_name_to_transformer).intersection(set(self.context_columns)):
|
|
443
451
|
if self._get_table_metadata().columns[column]['sdtype'] in MODELABLE_SDTYPES:
|
|
@@ -448,7 +456,7 @@ class PARSynthesizer(LossValuesMixin, MissingModuleMixin, BaseSynthesizer):
|
|
|
448
456
|
'Transformers for context columns are not allowed to be updated.'
|
|
449
457
|
)
|
|
450
458
|
|
|
451
|
-
super().update_transformers(column_name_to_transformer)
|
|
459
|
+
super().update_transformers(column_name_to_transformer, table_name=table_name)
|
|
452
460
|
|
|
453
461
|
def _fit_context_model(self, processed_table_data):
|
|
454
462
|
LOGGER.debug(f'Fitting context synthesizer {self._context_synthesizer.__class__.__name__}')
|
|
@@ -639,8 +647,8 @@ class PARSynthesizer(LossValuesMixin, MissingModuleMixin, BaseSynthesizer):
|
|
|
639
647
|
|
|
640
648
|
def sample(
|
|
641
649
|
self,
|
|
642
|
-
table_name,
|
|
643
650
|
num_rows,
|
|
651
|
+
main_table_name=None,
|
|
644
652
|
max_tries_per_batch=100,
|
|
645
653
|
batch_size=None,
|
|
646
654
|
output_folder_path=None,
|
|
@@ -651,10 +659,10 @@ class PARSynthesizer(LossValuesMixin, MissingModuleMixin, BaseSynthesizer):
|
|
|
651
659
|
``sample_sequences`` instead.
|
|
652
660
|
|
|
653
661
|
Args:
|
|
654
|
-
table_name (str):
|
|
655
|
-
Name of the table to sample.
|
|
656
662
|
num_rows (int):
|
|
657
663
|
Number of rows to sample.
|
|
664
|
+
main_table_name (str or None):
|
|
665
|
+
Name of the table to sample.
|
|
658
666
|
max_tries_per_batch (int):
|
|
659
667
|
Number of times to retry sampling discarded rows. Defaults to 100.
|
|
660
668
|
batch_size (int or None):
|
|
@@ -725,8 +733,8 @@ class PARSynthesizer(LossValuesMixin, MissingModuleMixin, BaseSynthesizer):
|
|
|
725
733
|
condition_columns = context_columns[condition_columns].to_dict('records')
|
|
726
734
|
synthesizer_conditions = [Condition(conditions) for conditions in condition_columns]
|
|
727
735
|
context = self._context_synthesizer.sample_from_conditions(synthesizer_conditions)
|
|
728
|
-
context.update(context_columns)
|
|
729
|
-
return self._sample(context, sequence_length)
|
|
736
|
+
context[self._table_name].update(context_columns)
|
|
737
|
+
return {self._table_name: self._sample(context[self._table_name], sequence_length)}
|
|
730
738
|
|
|
731
739
|
def _process_context_columns(self, context_columns):
|
|
732
740
|
"""Process context columns by applying appropriate transformations.
|
|
@@ -212,6 +212,13 @@ class BaseSynthesizer:
|
|
|
212
212
|
'SYNTHESIZER ID': self._synthesizer_id,
|
|
213
213
|
})
|
|
214
214
|
|
|
215
|
+
def _validate_table_name(self, table_name):
|
|
216
|
+
if table_name != self._table_name:
|
|
217
|
+
raise ValueError(
|
|
218
|
+
'The provided table name does not match the metadata:'
|
|
219
|
+
f"\nTable '{table_name}' is not present in the metadata."
|
|
220
|
+
)
|
|
221
|
+
|
|
215
222
|
def _validate_metadata(self, table_data):
|
|
216
223
|
"""Validate that the table data follows the metadata."""
|
|
217
224
|
errors = []
|
|
@@ -293,13 +300,21 @@ class BaseSynthesizer:
|
|
|
293
300
|
'parameter to False.'
|
|
294
301
|
)
|
|
295
302
|
|
|
296
|
-
def update_transformers(self, column_name_to_transformer):
|
|
303
|
+
def update_transformers(self, column_name_to_transformer, table_name=None):
|
|
297
304
|
"""Update any of the transformers assigned to each of the column names.
|
|
298
305
|
|
|
299
306
|
Args:
|
|
300
307
|
column_name_to_transformer (dict):
|
|
301
308
|
Dict mapping column names to transformers to be used for that column.
|
|
309
|
+
table_name (str, optional):
|
|
310
|
+
The name of the table for which to update the transformers. If not provided,
|
|
311
|
+
will use the default table name associated with the synthesizer. Defaults to None.
|
|
302
312
|
"""
|
|
313
|
+
if table_name is not None:
|
|
314
|
+
self._validate_table_name(table_name)
|
|
315
|
+
else:
|
|
316
|
+
table_name = self._table_name
|
|
317
|
+
|
|
303
318
|
self._validate_transformers(column_name_to_transformer)
|
|
304
319
|
self._warn_quality_and_performance(column_name_to_transformer)
|
|
305
320
|
self._warn_unable_to_enforce_rounding(column_name_to_transformer)
|
|
@@ -358,16 +373,26 @@ class BaseSynthesizer:
|
|
|
358
373
|
self.validate(data)
|
|
359
374
|
self._auto_assign_transformers(data)
|
|
360
375
|
|
|
361
|
-
def get_transformers(self):
|
|
376
|
+
def get_transformers(self, table_name=None):
|
|
362
377
|
"""Get a dictionary mapping of ``column_name`` and ``rdt.transformers``.
|
|
363
378
|
|
|
364
379
|
A dictionary representing the column names and the transformers that will be used
|
|
365
380
|
to transform the data.
|
|
366
381
|
|
|
382
|
+
Args:
|
|
383
|
+
table_name (str, optional):
|
|
384
|
+
The name of the table for which to get the transformers. If not provided,
|
|
385
|
+
the default table name will be used. Defaults to None.
|
|
386
|
+
|
|
367
387
|
Returns:
|
|
368
388
|
dict:
|
|
369
389
|
A dictionary mapping with column names and transformers.
|
|
370
390
|
"""
|
|
391
|
+
if table_name is not None:
|
|
392
|
+
self._validate_table_name(table_name)
|
|
393
|
+
else:
|
|
394
|
+
table_name = self._table_name
|
|
395
|
+
|
|
371
396
|
field_transformers = self._data_processor._hyper_transformer.field_transformers
|
|
372
397
|
if field_transformers == {}:
|
|
373
398
|
raise ValueError(
|
|
@@ -1179,17 +1204,10 @@ class BaseSingleTableSynthesizer(BaseSynthesizer):
|
|
|
1179
1204
|
' sampling synthetic data.'
|
|
1180
1205
|
)
|
|
1181
1206
|
|
|
1182
|
-
def _validate_table_name(self, table_name):
|
|
1183
|
-
if table_name != self._table_name:
|
|
1184
|
-
raise ValueError(
|
|
1185
|
-
'The provided table name does not match the metadata:'
|
|
1186
|
-
f"\nTable '{table_name}' is not present in the metadata."
|
|
1187
|
-
)
|
|
1188
|
-
|
|
1189
1207
|
def sample(
|
|
1190
1208
|
self,
|
|
1191
|
-
table_name,
|
|
1192
1209
|
num_rows,
|
|
1210
|
+
main_table_name=None,
|
|
1193
1211
|
max_tries_per_batch=100,
|
|
1194
1212
|
batch_size=None,
|
|
1195
1213
|
output_folder_path=None,
|
|
@@ -1197,10 +1215,10 @@ class BaseSingleTableSynthesizer(BaseSynthesizer):
|
|
|
1197
1215
|
"""Sample rows from this table.
|
|
1198
1216
|
|
|
1199
1217
|
Args:
|
|
1200
|
-
table_name (str):
|
|
1201
|
-
Name of the table to sample. This parameter is required.
|
|
1202
1218
|
num_rows (int):
|
|
1203
1219
|
Number of rows to sample. This parameter is required.
|
|
1220
|
+
main_table_name (str):
|
|
1221
|
+
Name of the table to sample.
|
|
1204
1222
|
max_tries_per_batch (int):
|
|
1205
1223
|
Number of times to retry sampling until the batch size is met. Defaults to 100.
|
|
1206
1224
|
batch_size (int or None):
|
|
@@ -1213,6 +1231,7 @@ class BaseSingleTableSynthesizer(BaseSynthesizer):
|
|
|
1213
1231
|
dict[str, pandas.DataFrame]:
|
|
1214
1232
|
Dictionary mapping the table name to the sampled data.
|
|
1215
1233
|
"""
|
|
1234
|
+
table_name = self._table_name if main_table_name is None else main_table_name
|
|
1216
1235
|
self._validate_table_name(table_name)
|
|
1217
1236
|
self._validate_fit_before_sample()
|
|
1218
1237
|
self._check_input_metadata_updated()
|
|
@@ -1422,8 +1441,9 @@ class BaseSingleTableSynthesizer(BaseSynthesizer):
|
|
|
1422
1441
|
The folder to periodically write sampled rows to. Defaults to None.
|
|
1423
1442
|
|
|
1424
1443
|
Returns:
|
|
1425
|
-
pandas.DataFrame:
|
|
1426
|
-
|
|
1444
|
+
dict[str, pandas.DataFrame]:
|
|
1445
|
+
Dictionary mapping the table name to the sampled data.
|
|
1446
|
+
|
|
1427
1447
|
|
|
1428
1448
|
Raises:
|
|
1429
1449
|
ConstraintsNotMetError:
|
|
@@ -1483,7 +1503,7 @@ class BaseSingleTableSynthesizer(BaseSynthesizer):
|
|
|
1483
1503
|
'TOTAL NUMBER OF COLUMNS': len(sampled.columns),
|
|
1484
1504
|
})
|
|
1485
1505
|
|
|
1486
|
-
return sampled
|
|
1506
|
+
return {self._table_name: sampled}
|
|
1487
1507
|
|
|
1488
1508
|
def _validate_known_columns(self, conditions):
|
|
1489
1509
|
"""Validate the user-passed conditions."""
|
|
@@ -1507,8 +1527,8 @@ class BaseSingleTableSynthesizer(BaseSynthesizer):
|
|
|
1507
1527
|
The folder to periodically write sampled rows to. Defaults to None.
|
|
1508
1528
|
|
|
1509
1529
|
Returns:
|
|
1510
|
-
pandas.DataFrame:
|
|
1511
|
-
|
|
1530
|
+
dict[str, pandas.DataFrame]:
|
|
1531
|
+
Dictionary mapping the table name to the sampled data.
|
|
1512
1532
|
|
|
1513
1533
|
Raises:
|
|
1514
1534
|
ConstraintsNotMetError:
|
|
@@ -1557,4 +1577,4 @@ class BaseSingleTableSynthesizer(BaseSynthesizer):
|
|
|
1557
1577
|
'TOTAL NUMBER OF COLUMNS': len(sampled.columns),
|
|
1558
1578
|
})
|
|
1559
1579
|
|
|
1560
|
-
return sampled
|
|
1580
|
+
return {self._table_name: sampled}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sdv
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.1.dev0
|
|
4
4
|
Summary: Generate synthetic data for single table, multi table and sequential data
|
|
5
5
|
Author-email: "DataCebo, Inc." <info@sdv.dev>
|
|
6
6
|
License-Expression: BUSL-1.1
|
|
@@ -14,14 +14,13 @@ Classifier: Development Status :: 5 - Production/Stable
|
|
|
14
14
|
Classifier: Intended Audience :: Developers
|
|
15
15
|
Classifier: Natural Language :: English
|
|
16
16
|
Classifier: Programming Language :: Python :: 3
|
|
17
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
18
17
|
Classifier: Programming Language :: Python :: 3.10
|
|
19
18
|
Classifier: Programming Language :: Python :: 3.11
|
|
20
19
|
Classifier: Programming Language :: Python :: 3.12
|
|
21
20
|
Classifier: Programming Language :: Python :: 3.13
|
|
22
21
|
Classifier: Programming Language :: Python :: 3.14
|
|
23
22
|
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
24
|
-
Requires-Python: <3.15,>=3.
|
|
23
|
+
Requires-Python: <3.15,>=3.10
|
|
25
24
|
Description-Content-Type: text/markdown
|
|
26
25
|
License-File: LICENSE
|
|
27
26
|
Requires-Dist: boto3<2.0.0,>=1.28
|
|
@@ -29,8 +28,7 @@ Requires-Dist: botocore<2.0.0,>=1.31
|
|
|
29
28
|
Requires-Dist: cloudpickle>=2.1.0; python_version < "3.14"
|
|
30
29
|
Requires-Dist: cloudpickle>=3.1.1; python_version >= "3.14"
|
|
31
30
|
Requires-Dist: graphviz>=0.13.2
|
|
32
|
-
Requires-Dist: numpy>=1.
|
|
33
|
-
Requires-Dist: numpy>=1.24.0; python_version >= "3.10" and python_version < "3.12"
|
|
31
|
+
Requires-Dist: numpy>=1.24.0; python_version < "3.12"
|
|
34
32
|
Requires-Dist: numpy>=1.26.0; python_version >= "3.12" and python_version < "3.13"
|
|
35
33
|
Requires-Dist: numpy>=2.1.0; python_version >= "3.13" and python_version < "3.14"
|
|
36
34
|
Requires-Dist: numpy>=2.3.2; python_version >= "3.14"
|
|
@@ -46,7 +44,7 @@ Requires-Dist: ctgan>=0.11.1; python_version < "3.14"
|
|
|
46
44
|
Requires-Dist: ctgan>=0.12.0; python_version >= "3.14"
|
|
47
45
|
Requires-Dist: deepecho>=0.7.0; python_version < "3.14"
|
|
48
46
|
Requires-Dist: deepecho>=0.8.0; python_version >= "3.14"
|
|
49
|
-
Requires-Dist: rdt>=2.0.0
|
|
47
|
+
Requires-Dist: rdt>=2.0.0
|
|
50
48
|
Requires-Dist: sdmetrics>=0.32.0
|
|
51
49
|
Requires-Dist: platformdirs>=4.0
|
|
52
50
|
Requires-Dist: pyyaml>=6.0.1
|
|
@@ -64,7 +62,6 @@ Requires-Dist: google-api-python-client; extra == "test"
|
|
|
64
62
|
Requires-Dist: google-auth; extra == "test"
|
|
65
63
|
Requires-Dist: google-auth-oauthlib; extra == "test"
|
|
66
64
|
Requires-Dist: requests; extra == "test"
|
|
67
|
-
Requires-Dist: pyarrow; extra == "test"
|
|
68
65
|
Requires-Dist: gitpython; extra == "test"
|
|
69
66
|
Requires-Dist: slack-sdk<4.0,>=3.23; extra == "test"
|
|
70
67
|
Provides-Extra: pomegranate
|
|
@@ -91,6 +88,8 @@ Requires-Dist: coverage<8,>=4.5.12; extra == "dev"
|
|
|
91
88
|
Requires-Dist: invoke; extra == "dev"
|
|
92
89
|
Provides-Extra: readme
|
|
93
90
|
Requires-Dist: rundoc<0.5,>=0.4.3; extra == "readme"
|
|
91
|
+
Provides-Extra: benchmark
|
|
92
|
+
Requires-Dist: pyarrow; extra == "benchmark"
|
|
94
93
|
Dynamic: license-file
|
|
95
94
|
|
|
96
95
|
<div align="center">
|
|
@@ -2,26 +2,23 @@ boto3<2.0.0,>=1.28
|
|
|
2
2
|
botocore<2.0.0,>=1.31
|
|
3
3
|
graphviz>=0.13.2
|
|
4
4
|
tqdm>=4.29
|
|
5
|
-
rdt>=2.0.0
|
|
5
|
+
rdt>=2.0.0
|
|
6
6
|
sdmetrics>=0.32.0
|
|
7
7
|
platformdirs>=4.0
|
|
8
8
|
pyyaml>=6.0.1
|
|
9
9
|
|
|
10
|
-
[:python_version < "3.10"]
|
|
11
|
-
numpy>=1.22.2
|
|
12
|
-
|
|
13
10
|
[:python_version < "3.11"]
|
|
14
11
|
pandas<3,>=1.4.0
|
|
15
12
|
|
|
13
|
+
[:python_version < "3.12"]
|
|
14
|
+
numpy>=1.24.0
|
|
15
|
+
|
|
16
16
|
[:python_version < "3.14"]
|
|
17
17
|
cloudpickle>=2.1.0
|
|
18
18
|
copulas>=0.12.1
|
|
19
19
|
ctgan>=0.11.1
|
|
20
20
|
deepecho>=0.7.0
|
|
21
21
|
|
|
22
|
-
[:python_version >= "3.10" and python_version < "3.12"]
|
|
23
|
-
numpy>=1.24.0
|
|
24
|
-
|
|
25
22
|
[:python_version >= "3.11" and python_version < "3.12"]
|
|
26
23
|
pandas<3,>=1.5.0
|
|
27
24
|
|
|
@@ -41,6 +38,9 @@ copulas>=0.14.0
|
|
|
41
38
|
ctgan>=0.12.0
|
|
42
39
|
deepecho>=0.8.0
|
|
43
40
|
|
|
41
|
+
[benchmark]
|
|
42
|
+
pyarrow
|
|
43
|
+
|
|
44
44
|
[dev]
|
|
45
45
|
sdv[test]
|
|
46
46
|
build<2,>=1.0.0
|
|
@@ -83,6 +83,5 @@ google-api-python-client
|
|
|
83
83
|
google-auth
|
|
84
84
|
google-auth-oauthlib
|
|
85
85
|
requests
|
|
86
|
-
pyarrow
|
|
87
86
|
gitpython
|
|
88
87
|
slack-sdk<4.0,>=3.23
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|