plexus-python-common 1.0.46__tar.gz → 1.0.47__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 (94) hide show
  1. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/PKG-INFO +1 -1
  2. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/src/plexus/common/utils/bagutils.py +33 -34
  3. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/src/plexus/common/utils/config.py +5 -3
  4. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/src/plexus/common/utils/jsonutils.py +1 -1
  5. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/src/plexus/common/utils/s3utils.py +30 -25
  6. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/src/plexus/common/utils/tagutils.py +10 -10
  7. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/src/plexus_python_common.egg-info/PKG-INFO +1 -1
  8. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/src/plexus_python_common.egg-info/SOURCES.txt +22 -19
  9. plexus_python_common-1.0.47/test/plexus_tests/__init__.py +0 -0
  10. plexus_python_common-1.0.47/test/plexus_tests/common/__init__.py +0 -0
  11. plexus_python_common-1.0.47/test/plexus_tests/common/carto/__init__.py +0 -0
  12. plexus_python_common-1.0.47/test/plexus_tests/common/utils/__init__.py +0 -0
  13. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/test/plexus_tests/common/utils/jsonutils_test.py +2 -3
  14. plexus_python_common-1.0.46/test/plexus_tests/common/utils/shutils_test.py → plexus_python_common-1.0.47/test/plexus_tests/common/utils/pathutils_test.py +9 -14
  15. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/test/plexus_tests/common/utils/s3utils_test.py +69 -59
  16. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/test/plexus_tests/common/utils/tagutils_test.py +1 -2
  17. plexus_python_common-1.0.47/test/testenv.py +15 -0
  18. plexus_python_common-1.0.46/test/plexus_test.py +0 -13
  19. plexus_python_common-1.0.46/test/plexus_tests/__init__.py +0 -15
  20. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/.editorconfig +0 -0
  21. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/.github/workflows/pr.yml +0 -0
  22. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/.github/workflows/push.yml +0 -0
  23. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/.gitignore +0 -0
  24. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/MANIFEST.in +0 -0
  25. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/README.md +0 -0
  26. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/VERSION +0 -0
  27. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/pyproject.toml +0 -0
  28. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/resources/unittest/jsonutils/dummy.0.jsonl +0 -0
  29. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/resources/unittest/jsonutils/dummy.1.jsonl +0 -0
  30. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/resources/unittest/jsonutils/dummy.2.jsonl +0 -0
  31. {plexus_python_common-1.0.46/resources/unittest/shutils → plexus_python_common-1.0.47/resources/unittest/pathutils}/0-dummy +0 -0
  32. {plexus_python_common-1.0.46/resources/unittest/shutils → plexus_python_common-1.0.47/resources/unittest/pathutils}/1-dummy +0 -0
  33. {plexus_python_common-1.0.46/resources/unittest/shutils → plexus_python_common-1.0.47/resources/unittest/pathutils}/2-dummy +0 -0
  34. {plexus_python_common-1.0.46/resources/unittest/shutils → plexus_python_common-1.0.47/resources/unittest/pathutils}/dummy.0.0.jsonl +0 -0
  35. {plexus_python_common-1.0.46/resources/unittest/shutils → plexus_python_common-1.0.47/resources/unittest/pathutils}/dummy.0.0.vol-0.jsonl +0 -0
  36. {plexus_python_common-1.0.46/resources/unittest/shutils → plexus_python_common-1.0.47/resources/unittest/pathutils}/dummy.0.jsonl +0 -0
  37. {plexus_python_common-1.0.46/resources/unittest/shutils → plexus_python_common-1.0.47/resources/unittest/pathutils}/dummy.1.1.jsonl +0 -0
  38. {plexus_python_common-1.0.46/resources/unittest/shutils → plexus_python_common-1.0.47/resources/unittest/pathutils}/dummy.1.1.vol-1.jsonl +0 -0
  39. {plexus_python_common-1.0.46/resources/unittest/shutils → plexus_python_common-1.0.47/resources/unittest/pathutils}/dummy.1.jsonl +0 -0
  40. {plexus_python_common-1.0.46/resources/unittest/shutils → plexus_python_common-1.0.47/resources/unittest/pathutils}/dummy.2.2.jsonl +0 -0
  41. {plexus_python_common-1.0.46/resources/unittest/shutils → plexus_python_common-1.0.47/resources/unittest/pathutils}/dummy.2.2.vol-2.jsonl +0 -0
  42. {plexus_python_common-1.0.46/resources/unittest/shutils → plexus_python_common-1.0.47/resources/unittest/pathutils}/dummy.2.jsonl +0 -0
  43. {plexus_python_common-1.0.46/resources/unittest/shutils → plexus_python_common-1.0.47/resources/unittest/pathutils}/dummy.csv.part0 +0 -0
  44. {plexus_python_common-1.0.46/resources/unittest/shutils → plexus_python_common-1.0.47/resources/unittest/pathutils}/dummy.csv.part1 +0 -0
  45. {plexus_python_common-1.0.46/resources/unittest/shutils → plexus_python_common-1.0.47/resources/unittest/pathutils}/dummy.csv.part2 +0 -0
  46. {plexus_python_common-1.0.46/resources/unittest/shutils → plexus_python_common-1.0.47/resources/unittest/pathutils}/dummy.txt +0 -0
  47. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/resources/unittest/s3utils/dir.baz/file.bar.baz +0 -0
  48. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/resources/unittest/s3utils/dir.baz/file.foo.bar +0 -0
  49. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/resources/unittest/s3utils/dir.baz/file.foo.baz +0 -0
  50. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/resources/unittest/s3utils/dir.foo/dir.foo.bar/dir.foo.bar.baz/file.foo.bar.baz +0 -0
  51. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/resources/unittest/s3utils/dir.foo/dir.foo.bar/file.bar.baz +0 -0
  52. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/resources/unittest/s3utils/dir.foo/dir.foo.bar/file.foo.bar +0 -0
  53. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/resources/unittest/s3utils/dir.foo/dir.foo.bar/file.foo.baz +0 -0
  54. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/resources/unittest/s3utils/dir.foo/file.bar +0 -0
  55. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/resources/unittest/s3utils/dir.foo/file.baz +0 -0
  56. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/resources/unittest/s3utils/dir.foo/file.foo +0 -0
  57. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/resources/unittest/s3utils_archive/archive.compressed.zip +0 -0
  58. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/resources/unittest/s3utils_archive/archive.uncompressed.zip +0 -0
  59. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/setup.cfg +0 -0
  60. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/setup.py +0 -0
  61. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/src/plexus/common/__init__.py +0 -0
  62. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/src/plexus/common/carto/OSMFile.py +0 -0
  63. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/src/plexus/common/carto/OSMNode.py +0 -0
  64. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/src/plexus/common/carto/OSMTags.py +0 -0
  65. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/src/plexus/common/carto/OSMWay.py +0 -0
  66. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/src/plexus/common/carto/__init__.py +0 -0
  67. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/src/plexus/common/pose.py +0 -0
  68. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/src/plexus/common/proj.py +0 -0
  69. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/src/plexus/common/resources/__init__.py +0 -0
  70. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/src/plexus/common/resources/tags/__init__.py +0 -0
  71. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/src/plexus/common/resources/tags/universal.tagset.yaml +0 -0
  72. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/src/plexus/common/utils/__init__.py +0 -0
  73. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/src/plexus/common/utils/apiutils.py +0 -0
  74. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/src/plexus/common/utils/datautils.py +0 -0
  75. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/src/plexus/common/utils/dockerutils.py +0 -0
  76. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/src/plexus/common/utils/ormutils.py +0 -0
  77. /plexus_python_common-1.0.46/src/plexus/common/utils/shutils.py → /plexus_python_common-1.0.47/src/plexus/common/utils/pathutils.py +0 -0
  78. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/src/plexus/common/utils/sqlutils.py +0 -0
  79. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/src/plexus/common/utils/strutils.py +0 -0
  80. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/src/plexus/common/utils/testutils.py +0 -0
  81. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/src/plexus_python_common.egg-info/dependency_links.txt +0 -0
  82. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/src/plexus_python_common.egg-info/not-zip-safe +0 -0
  83. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/src/plexus_python_common.egg-info/requires.txt +0 -0
  84. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/src/plexus_python_common.egg-info/top_level.txt +0 -0
  85. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/test/plexus_tests/common/carto/osm_file_test.py +0 -0
  86. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/test/plexus_tests/common/carto/osm_tags_test.py +0 -0
  87. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/test/plexus_tests/common/pose_test.py +0 -0
  88. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/test/plexus_tests/common/proj_test.py +0 -0
  89. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/test/plexus_tests/common/utils/bagutils_test.py +0 -0
  90. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/test/plexus_tests/common/utils/datautils_test.py +0 -0
  91. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/test/plexus_tests/common/utils/dockerutils_test.py +0 -0
  92. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/test/plexus_tests/common/utils/ormutils_test.py +0 -0
  93. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/test/plexus_tests/common/utils/strutils_test.py +0 -0
  94. {plexus_python_common-1.0.46 → plexus_python_common-1.0.47}/test/plexus_tests/common/utils/testutils_test.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plexus-python-common
3
- Version: 1.0.46
3
+ Version: 1.0.47
4
4
  Classifier: Programming Language :: Python :: 3
5
5
  Classifier: Programming Language :: Python :: 3.12
6
6
  Classifier: Programming Language :: Python :: 3.13
@@ -5,6 +5,7 @@ from typing import Literal
5
5
 
6
6
  import sqlalchemy as sa
7
7
  import sqlalchemy.orm as sa_orm
8
+ from iker.common.utils.pathutils import make_path
8
9
 
9
10
  __all__ = [
10
11
  "SerializationFormat",
@@ -77,12 +78,20 @@ class BagMessage(BagBase):
77
78
 
78
79
 
79
80
  class BagReader(AbstractContextManager):
80
- def __init__(self, db_dir: str, db_file: str = default_bag_db_file):
81
- self.db_path = os.path.join(db_dir, db_file)
82
- if not os.path.exists(self.db_path):
83
- raise FileNotFoundError(f"could not find SQLite DB at '{db_dir}'")
84
-
85
- self.engine = sa.create_engine(f"sqlite:///{self.db_path}")
81
+ def __init__(self, db_dir: str | os.PathLike[str], db_file: str | os.PathLike[str] = default_bag_db_file):
82
+ """
83
+ Creates a BagReader instance to read messages from a ROS2 bag file.
84
+
85
+ :param db_dir: directory containing the SQLite DB file.
86
+ :param db_file: name of the SQLite DB file.
87
+ :return: BagReader instance.
88
+ """
89
+ self.db_dir = make_path(db_dir)
90
+ self.db_path = self.db_dir / db_file
91
+ if not self.db_path.exists():
92
+ raise FileNotFoundError(f"could not find SQLite DB at '{str(self.db_path)}'")
93
+
94
+ self.engine = sa.create_engine(f"sqlite:///{str(self.db_path.absolute())}")
86
95
  self.session = sa_orm.Session(self.engine)
87
96
  self.topic_map = None
88
97
 
@@ -121,12 +130,22 @@ class BagReader(AbstractContextManager):
121
130
 
122
131
 
123
132
  class BagWriter(AbstractContextManager):
124
- def __init__(self, db_dir: str, db_file: str = default_bag_db_file):
125
- self.db_path = os.path.join(db_dir, db_file)
126
- if os.path.exists(self.db_path):
127
- os.remove(self.db_path)
128
-
129
- self.engine = sa.create_engine(f"sqlite:///{self.db_path}")
133
+ def __init__(self, db_dir: str | os.PathLike[str], db_file: str | os.PathLike[str] = default_bag_db_file):
134
+ """
135
+ Creates a BagWriter instance to write messages to a ROS2 bag file.
136
+
137
+ :param db_dir: directory to store the SQLite DB file.
138
+ :param db_file: name of the SQLite DB file.
139
+ :return: BagWriter instance.
140
+ """
141
+ self.db_dir = make_path(db_dir)
142
+ if not self.db_dir.exists():
143
+ self.db_dir.mkdir(parents=True, exist_ok=True)
144
+ self.db_path = self.db_dir / db_file
145
+ if self.db_path.exists():
146
+ self.db_path.unlink()
147
+
148
+ self.engine = sa.create_engine(f"sqlite:///{str(self.db_path.absolute())}")
130
149
  self.session = sa_orm.Session(self.engine)
131
150
  self.topic_map = {}
132
151
 
@@ -191,25 +210,5 @@ class BagWriter(AbstractContextManager):
191
210
  return db_message
192
211
 
193
212
 
194
- def bag_reader(db_dir: str, db_file: str = default_bag_db_file) -> BagReader:
195
- """
196
- Creates a BagReader instance to read messages from a ROS2 bag file.
197
-
198
- :param db_dir: directory containing the SQLite DB file.
199
- :param db_file: name of the SQLite DB file.
200
- :return: BagReader instance.
201
- """
202
- return BagReader(db_dir, db_file)
203
-
204
-
205
- def bag_writer(db_dir: str, db_file: str = default_bag_db_file) -> BagWriter:
206
- """
207
- Creates a BagWriter instance to write messages to a ROS2 bag file.
208
-
209
- :param db_dir: directory to store the SQLite DB file.
210
- :param db_file: name of the SQLite DB file.
211
- :return: BagWriter instance.
212
- """
213
- if not os.path.exists(db_dir):
214
- os.makedirs(db_dir, exist_ok=True)
215
- return BagWriter(db_dir, db_file)
213
+ bag_reader = BagReader
214
+ bag_writer = BagWriter
@@ -1,17 +1,19 @@
1
+ import os
2
+
1
3
  from iker.common.utils import logger
2
4
  from iker.common.utils.config import Config
3
5
  from iker.common.utils.funcutils import memorized
4
- from iker.common.utils.shutils import expanded_path
6
+ from iker.common.utils.pathutils import make_path
5
7
 
6
8
 
7
9
  @memorized()
8
- def config(config_path: str = "") -> Config:
10
+ def config(config_path: str | os.PathLike[str] = "") -> Config:
9
11
  default_items: list[tuple[str, str, str]] = [
10
12
  ("plexus", "logging.level", "INFO"),
11
13
  ("plexus", "logging.format", "%(asctime)s [%(levelname)s] %(name)s: %(message)s"),
12
14
  ]
13
15
 
14
- instance = Config(config_path or expanded_path("~/.plexus.cfg"))
16
+ instance = Config(config_path or make_path("~/.plexus.cfg", expand=True, normalize=True, absolute=True))
15
17
  instance.restore()
16
18
  instance.update(default_items, overwrite=False)
17
19
 
@@ -9,7 +9,7 @@ from iker.common.utils.iterutils import batched
9
9
  from iker.common.utils.jsonutils import JsonType, JsonValueCompatible
10
10
  from iker.common.utils.jsonutils import json_reformat
11
11
 
12
- from plexus.common.utils.shutils import collect_volumed_filenames, populate_volumed_filenames
12
+ from plexus.common.utils.pathutils import collect_volumed_filenames, populate_volumed_filenames
13
13
 
14
14
  __all__ = [
15
15
  "json_datetime_decoder",
@@ -6,7 +6,7 @@ import functools
6
6
  import io
7
7
  import mimetypes
8
8
  import os
9
- import os.path
9
+ import pathlib
10
10
  import shutil
11
11
  import tempfile
12
12
  import typing
@@ -20,7 +20,7 @@ import fsspec
20
20
  import fsspec.utils
21
21
  from iker.common.utils.iterutils import chunk_between, head, last
22
22
  from iker.common.utils.jsonutils import JsonObject
23
- from iker.common.utils.shutils import glob_match, listfile, path_depth
23
+ from iker.common.utils.pathutils import glob_match, make_path, path_depth, scan_files
24
24
  from iker.common.utils.strutils import is_empty, trim_to_none
25
25
  from mypy_boto3_s3 import S3Client
26
26
  from rich.progress import BarColumn, DownloadColumn, Progress, TextColumn, TransferSpeedColumn
@@ -30,7 +30,7 @@ __all__ = [
30
30
  "s3_make_client",
31
31
  "s3_head_object",
32
32
  "s3_list_objects",
33
- "s3_listfile",
33
+ "s3_list_files",
34
34
  "s3_cp_download",
35
35
  "s3_cp_upload",
36
36
  "s3_sync_download",
@@ -40,7 +40,7 @@ __all__ = [
40
40
  "s3_make_progressed_client",
41
41
  "ArchiveMemberChunk",
42
42
  "s3_archive_member_tree",
43
- "s3_archive_listfile",
43
+ "s3_archive_list_files",
44
44
  "s3_archive_open_member",
45
45
  "s3_archive_use_ranged_requests",
46
46
  "s3_archive_use_chunked_reads",
@@ -147,7 +147,7 @@ def s3_list_objects(
147
147
  continuation_token = response.get("NextContinuationToken")
148
148
 
149
149
 
150
- def s3_listfile(
150
+ def s3_list_files(
151
151
  client: S3Client,
152
152
  bucket: str,
153
153
  prefix: str,
@@ -173,9 +173,10 @@ def s3_listfile(
173
173
  prefix = prefix + "/"
174
174
 
175
175
  def filter_object_meta(object_meta: S3ObjectMeta) -> bool:
176
- if 0 < depth <= path_depth(prefix, os.path.dirname(object_meta.key)):
176
+ object_path = make_path(object_meta.key)
177
+ if 0 < depth <= path_depth(prefix, object_path.parent):
177
178
  return False
178
- if len(glob_match([os.path.basename(object_meta.key)], include_patterns, exclude_patterns)) == 0:
179
+ if len(glob_match([object_path.name], include_patterns, exclude_patterns)) == 0:
179
180
  return False
180
181
  return True
181
182
 
@@ -238,16 +239,18 @@ def s3_sync_download(
238
239
  if not prefix.endswith("/"):
239
240
  prefix = prefix + "/"
240
241
 
241
- objects = s3_listfile(client,
242
- bucket,
243
- prefix,
244
- include_patterns=include_patterns,
245
- exclude_patterns=exclude_patterns,
246
- depth=depth)
242
+ dir_path = make_path(dir_path)
243
+
244
+ objects = s3_list_files(client,
245
+ bucket,
246
+ prefix,
247
+ include_patterns=include_patterns,
248
+ exclude_patterns=exclude_patterns,
249
+ depth=depth)
247
250
 
248
251
  def download_file(key: str):
249
- file_path = os.path.join(dir_path, key[len(prefix):])
250
- os.makedirs(os.path.dirname(file_path), exist_ok=True)
252
+ file_path = dir_path / key[len(prefix):]
253
+ file_path.parent.mkdir(parents=True, exist_ok=True)
251
254
  s3_cp_download(client, bucket, key, file_path)
252
255
 
253
256
  with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor:
@@ -293,13 +296,15 @@ def s3_sync_upload(
293
296
  if not prefix.endswith("/"):
294
297
  prefix = prefix + "/"
295
298
 
296
- file_paths = listfile(dir_path,
297
- include_patterns=include_patterns,
298
- exclude_patterns=exclude_patterns,
299
- depth=depth)
299
+ dir_path = make_path(dir_path)
300
+
301
+ file_paths = scan_files(dir_path,
302
+ include_patterns=include_patterns,
303
+ exclude_patterns=exclude_patterns,
304
+ depth=depth)
300
305
 
301
- def upload_file(file_path: str):
302
- s3_cp_upload(client, file_path, bucket, prefix + os.path.relpath(file_path, dir_path))
306
+ def upload_file(file_path: pathlib.Path):
307
+ s3_cp_upload(client, file_path, bucket, prefix + str(file_path.relative_to(dir_path)))
303
308
 
304
309
  with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor:
305
310
  futures = [executor.submit(upload_file, file_path) for file_path in file_paths]
@@ -415,7 +420,7 @@ class S3ClientProgressProxy(object):
415
420
  Callback=None,
416
421
  Config=None,
417
422
  ):
418
- bytes_total = os.path.getsize(Filename)
423
+ bytes_total = make_path(Filename).stat().st_size
419
424
  with (
420
425
  contextlib.nullcontext(Callback) if Callback is not None
421
426
  else self.make_transfer_callback(Key, bytes_total, "upload")
@@ -585,7 +590,7 @@ def s3_archive_member_tree(
585
590
  return root_member_tree
586
591
 
587
592
 
588
- def s3_archive_listfile(
593
+ def s3_archive_list_files(
589
594
  client: S3Client,
590
595
  bucket: str,
591
596
  key: str,
@@ -597,7 +602,7 @@ def s3_archive_listfile(
597
602
  under that directory will be included in the results.
598
603
 
599
604
  Example usage:
600
- >>> archive_size, member_zip_infos, missed_members = s3_archive_listfile(client, bucket, key, members=["file1.txt", "dir1/"])
605
+ >>> archive_size, member_zip_infos, missed_members = s3_archive_list_files(client, bucket, key, members=["file1.txt", "dir1/"])
601
606
  >>> for info in member_zip_infos:
602
607
  ... print(info.filename, info.file_size)
603
608
  >>> if missed_members:
@@ -836,7 +841,7 @@ def s3_archive_open_members(
836
841
 
837
842
  s3_options = s3_options_from_s3_client(client)
838
843
 
839
- archive_size, member_zip_infos, missed_members = s3_archive_listfile(client, bucket, key, members)
844
+ archive_size, member_zip_infos, missed_members = s3_archive_list_files(client, bucket, key, members)
840
845
  if missed_members:
841
846
  raise FileNotFoundError(f"Archive members not found: {', '.join(missed_members)}")
842
847
 
@@ -1,6 +1,7 @@
1
1
  import dataclasses
2
2
  import datetime
3
- import os.path
3
+ import os
4
+ import pathlib
4
5
  import textwrap
5
6
  import typing
6
7
  from collections.abc import Generator, Mapping, Sequence
@@ -324,18 +325,17 @@ def render_tagset_markdown_readme(tagset: Tagset) -> str:
324
325
 
325
326
 
326
327
  @singleton
327
- def tag_cache_file_path() -> str:
328
- return os.path.expanduser(f"~/.local/plus/datahub/tag_cache/{randomizer().random_alphanumeric(7)}.db")
328
+ def tag_cache_file_path() -> pathlib.Path:
329
+ return pathlib.Path.home() / ".local" / "plus" / "datahub" / "tag_cache" / f"{randomizer().random_alphanumeric(7)}.db"
329
330
 
330
331
 
331
332
  class TagCache(object):
332
- def __init__(self, *, file_path: str | None = None, fail_if_exists: bool = False):
333
- self.file_path = file_path or tag_cache_file_path()
334
- if fail_if_exists and os.path.exists(self.file_path):
335
- raise FileExistsError(f"tag cache file '{self.file_path}' already exists")
336
- if not os.path.exists(os.path.dirname(self.file_path)):
337
- os.makedirs(os.path.dirname(self.file_path), exist_ok=True)
338
- self.conn_maker = ConnectionMaker.from_url(f"sqlite:///{self.file_path}",
333
+ def __init__(self, *, file_path: str | os.PathLike[str] | None = None, fail_if_exists: bool = False):
334
+ self.file_path = pathlib.Path(file_path or tag_cache_file_path())
335
+ if fail_if_exists and self.file_path.exists():
336
+ raise FileExistsError(f"tag cache file '{str(self.file_path)}' already exists")
337
+ self.file_path.parent.mkdir(parents=True, exist_ok=True)
338
+ self.conn_maker = ConnectionMaker.from_url(f"sqlite:///{str(self.file_path.absolute())}",
339
339
  engine_opts=dict(connect_args={"check_same_thread": False}))
340
340
  BaseModel.metadata.create_all(self.conn_maker.engine)
341
341
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plexus-python-common
3
- Version: 1.0.46
3
+ Version: 1.0.47
4
4
  Classifier: Programming Language :: Python :: 3
5
5
  Classifier: Programming Language :: Python :: 3.12
6
6
  Classifier: Programming Language :: Python :: 3.13
@@ -10,6 +10,22 @@ setup.py
10
10
  resources/unittest/jsonutils/dummy.0.jsonl
11
11
  resources/unittest/jsonutils/dummy.1.jsonl
12
12
  resources/unittest/jsonutils/dummy.2.jsonl
13
+ resources/unittest/pathutils/0-dummy
14
+ resources/unittest/pathutils/1-dummy
15
+ resources/unittest/pathutils/2-dummy
16
+ resources/unittest/pathutils/dummy.0.0.jsonl
17
+ resources/unittest/pathutils/dummy.0.0.vol-0.jsonl
18
+ resources/unittest/pathutils/dummy.0.jsonl
19
+ resources/unittest/pathutils/dummy.1.1.jsonl
20
+ resources/unittest/pathutils/dummy.1.1.vol-1.jsonl
21
+ resources/unittest/pathutils/dummy.1.jsonl
22
+ resources/unittest/pathutils/dummy.2.2.jsonl
23
+ resources/unittest/pathutils/dummy.2.2.vol-2.jsonl
24
+ resources/unittest/pathutils/dummy.2.jsonl
25
+ resources/unittest/pathutils/dummy.csv.part0
26
+ resources/unittest/pathutils/dummy.csv.part1
27
+ resources/unittest/pathutils/dummy.csv.part2
28
+ resources/unittest/pathutils/dummy.txt
13
29
  resources/unittest/s3utils/dir.baz/file.bar.baz
14
30
  resources/unittest/s3utils/dir.baz/file.foo.bar
15
31
  resources/unittest/s3utils/dir.baz/file.foo.baz
@@ -22,22 +38,6 @@ resources/unittest/s3utils/dir.foo/dir.foo.bar/file.foo.baz
22
38
  resources/unittest/s3utils/dir.foo/dir.foo.bar/dir.foo.bar.baz/file.foo.bar.baz
23
39
  resources/unittest/s3utils_archive/archive.compressed.zip
24
40
  resources/unittest/s3utils_archive/archive.uncompressed.zip
25
- resources/unittest/shutils/0-dummy
26
- resources/unittest/shutils/1-dummy
27
- resources/unittest/shutils/2-dummy
28
- resources/unittest/shutils/dummy.0.0.jsonl
29
- resources/unittest/shutils/dummy.0.0.vol-0.jsonl
30
- resources/unittest/shutils/dummy.0.jsonl
31
- resources/unittest/shutils/dummy.1.1.jsonl
32
- resources/unittest/shutils/dummy.1.1.vol-1.jsonl
33
- resources/unittest/shutils/dummy.1.jsonl
34
- resources/unittest/shutils/dummy.2.2.jsonl
35
- resources/unittest/shutils/dummy.2.2.vol-2.jsonl
36
- resources/unittest/shutils/dummy.2.jsonl
37
- resources/unittest/shutils/dummy.csv.part0
38
- resources/unittest/shutils/dummy.csv.part1
39
- resources/unittest/shutils/dummy.csv.part2
40
- resources/unittest/shutils/dummy.txt
41
41
  src/plexus/common/__init__.py
42
42
  src/plexus/common/pose.py
43
43
  src/plexus/common/proj.py
@@ -57,8 +57,8 @@ src/plexus/common/utils/datautils.py
57
57
  src/plexus/common/utils/dockerutils.py
58
58
  src/plexus/common/utils/jsonutils.py
59
59
  src/plexus/common/utils/ormutils.py
60
+ src/plexus/common/utils/pathutils.py
60
61
  src/plexus/common/utils/s3utils.py
61
- src/plexus/common/utils/shutils.py
62
62
  src/plexus/common/utils/sqlutils.py
63
63
  src/plexus/common/utils/strutils.py
64
64
  src/plexus/common/utils/tagutils.py
@@ -69,19 +69,22 @@ src/plexus_python_common.egg-info/dependency_links.txt
69
69
  src/plexus_python_common.egg-info/not-zip-safe
70
70
  src/plexus_python_common.egg-info/requires.txt
71
71
  src/plexus_python_common.egg-info/top_level.txt
72
- test/plexus_test.py
72
+ test/testenv.py
73
73
  test/plexus_tests/__init__.py
74
+ test/plexus_tests/common/__init__.py
74
75
  test/plexus_tests/common/pose_test.py
75
76
  test/plexus_tests/common/proj_test.py
77
+ test/plexus_tests/common/carto/__init__.py
76
78
  test/plexus_tests/common/carto/osm_file_test.py
77
79
  test/plexus_tests/common/carto/osm_tags_test.py
80
+ test/plexus_tests/common/utils/__init__.py
78
81
  test/plexus_tests/common/utils/bagutils_test.py
79
82
  test/plexus_tests/common/utils/datautils_test.py
80
83
  test/plexus_tests/common/utils/dockerutils_test.py
81
84
  test/plexus_tests/common/utils/jsonutils_test.py
82
85
  test/plexus_tests/common/utils/ormutils_test.py
86
+ test/plexus_tests/common/utils/pathutils_test.py
83
87
  test/plexus_tests/common/utils/s3utils_test.py
84
- test/plexus_tests/common/utils/shutils_test.py
85
88
  test/plexus_tests/common/utils/strutils_test.py
86
89
  test/plexus_tests/common/utils/tagutils_test.py
87
90
  test/plexus_tests/common/utils/testutils_test.py
@@ -4,13 +4,12 @@ import unittest
4
4
  import ddt
5
5
 
6
6
  from plexus.common.utils.jsonutils import read_chunked_jsonl
7
- from plexus_test import resources_directory
7
+ from testenv import resources_directory
8
8
 
9
9
 
10
10
  @ddt.ddt
11
11
  class JsonUtilsTest(unittest.TestCase):
12
12
 
13
13
  def test_read_chunked_jsonl(self):
14
- for data, path in read_chunked_jsonl(
15
- os.path.join(resources_directory, "unittest/jsonutils", "dummy.{{}}.jsonl")):
14
+ for data, path in read_chunked_jsonl(str(resources_directory / "unittest" / "jsonutils" / "dummy.{{}}.jsonl")):
16
15
  self.assertEqual(data["file"], os.path.basename(path))
@@ -1,16 +1,15 @@
1
- import os
2
1
  import unittest
3
2
  from collections.abc import Callable, Generator
4
3
 
5
4
  import ddt
6
5
  from iker.common.utils.dtutils import dt_parse_iso
7
6
 
8
- from plexus.common.utils.shutils import collect_volumed_filenames, populate_volumed_filenames
9
- from plexus_tests import resources_directory
7
+ from plexus.common.utils.pathutils import collect_volumed_filenames, populate_volumed_filenames
8
+ from testenv import resources_directory
10
9
 
11
10
 
12
11
  @ddt.ddt
13
- class ShUtilsTest(unittest.TestCase):
12
+ class PathUtilsTest(unittest.TestCase):
14
13
  data_collect_volumed_filenames = [
15
14
  ("dummy.txt", [("dummy.txt", {})]),
16
15
  (
@@ -75,10 +74,8 @@ class ShUtilsTest(unittest.TestCase):
75
74
  @ddt.unpack
76
75
  def test_collect_volumed_filenames(self, template, names):
77
76
  self.assertEqual(
78
- list((os.path.join(resources_directory, "unittest/shutils", name), volumes)
79
- for name, volumes in names),
80
- list(sorted(
81
- collect_volumed_filenames(os.path.join(resources_directory, "unittest/shutils", template)))),
77
+ list((str(resources_directory / "unittest" / "pathutils" / name), volumes) for name, volumes in names),
78
+ list(sorted(collect_volumed_filenames(resources_directory / "unittest" / "pathutils" / template))),
82
79
  )
83
80
 
84
81
  data_populate_volumed_filenames = [
@@ -144,10 +141,9 @@ class ShUtilsTest(unittest.TestCase):
144
141
  @ddt.idata(data_populate_volumed_filenames)
145
142
  @ddt.unpack
146
143
  def test_populate_volumed_filenames(self, template, names):
147
- generator = populate_volumed_filenames(os.path.join(resources_directory, "unittest/shutils", template))
144
+ generator = populate_volumed_filenames(resources_directory / "unittest" / "pathutils" / template)
148
145
  self.assertEqual(
149
- list((os.path.join(resources_directory, "unittest/shutils", name), volumes)
150
- for name, volumes in names),
146
+ list((str(resources_directory / "unittest" / "pathutils" / name), volumes) for name, volumes in names),
151
147
  list(next(generator) for _ in names),
152
148
  )
153
149
 
@@ -258,10 +254,9 @@ class ShUtilsTest(unittest.TestCase):
258
254
 
259
255
  return volume_func
260
256
 
261
- generator = populate_volumed_filenames(os.path.join(resources_directory, "unittest/shutils", template),
257
+ generator = populate_volumed_filenames(resources_directory / "unittest" / "pathutils" / template,
262
258
  volume_func=make_custom_volume_func())
263
259
  self.assertEqual(
264
- list((os.path.join(resources_directory, "unittest/shutils", name), volumes)
265
- for name, volumes in names),
260
+ list((str(resources_directory / "unittest" / "pathutils" / name), volumes) for name, volumes in names),
266
261
  list(next(generator) for _ in names),
267
262
  )
@@ -1,18 +1,16 @@
1
1
  import contextlib
2
2
  import itertools
3
- import os
4
3
  import tempfile
5
4
  import unittest
6
5
 
7
6
  import ddt
8
7
  import moto
9
8
  import moto.server
9
+ from iker.common.utils.pathutils import make_path, scan_files
10
10
  from iker.common.utils.randutils import randomizer
11
- from iker.common.utils.shutils import listfile
12
- from iker.common.utils.testutils import norm_path
13
11
 
14
12
  from plexus.common.utils.s3utils import *
15
- from plexus_tests import resources_directory
13
+ from testenv import resources_directory
16
14
 
17
15
 
18
16
  @contextlib.contextmanager
@@ -66,7 +64,7 @@ class S3UtilsTest(unittest.TestCase):
66
64
  self.assertTrue(any(o.key == key for o in result))
67
65
  self.assertEqual(s3_pull_text(client, "dummy-bucket", key), text)
68
66
 
69
- def test_s3_listfile__random_text_files(self):
67
+ def test_s3_list_files__random_text_files(self):
70
68
  with moto.mock_aws(), s3_make_client() as client:
71
69
  client.create_bucket(Bucket="dummy-bucket")
72
70
 
@@ -79,7 +77,7 @@ class S3UtilsTest(unittest.TestCase):
79
77
  for key, text in data:
80
78
  s3_push_text(client, text, "dummy-bucket", key)
81
79
 
82
- result = list(s3_listfile(client, "dummy-bucket", "dummy_prefix/"))
80
+ result = list(s3_list_files(client, "dummy-bucket", "dummy_prefix/"))
83
81
 
84
82
  for key, text in data:
85
83
  self.assertTrue(any(o.key == key for o in result))
@@ -97,13 +95,13 @@ class S3UtilsTest(unittest.TestCase):
97
95
  for key, text in data:
98
96
  s3_push_text(client, text, "dummy-bucket", key)
99
97
 
100
- result = list(s3_listfile(client, "dummy-bucket", "dummy_prefix/"))
98
+ result = list(s3_list_files(client, "dummy-bucket", "dummy_prefix/"))
101
99
 
102
100
  for key, text in data:
103
101
  self.assertTrue(any(o.key == key for o in result))
104
102
  self.assertEqual(s3_pull_text(client, "dummy-bucket", key), text)
105
103
 
106
- data_s3_listfile = [
104
+ data_s3_list_files = [
107
105
  (
108
106
  "unittest/s3utils/",
109
107
  "dummy-bucket",
@@ -232,26 +230,26 @@ class S3UtilsTest(unittest.TestCase):
232
230
  ),
233
231
  ]
234
232
 
235
- @ddt.idata(data_s3_listfile)
233
+ @ddt.idata(data_s3_list_files)
236
234
  @ddt.unpack
237
- def test_s3_listfile(self, src, bucket, prefix, include_patterns, exclude_patterns, depth, expect):
235
+ def test_s3_list_files(self, src, bucket, prefix, include_patterns, exclude_patterns, depth, expect):
238
236
  with moto.mock_aws(), s3_make_client() as client:
239
237
  client.create_bucket(Bucket=bucket)
240
238
 
241
239
  s3_sync_upload(client,
242
- os.path.join(resources_directory, src),
240
+ resources_directory / src,
243
241
  bucket,
244
242
  prefix)
245
243
 
246
- object_metas = s3_listfile(client,
247
- bucket,
248
- prefix,
249
- include_patterns=include_patterns,
250
- exclude_patterns=exclude_patterns,
251
- depth=depth)
244
+ object_metas = s3_list_files(client,
245
+ bucket,
246
+ prefix,
247
+ include_patterns=include_patterns,
248
+ exclude_patterns=exclude_patterns,
249
+ depth=depth)
252
250
 
253
- self.assertSetEqual(set(map(lambda x: norm_path(x.key), object_metas)),
254
- set(map(lambda x: norm_path(x), expect)))
251
+ self.assertSetEqual(set(map(lambda x: make_path(x.key, normalize=True), object_metas)),
252
+ set(map(lambda x: make_path(x, normalize=True), expect)))
255
253
 
256
254
  data_s3_sync = [
257
255
  (
@@ -397,7 +395,7 @@ class S3UtilsTest(unittest.TestCase):
397
395
  client.create_bucket(Bucket=bucket)
398
396
 
399
397
  s3_sync_upload(client,
400
- os.path.join(resources_directory, src),
398
+ resources_directory / src,
401
399
  bucket,
402
400
  prefix,
403
401
  include_patterns=include_patterns,
@@ -405,54 +403,63 @@ class S3UtilsTest(unittest.TestCase):
405
403
  depth=depth)
406
404
 
407
405
  with tempfile.TemporaryDirectory() as temp_directory:
406
+ temp_directory = make_path(temp_directory)
408
407
  s3_sync_download(client,
409
408
  bucket,
410
409
  prefix,
411
- os.path.join(temp_directory, dst))
410
+ temp_directory / dst)
412
411
 
413
- self.assertSetEqual(set(map(lambda x: norm_path(x), listfile(os.path.join(temp_directory, dst)))),
414
- set(map(lambda x: norm_path(os.path.join(temp_directory, x)), expect)))
412
+ self.assertSetEqual(
413
+ set(map(lambda x: make_path(x, normalize=True), scan_files(temp_directory / dst))),
414
+ set(map(lambda x: make_path(temp_directory / x, normalize=True), expect)),
415
+ )
415
416
 
416
417
  with moto.mock_aws(), s3_make_client() as client:
417
418
  client.create_bucket(Bucket=bucket)
418
419
 
419
420
  s3_sync_upload(client,
420
- os.path.join(resources_directory, src),
421
+ resources_directory / src,
421
422
  bucket,
422
423
  prefix)
423
424
 
424
425
  with tempfile.TemporaryDirectory() as temp_directory:
426
+ temp_directory = make_path(temp_directory)
425
427
  s3_sync_download(client,
426
428
  bucket,
427
429
  prefix,
428
- os.path.join(temp_directory, dst),
430
+ temp_directory / dst,
429
431
  include_patterns=include_patterns,
430
432
  exclude_patterns=exclude_patterns,
431
433
  depth=depth)
432
434
 
433
- self.assertSetEqual(set(map(lambda x: norm_path(x), listfile(os.path.join(temp_directory, dst)))),
434
- set(map(lambda x: norm_path(os.path.join(temp_directory, x)), expect)))
435
+ self.assertSetEqual(
436
+ set(map(lambda x: make_path(x, normalize=True), scan_files(temp_directory / dst))),
437
+ set(map(lambda x: make_path(temp_directory / x, normalize=True), expect)),
438
+ )
435
439
 
436
440
  with moto.mock_aws(), s3_make_client() as client:
437
441
  client.create_bucket(Bucket=bucket)
438
442
 
439
443
  s3_sync_upload(client,
440
- os.path.join(resources_directory, src),
444
+ resources_directory / src,
441
445
  bucket,
442
446
  prefix,
443
447
  include_patterns=include_patterns,
444
448
  depth=depth)
445
449
 
446
450
  with tempfile.TemporaryDirectory() as temp_directory:
451
+ temp_directory = make_path(temp_directory)
447
452
  s3_sync_download(client,
448
453
  bucket,
449
454
  prefix,
450
- os.path.join(temp_directory, dst),
455
+ temp_directory / dst,
451
456
  exclude_patterns=exclude_patterns,
452
457
  depth=depth)
453
458
 
454
- self.assertSetEqual(set(map(lambda x: norm_path(x), listfile(os.path.join(temp_directory, dst)))),
455
- set(map(lambda x: norm_path(os.path.join(temp_directory, x)), expect)))
459
+ self.assertSetEqual(
460
+ set(map(lambda x: make_path(x, normalize=True), scan_files(temp_directory / dst))),
461
+ set(map(lambda x: make_path(temp_directory / x, normalize=True), expect)),
462
+ )
456
463
 
457
464
  data_s3_text = [
458
465
  ("dummy-bucket", "dummy/key", "dummy content", None),
@@ -472,7 +479,7 @@ class S3UtilsTest(unittest.TestCase):
472
479
  s3_push_text(client, text, bucket, key, encoding=encoding)
473
480
  self.assertEqual(s3_pull_text(client, bucket, key, encoding=encoding), text)
474
481
 
475
- def test_s3_archive_listfile(self):
482
+ def test_s3_archive_list_files(self):
476
483
  with (
477
484
  moto.mock_aws(),
478
485
  moto_server_endpoint_url() as endpoint_url,
@@ -481,21 +488,21 @@ class S3UtilsTest(unittest.TestCase):
481
488
  client.create_bucket(Bucket="dummy-bucket")
482
489
 
483
490
  s3_sync_upload(client,
484
- os.path.join(resources_directory, "unittest", "s3utils_archive"),
491
+ resources_directory / "unittest" / "s3utils_archive",
485
492
  "dummy-bucket",
486
493
  "s3utils_archive")
487
494
 
488
- local_root = os.path.join(resources_directory, "unittest", "s3utils")
489
- local_members = [os.path.relpath(file_path, local_root) for file_path in listfile(local_root)]
495
+ local_root = resources_directory / "unittest" / "s3utils"
496
+ local_members = [str(file_path.relative_to(local_root)) for file_path in scan_files(local_root)]
490
497
 
491
498
  for archive_key, members in itertools.product(
492
499
  ["s3utils_archive/archive.uncompressed.zip", "s3utils_archive/archive.compressed.zip"],
493
500
  [local_members, None],
494
501
  ):
495
- archive_size, member_zip_infos, missed_members = s3_archive_listfile(client,
496
- "dummy-bucket",
497
- archive_key,
498
- members)
502
+ archive_size, member_zip_infos, missed_members = s3_archive_list_files(client,
503
+ "dummy-bucket",
504
+ archive_key,
505
+ members)
499
506
 
500
507
  self.assertEqual(archive_size - sum(info.compress_size for info in member_zip_infos), 2470)
501
508
  self.assertEqual(set(info.filename for info in member_zip_infos), set(local_members))
@@ -506,28 +513,31 @@ class S3UtilsTest(unittest.TestCase):
506
513
  [(local_members, local_members),
507
514
  (None, local_members),
508
515
  (["dir.baz/", "dir.foo/"],
509
- [os.path.relpath(file_path, local_root)
516
+ [str(file_path.relative_to(local_root))
510
517
  for file_path in
511
- listfile(os.path.join(local_root, "dir.baz")) + listfile(os.path.join(local_root, "dir.foo"))],
518
+ itertools.chain(scan_files(local_root / "dir.baz"),
519
+ scan_files(local_root / "dir.foo"))],
512
520
  ),
513
521
  (["dir.foo/"],
514
- [os.path.relpath(file_path, local_root)
515
- for file_path in listfile(os.path.join(local_root, "dir.foo"))],
522
+ [str(file_path.relative_to(local_root))
523
+ for file_path in scan_files(local_root / "dir.foo")],
516
524
  ),
517
525
  (["dir.foo/"] * 3, # Duplicate entries, the result should repeat them as well
518
- [os.path.relpath(file_path, local_root)
519
- for file_path in (listfile(os.path.join(local_root, "dir.foo")) * 3)],
526
+ [str(file_path.relative_to(local_root))
527
+ for file_path in itertools.chain(scan_files(local_root / "dir.foo"),
528
+ scan_files(local_root / "dir.foo"),
529
+ scan_files(local_root / "dir.foo"))],
520
530
  ),
521
531
  (["dir.foo/dir.foo.bar/"],
522
- [os.path.relpath(file_path, local_root)
523
- for file_path in listfile(os.path.join(local_root, "dir.foo", "dir.foo.bar"))],
532
+ [str(file_path.relative_to(local_root))
533
+ for file_path in scan_files(local_root / "dir.foo" / "dir.foo.bar")],
524
534
  ),
525
535
  ],
526
536
  ):
527
- archive_size, member_zip_infos, missed_members = s3_archive_listfile(client,
528
- "dummy-bucket",
529
- archive_key,
530
- members)
537
+ archive_size, member_zip_infos, missed_members = s3_archive_list_files(client,
538
+ "dummy-bucket",
539
+ archive_key,
540
+ members)
531
541
 
532
542
  self.assertEqual(sorted(list(info.filename for info in member_zip_infos)), sorted(members_expect))
533
543
  self.assertEqual(len(missed_members), 0)
@@ -541,12 +551,12 @@ class S3UtilsTest(unittest.TestCase):
541
551
  client.create_bucket(Bucket="dummy-bucket")
542
552
 
543
553
  s3_sync_upload(client,
544
- os.path.join(resources_directory, "unittest", "s3utils_archive"),
554
+ resources_directory / "unittest" / "s3utils_archive",
545
555
  "dummy-bucket",
546
556
  "s3utils_archive")
547
557
 
548
- local_root = os.path.join(resources_directory, "unittest", "s3utils")
549
- local_members = [os.path.relpath(file_path, local_root) for file_path in listfile(local_root)]
558
+ local_root = resources_directory / "unittest" / "s3utils"
559
+ local_members = [str(file_path.relative_to(local_root)) for file_path in scan_files(local_root)]
550
560
 
551
561
  for archive_key, mode in itertools.product(
552
562
  ["s3utils_archive/archive.uncompressed.zip", "s3utils_archive/archive.compressed.zip"],
@@ -554,7 +564,7 @@ class S3UtilsTest(unittest.TestCase):
554
564
  ):
555
565
  for local_member in local_members:
556
566
  with (
557
- open(os.path.join(local_root, local_member), mode) as local_fh,
567
+ open(local_root / local_member, mode) as local_fh,
558
568
  s3_archive_open_member(client, "dummy-bucket", archive_key, local_member, mode) as s3_fh,
559
569
  ):
560
570
  self.assertEqual(local_fh.read(), s3_fh.read())
@@ -568,12 +578,12 @@ class S3UtilsTest(unittest.TestCase):
568
578
  client.create_bucket(Bucket="dummy-bucket")
569
579
 
570
580
  s3_sync_upload(client,
571
- os.path.join(resources_directory, "unittest", "s3utils_archive"),
581
+ resources_directory / "unittest" / "s3utils_archive",
572
582
  "dummy-bucket",
573
583
  "s3utils_archive")
574
584
 
575
- local_root = os.path.join(resources_directory, "unittest", "s3utils")
576
- local_members = [os.path.relpath(file_path, local_root) for file_path in listfile(local_root)]
585
+ local_root = resources_directory / "unittest" / "s3utils"
586
+ local_members = [str(file_path.relative_to(local_root)) for file_path in scan_files(local_root)]
577
587
 
578
588
  for archive_key, members, mode, use_ranged_requests, use_chunked_reads in itertools.product(
579
589
  ["s3utils_archive/archive.uncompressed.zip", "s3utils_archive/archive.compressed.zip"],
@@ -591,5 +601,5 @@ class S3UtilsTest(unittest.TestCase):
591
601
  use_ranged_requests=use_ranged_requests,
592
602
  use_chunked_reads=use_chunked_reads,
593
603
  ):
594
- with open(os.path.join(local_root, member), mode) as local_fh, opener() as s3_fh:
604
+ with open(local_root / member, mode) as local_fh, opener() as s3_fh:
595
605
  self.assertEqual(local_fh.read(), s3_fh.read())
@@ -1,5 +1,4 @@
1
1
  import datetime
2
- import os.path
3
2
  import unittest
4
3
 
5
4
  import ddt
@@ -33,7 +32,7 @@ class TagUtilsTest(unittest.TestCase):
33
32
  tag_cache = TagCache()
34
33
 
35
34
  self.assertEqual(tag_cache.file_path, tag_cache_file_path())
36
- self.assertTrue(os.path.exists(tag_cache.file_path))
35
+ self.assertTrue(tag_cache.file_path.exists())
37
36
 
38
37
  self.assertEqual(len(tag_cache.query("dummy_vehicle")), 0)
39
38
 
@@ -0,0 +1,15 @@
1
+ import pathlib
2
+
3
+ __all__ = [
4
+ "module_directory",
5
+ "source_directory",
6
+ "test_directory",
7
+ "resources_directory",
8
+ "temporary_directory",
9
+ ]
10
+
11
+ module_directory: pathlib.Path = pathlib.Path(__file__).absolute().parent.parent
12
+ source_directory: pathlib.Path = module_directory / "src"
13
+ test_directory: pathlib.Path = module_directory / "test"
14
+ resources_directory: pathlib.Path = module_directory / "resources"
15
+ temporary_directory: pathlib.Path = module_directory / "tmp"
@@ -1,13 +0,0 @@
1
- import unittest
2
-
3
- from plexus_tests import *
4
-
5
-
6
- class Test(unittest.TestCase):
7
-
8
- def test(self):
9
- self.assertIsNotNone(module_directory)
10
- self.assertIsNotNone(source_directory)
11
- self.assertIsNotNone(test_directory)
12
- self.assertIsNotNone(resources_directory)
13
- self.assertIsNotNone(temporary_directory)
@@ -1,15 +0,0 @@
1
- import os
2
-
3
- __all__ = [
4
- "module_directory",
5
- "source_directory",
6
- "test_directory",
7
- "resources_directory",
8
- "temporary_directory",
9
- ]
10
-
11
- module_directory: str = os.path.abspath(os.path.dirname(os.path.dirname(os.path.dirname(__file__))))
12
- source_directory: str = os.path.abspath(os.path.join(module_directory, "src"))
13
- test_directory: str = os.path.abspath(os.path.join(module_directory, "test"))
14
- resources_directory: str = os.path.abspath(os.path.join(module_directory, "resources"))
15
- temporary_directory: str = os.path.abspath(os.path.join(module_directory, "tmp"))