jetpytools 2.2.1__tar.gz → 2.2.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. {jetpytools-2.2.1 → jetpytools-2.2.3}/PKG-INFO +1 -1
  2. jetpytools-2.2.3/jetpytools/_version.py +2 -0
  3. {jetpytools-2.2.1 → jetpytools-2.2.3}/jetpytools/enums/base.py +1 -1
  4. {jetpytools-2.2.1 → jetpytools-2.2.3}/jetpytools/types/file.py +17 -15
  5. {jetpytools-2.2.1 → jetpytools-2.2.3}/jetpytools/types/supports.py +6 -6
  6. {jetpytools-2.2.1 → jetpytools-2.2.3}/jetpytools/types/utils.py +13 -6
  7. {jetpytools-2.2.1 → jetpytools-2.2.3}/pyproject.toml +1 -1
  8. jetpytools-2.2.1/jetpytools/_version.py +0 -2
  9. {jetpytools-2.2.1 → jetpytools-2.2.3}/.gitignore +0 -0
  10. {jetpytools-2.2.1 → jetpytools-2.2.3}/LICENSE +0 -0
  11. {jetpytools-2.2.1 → jetpytools-2.2.3}/README.md +0 -0
  12. {jetpytools-2.2.1 → jetpytools-2.2.3}/jetpytools/__init__.py +0 -0
  13. {jetpytools-2.2.1 → jetpytools-2.2.3}/jetpytools/enums/__init__.py +0 -0
  14. {jetpytools-2.2.1 → jetpytools-2.2.3}/jetpytools/enums/other.py +0 -0
  15. {jetpytools-2.2.1 → jetpytools-2.2.3}/jetpytools/exceptions/__init__.py +0 -0
  16. {jetpytools-2.2.1 → jetpytools-2.2.3}/jetpytools/exceptions/base.py +0 -0
  17. {jetpytools-2.2.1 → jetpytools-2.2.3}/jetpytools/exceptions/enum.py +0 -0
  18. {jetpytools-2.2.1 → jetpytools-2.2.3}/jetpytools/exceptions/file.py +0 -0
  19. {jetpytools-2.2.1 → jetpytools-2.2.3}/jetpytools/exceptions/generic.py +0 -0
  20. {jetpytools-2.2.1 → jetpytools-2.2.3}/jetpytools/exceptions/module.py +0 -0
  21. {jetpytools-2.2.1 → jetpytools-2.2.3}/jetpytools/functions/__init__.py +0 -0
  22. {jetpytools-2.2.1 → jetpytools-2.2.3}/jetpytools/functions/funcs.py +0 -0
  23. {jetpytools-2.2.1 → jetpytools-2.2.3}/jetpytools/functions/normalize.py +0 -0
  24. {jetpytools-2.2.1 → jetpytools-2.2.3}/jetpytools/functions/other.py +0 -0
  25. {jetpytools-2.2.1 → jetpytools-2.2.3}/jetpytools/py.typed +0 -0
  26. {jetpytools-2.2.1 → jetpytools-2.2.3}/jetpytools/types/__init__.py +0 -0
  27. {jetpytools-2.2.1 → jetpytools-2.2.3}/jetpytools/types/builtins.py +0 -0
  28. {jetpytools-2.2.1 → jetpytools-2.2.3}/jetpytools/types/check.py +0 -0
  29. {jetpytools-2.2.1 → jetpytools-2.2.3}/jetpytools/types/funcs.py +0 -0
  30. {jetpytools-2.2.1 → jetpytools-2.2.3}/jetpytools/types/generic.py +0 -0
  31. {jetpytools-2.2.1 → jetpytools-2.2.3}/jetpytools/utils/__init__.py +0 -0
  32. {jetpytools-2.2.1 → jetpytools-2.2.3}/jetpytools/utils/file.py +0 -0
  33. {jetpytools-2.2.1 → jetpytools-2.2.3}/jetpytools/utils/funcs.py +0 -0
  34. {jetpytools-2.2.1 → jetpytools-2.2.3}/jetpytools/utils/math.py +0 -0
  35. {jetpytools-2.2.1 → jetpytools-2.2.3}/jetpytools/utils/ranges.py +0 -0
  36. {jetpytools-2.2.1 → jetpytools-2.2.3}/tests/test_file.py +0 -0
  37. {jetpytools-2.2.1 → jetpytools-2.2.3}/tests/test_funcs.py +0 -0
  38. {jetpytools-2.2.1 → jetpytools-2.2.3}/tests/test_normalize.py +0 -0
  39. {jetpytools-2.2.1 → jetpytools-2.2.3}/tests/test_types_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: jetpytools
3
- Version: 2.2.1
3
+ Version: 2.2.3
4
4
  Summary: Collection of stuff that's useful in general python programming
5
5
  Project-URL: Source Code, https://github.com/Jaded-Encoding-Thaumaturgy/jetpytools
6
6
  Project-URL: Contact, https://discord.gg/XTpc6Fa9eB
@@ -0,0 +1,2 @@
1
+ __version__ = "2.2.3"
2
+ __version_tuple__ = (2, 2, 3)
@@ -71,7 +71,7 @@ class CustomEnum(Enum):
71
71
  var_name=var_name,
72
72
  enum_name=cls,
73
73
  value=value,
74
- readable_enum=(f"{name} ({value!r})" for name, value in cls.__members__.items()),
74
+ readable_enum=(f"{name} ({value!s})" for name, value in cls.__members__.items()),
75
75
  reason=value,
76
76
  ) from None
77
77
 
@@ -132,7 +132,7 @@ class SPath(Path):
132
132
  import shutil
133
133
 
134
134
  try:
135
- return shutil.rmtree(str(self.get_folder()), ignore_errors)
135
+ return shutil.rmtree(self.get_folder(), ignore_errors)
136
136
  except FileNotFoundError:
137
137
  if not missing_ok:
138
138
  raise
@@ -161,9 +161,11 @@ class SPath(Path):
161
161
 
162
162
  return self.is_dir() and not any(self.iterdir())
163
163
 
164
- def move_dir(self, dst: SPath, *, mode: int = 0o777) -> None:
164
+ def move_dir(self, dst: SPathLike, *, mode: int = 0o777) -> None:
165
165
  """Move the directory to the specified destination."""
166
166
 
167
+ dst = SPath(dst)
168
+
167
169
  dst.mkdir(mode, True, True)
168
170
 
169
171
  for file in listdir(self):
@@ -177,21 +179,22 @@ class SPath(Path):
177
179
 
178
180
  self.rmdir()
179
181
 
180
- def copy_dir(self, dst: SPath) -> SPath:
182
+ def copy_dir(self, dst: SPathLike) -> SPath:
181
183
  """Copy the directory to the specified destination."""
184
+ import shutil
182
185
 
183
186
  if not self.is_dir():
184
187
  from ..exceptions import PathIsNotADirectoryError
185
188
 
186
189
  raise PathIsNotADirectoryError('The given path, "{self}" is not a directory!', self.copy_dir)
187
190
 
188
- dst.mkdirp()
191
+ dst = SPath(dst)
189
192
 
190
- import shutil
193
+ dst.mkdirp()
191
194
 
192
195
  shutil.copytree(self, dst, dirs_exist_ok=True)
193
196
 
194
- return SPath(dst)
197
+ return dst
195
198
 
196
199
  def lglob(self, pattern: str = "*") -> list[SPath]:
197
200
  """Glob the path and return the list of paths."""
@@ -209,17 +212,16 @@ class SPath(Path):
209
212
 
210
213
  return None
211
214
 
212
- def find_newest_file(self, pattern: str = "*") -> SPath | None:
215
+ def find_newest_file(
216
+ self, pattern: str = "*", *, case_sensitive: bool | None = None, recurse_symlinks: bool = False
217
+ ) -> SPath | None:
213
218
  """Find the most recently modified file matching the given pattern in the directory."""
214
219
 
215
- matching_files = self.get_folder().glob(pattern)
216
-
217
- try:
218
- next(matching_files)
219
- except StopIteration:
220
- return None
221
-
222
- return max(matching_files, key=lambda p: p.stat().st_mtime)
220
+ return max(
221
+ self.get_folder().glob(pattern, case_sensitive=case_sensitive, recurse_symlinks=recurse_symlinks),
222
+ key=lambda p: p.stat().st_mtime,
223
+ default=None,
224
+ )
223
225
 
224
226
  def get_size(self) -> int:
225
227
  """Get the size of the file or directory in bytes."""
@@ -52,22 +52,22 @@ class SupportsString(Protocol):
52
52
 
53
53
  @runtime_checkable
54
54
  class SupportsDunderLT[T_contra](Protocol):
55
- def __lt__(self, other: T_contra) -> bool: ...
55
+ def __lt__(self, other: T_contra, /) -> bool: ...
56
56
 
57
57
 
58
58
  @runtime_checkable
59
59
  class SupportsDunderGT[T_contra](Protocol):
60
- def __gt__(self, other: T_contra) -> bool: ...
60
+ def __gt__(self, other: T_contra, /) -> bool: ...
61
61
 
62
62
 
63
63
  @runtime_checkable
64
64
  class SupportsDunderLE[T_contra](Protocol):
65
- def __le__(self, other: T_contra) -> bool: ...
65
+ def __le__(self, other: T_contra, /) -> bool: ...
66
66
 
67
67
 
68
68
  @runtime_checkable
69
69
  class SupportsDunderGE[T_contra](Protocol):
70
- def __ge__(self, other: T_contra) -> bool: ...
70
+ def __ge__(self, other: T_contra, /) -> bool: ...
71
71
 
72
72
 
73
73
  @runtime_checkable
@@ -115,14 +115,14 @@ class ComparatorFunc(Protocol):
115
115
 
116
116
  @runtime_checkable
117
117
  class SupportsIndexing[T](Protocol):
118
- def __getitem__(self, k: int) -> T: ...
118
+ def __getitem__(self, k: int, /) -> T: ...
119
119
 
120
120
 
121
121
  @runtime_checkable
122
122
  class SupportsKeysAndGetItem[KT, VT](Protocol):
123
123
  def keys(self) -> Iterable[KT]: ...
124
124
 
125
- def __getitem__(self, k: KT) -> VT: ...
125
+ def __getitem__(self, k: KT, /) -> VT: ...
126
126
 
127
127
 
128
128
  SupportsFloatOrIndex = SupportsFloat | SupportsIndex
@@ -3,6 +3,7 @@ from __future__ import annotations
3
3
  import sys
4
4
  from contextlib import suppress
5
5
  from functools import wraps
6
+ from threading import Lock
6
7
  from types import LambdaType
7
8
  from typing import (
8
9
  TYPE_CHECKING,
@@ -156,7 +157,7 @@ _P0 = ParamSpec("_P0")
156
157
  _P1 = ParamSpec("_P1")
157
158
 
158
159
 
159
- class _InjectedSelfFunc(Protocol[_T_co, _P, _R_co]):
160
+ class _InjectedSelfFunc(Protocol[_T_co, _P, _R_co]): # type: ignore[misc]
160
161
  """
161
162
  Protocol defining the callable interface for wrapped functions under `inject_self`.
162
163
 
@@ -858,6 +859,8 @@ class KwargsNotNone(KwargsT):
858
859
 
859
860
  class SingletonMeta(type):
860
861
  _instances: ClassVar[dict[SingletonMeta, Any]] = {}
862
+ _lock = Lock()
863
+
861
864
  _singleton_init: bool
862
865
 
863
866
  def __new__[MetaSelf: SingletonMeta](
@@ -876,12 +879,16 @@ class SingletonMeta(type):
876
879
  if not TYPE_CHECKING:
877
880
 
878
881
  def __call__(cls, *args: Any, **kwargs: Any) -> Any:
879
- if cls not in cls._instances:
880
- cls._instances[cls] = obj = super().__call__(*args, **kwargs)
881
- return obj
882
+ if cls in cls._instances and not cls._singleton_init:
883
+ return cls._instances[cls]
884
+
885
+ with cls._lock:
886
+ if cls not in cls._instances:
887
+ cls._instances[cls] = obj = super().__call__(*args, **kwargs)
888
+ return obj
882
889
 
883
- if cls._singleton_init:
884
- cls._instances[cls].__init__(*args, **kwargs)
890
+ if cls._singleton_init:
891
+ cls._instances[cls].__init__(*args, **kwargs)
885
892
 
886
893
  return cls._instances[cls]
887
894
 
@@ -25,7 +25,7 @@ dependencies = ["typing_extensions>=4.15.0; python_version<'3.13'"]
25
25
  "Contact" = "https://discord.gg/XTpc6Fa9eB"
26
26
 
27
27
  [dependency-groups]
28
- dev = ["mypy~=1.18.0", "ruff~=0.14.0", "pytest>=9.0.0, <10.0.0", "twine>=6.2.0"]
28
+ dev = ["mypy~=1.19.0", "ruff~=0.14.0", "pytest>=9.0.0, <10.0.0", "twine>=6.2.0"]
29
29
 
30
30
  [build-system]
31
31
  requires = ["hatchling>=1.27.0", "versioningit"]
@@ -1,2 +0,0 @@
1
- __version__ = "2.2.1"
2
- __version_tuple__ = (2, 2, 1)
File without changes
File without changes
File without changes