plexus-python-common 1.0.10__tar.gz → 1.0.12__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 (65) hide show
  1. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/PKG-INFO +1 -1
  2. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/src/plexus/common/utils/datautils.py +8 -3
  3. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/src/plexus/common/utils/ormutils.py +32 -16
  4. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/src/plexus/common/utils/strutils.py +13 -6
  5. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/src/plexus_python_common.egg-info/PKG-INFO +1 -1
  6. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/test/plexus_tests/common/utils/strutils_test.py +50 -19
  7. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/.editorconfig +0 -0
  8. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/.github/workflows/pr.yml +0 -0
  9. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/.github/workflows/push.yml +0 -0
  10. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/.gitignore +0 -0
  11. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/MANIFEST.in +0 -0
  12. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/README.md +0 -0
  13. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/VERSION +0 -0
  14. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/pyproject.toml +0 -0
  15. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/resources/unittest/jsonutils/dummy.0.jsonl +0 -0
  16. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/resources/unittest/jsonutils/dummy.1.jsonl +0 -0
  17. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/resources/unittest/jsonutils/dummy.2.jsonl +0 -0
  18. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/resources/unittest/shutils/0-dummy +0 -0
  19. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/resources/unittest/shutils/1-dummy +0 -0
  20. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/resources/unittest/shutils/2-dummy +0 -0
  21. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/resources/unittest/shutils/dummy.0.0.jsonl +0 -0
  22. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/resources/unittest/shutils/dummy.0.0.vol-0.jsonl +0 -0
  23. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/resources/unittest/shutils/dummy.0.jsonl +0 -0
  24. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/resources/unittest/shutils/dummy.1.1.jsonl +0 -0
  25. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/resources/unittest/shutils/dummy.1.1.vol-1.jsonl +0 -0
  26. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/resources/unittest/shutils/dummy.1.jsonl +0 -0
  27. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/resources/unittest/shutils/dummy.2.2.jsonl +0 -0
  28. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/resources/unittest/shutils/dummy.2.2.vol-2.jsonl +0 -0
  29. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/resources/unittest/shutils/dummy.2.jsonl +0 -0
  30. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/resources/unittest/shutils/dummy.csv.part0 +0 -0
  31. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/resources/unittest/shutils/dummy.csv.part1 +0 -0
  32. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/resources/unittest/shutils/dummy.csv.part2 +0 -0
  33. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/resources/unittest/shutils/dummy.txt +0 -0
  34. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/setup.cfg +0 -0
  35. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/setup.py +0 -0
  36. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/src/plexus/common/__init__.py +0 -0
  37. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/src/plexus/common/carto/OSMFile.py +0 -0
  38. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/src/plexus/common/carto/OSMNode.py +0 -0
  39. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/src/plexus/common/carto/OSMTags.py +0 -0
  40. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/src/plexus/common/carto/OSMWay.py +0 -0
  41. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/src/plexus/common/carto/__init__.py +0 -0
  42. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/src/plexus/common/config.py +0 -0
  43. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/src/plexus/common/pose.py +0 -0
  44. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/src/plexus/common/proj.py +0 -0
  45. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/src/plexus/common/utils/__init__.py +0 -0
  46. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/src/plexus/common/utils/bagutils.py +0 -0
  47. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/src/plexus/common/utils/jsonutils.py +0 -0
  48. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/src/plexus/common/utils/s3utils.py +0 -0
  49. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/src/plexus/common/utils/shutils.py +0 -0
  50. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/src/plexus_python_common.egg-info/SOURCES.txt +0 -0
  51. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/src/plexus_python_common.egg-info/dependency_links.txt +0 -0
  52. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/src/plexus_python_common.egg-info/not-zip-safe +0 -0
  53. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/src/plexus_python_common.egg-info/requires.txt +0 -0
  54. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/src/plexus_python_common.egg-info/top_level.txt +0 -0
  55. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/test/plexus_test.py +0 -0
  56. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/test/plexus_tests/__init__.py +0 -0
  57. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/test/plexus_tests/common/carto/osm_file_test.py +0 -0
  58. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/test/plexus_tests/common/carto/osm_tags_test.py +0 -0
  59. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/test/plexus_tests/common/pose_test.py +0 -0
  60. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/test/plexus_tests/common/proj_test.py +0 -0
  61. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/test/plexus_tests/common/utils/bagutils_test.py +0 -0
  62. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/test/plexus_tests/common/utils/datautils_test.py +0 -0
  63. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/test/plexus_tests/common/utils/jsonutils_test.py +0 -0
  64. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/test/plexus_tests/common/utils/ormutils_test.py +0 -0
  65. {plexus_python_common-1.0.10 → plexus_python_common-1.0.12}/test/plexus_tests/common/utils/shutils_test.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plexus-python-common
3
- Version: 1.0.10
3
+ Version: 1.0.12
4
4
  Classifier: Programming Language :: Python :: 3
5
5
  Classifier: Programming Language :: Python :: 3.11
6
6
  Classifier: Programming Language :: Python :: 3.12
@@ -9,12 +9,13 @@ from iker.common.utils.jsonutils import JsonType
9
9
  from iker.common.utils.randutils import randomizer
10
10
 
11
11
  from plexus.common.utils.strutils import BagName, UserName, VehicleName
12
+ from plexus.common.utils.strutils import colon_tag_parser, slash_tag_parser
12
13
  from plexus.common.utils.strutils import dot_case_parser, kebab_case_parser, snake_case_parser
13
14
  from plexus.common.utils.strutils import hex_string_parser
14
15
  from plexus.common.utils.strutils import parse_bag_name, parse_user_name, parse_vehicle_name
16
+ from plexus.common.utils.strutils import semver_parser, uuid_parser
15
17
  from plexus.common.utils.strutils import strict_abspath_parser, strict_relpath_parser
16
- from plexus.common.utils.strutils import tag_parser, topic_parser, vin_code_chars, vin_code_parser
17
- from plexus.common.utils.strutils import uuid_parser
18
+ from plexus.common.utils.strutils import topic_parser, vin_code_chars, vin_code_parser
18
19
 
19
20
 
20
21
  def make_compute_vin_code_check_digit() -> Callable[[str], str]:
@@ -55,7 +56,11 @@ validate_uuid = make_validate_string(uuid_parser)
55
56
  validate_strict_relpath = make_validate_string(strict_relpath_parser)
56
57
  validate_strict_abspath = make_validate_string(strict_abspath_parser)
57
58
 
58
- validate_tag = make_validate_string(tag_parser)
59
+ validate_semver = make_validate_string(semver_parser)
60
+
61
+ validate_colon_tag = make_validate_string(colon_tag_parser)
62
+ validate_slash_tag = make_validate_string(slash_tag_parser)
63
+
59
64
  validate_topic = make_validate_string(topic_parser)
60
65
 
61
66
 
@@ -153,7 +153,13 @@ class RecordModelMixinProto(Protocol):
153
153
  updated_at: datetime.datetime | None
154
154
 
155
155
  @classmethod
156
- def make_index_created_at(cls, index_name: str) -> sa.Index: ...
156
+ def make_index_created_at(cls, index_name: str) -> sa.Index:
157
+ """
158
+ Helper to create an index on the `created_at` field with the given index name.
159
+ :param index_name: Name of the index to create.
160
+ :return: The created SQLAlchemy Index object.
161
+ """
162
+ ...
157
163
 
158
164
 
159
165
  def make_record_model_mixin() -> type[RecordModelMixinProto]:
@@ -202,9 +208,6 @@ def make_record_model_mixin() -> type[RecordModelMixinProto]:
202
208
 
203
209
  @classmethod
204
210
  def make_index_created_at(cls, index_name: str) -> sa.Index:
205
- """
206
- Helper to create an index on the `created_at` field with the given index name.
207
- """
208
211
  return sa.Index(index_name, "created_at")
209
212
 
210
213
  return ModelMixin
@@ -217,13 +220,35 @@ class SnapshotModelMixinProto(Protocol):
217
220
  record_sid: int | None
218
221
 
219
222
  @classmethod
220
- def make_index_created_at_expired_at(cls, index_name: str) -> sa.Index: ...
223
+ def make_index_created_at_expired_at(cls, index_name: str) -> sa.Index:
224
+ """
225
+ Helper to create an index on the `created_at` and `expired_at` fields with the given index name.
226
+ :param index_name: Name of the index to create.
227
+ :return: The created SQLAlchemy Index object.
228
+ """
229
+ ...
221
230
 
222
231
  @classmethod
223
- def make_active_unique_index_record_sid(cls, index_name: str) -> sa.Index: ...
232
+ def make_active_unique_index_record_sid(cls, index_name: str) -> sa.Index:
233
+ """
234
+ Helper to create a unique index on the `record_sid` field for active records (where `expired_at` is NULL).
235
+ This ensures that there is only one active snapshot per record at any given time.
236
+ :param index_name: Name of the index to create.
237
+ :return: The created SQLAlchemy Index object.
238
+ """
239
+ ...
224
240
 
225
241
  @classmethod
226
- def make_active_unique_index_for(cls, index_name: str, *fields: str) -> sa.Index: ...
242
+ def make_active_unique_index_for(cls, index_name: str, *fields: str) -> sa.Index:
243
+ """
244
+ Helper to create a unique index on the specified fields for active records (where `expired_at` is NULL).
245
+ This ensures that there is only one active snapshot per combination of the specified fields at any given
246
+ time.
247
+ :param index_name: Name of the index to create.
248
+ :param fields: Fields to include in the unique index.
249
+ :return: The created SQLAlchemy Index object.
250
+ """
251
+ ...
227
252
 
228
253
 
229
254
  def make_snapshot_model_mixin() -> type[SnapshotModelMixinProto]:
@@ -289,10 +314,6 @@ def make_snapshot_model_mixin() -> type[SnapshotModelMixinProto]:
289
314
 
290
315
  @classmethod
291
316
  def make_active_unique_index_record_sid(cls, index_name: str) -> sa.Index:
292
- """
293
- Helper to create a unique index on the `record_sid` field for active records (where `expired_at` is NULL).
294
- This ensures that there is only one active snapshot per record at any given time.
295
- """
296
317
  return sa.Index(
297
318
  index_name,
298
319
  "record_sid",
@@ -302,11 +323,6 @@ def make_snapshot_model_mixin() -> type[SnapshotModelMixinProto]:
302
323
 
303
324
  @classmethod
304
325
  def make_active_unique_index_for(cls, index_name: str, *fields: str) -> sa.Index:
305
- """
306
- Helper to create a unique index on the specified fields for active records (where `expired_at` is NULL).
307
- This ensures that there is only one active snapshot per combination of the specified fields at any given
308
- time.
309
- """
310
326
  return sa.Index(
311
327
  index_name,
312
328
  *fields,
@@ -24,8 +24,10 @@ __all__ = [
24
24
  "strict_abspath_parser",
25
25
  "semver_pattern",
26
26
  "semver_parser",
27
- "tag_pattern",
28
- "tag_parser",
27
+ "colon_tag_pattern",
28
+ "colon_tag_parser",
29
+ "slash_tag_pattern",
30
+ "slash_tag_parser",
29
31
  "topic_pattern",
30
32
  "topic_parser",
31
33
  "vin_code_chars",
@@ -146,8 +148,11 @@ semver_regexp: re.Pattern[str] = re.compile(
146
148
  rf"(?:\+{alpha_digits_regexp.pattern}(?:\.{alpha_digits_regexp.pattern})*)?")
147
149
  semver_element: pp.ParserElement = pp.Regex(semver_regexp.pattern)
148
150
 
149
- tag_regexp: re.Pattern[str] = re.compile(rf"{snake_case_regexp.pattern}(?:::{snake_case_regexp.pattern})*")
150
- tag_element: pp.ParserElement = pp.Combine(snake_case_element + (colon_token + colon_token + snake_case_element)[...])
151
+ colon_tag_regexp: re.Pattern[str] = re.compile(rf"{snake_case_regexp.pattern}(?::{snake_case_regexp.pattern})*")
152
+ colon_tag_element: pp.ParserElement = pp.Combine(snake_case_element + (colon_token + snake_case_element)[...])
153
+
154
+ slash_tag_regexp: re.Pattern[str] = re.compile(rf"{snake_case_regexp.pattern}(?:/{snake_case_regexp.pattern})*")
155
+ slash_tag_element: pp.ParserElement = pp.Combine(snake_case_element + (slash_token + snake_case_element)[...])
151
156
 
152
157
  topic_regexp: re.Pattern[str] = re.compile(rf"(?:/{snake_case_regexp.pattern})+")
153
158
  topic_element: pp.ParserElement = pp.Combine((slash_token + snake_case_element)[1, ...])
@@ -178,8 +183,10 @@ strict_abspath_parser = make_string_parser(strict_abspath_element)
178
183
  semver_pattern = make_string_pattern(semver_regexp)
179
184
  semver_parser = make_string_parser(semver_element)
180
185
 
181
- tag_pattern = make_string_pattern(tag_regexp)
182
- tag_parser = make_string_parser(tag_element)
186
+ colon_tag_pattern = make_string_pattern(colon_tag_regexp)
187
+ colon_tag_parser = make_string_parser(colon_tag_element)
188
+ slash_tag_pattern = make_string_pattern(slash_tag_regexp)
189
+ slash_tag_parser = make_string_parser(slash_tag_element)
183
190
  topic_pattern = make_string_pattern(topic_regexp)
184
191
  topic_parser = make_string_parser(topic_element)
185
192
  vin_code_pattern = make_string_pattern(vin_code_regexp)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plexus-python-common
3
- Version: 1.0.10
3
+ Version: 1.0.12
4
4
  Classifier: Programming Language :: Python :: 3
5
5
  Classifier: Programming Language :: Python :: 3.11
6
6
  Classifier: Programming Language :: Python :: 3.12
@@ -5,6 +5,7 @@ import pyparsing as pp
5
5
  from iker.common.utils.dtutils import dt_parse_iso
6
6
 
7
7
  from plexus.common.utils.strutils import BagName, UserName, VehicleName
8
+ from plexus.common.utils.strutils import colon_tag_parser, colon_tag_pattern, slash_tag_parser, slash_tag_pattern
8
9
  from plexus.common.utils.strutils import dot_case_parser, dot_case_pattern
9
10
  from plexus.common.utils.strutils import hex_string_parser, hex_string_pattern
10
11
  from plexus.common.utils.strutils import kebab_case_parser, kebab_case_pattern
@@ -13,7 +14,6 @@ from plexus.common.utils.strutils import semver_parser, semver_pattern
13
14
  from plexus.common.utils.strutils import snake_case_parser, snake_case_pattern
14
15
  from plexus.common.utils.strutils import strict_abspath_parser, strict_abspath_pattern
15
16
  from plexus.common.utils.strutils import strict_relpath_parser, strict_relpath_pattern
16
- from plexus.common.utils.strutils import tag_parser, tag_pattern
17
17
  from plexus.common.utils.strutils import topic_parser, topic_pattern
18
18
  from plexus.common.utils.strutils import vin_code_parser, vin_code_pattern
19
19
 
@@ -415,36 +415,67 @@ class StrUtilsTest(unittest.TestCase):
415
415
  with self.assertRaises(pp.ParseException):
416
416
  semver_parser.parse_string(data, parse_all=True)
417
417
 
418
- data_tag_pattern = [
418
+ data_colon_tag_pattern = [
419
419
  ("dummy",),
420
- ("dummy::dummy",),
421
- ("dummy::dummy::dummy",),
422
- ("dummy_12345::dummy_12345::dummy_12345",),
420
+ ("dummy:dummy",),
421
+ ("dummy:dummy:dummy",),
422
+ ("dummy_12345:dummy_12345:dummy_12345",),
423
423
  ]
424
424
 
425
- @ddt.idata(data_tag_pattern)
425
+ @ddt.idata(data_colon_tag_pattern)
426
426
  @ddt.unpack
427
- def test_tag_pattern(self, data):
428
- self.assertIsNotNone(tag_pattern.match(data))
429
- self.assertIsNotNone(tag_parser.parse_string(data, parse_all=True))
427
+ def test_colon_tag_pattern(self, data):
428
+ self.assertIsNotNone(colon_tag_pattern.match(data))
429
+ self.assertIsNotNone(colon_tag_parser.parse_string(data, parse_all=True))
430
430
 
431
- data_tag_pattern__bad_cases = [
431
+ data_colon_tag_pattern__bad_cases = [
432
432
  ("",),
433
- ("::",),
433
+ (":",),
434
434
  ("dummy_",),
435
435
  ("_dummy",),
436
- ("dummy_::",),
437
- ("_dummy::",),
438
- ("dummy::dummy_",),
439
- ("dummy::_dummy",),
436
+ ("dummy_:",),
437
+ ("_dummy:",),
438
+ ("dummy:dummy_",),
439
+ ("dummy:_dummy",),
440
440
  ]
441
441
 
442
- @ddt.idata(data_tag_pattern__bad_cases)
442
+ @ddt.idata(data_colon_tag_pattern__bad_cases)
443
443
  @ddt.unpack
444
- def test_tag_pattern__bad_cases(self, data):
445
- self.assertIsNone(tag_pattern.match(data))
444
+ def test_colon_tag_pattern__bad_cases(self, data):
445
+ self.assertIsNone(colon_tag_pattern.match(data))
446
446
  with self.assertRaises(pp.ParseException):
447
- tag_parser.parse_string(data, parse_all=True)
447
+ colon_tag_parser.parse_string(data, parse_all=True)
448
+
449
+ data_slash_tag_pattern = [
450
+ ("dummy",),
451
+ ("dummy/dummy",),
452
+ ("dummy/dummy/dummy",),
453
+ ("dummy_12345/dummy_12345/dummy_12345",),
454
+ ]
455
+
456
+ @ddt.idata(data_slash_tag_pattern)
457
+ @ddt.unpack
458
+ def test_slash_tag_pattern(self, data):
459
+ self.assertIsNotNone(slash_tag_pattern.match(data))
460
+ self.assertIsNotNone(slash_tag_parser.parse_string(data, parse_all=True))
461
+
462
+ data_slash_tag_pattern__bad_cases = [
463
+ ("",),
464
+ ("/",),
465
+ ("dummy_",),
466
+ ("_dummy",),
467
+ ("dummy_/",),
468
+ ("_dummy/",),
469
+ ("dummy/dummy_",),
470
+ ("dummy/_dummy",),
471
+ ]
472
+
473
+ @ddt.idata(data_slash_tag_pattern__bad_cases)
474
+ @ddt.unpack
475
+ def test_slash_tag_pattern__bad_cases(self, data):
476
+ self.assertIsNone(slash_tag_pattern.match(data))
477
+ with self.assertRaises(pp.ParseException):
478
+ slash_tag_parser.parse_string(data, parse_all=True)
448
479
 
449
480
  data_topic_pattern = [
450
481
  ("/dummy_sensor",),