singer-python 5.14.1__tar.gz → 5.14.3__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.
- {singer-python-5.14.1/singer_python.egg-info → singer_python-5.14.3}/PKG-INFO +9 -2
- {singer-python-5.14.1 → singer_python-5.14.3}/setup.py +1 -1
- {singer-python-5.14.1 → singer_python-5.14.3}/singer/schema_generation.py +16 -17
- {singer-python-5.14.1 → singer_python-5.14.3}/singer/transform.py +2 -0
- {singer-python-5.14.1 → singer_python-5.14.3/singer_python.egg-info}/PKG-INFO +9 -2
- {singer-python-5.14.1 → singer_python-5.14.3}/tests/test_schema_generation.py +13 -17
- {singer-python-5.14.1 → singer_python-5.14.3}/LICENSE +0 -0
- {singer-python-5.14.1 → singer_python-5.14.3}/README.md +0 -0
- {singer-python-5.14.1 → singer_python-5.14.3}/setup.cfg +0 -0
- {singer-python-5.14.1 → singer_python-5.14.3}/singer/__init__.py +0 -0
- {singer-python-5.14.1 → singer_python-5.14.3}/singer/bookmarks.py +0 -0
- {singer-python-5.14.1 → singer_python-5.14.3}/singer/catalog.py +0 -0
- {singer-python-5.14.1 → singer_python-5.14.3}/singer/exceptions.py +0 -0
- {singer-python-5.14.1 → singer_python-5.14.3}/singer/logger.py +0 -0
- {singer-python-5.14.1 → singer_python-5.14.3}/singer/logging.conf +0 -0
- {singer-python-5.14.1 → singer_python-5.14.3}/singer/messages.py +0 -0
- {singer-python-5.14.1 → singer_python-5.14.3}/singer/metadata.py +0 -0
- {singer-python-5.14.1 → singer_python-5.14.3}/singer/metrics.py +0 -0
- {singer-python-5.14.1 → singer_python-5.14.3}/singer/requests.py +0 -0
- {singer-python-5.14.1 → singer_python-5.14.3}/singer/schema.py +0 -0
- {singer-python-5.14.1 → singer_python-5.14.3}/singer/statediff.py +0 -0
- {singer-python-5.14.1 → singer_python-5.14.3}/singer/utils.py +0 -0
- {singer-python-5.14.1 → singer_python-5.14.3}/singer_python.egg-info/SOURCES.txt +0 -0
- {singer-python-5.14.1 → singer_python-5.14.3}/singer_python.egg-info/dependency_links.txt +0 -0
- {singer-python-5.14.1 → singer_python-5.14.3}/singer_python.egg-info/requires.txt +0 -0
- {singer-python-5.14.1 → singer_python-5.14.3}/singer_python.egg-info/top_level.txt +0 -0
- {singer-python-5.14.1 → singer_python-5.14.3}/tests/__init__.py +0 -0
- {singer-python-5.14.1 → singer_python-5.14.3}/tests/test_bookmarks.py +0 -0
- {singer-python-5.14.1 → singer_python-5.14.3}/tests/test_catalog.py +0 -0
- {singer-python-5.14.1 → singer_python-5.14.3}/tests/test_exceptions.py +0 -0
- {singer-python-5.14.1 → singer_python-5.14.3}/tests/test_metadata.py +0 -0
- {singer-python-5.14.1 → singer_python-5.14.3}/tests/test_metrics.py +0 -0
- {singer-python-5.14.1 → singer_python-5.14.3}/tests/test_schema.py +0 -0
- {singer-python-5.14.1 → singer_python-5.14.3}/tests/test_singer.py +0 -0
- {singer-python-5.14.1 → singer_python-5.14.3}/tests/test_statediff.py +0 -0
- {singer-python-5.14.1 → singer_python-5.14.3}/tests/test_transform.py +0 -0
- {singer-python-5.14.1 → singer_python-5.14.3}/tests/test_utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: singer-python
|
|
3
|
-
Version: 5.14.
|
|
3
|
+
Version: 5.14.3
|
|
4
4
|
Summary: Singer.io utility library
|
|
5
5
|
Home-page: http://singer.io
|
|
6
6
|
Author: Stitch
|
|
@@ -18,3 +18,10 @@ Requires-Dist: ipython; extra == "dev"
|
|
|
18
18
|
Requires-Dist: ipdb; extra == "dev"
|
|
19
19
|
Requires-Dist: nose; extra == "dev"
|
|
20
20
|
Requires-Dist: singer-tools; extra == "dev"
|
|
21
|
+
Dynamic: author
|
|
22
|
+
Dynamic: classifier
|
|
23
|
+
Dynamic: home-page
|
|
24
|
+
Dynamic: license-file
|
|
25
|
+
Dynamic: provides-extra
|
|
26
|
+
Dynamic: requires-dist
|
|
27
|
+
Dynamic: summary
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
import dateutil.parser
|
|
2
|
-
|
|
3
|
-
|
|
4
1
|
def add_observation(acc, path):
|
|
5
2
|
|
|
6
3
|
node = acc
|
|
@@ -37,13 +34,6 @@ def add_observations(acc, path, data):
|
|
|
37
34
|
return acc
|
|
38
35
|
except (ValueError, TypeError):
|
|
39
36
|
pass
|
|
40
|
-
try:
|
|
41
|
-
# If the string parses as a date, add an observation that it's a date
|
|
42
|
-
dateutil.parser.parse(data)
|
|
43
|
-
add_observation(acc, path + ["date"])
|
|
44
|
-
return acc
|
|
45
|
-
except (dateutil.parser.ParserError, OverflowError):
|
|
46
|
-
pass
|
|
47
37
|
add_observation(acc, path + ["string"])
|
|
48
38
|
elif isinstance(data, bool):
|
|
49
39
|
add_observation(acc, path + ["boolean"])
|
|
@@ -54,14 +44,18 @@ def add_observations(acc, path, data):
|
|
|
54
44
|
elif data is None:
|
|
55
45
|
add_observation(acc, path + ["null"])
|
|
56
46
|
else:
|
|
57
|
-
|
|
47
|
+
add_observation(acc, path + ["string"])
|
|
58
48
|
|
|
59
49
|
return acc
|
|
60
50
|
|
|
61
51
|
def to_json_schema(obs):
|
|
62
|
-
|
|
52
|
+
types = []
|
|
53
|
+
# add schema types in a specific order to anyOf list
|
|
54
|
+
for key in ['array', 'object', 'number', 'integer', 'boolean', 'string', 'null']:
|
|
55
|
+
if key not in obs:
|
|
56
|
+
continue
|
|
63
57
|
|
|
64
|
-
|
|
58
|
+
result = {'type': ['null']}
|
|
65
59
|
|
|
66
60
|
if key == 'object':
|
|
67
61
|
result['type'] += ['object']
|
|
@@ -74,9 +68,6 @@ def to_json_schema(obs):
|
|
|
74
68
|
result['type'] += ['array']
|
|
75
69
|
result['items'] = to_json_schema(obs['array'])
|
|
76
70
|
|
|
77
|
-
elif key == 'date':
|
|
78
|
-
result['type'] += ['string']
|
|
79
|
-
result['format'] = 'date-time'
|
|
80
71
|
elif key == 'string':
|
|
81
72
|
result['type'] += ['string']
|
|
82
73
|
|
|
@@ -97,7 +88,15 @@ def to_json_schema(obs):
|
|
|
97
88
|
else:
|
|
98
89
|
raise Exception("Unexpected data type " + key)
|
|
99
90
|
|
|
100
|
-
|
|
91
|
+
types.append(result)
|
|
92
|
+
|
|
93
|
+
if len(types) == 0:
|
|
94
|
+
return {'type': ['null', 'string']}
|
|
95
|
+
|
|
96
|
+
if len(types) == 1:
|
|
97
|
+
return types[0]
|
|
98
|
+
|
|
99
|
+
return {'anyOf': types}
|
|
101
100
|
|
|
102
101
|
def generate_schema(records):
|
|
103
102
|
obs = {}
|
|
@@ -185,6 +185,8 @@ class Transformer:
|
|
|
185
185
|
success, transformed_data = self.transform_recur(data, subschema, path)
|
|
186
186
|
if success:
|
|
187
187
|
return success, transformed_data
|
|
188
|
+
else:
|
|
189
|
+
self.errors.pop()
|
|
188
190
|
else: # pylint: disable=useless-else-on-loop
|
|
189
191
|
# exhaused all schemas and didn't return, so we failed :-(
|
|
190
192
|
self.errors.append(Error(path, data, schema, logging_level=LOGGER.level))
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: singer-python
|
|
3
|
-
Version: 5.14.
|
|
3
|
+
Version: 5.14.3
|
|
4
4
|
Summary: Singer.io utility library
|
|
5
5
|
Home-page: http://singer.io
|
|
6
6
|
Author: Stitch
|
|
@@ -18,3 +18,10 @@ Requires-Dist: ipython; extra == "dev"
|
|
|
18
18
|
Requires-Dist: ipdb; extra == "dev"
|
|
19
19
|
Requires-Dist: nose; extra == "dev"
|
|
20
20
|
Requires-Dist: singer-tools; extra == "dev"
|
|
21
|
+
Dynamic: author
|
|
22
|
+
Dynamic: classifier
|
|
23
|
+
Dynamic: home-page
|
|
24
|
+
Dynamic: license-file
|
|
25
|
+
Dynamic: provides-extra
|
|
26
|
+
Dynamic: requires-dist
|
|
27
|
+
Dynamic: summary
|
|
@@ -10,7 +10,7 @@ class TestSchemaGeneration(unittest.TestCase):
|
|
|
10
10
|
'a': {'type': ['null', 'integer']},
|
|
11
11
|
'b': {'type': ['null', 'string']},
|
|
12
12
|
'c': {'type': ['null', 'boolean']},
|
|
13
|
-
'dt': {'type': ['null', 'string']
|
|
13
|
+
'dt': {'type': ['null', 'string']}
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
16
|
self.assertEqual(expected_schema, generate_schema(records))
|
|
@@ -23,24 +23,20 @@ class TestSchemaGeneration(unittest.TestCase):
|
|
|
23
23
|
]
|
|
24
24
|
expected_schema = {
|
|
25
25
|
'type': ['null', 'object'],
|
|
26
|
-
'properties': {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
26
|
+
'properties': {'a': {'anyOf': [{'type': ['null', 'integer']},
|
|
27
|
+
{'type': ['null', 'boolean']},
|
|
28
|
+
{'type': ['null', 'string']}]},
|
|
29
|
+
'b': {'type': ['null', 'string']},
|
|
30
|
+
'c': {'anyOf': [{'type': ['null', 'string'], 'format': 'singer.decimal'},
|
|
31
|
+
{'type': ['null', 'integer']}]},
|
|
32
|
+
'd': {'anyOf': [{'type': ['null', 'array'],
|
|
33
|
+
'items': {'anyOf': [{'type': ['null', 'integer']},
|
|
34
|
+
{'type': ['null', 'string']}]}},
|
|
35
|
+
{'type': ['null', 'object'],
|
|
36
|
+
'properties': {'one': {'type': ['null', 'integer']},
|
|
37
|
+
'two': {'type': ['null', 'string']}}}]}}
|
|
38
38
|
}
|
|
39
39
|
actual_schema = generate_schema(records)
|
|
40
|
-
actual_schema['properties']['a']['type'] = set(actual_schema['properties']['a']['type'])
|
|
41
|
-
actual_schema['properties']['c']['type'] = set(actual_schema['properties']['c']['type'])
|
|
42
|
-
actual_schema['properties']['d']['type'] = set(actual_schema['properties']['d']['type'])
|
|
43
|
-
actual_schema['properties']['d']['items']['type'] = set(actual_schema['properties']['d']['items']['type'])
|
|
44
40
|
self.assertEqual(expected_schema, actual_schema)
|
|
45
41
|
|
|
46
42
|
def test_nested_structue_schema(self):
|
|
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
|