plexus-python-common 1.0.21__tar.gz → 1.0.23__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 (76) hide show
  1. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/PKG-INFO +1 -1
  2. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/src/plexus/common/utils/s3utils.py +10 -8
  3. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/src/plexus/common/utils/strutils.py +47 -21
  4. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/src/plexus_python_common.egg-info/PKG-INFO +1 -1
  5. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/test/plexus_tests/common/utils/strutils_test.py +38 -1
  6. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/.editorconfig +0 -0
  7. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/.github/workflows/pr.yml +0 -0
  8. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/.github/workflows/push.yml +0 -0
  9. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/.gitignore +0 -0
  10. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/MANIFEST.in +0 -0
  11. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/README.md +0 -0
  12. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/VERSION +0 -0
  13. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/pyproject.toml +0 -0
  14. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/resources/unittest/jsonutils/dummy.0.jsonl +0 -0
  15. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/resources/unittest/jsonutils/dummy.1.jsonl +0 -0
  16. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/resources/unittest/jsonutils/dummy.2.jsonl +0 -0
  17. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/resources/unittest/s3utils/dir.baz/file.bar.baz +0 -0
  18. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/resources/unittest/s3utils/dir.baz/file.foo.bar +0 -0
  19. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/resources/unittest/s3utils/dir.baz/file.foo.baz +0 -0
  20. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/resources/unittest/s3utils/dir.foo/dir.foo.bar/dir.foo.bar.baz/file.foo.bar.baz +0 -0
  21. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/resources/unittest/s3utils/dir.foo/dir.foo.bar/file.bar.baz +0 -0
  22. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/resources/unittest/s3utils/dir.foo/dir.foo.bar/file.foo.bar +0 -0
  23. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/resources/unittest/s3utils/dir.foo/dir.foo.bar/file.foo.baz +0 -0
  24. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/resources/unittest/s3utils/dir.foo/file.bar +0 -0
  25. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/resources/unittest/s3utils/dir.foo/file.baz +0 -0
  26. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/resources/unittest/s3utils/dir.foo/file.foo +0 -0
  27. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/resources/unittest/shutils/0-dummy +0 -0
  28. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/resources/unittest/shutils/1-dummy +0 -0
  29. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/resources/unittest/shutils/2-dummy +0 -0
  30. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/resources/unittest/shutils/dummy.0.0.jsonl +0 -0
  31. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/resources/unittest/shutils/dummy.0.0.vol-0.jsonl +0 -0
  32. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/resources/unittest/shutils/dummy.0.jsonl +0 -0
  33. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/resources/unittest/shutils/dummy.1.1.jsonl +0 -0
  34. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/resources/unittest/shutils/dummy.1.1.vol-1.jsonl +0 -0
  35. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/resources/unittest/shutils/dummy.1.jsonl +0 -0
  36. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/resources/unittest/shutils/dummy.2.2.jsonl +0 -0
  37. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/resources/unittest/shutils/dummy.2.2.vol-2.jsonl +0 -0
  38. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/resources/unittest/shutils/dummy.2.jsonl +0 -0
  39. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/resources/unittest/shutils/dummy.csv.part0 +0 -0
  40. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/resources/unittest/shutils/dummy.csv.part1 +0 -0
  41. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/resources/unittest/shutils/dummy.csv.part2 +0 -0
  42. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/resources/unittest/shutils/dummy.txt +0 -0
  43. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/setup.cfg +0 -0
  44. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/setup.py +0 -0
  45. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/src/plexus/common/__init__.py +0 -0
  46. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/src/plexus/common/carto/OSMFile.py +0 -0
  47. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/src/plexus/common/carto/OSMNode.py +0 -0
  48. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/src/plexus/common/carto/OSMTags.py +0 -0
  49. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/src/plexus/common/carto/OSMWay.py +0 -0
  50. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/src/plexus/common/carto/__init__.py +0 -0
  51. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/src/plexus/common/config.py +0 -0
  52. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/src/plexus/common/pose.py +0 -0
  53. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/src/plexus/common/proj.py +0 -0
  54. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/src/plexus/common/utils/__init__.py +0 -0
  55. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/src/plexus/common/utils/bagutils.py +0 -0
  56. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/src/plexus/common/utils/datautils.py +0 -0
  57. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/src/plexus/common/utils/jsonutils.py +0 -0
  58. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/src/plexus/common/utils/ormutils.py +0 -0
  59. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/src/plexus/common/utils/shutils.py +0 -0
  60. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/src/plexus_python_common.egg-info/SOURCES.txt +0 -0
  61. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/src/plexus_python_common.egg-info/dependency_links.txt +0 -0
  62. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/src/plexus_python_common.egg-info/not-zip-safe +0 -0
  63. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/src/plexus_python_common.egg-info/requires.txt +0 -0
  64. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/src/plexus_python_common.egg-info/top_level.txt +0 -0
  65. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/test/plexus_test.py +0 -0
  66. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/test/plexus_tests/__init__.py +0 -0
  67. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/test/plexus_tests/common/carto/osm_file_test.py +0 -0
  68. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/test/plexus_tests/common/carto/osm_tags_test.py +0 -0
  69. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/test/plexus_tests/common/pose_test.py +0 -0
  70. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/test/plexus_tests/common/proj_test.py +0 -0
  71. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/test/plexus_tests/common/utils/bagutils_test.py +0 -0
  72. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/test/plexus_tests/common/utils/datautils_test.py +0 -0
  73. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/test/plexus_tests/common/utils/jsonutils_test.py +0 -0
  74. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/test/plexus_tests/common/utils/ormutils_test.py +0 -0
  75. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/test/plexus_tests/common/utils/s3utils_test.py +0 -0
  76. {plexus_python_common-1.0.21 → plexus_python_common-1.0.23}/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.21
3
+ Version: 1.0.23
4
4
  Classifier: Programming Language :: Python :: 3
5
5
  Classifier: Programming Language :: Python :: 3.12
6
6
  Classifier: Programming Language :: Python :: 3.13
@@ -9,10 +9,10 @@ import os.path
9
9
  import tempfile
10
10
  from collections.abc import Callable, Generator
11
11
  from pathlib import Path
12
- from typing import Iterable, Literal
12
+ from typing import Literal
13
13
 
14
14
  import boto3
15
- from cloudpathlib import AnyPath, CloudPath, S3Client, S3Path
15
+ from cloudpathlib import CloudPath, S3Client, S3Path
16
16
  from iker.common.utils.shutils import glob_match, listfile, path_depth
17
17
  from iker.common.utils.strutils import is_empty, trim_to_none
18
18
  from rich.progress import BarColumn, DownloadColumn, Progress, TaskID, TextColumn, TransferSpeedColumn
@@ -63,7 +63,7 @@ def s3_make_client(
63
63
  yield S3Client(boto3_session=session, endpoint_url=trim_to_none(endpoint_url))
64
64
 
65
65
 
66
- def s3_list_objects(client: S3Client, bucket: str, prefix: str, limit: int = None) -> Iterable[S3ObjectMeta]:
66
+ def s3_list_objects(client: S3Client, bucket: str, prefix: str, limit: int = None) -> Generator[S3ObjectMeta]:
67
67
  """
68
68
  Lists all objects from the given S3 ``bucket`` and ``prefix``.
69
69
 
@@ -105,7 +105,7 @@ def s3_listfile(
105
105
  include_patterns: list[str] | None = None,
106
106
  exclude_patterns: list[str] | None = None,
107
107
  depth: int = 0,
108
- ) -> Iterable[S3ObjectMeta]:
108
+ ) -> Generator[S3ObjectMeta]:
109
109
  """
110
110
  Lists all objects from the given S3 ``bucket`` and ``prefix``, filtered by patterns and directory depth.
111
111
 
@@ -323,7 +323,7 @@ class S3TransferCallbackClient(S3Client):
323
323
  def __init__(
324
324
  self,
325
325
  *args,
326
- transfer_callback: Callable[[CloudPath, TransferDirection, TransferState, int], None],
326
+ transfer_callback: Callable[[Path | CloudPath, TransferDirection, TransferState, int], None],
327
327
  **kwargs,
328
328
  ):
329
329
  super().__init__(*args, **kwargs)
@@ -367,10 +367,12 @@ class S3TransferCallbackClient(S3Client):
367
367
  return cloud_path
368
368
 
369
369
 
370
- def s3_make_progress_callback(progress: Progress) -> Callable[[AnyPath, TransferDirection, TransferState, int], None]:
371
- task_ids: dict[AnyPath, TaskID] = {}
370
+ def s3_make_progress_callback(
371
+ progress: Progress,
372
+ ) -> Callable[[Path | CloudPath, TransferDirection, TransferState, int], None]:
373
+ task_ids: dict[Path | CloudPath, TaskID] = {}
372
374
 
373
- def progress_callback(path: AnyPath, direction: TransferDirection, state: TransferState, bytes_sent: int):
375
+ def progress_callback(path: Path | CloudPath, direction: TransferDirection, state: TransferState, bytes_sent: int):
374
376
  if state == "start":
375
377
  size = path.stat().st_size
376
378
  task_ids[path] = progress.add_task(direction, total=size, filename=path.name)
@@ -22,6 +22,8 @@ __all__ = [
22
22
  "strict_relpath_parser",
23
23
  "strict_abspath_pattern",
24
24
  "strict_abspath_parser",
25
+ "email_address_pattern",
26
+ "email_address_parser",
25
27
  "semver_pattern",
26
28
  "semver_parser",
27
29
  "colon_tag_pattern",
@@ -74,16 +76,39 @@ def make_string_parser(element: pp.ParserElement) -> pp.ParserElement:
74
76
  return pp.Combine(pp.StringStart() + element + pp.StringEnd())
75
77
 
76
78
 
77
- lowers_regexp: re.Pattern[str] = re.compile(r"[a-z]+")
78
- uppers_regexp: re.Pattern[str] = re.compile(r"[A-Z]+")
79
- digits_regexp: re.Pattern[str] = re.compile(r"[0-9]+")
80
- lower_digits_regexp: re.Pattern[str] = re.compile(r"[a-z0-9]+")
81
- upper_digits_regexp: re.Pattern[str] = re.compile(r"[A-Z0-9]+")
82
- alpha_digits_regexp: re.Pattern[str] = re.compile(r"[a-zA-Z0-9]+")
83
- hex_digits_regexp: re.Pattern[str] = re.compile(r"[a-f0-9]+")
84
- lower_identifier_regexp: re.Pattern[str] = re.compile(r"[a-z][a-z0-9]*")
85
- upper_identifier_regexp: re.Pattern[str] = re.compile(r"[A-Z][A-Z0-9]*")
86
- strict_chars_regexp: re.Pattern[str] = re.compile(r"[a-zA-Z0-9._-]+")
79
+ underscore_token: pp.ParserElement = pp.Char("_")
80
+ hyphen_token: pp.ParserElement = pp.Char("-")
81
+ period_token: pp.ParserElement = pp.Char(".")
82
+ colon_token: pp.ParserElement = pp.Char(":")
83
+ slash_token: pp.ParserElement = pp.Char("/")
84
+ plus_token: pp.ParserElement = pp.Char("+")
85
+
86
+ lower_regexp: re.Pattern[str] = re.compile(r"[a-z]")
87
+ upper_regexp: re.Pattern[str] = re.compile(r"[A-Z]")
88
+ digit_regexp: re.Pattern[str] = re.compile(r"[0-9]")
89
+ lower_digit_regexp: re.Pattern[str] = re.compile(r"[a-z0-9]")
90
+ upper_digit_regexp: re.Pattern[str] = re.compile(r"[A-Z0-9]")
91
+ alpha_digit_regexp: re.Pattern[str] = re.compile(r"[a-zA-Z0-9]")
92
+ hex_digit_regexp: re.Pattern[str] = re.compile(r"[a-f0-9]")
93
+
94
+ lowers_regexp: re.Pattern[str] = re.compile(rf"{lower_regexp.pattern}+")
95
+ uppers_regexp: re.Pattern[str] = re.compile(rf"{upper_regexp.pattern}+")
96
+ digits_regexp: re.Pattern[str] = re.compile(rf"{digit_regexp.pattern}+")
97
+ lower_digits_regexp: re.Pattern[str] = re.compile(rf"{lower_digit_regexp.pattern}+")
98
+ upper_digits_regexp: re.Pattern[str] = re.compile(rf"{upper_digit_regexp.pattern}+")
99
+ alpha_digits_regexp: re.Pattern[str] = re.compile(rf"{alpha_digit_regexp.pattern}+")
100
+ hex_digits_regexp: re.Pattern[str] = re.compile(rf"{hex_digit_regexp.pattern}+")
101
+ lower_identifier_regexp: re.Pattern[str] = re.compile(rf"{lower_regexp.pattern}{lower_digit_regexp.pattern}*")
102
+ upper_identifier_regexp: re.Pattern[str] = re.compile(rf"{upper_regexp.pattern}{upper_digit_regexp.pattern}*")
103
+ strict_chars_regexp: re.Pattern[str] = re.compile(rf"({alpha_digit_regexp.pattern}|[._-])+")
104
+
105
+ lower_element: pp.ParserElement = pp.Regex(lower_regexp.pattern)
106
+ upper_element: pp.ParserElement = pp.Regex(upper_regexp.pattern)
107
+ digit_element: pp.ParserElement = pp.Regex(digit_regexp.pattern)
108
+ lower_digit_element: pp.ParserElement = pp.Regex(lower_digit_regexp.pattern)
109
+ upper_digit_element: pp.ParserElement = pp.Regex(upper_digit_regexp.pattern)
110
+ alpha_digit_element: pp.ParserElement = pp.Regex(alpha_digit_regexp.pattern)
111
+ hex_digit_element: pp.ParserElement = pp.Regex(hex_digit_regexp.pattern)
87
112
 
88
113
  lowers_element: pp.ParserElement = pp.Regex(lowers_regexp.pattern)
89
114
  uppers_element: pp.ParserElement = pp.Regex(uppers_regexp.pattern)
@@ -96,24 +121,17 @@ lower_identifier_element: pp.ParserElement = pp.Regex(lower_identifier_regexp.pa
96
121
  upper_identifier_element: pp.ParserElement = pp.Regex(upper_identifier_regexp.pattern)
97
122
  strict_chars_element: pp.ParserElement = pp.Regex(strict_chars_regexp.pattern)
98
123
 
99
- underscore_token: pp.ParserElement = pp.Char("_")
100
- hyphen_token: pp.ParserElement = pp.Char("-")
101
- period_token: pp.ParserElement = pp.Char(".")
102
- colon_token: pp.ParserElement = pp.Char(":")
103
- slash_token: pp.ParserElement = pp.Char("/")
104
- plus_token: pp.ParserElement = pp.Char("+")
105
-
106
124
  basic_datetime_regexp: re.Pattern[str] = re.compile(r"\d{8}T\d{6}")
107
125
  extended_datetime_regexp: re.Pattern[str] = re.compile(r"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}")
108
126
 
109
127
  basic_datetime_element: pp.ParserElement = pp.Regex(basic_datetime_regexp.pattern)
110
128
  extended_datetime_element: pp.ParserElement = pp.Regex(extended_datetime_regexp.pattern)
111
129
 
112
- number_regexp: re.Pattern[str] = re.compile(r"0|([1-9][0-9]*)")
113
- positive_number_regexp: re.Pattern[str] = re.compile(r"[1-9][0-9]*")
130
+ positive_number_regexp: re.Pattern[str] = re.compile(rf"[1-9]{digit_regexp.pattern}*")
131
+ number_regexp: re.Pattern[str] = re.compile(rf"0|({positive_number_regexp.pattern})")
114
132
 
115
- number_element: pp.ParserElement = pp.Regex(number_regexp.pattern)
116
133
  positive_number_element: pp.ParserElement = pp.Regex(positive_number_regexp.pattern)
134
+ number_element: pp.ParserElement = pp.Regex(number_regexp.pattern)
117
135
 
118
136
  snake_case_regexp: re.Pattern[str] = re.compile(
119
137
  rf"{lower_digits_regexp.pattern}(?:_{lower_digits_regexp.pattern})*")
@@ -129,7 +147,8 @@ kebab_case_element: pp.ParserElement = pp.Combine(
129
147
  dot_case_element: pp.ParserElement = pp.Combine(
130
148
  lower_digits_element + (period_token + lower_digits_element)[...])
131
149
 
132
- uuid_regexp: re.Pattern[str] = re.compile(r"[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}")
150
+ uuid_regexp: re.Pattern[str] = re.compile(
151
+ rf"{hex_digit_regexp.pattern}{{8}}(-{hex_digit_regexp.pattern}{{4}}){{3}}-{hex_digit_regexp.pattern}{{12}}")
133
152
  uuid_element: pp.ParserElement = pp.Regex(uuid_regexp.pattern)
134
153
 
135
154
  strict_relpath_regexp: re.Pattern[str] = re.compile(
@@ -146,6 +165,10 @@ strict_relpath_element: pp.ParserElement = pp.Combine(
146
165
  strict_abspath_element: pp.ParserElement = pp.Combine(
147
166
  slash_token + (strict_path_chars_element + slash_token)[...] + strict_path_chars_element[0, 1])
148
167
 
168
+ email_address_regexp: re.Pattern[str] = re.compile(
169
+ rf"(({lower_digit_regexp.pattern}|[_-])+)(?:\.({lower_digit_regexp.pattern}|[_-])+)*@(?:{kebab_case_regexp.pattern}\.)+({lower_digit_regexp.pattern}{{2,63}})")
170
+ email_address_element: pp.ParserElement = pp.Regex(email_address_regexp.pattern)
171
+
149
172
  semver_regexp: re.Pattern[str] = re.compile(
150
173
  rf"({number_regexp.pattern})\.({number_regexp.pattern})\.({number_regexp.pattern})"
151
174
  rf"(?:-{alpha_digits_regexp.pattern}(?:\.{alpha_digits_regexp.pattern})*)?"
@@ -184,6 +207,9 @@ strict_relpath_parser = make_string_parser(strict_relpath_element)
184
207
  strict_abspath_pattern = make_string_pattern(strict_abspath_regexp)
185
208
  strict_abspath_parser = make_string_parser(strict_abspath_element)
186
209
 
210
+ email_address_pattern = make_string_pattern(email_address_regexp)
211
+ email_address_parser = make_string_parser(email_address_element)
212
+
187
213
  semver_pattern = make_string_pattern(semver_regexp)
188
214
  semver_parser = make_string_parser(semver_element)
189
215
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plexus-python-common
3
- Version: 1.0.21
3
+ Version: 1.0.23
4
4
  Classifier: Programming Language :: Python :: 3
5
5
  Classifier: Programming Language :: Python :: 3.12
6
6
  Classifier: Programming Language :: Python :: 3.13
@@ -7,10 +7,10 @@ from iker.common.utils.dtutils import dt_parse_iso
7
7
  from plexus.common.utils.strutils import BagName, UserEmail, UserName, VehicleName
8
8
  from plexus.common.utils.strutils import colon_tag_parser, colon_tag_pattern, slash_tag_parser, slash_tag_pattern
9
9
  from plexus.common.utils.strutils import dot_case_parser, dot_case_pattern
10
+ from plexus.common.utils.strutils import email_address_parser, email_address_pattern, semver_parser, semver_pattern
10
11
  from plexus.common.utils.strutils import hex_string_parser, hex_string_pattern
11
12
  from plexus.common.utils.strutils import kebab_case_parser, kebab_case_pattern
12
13
  from plexus.common.utils.strutils import parse_bag_name, parse_user_email, parse_user_name, parse_vehicle_name
13
- from plexus.common.utils.strutils import semver_parser, semver_pattern
14
14
  from plexus.common.utils.strutils import snake_case_parser, snake_case_pattern
15
15
  from plexus.common.utils.strutils import strict_abspath_parser, strict_abspath_pattern
16
16
  from plexus.common.utils.strutils import strict_relpath_parser, strict_relpath_pattern
@@ -377,6 +377,43 @@ class StrUtilsTest(unittest.TestCase):
377
377
  with self.assertRaises(pp.ParseException):
378
378
  strict_abspath_parser.parse_string(data, parse_all=True)
379
379
 
380
+ data_email_address_pattern = [
381
+ ("someone@dummy.com",),
382
+ ("some.one@dummy.com",),
383
+ ("some.1@dummy.com",),
384
+ ("some-one@dummy.com",),
385
+ ("someone-@dummy.com",),
386
+ ("someone@dummy.company.com",),
387
+ ("some.one@dummy-company.com",),
388
+ ("some.1@dummy.company-company.com",),
389
+ ("some_one@dummy-1st-company.co-ltd.com",),
390
+ ]
391
+
392
+ @ddt.idata(data_email_address_pattern)
393
+ @ddt.unpack
394
+ def test_email_address_pattern(self, data):
395
+ self.assertIsNotNone(email_address_pattern.match(data))
396
+ self.assertIsNotNone(email_address_parser.parse_string(data, parse_all=True))
397
+
398
+ data_email_address_pattern__bad_cases = [
399
+ ("",),
400
+ ("some.one",),
401
+ ("@dummy.com",),
402
+ ("someone@dummy",),
403
+ ("someone@dummy.methionylthreonylthreonylglutaminylarginyltyrosylglutamylserylleucine",),
404
+ ("someone+one@dummy.com",),
405
+ ("someone.@dummy.com",),
406
+ ("someone@.dummy.com",),
407
+ ("someone@dummy-.com",),
408
+ ]
409
+
410
+ @ddt.idata(data_email_address_pattern__bad_cases)
411
+ @ddt.unpack
412
+ def test_email_address_pattern__bad_cases(self, data):
413
+ self.assertIsNone(email_address_pattern.match(data))
414
+ with self.assertRaises(pp.ParseException):
415
+ email_address_parser.parse_string(data, parse_all=True)
416
+
380
417
  data_semver_pattern = [
381
418
  ("0.0.0",),
382
419
  ("1.2.3",),