singer-python 6.2.2__tar.gz → 6.3.0__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.
Files changed (39) hide show
  1. singer-python-6.3.0/PKG-INFO +9 -0
  2. {singer_python-6.2.2 → singer-python-6.3.0}/setup.py +1 -1
  3. {singer_python-6.2.2 → singer-python-6.3.0}/singer/messages.py +9 -4
  4. {singer_python-6.2.2 → singer-python-6.3.0}/singer/schema_generation.py +1 -1
  5. singer-python-6.3.0/singer_python.egg-info/PKG-INFO +9 -0
  6. {singer_python-6.2.2 → singer-python-6.3.0}/tests/test_transform.py +59 -1
  7. singer_python-6.2.2/PKG-INFO +0 -27
  8. singer_python-6.2.2/singer_python.egg-info/PKG-INFO +0 -27
  9. {singer_python-6.2.2 → singer-python-6.3.0}/LICENSE +0 -0
  10. {singer_python-6.2.2 → singer-python-6.3.0}/README.md +0 -0
  11. {singer_python-6.2.2 → singer-python-6.3.0}/setup.cfg +0 -0
  12. {singer_python-6.2.2 → singer-python-6.3.0}/singer/__init__.py +0 -0
  13. {singer_python-6.2.2 → singer-python-6.3.0}/singer/bookmarks.py +0 -0
  14. {singer_python-6.2.2 → singer-python-6.3.0}/singer/catalog.py +0 -0
  15. {singer_python-6.2.2 → singer-python-6.3.0}/singer/exceptions.py +0 -0
  16. {singer_python-6.2.2 → singer-python-6.3.0}/singer/logger.py +0 -0
  17. {singer_python-6.2.2 → singer-python-6.3.0}/singer/logging.conf +0 -0
  18. {singer_python-6.2.2 → singer-python-6.3.0}/singer/metadata.py +0 -0
  19. {singer_python-6.2.2 → singer-python-6.3.0}/singer/metrics.py +0 -0
  20. {singer_python-6.2.2 → singer-python-6.3.0}/singer/requests.py +0 -0
  21. {singer_python-6.2.2 → singer-python-6.3.0}/singer/schema.py +0 -0
  22. {singer_python-6.2.2 → singer-python-6.3.0}/singer/statediff.py +0 -0
  23. {singer_python-6.2.2 → singer-python-6.3.0}/singer/transform.py +0 -0
  24. {singer_python-6.2.2 → singer-python-6.3.0}/singer/utils.py +0 -0
  25. {singer_python-6.2.2 → singer-python-6.3.0}/singer_python.egg-info/SOURCES.txt +0 -0
  26. {singer_python-6.2.2 → singer-python-6.3.0}/singer_python.egg-info/dependency_links.txt +0 -0
  27. {singer_python-6.2.2 → singer-python-6.3.0}/singer_python.egg-info/requires.txt +0 -0
  28. {singer_python-6.2.2 → singer-python-6.3.0}/singer_python.egg-info/top_level.txt +0 -0
  29. {singer_python-6.2.2 → singer-python-6.3.0}/tests/__init__.py +0 -0
  30. {singer_python-6.2.2 → singer-python-6.3.0}/tests/test_bookmarks.py +0 -0
  31. {singer_python-6.2.2 → singer-python-6.3.0}/tests/test_catalog.py +0 -0
  32. {singer_python-6.2.2 → singer-python-6.3.0}/tests/test_exceptions.py +0 -0
  33. {singer_python-6.2.2 → singer-python-6.3.0}/tests/test_metadata.py +0 -0
  34. {singer_python-6.2.2 → singer-python-6.3.0}/tests/test_metrics.py +0 -0
  35. {singer_python-6.2.2 → singer-python-6.3.0}/tests/test_schema.py +0 -0
  36. {singer_python-6.2.2 → singer-python-6.3.0}/tests/test_schema_generation.py +0 -0
  37. {singer_python-6.2.2 → singer-python-6.3.0}/tests/test_singer.py +0 -0
  38. {singer_python-6.2.2 → singer-python-6.3.0}/tests/test_statediff.py +0 -0
  39. {singer_python-6.2.2 → singer-python-6.3.0}/tests/test_utils.py +0 -0
@@ -0,0 +1,9 @@
1
+ Metadata-Version: 2.1
2
+ Name: singer-python
3
+ Version: 6.3.0
4
+ Summary: Singer.io utility library
5
+ Home-page: http://singer.io
6
+ Author: Stitch
7
+ Classifier: Programming Language :: Python :: 3 :: Only
8
+ Provides-Extra: dev
9
+ License-File: LICENSE
@@ -4,7 +4,7 @@ from setuptools import setup, find_packages
4
4
  import subprocess
5
5
 
6
6
  setup(name="singer-python",
7
- version='6.2.2',
7
+ version='6.3.0',
8
8
  description="Singer.io utility library",
9
9
  author="Stitch",
10
10
  classifiers=['Programming Language :: Python :: 3 :: Only'],
@@ -218,12 +218,17 @@ def parse_message(msg):
218
218
  return None
219
219
 
220
220
 
221
- def format_message(message, ensure_ascii=True):
222
- return json.dumps(message.asdict(), use_decimal=True, ensure_ascii=ensure_ascii)
221
+ def format_message(message, ensure_ascii=True, allow_nan=False):
222
+ return json.dumps(
223
+ message.asdict(),
224
+ use_decimal=True,
225
+ ensure_ascii=ensure_ascii,
226
+ allow_nan=allow_nan
227
+ )
223
228
 
224
229
 
225
- def write_message(message, ensure_ascii=True):
226
- sys.stdout.write(format_message(message, ensure_ascii=ensure_ascii) + '\n')
230
+ def write_message(message, ensure_ascii=True, allow_nan=False):
231
+ sys.stdout.write(format_message(message, ensure_ascii=ensure_ascii, allow_nan=allow_nan) + '\n')
227
232
  sys.stdout.flush()
228
233
 
229
234
 
@@ -44,7 +44,7 @@ def add_observations(acc, path, data):
44
44
  elif data is None:
45
45
  add_observation(acc, path + ["null"])
46
46
  else:
47
- raise Exception("Unexpected value " + repr(data) + " at path " + repr(path))
47
+ add_observation(acc, path + ["string"])
48
48
 
49
49
  return acc
50
50
 
@@ -0,0 +1,9 @@
1
+ Metadata-Version: 2.1
2
+ Name: singer-python
3
+ Version: 6.3.0
4
+ Summary: Singer.io utility library
5
+ Home-page: http://singer.io
6
+ Author: Stitch
7
+ Classifier: Programming Language :: Python :: 3 :: Only
8
+ Provides-Extra: dev
9
+ License-File: LICENSE
@@ -1,9 +1,12 @@
1
+ import io
2
+ import sys
1
3
  import unittest
2
4
  import decimal
5
+ import simplejson as json
6
+ import singer.messages as messages
3
7
  from singer import transform
4
8
  from singer.transform import *
5
9
 
6
-
7
10
  class TestTransform(unittest.TestCase):
8
11
  def test_integer_transform(self):
9
12
  schema = {'type': 'integer'}
@@ -486,3 +489,58 @@ class TestPatternProperties(unittest.TestCase):
486
489
  dict_value = {"name": "chicken", "unit_cost": 1.45, "SKU": '123456'}
487
490
  expected = dict(dict_value)
488
491
  self.assertEqual(expected, transform(dict_value, schema))
492
+
493
+ class DummyMessage:
494
+ """A dummy message object with an asdict() method."""
495
+ def __init__(self, value):
496
+ self.value = value
497
+
498
+ def asdict(self):
499
+ return {"value": self.value}
500
+
501
+
502
+ class TestAllowNan(unittest.TestCase):
503
+ """Unit tests for allow_nan support in singer.messages."""
504
+
505
+ def test_format_message_allow_nan_true(self):
506
+ """Should serialize NaN successfully when allow_nan=True."""
507
+ msg = DummyMessage(float("nan"))
508
+ result = messages.format_message(msg, allow_nan=True)
509
+
510
+ # The output JSON should contain NaN literal (not quoted)
511
+ self.assertIn("NaN", result)
512
+
513
+ # Replace NaN with null to make it valid JSON for parsing check
514
+ json.loads(result.replace("NaN", "null"))
515
+
516
+ def test_format_message_allow_nan_false(self):
517
+ """Should raise ValueError when allow_nan=False and value is NaN."""
518
+ msg = DummyMessage(float("nan"))
519
+ with self.assertRaises(ValueError):
520
+ messages.format_message(msg, allow_nan=False)
521
+
522
+ def test_write_message_allow_nan_true(self):
523
+ """Should write to stdout successfully when allow_nan=True."""
524
+ msg = DummyMessage(float("nan"))
525
+ fake_stdout = io.StringIO()
526
+ original_stdout = sys.stdout
527
+ sys.stdout = fake_stdout
528
+ try:
529
+ messages.write_message(msg, allow_nan=True)
530
+ output = fake_stdout.getvalue()
531
+ self.assertIn("NaN", output)
532
+ self.assertTrue(output.endswith("\n"))
533
+ finally:
534
+ sys.stdout = original_stdout
535
+
536
+ def test_write_message_allow_nan_false(self):
537
+ """Should raise ValueError when allow_nan=False and message has NaN."""
538
+ msg = DummyMessage(float("nan"))
539
+ fake_stdout = io.StringIO()
540
+ original_stdout = sys.stdout
541
+ sys.stdout = fake_stdout
542
+ try:
543
+ with self.assertRaises(ValueError):
544
+ messages.write_message(msg, allow_nan=False)
545
+ finally:
546
+ sys.stdout = original_stdout
@@ -1,27 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: singer-python
3
- Version: 6.2.2
4
- Summary: Singer.io utility library
5
- Home-page: http://singer.io
6
- Author: Stitch
7
- Classifier: Programming Language :: Python :: 3 :: Only
8
- License-File: LICENSE
9
- Requires-Dist: pytz>=2018.4
10
- Requires-Dist: jsonschema==2.*,>=2.6.0
11
- Requires-Dist: simplejson==3.*,>=3.13.2
12
- Requires-Dist: python-dateutil==2.*,>=2.7.3
13
- Requires-Dist: backoff==2.*,>=2.2.1
14
- Requires-Dist: ciso8601==2.*,>=2.3.1
15
- Provides-Extra: dev
16
- Requires-Dist: pylint; extra == "dev"
17
- Requires-Dist: ipython; extra == "dev"
18
- Requires-Dist: ipdb; extra == "dev"
19
- Requires-Dist: nose; extra == "dev"
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,27 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: singer-python
3
- Version: 6.2.2
4
- Summary: Singer.io utility library
5
- Home-page: http://singer.io
6
- Author: Stitch
7
- Classifier: Programming Language :: Python :: 3 :: Only
8
- License-File: LICENSE
9
- Requires-Dist: pytz>=2018.4
10
- Requires-Dist: jsonschema==2.*,>=2.6.0
11
- Requires-Dist: simplejson==3.*,>=3.13.2
12
- Requires-Dist: python-dateutil==2.*,>=2.7.3
13
- Requires-Dist: backoff==2.*,>=2.2.1
14
- Requires-Dist: ciso8601==2.*,>=2.3.1
15
- Provides-Extra: dev
16
- Requires-Dist: pylint; extra == "dev"
17
- Requires-Dist: ipython; extra == "dev"
18
- Requires-Dist: ipdb; extra == "dev"
19
- Requires-Dist: nose; extra == "dev"
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
File without changes
File without changes
File without changes