plexus-python-pulse-common 1.1.85__tar.gz → 1.1.86__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 (95) hide show
  1. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/PKG-INFO +1 -1
  2. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/src/plexus_python_pulse_common.egg-info/PKG-INFO +1 -1
  3. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/test/plexus_tests/pulse/common/utils/ormutils_test.py +11 -3
  4. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/test/plexus_tests/pulse/common/utils/s3utils_test.py +47 -29
  5. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/.editorconfig +0 -0
  6. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/.github/workflows/pr.yml +0 -0
  7. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/.github/workflows/push.yml +0 -0
  8. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/.gitignore +0 -0
  9. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/MANIFEST.in +0 -0
  10. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/README.md +0 -0
  11. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/VERSION +0 -0
  12. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/pyproject.toml +0 -0
  13. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/resources/unittest/jsonutils/dummy.0.jsonl +0 -0
  14. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/resources/unittest/jsonutils/dummy.1.jsonl +0 -0
  15. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/resources/unittest/jsonutils/dummy.2.jsonl +0 -0
  16. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/resources/unittest/pathutils/0-dummy +0 -0
  17. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/resources/unittest/pathutils/1-dummy +0 -0
  18. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/resources/unittest/pathutils/2-dummy +0 -0
  19. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/resources/unittest/pathutils/dummy.0.0.jsonl +0 -0
  20. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/resources/unittest/pathutils/dummy.0.0.vol-0.jsonl +0 -0
  21. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/resources/unittest/pathutils/dummy.0.jsonl +0 -0
  22. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/resources/unittest/pathutils/dummy.1.1.jsonl +0 -0
  23. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/resources/unittest/pathutils/dummy.1.1.vol-1.jsonl +0 -0
  24. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/resources/unittest/pathutils/dummy.1.jsonl +0 -0
  25. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/resources/unittest/pathutils/dummy.2.2.jsonl +0 -0
  26. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/resources/unittest/pathutils/dummy.2.2.vol-2.jsonl +0 -0
  27. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/resources/unittest/pathutils/dummy.2.jsonl +0 -0
  28. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/resources/unittest/pathutils/dummy.csv.part0 +0 -0
  29. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/resources/unittest/pathutils/dummy.csv.part1 +0 -0
  30. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/resources/unittest/pathutils/dummy.csv.part2 +0 -0
  31. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/resources/unittest/pathutils/dummy.txt +0 -0
  32. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/resources/unittest/s3utils/dir.baz/file.bar.baz +0 -0
  33. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/resources/unittest/s3utils/dir.baz/file.foo.bar +0 -0
  34. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/resources/unittest/s3utils/dir.baz/file.foo.baz +0 -0
  35. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/resources/unittest/s3utils/dir.foo/dir.foo.bar/dir.foo.bar.baz/file.foo.bar.baz +0 -0
  36. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/resources/unittest/s3utils/dir.foo/dir.foo.bar/file.bar.baz +0 -0
  37. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/resources/unittest/s3utils/dir.foo/dir.foo.bar/file.foo.bar +0 -0
  38. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/resources/unittest/s3utils/dir.foo/dir.foo.bar/file.foo.baz +0 -0
  39. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/resources/unittest/s3utils/dir.foo/file.bar +0 -0
  40. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/resources/unittest/s3utils/dir.foo/file.baz +0 -0
  41. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/resources/unittest/s3utils/dir.foo/file.foo +0 -0
  42. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/resources/unittest/s3utils_archive/archive.compressed.zip +0 -0
  43. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/resources/unittest/s3utils_archive/archive.uncompressed.zip +0 -0
  44. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/setup.cfg +0 -0
  45. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/setup.py +0 -0
  46. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/src/plexus/pulse/common/__init__.py +0 -0
  47. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/src/plexus/pulse/common/carto/OSMFile.py +0 -0
  48. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/src/plexus/pulse/common/carto/OSMNode.py +0 -0
  49. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/src/plexus/pulse/common/carto/OSMTags.py +0 -0
  50. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/src/plexus/pulse/common/carto/OSMWay.py +0 -0
  51. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/src/plexus/pulse/common/carto/__init__.py +0 -0
  52. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/src/plexus/pulse/common/resources/__init__.py +0 -0
  53. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/src/plexus/pulse/common/resources/tags/__init__.py +0 -0
  54. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/src/plexus/pulse/common/resources/tags/unittest-1.0.0.tagset.yaml +0 -0
  55. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/src/plexus/pulse/common/resources/tags/universal-1.0.0.tagset.yaml +0 -0
  56. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/src/plexus/pulse/common/utils/__init__.py +0 -0
  57. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/src/plexus/pulse/common/utils/apiutils.py +0 -0
  58. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/src/plexus/pulse/common/utils/bagutils.py +0 -0
  59. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/src/plexus/pulse/common/utils/config.py +0 -0
  60. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/src/plexus/pulse/common/utils/datautils.py +0 -0
  61. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/src/plexus/pulse/common/utils/dockerutils.py +0 -0
  62. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/src/plexus/pulse/common/utils/flowutils.py +0 -0
  63. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/src/plexus/pulse/common/utils/gisutils.py +0 -0
  64. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/src/plexus/pulse/common/utils/jsonutils.py +0 -0
  65. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/src/plexus/pulse/common/utils/ormutils.py +0 -0
  66. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/src/plexus/pulse/common/utils/pathutils.py +0 -0
  67. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/src/plexus/pulse/common/utils/s3utils.py +0 -0
  68. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/src/plexus/pulse/common/utils/sqlutils.py +0 -0
  69. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/src/plexus/pulse/common/utils/strutils.py +0 -0
  70. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/src/plexus/pulse/common/utils/tagutils.py +0 -0
  71. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/src/plexus/pulse/common/utils/testutils.py +0 -0
  72. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/src/plexus_python_pulse_common.egg-info/SOURCES.txt +0 -0
  73. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/src/plexus_python_pulse_common.egg-info/dependency_links.txt +0 -0
  74. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/src/plexus_python_pulse_common.egg-info/not-zip-safe +0 -0
  75. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/src/plexus_python_pulse_common.egg-info/requires.txt +0 -0
  76. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/src/plexus_python_pulse_common.egg-info/top_level.txt +0 -0
  77. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/test/plexus_tests/__init__.py +0 -0
  78. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/test/plexus_tests/pulse/__init__.py +0 -0
  79. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/test/plexus_tests/pulse/common/__init__.py +0 -0
  80. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/test/plexus_tests/pulse/common/carto/__init__.py +0 -0
  81. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/test/plexus_tests/pulse/common/carto/osm_file_test.py +0 -0
  82. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/test/plexus_tests/pulse/common/carto/osm_tags_test.py +0 -0
  83. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/test/plexus_tests/pulse/common/utils/__init__.py +0 -0
  84. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/test/plexus_tests/pulse/common/utils/apiutils_test.py +0 -0
  85. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/test/plexus_tests/pulse/common/utils/bagutils_test.py +0 -0
  86. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/test/plexus_tests/pulse/common/utils/datautils_test.py +0 -0
  87. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/test/plexus_tests/pulse/common/utils/dockerutils_test.py +0 -0
  88. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/test/plexus_tests/pulse/common/utils/flowutils_test.py +0 -0
  89. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/test/plexus_tests/pulse/common/utils/gisutils_test.py +0 -0
  90. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/test/plexus_tests/pulse/common/utils/jsonutils_test.py +0 -0
  91. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/test/plexus_tests/pulse/common/utils/pathutils_test.py +0 -0
  92. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/test/plexus_tests/pulse/common/utils/strutils_test.py +0 -0
  93. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/test/plexus_tests/pulse/common/utils/tagutils_test.py +0 -0
  94. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/test/plexus_tests/pulse/common/utils/testutils_test.py +0 -0
  95. {plexus_python_pulse_common-1.1.85 → plexus_python_pulse_common-1.1.86}/test/testenv.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plexus-python-pulse-common
3
- Version: 1.1.85
3
+ Version: 1.1.86
4
4
  Classifier: Programming Language :: Python :: 3
5
5
  Classifier: Programming Language :: Python :: 3.12
6
6
  Classifier: Programming Language :: Python :: 3.13
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plexus-python-pulse-common
3
- Version: 1.1.85
3
+ Version: 1.1.86
4
4
  Classifier: Programming Language :: Python :: 3
5
5
  Classifier: Programming Language :: Python :: 3.12
6
6
  Classifier: Programming Language :: Python :: 3.13
@@ -17,9 +17,17 @@ from sqlmodel import Field, SQLModel
17
17
 
18
18
  from plexus.pulse.common.utils.apiutils import managed_db_session
19
19
  from plexus.pulse.common.utils.ormutils import (
20
- changing_model_mixin, make_base_model, make_changing_model_mixin,
21
- make_revision_model_mixin, make_revision_model_trigger, make_sequence_model_mixin, make_snapshot_model_mixin,
22
- make_snapshot_model_trigger, model_copy_from, revision_model_mixin, snapshot_model_mixin,
20
+ changing_model_mixin,
21
+ make_base_model,
22
+ make_changing_model_mixin,
23
+ make_revision_model_mixin,
24
+ make_revision_model_trigger,
25
+ make_sequence_model_mixin,
26
+ make_snapshot_model_mixin,
27
+ make_snapshot_model_trigger,
28
+ model_copy_from,
29
+ revision_model_mixin,
30
+ snapshot_model_mixin,
23
31
  )
24
32
  from plexus.pulse.common.utils.ormutils import (
25
33
  db_activate_revision_model,
@@ -43,8 +43,9 @@ class S3UtilsTest(unittest.TestCase):
43
43
  result = list(s3_list_objects(client, "dummy-bucket", "dummy_prefix/"))
44
44
 
45
45
  for key, text in data:
46
- self.assertTrue(any(o.key == key for o in result))
47
- self.assertEqual(s3_pull_text(client, "dummy-bucket", key), text)
46
+ with self.subTest(progressed_client=False, key=key):
47
+ self.assertTrue(any(o.key == key for o in result))
48
+ self.assertEqual(s3_pull_text(client, "dummy-bucket", key), text)
48
49
 
49
50
  with moto.mock_aws(), s3_make_progressed_client() as client:
50
51
  client.create_bucket(Bucket="dummy-bucket")
@@ -61,8 +62,9 @@ class S3UtilsTest(unittest.TestCase):
61
62
  result = list(s3_list_objects(client, "dummy-bucket", "dummy_prefix/"))
62
63
 
63
64
  for key, text in data:
64
- self.assertTrue(any(o.key == key for o in result))
65
- self.assertEqual(s3_pull_text(client, "dummy-bucket", key), text)
65
+ with self.subTest(progressed_client=True, key=key):
66
+ self.assertTrue(any(o.key == key for o in result))
67
+ self.assertEqual(s3_pull_text(client, "dummy-bucket", key), text)
66
68
 
67
69
  def test_s3_list_files__random_text_files(self):
68
70
  with moto.mock_aws(), s3_make_client() as client:
@@ -80,8 +82,9 @@ class S3UtilsTest(unittest.TestCase):
80
82
  result = list(s3_list_files(client, "dummy-bucket", "dummy_prefix/"))
81
83
 
82
84
  for key, text in data:
83
- self.assertTrue(any(o.key == key for o in result))
84
- self.assertEqual(s3_pull_text(client, "dummy-bucket", key), text)
85
+ with self.subTest(progressed_client=False, key=key):
86
+ self.assertTrue(any(o.key == key for o in result))
87
+ self.assertEqual(s3_pull_text(client, "dummy-bucket", key), text)
85
88
 
86
89
  with moto.mock_aws(), s3_make_progressed_client() as client:
87
90
  client.create_bucket(Bucket="dummy-bucket")
@@ -98,8 +101,9 @@ class S3UtilsTest(unittest.TestCase):
98
101
  result = list(s3_list_files(client, "dummy-bucket", "dummy_prefix/"))
99
102
 
100
103
  for key, text in data:
101
- self.assertTrue(any(o.key == key for o in result))
102
- self.assertEqual(s3_pull_text(client, "dummy-bucket", key), text)
104
+ with self.subTest(progressed_client=True, key=key):
105
+ self.assertTrue(any(o.key == key for o in result))
106
+ self.assertEqual(s3_pull_text(client, "dummy-bucket", key), text)
103
107
 
104
108
  data_s3_list_files = [
105
109
  (
@@ -498,14 +502,15 @@ class S3UtilsTest(unittest.TestCase):
498
502
  ["s3utils_archive/archive.uncompressed.zip", "s3utils_archive/archive.compressed.zip"],
499
503
  [local_members, None],
500
504
  ):
501
- archive_size, member_zip_infos, missed_members = s3_archive_list_files(client,
502
- "dummy-bucket",
503
- archive_key,
504
- members)
505
+ with self.subTest(archive_key=archive_key, members=members):
506
+ archive_size, member_zip_infos, missed_members = s3_archive_list_files(client,
507
+ "dummy-bucket",
508
+ archive_key,
509
+ members)
505
510
 
506
- self.assertEqual(archive_size - sum(info.compress_size for info in member_zip_infos), 2470)
507
- self.assertEqual(set(info.filename for info in member_zip_infos), set(local_members))
508
- self.assertEqual(len(missed_members), 0)
511
+ self.assertEqual(archive_size - sum(info.compress_size for info in member_zip_infos), 2470)
512
+ self.assertEqual(set(info.filename for info in member_zip_infos), set(local_members))
513
+ self.assertEqual(len(missed_members), 0)
509
514
 
510
515
  for archive_key, (members, members_expect) in itertools.product(
511
516
  ["s3utils_archive/archive.uncompressed.zip", "s3utils_archive/archive.compressed.zip"],
@@ -533,13 +538,14 @@ class S3UtilsTest(unittest.TestCase):
533
538
  ),
534
539
  ],
535
540
  ):
536
- archive_size, member_zip_infos, missed_members = s3_archive_list_files(client,
537
- "dummy-bucket",
538
- archive_key,
539
- members)
541
+ with self.subTest(archive_key=archive_key, members=members):
542
+ archive_size, member_zip_infos, missed_members = s3_archive_list_files(client,
543
+ "dummy-bucket",
544
+ archive_key,
545
+ members)
540
546
 
541
- self.assertEqual(sorted(list(info.filename for info in member_zip_infos)), sorted(members_expect))
542
- self.assertEqual(len(missed_members), 0)
547
+ self.assertEqual(sorted(list(info.filename for info in member_zip_infos)), sorted(members_expect))
548
+ self.assertEqual(len(missed_members), 0)
543
549
 
544
550
  def test_s3_archive_open_member(self):
545
551
  with (
@@ -562,6 +568,7 @@ class S3UtilsTest(unittest.TestCase):
562
568
  ):
563
569
  for local_member in local_members:
564
570
  with (
571
+ self.subTest(archive_key=archive_key, mode=mode, member=local_member),
565
572
  open(local_root / local_member, mode) as local_fh,
566
573
  s3_archive_open_member(client, "dummy-bucket", archive_key, local_member, mode) as s3_fh,
567
574
  ):
@@ -589,14 +596,25 @@ class S3UtilsTest(unittest.TestCase):
589
596
  [False, True, s3_archive_use_ranged_requests()],
590
597
  [False, True, s3_archive_use_chunked_reads()],
591
598
  ):
592
- for member, opener in s3_archive_open_members(
593
- client,
594
- "dummy-bucket",
595
- archive_key,
596
- members,
597
- mode,
599
+ with self.subTest(
600
+ archive_key=archive_key,
601
+ members=members,
602
+ mode=mode,
598
603
  use_ranged_requests=use_ranged_requests,
599
604
  use_chunked_reads=use_chunked_reads,
600
605
  ):
601
- with open(local_root / member, mode) as local_fh, opener() as s3_fh:
602
- self.assertEqual(local_fh.read(), s3_fh.read())
606
+ for member, opener in s3_archive_open_members(
607
+ client,
608
+ "dummy-bucket",
609
+ archive_key,
610
+ members,
611
+ mode,
612
+ use_ranged_requests=use_ranged_requests,
613
+ use_chunked_reads=use_chunked_reads,
614
+ ):
615
+ with (
616
+ self.subTest(member=member),
617
+ open(local_root / member, mode) as local_fh,
618
+ opener() as s3_fh,
619
+ ):
620
+ self.assertEqual(local_fh.read(), s3_fh.read())