jetpytools 1.2.8__tar.gz → 1.4.0__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.

Potentially problematic release.


This version of jetpytools might be problematic. Click here for more details.

Files changed (41) hide show
  1. {jetpytools-1.2.8 → jetpytools-1.4.0}/PKG-INFO +3 -1
  2. {jetpytools-1.2.8 → jetpytools-1.4.0}/jetpytools/_metadata.py +1 -1
  3. {jetpytools-1.2.8 → jetpytools-1.4.0}/jetpytools/enums/base.py +1 -5
  4. {jetpytools-1.2.8 → jetpytools-1.4.0}/jetpytools/exceptions/base.py +3 -13
  5. {jetpytools-1.2.8 → jetpytools-1.4.0}/jetpytools/types/builtins.py +8 -7
  6. {jetpytools-1.2.8 → jetpytools-1.4.0}/jetpytools/types/utils.py +65 -111
  7. {jetpytools-1.2.8 → jetpytools-1.4.0}/jetpytools.egg-info/PKG-INFO +3 -1
  8. {jetpytools-1.2.8 → jetpytools-1.4.0}/jetpytools.egg-info/SOURCES.txt +4 -1
  9. jetpytools-1.4.0/jetpytools.egg-info/requires.txt +1 -0
  10. {jetpytools-1.2.8 → jetpytools-1.4.0}/setup.cfg +1 -0
  11. {jetpytools-1.2.8 → jetpytools-1.4.0}/setup.py +1 -0
  12. jetpytools-1.4.0/tests/test_funcs.py +12 -0
  13. jetpytools-1.4.0/tests/test_normalize.py +9 -0
  14. {jetpytools-1.2.8 → jetpytools-1.4.0}/LICENSE +0 -0
  15. {jetpytools-1.2.8 → jetpytools-1.4.0}/README.md +0 -0
  16. {jetpytools-1.2.8 → jetpytools-1.4.0}/jetpytools/__init__.py +0 -0
  17. {jetpytools-1.2.8 → jetpytools-1.4.0}/jetpytools/enums/__init__.py +0 -0
  18. {jetpytools-1.2.8 → jetpytools-1.4.0}/jetpytools/enums/other.py +0 -0
  19. {jetpytools-1.2.8 → jetpytools-1.4.0}/jetpytools/exceptions/__init__.py +0 -0
  20. {jetpytools-1.2.8 → jetpytools-1.4.0}/jetpytools/exceptions/enum.py +0 -0
  21. {jetpytools-1.2.8 → jetpytools-1.4.0}/jetpytools/exceptions/file.py +0 -0
  22. {jetpytools-1.2.8 → jetpytools-1.4.0}/jetpytools/exceptions/generic.py +0 -0
  23. {jetpytools-1.2.8 → jetpytools-1.4.0}/jetpytools/exceptions/module.py +0 -0
  24. {jetpytools-1.2.8 → jetpytools-1.4.0}/jetpytools/functions/__init__.py +0 -0
  25. {jetpytools-1.2.8 → jetpytools-1.4.0}/jetpytools/functions/funcs.py +0 -0
  26. {jetpytools-1.2.8 → jetpytools-1.4.0}/jetpytools/functions/normalize.py +0 -0
  27. {jetpytools-1.2.8 → jetpytools-1.4.0}/jetpytools/functions/other.py +0 -0
  28. {jetpytools-1.2.8 → jetpytools-1.4.0}/jetpytools/py.typed +0 -0
  29. {jetpytools-1.2.8 → jetpytools-1.4.0}/jetpytools/types/__init__.py +0 -0
  30. {jetpytools-1.2.8 → jetpytools-1.4.0}/jetpytools/types/check.py +0 -0
  31. {jetpytools-1.2.8 → jetpytools-1.4.0}/jetpytools/types/file.py +0 -0
  32. {jetpytools-1.2.8 → jetpytools-1.4.0}/jetpytools/types/funcs.py +0 -0
  33. {jetpytools-1.2.8 → jetpytools-1.4.0}/jetpytools/types/generic.py +0 -0
  34. {jetpytools-1.2.8 → jetpytools-1.4.0}/jetpytools/types/supports.py +0 -0
  35. {jetpytools-1.2.8 → jetpytools-1.4.0}/jetpytools/utils/__init__.py +0 -0
  36. {jetpytools-1.2.8 → jetpytools-1.4.0}/jetpytools/utils/file.py +0 -0
  37. {jetpytools-1.2.8 → jetpytools-1.4.0}/jetpytools/utils/funcs.py +0 -0
  38. {jetpytools-1.2.8 → jetpytools-1.4.0}/jetpytools/utils/math.py +0 -0
  39. {jetpytools-1.2.8 → jetpytools-1.4.0}/jetpytools/utils/ranges.py +0 -0
  40. {jetpytools-1.2.8 → jetpytools-1.4.0}/jetpytools.egg-info/dependency_links.txt +0 -0
  41. {jetpytools-1.2.8 → jetpytools-1.4.0}/jetpytools.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: jetpytools
3
- Version: 1.2.8
3
+ Version: 1.4.0
4
4
  Summary: Collection of stuff that's useful in general python programming
5
5
  Author: Jaded Encoding Thaumaturgy
6
6
  Author-email: jaded.encoding.thaumaturgy@gmail.com
@@ -18,6 +18,7 @@ Classifier: Typing :: Typed
18
18
  Requires-Python: >=3.10
19
19
  Description-Content-Type: text/markdown
20
20
  License-File: LICENSE
21
+ Requires-Dist: typing_extensions>=4.12.2
21
22
  Dynamic: author
22
23
  Dynamic: author-email
23
24
  Dynamic: classifier
@@ -27,6 +28,7 @@ Dynamic: license-file
27
28
  Dynamic: maintainer
28
29
  Dynamic: maintainer-email
29
30
  Dynamic: project-url
31
+ Dynamic: requires-dist
30
32
  Dynamic: requires-python
31
33
  Dynamic: summary
32
34
 
@@ -1,6 +1,6 @@
1
1
  """Collection of stuff that's useful in general python programming"""
2
2
 
3
- __version__ = '1.2.8'
3
+ __version__ = '1.4.0'
4
4
 
5
5
  __author_name__, __author_email__ = 'Jaded Encoding Thaumaturgy', 'jaded.encoding.thaumaturgy@gmail.com'
6
6
  __maintainer_name__, __maintainer_email__ = __author_name__, __author_email__
@@ -1,7 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from enum import Enum
4
- from typing import Any, TypeVar
4
+ from typing import Any
5
5
 
6
6
  from typing_extensions import Self
7
7
 
@@ -9,7 +9,6 @@ from ..exceptions import CustomValueError, NotFoundEnumValue
9
9
  from ..types import FuncExceptT
10
10
 
11
11
  __all__ = [
12
- 'SelfEnum',
13
12
  'CustomEnum', 'CustomIntEnum', 'CustomStrEnum'
14
13
  ]
15
14
 
@@ -75,6 +74,3 @@ class CustomStrEnum(str, CustomEnum):
75
74
  """Base class for custom str enums."""
76
75
 
77
76
  value: str
78
-
79
-
80
- SelfEnum = TypeVar('SelfEnum', bound=CustomEnum)
@@ -72,10 +72,6 @@ class CustomErrorMeta(type):
72
72
 
73
73
  return exception
74
74
 
75
- if TYPE_CHECKING:
76
- def __getitem__(self, exception: type[Exception]) -> CustomError:
77
- ...
78
-
79
75
 
80
76
  SelfCErrorMeta = TypeVar('SelfCErrorMeta', bound=CustomErrorMeta)
81
77
 
@@ -102,17 +98,11 @@ class CustomError(ExceptionT, metaclass=CustomErrorMeta):
102
98
  super().__init__(message)
103
99
 
104
100
  def __class_getitem__(cls, exception: str | type[ExceptionT] | ExceptionT) -> CustomError:
105
- if isinstance(exception, str):
106
- class inner_exception(cls): # type: ignore
107
- ...
108
- else:
109
- if not issubclass(exception, type): # type: ignore
110
- exception = exception.__class__ # type: ignore
101
+ from warnings import warn
111
102
 
112
- class inner_exception(cls, exception): # type: ignore
113
- ...
103
+ warn("Custom error is not subscriptable anymore. Don't use it", DeprecationWarning)
114
104
 
115
- return CustomErrorMeta.setup_exception(inner_exception, exception) # type: ignore
105
+ return cls()
116
106
 
117
107
  def __call__(
118
108
  self,
@@ -3,12 +3,12 @@ from __future__ import annotations
3
3
  from typing import Any, Callable, ParamSpec, Sequence, SupportsFloat, SupportsIndex, TypeAlias, TypeVar, Union
4
4
 
5
5
  __all__ = [
6
- 'T', 'T0', 'T1', 'T2', 'T_contra',
6
+ 'T', 'T0', 'T1', 'T2', 'T_co', 'T0_co', 'T1_co', 'T_contra',
7
7
 
8
8
  'F', 'F0', 'F1', 'F2',
9
9
 
10
10
  'P', 'P0', 'P1', 'P2',
11
- 'R', 'R0', 'R1', 'R2', 'R_co', 'R0_co', 'R_contra',
11
+ 'R', 'R0', 'R1', 'R2', 'R_co', 'R0_co', 'R1_co', 'R_contra',
12
12
 
13
13
  'Nb',
14
14
 
@@ -20,13 +20,9 @@ __all__ = [
20
20
  'SimpleByteData', 'SimpleByteDataArray',
21
21
  'ByteData',
22
22
 
23
- 'KwargsT',
24
-
25
- 'Self'
23
+ 'KwargsT'
26
24
  ]
27
25
 
28
- Self = TypeVar('Self')
29
-
30
26
  Nb = TypeVar('Nb', float, int)
31
27
 
32
28
  T = TypeVar('T')
@@ -49,8 +45,13 @@ R0 = TypeVar('R0')
49
45
  R1 = TypeVar('R1')
50
46
  R2 = TypeVar('R2')
51
47
 
48
+ T_co = TypeVar('T_co', covariant=True)
49
+ T0_co = TypeVar('T0_co', covariant=True)
50
+ T1_co = TypeVar('T1_co', covariant=True)
51
+
52
52
  R_co = TypeVar('R_co', covariant=True)
53
53
  R0_co = TypeVar('R0_co', covariant=True)
54
+ R1_co = TypeVar('R1_co', covariant=True)
54
55
 
55
56
  T_contra = TypeVar('T_contra', contravariant=True)
56
57
  R_contra = TypeVar('R_contra', contravariant=True)
@@ -3,14 +3,14 @@ from __future__ import annotations
3
3
  from functools import partial, wraps
4
4
  from inspect import Signature
5
5
  from inspect import _empty as empty_param
6
- from inspect import isclass
7
6
  from typing import (
8
- TYPE_CHECKING, Any, Callable, Concatenate, Generator, Generic, Iterable, Iterator, Mapping,
9
- NoReturn, Protocol, Sequence, TypeVar, cast, overload
7
+ TYPE_CHECKING, Any, Callable, Concatenate, Generator, Generic, Iterable, Iterator, Mapping, NoReturn, Protocol,
8
+ Sequence, TypeVar, cast, overload
10
9
  )
10
+
11
11
  from typing_extensions import Self
12
12
 
13
- from .builtins import F0, F1, P0, P1, R0, R1, T0, T1, T2, KwargsT, P, R, R_co, R0_co, T
13
+ from .builtins import F0, F1, P0, P1, R0, R1, T0, T1, T2, KwargsT, P, R, R0_co, R1_co, R_co, T, T0_co, T1_co, T_co
14
14
 
15
15
  __all__ = [
16
16
  'copy_signature',
@@ -67,47 +67,33 @@ class copy_signature(Generic[F0]):
67
67
  return cast(F0, wrapped)
68
68
 
69
69
 
70
- class injected_self_func(Generic[T, P, R], Protocol): # type: ignore[misc]
70
+ class injected_self_func(Protocol[T_co, P, R_co]):
71
71
  @overload
72
72
  @staticmethod
73
- def __call__(*args: P.args, **kwargs: P.kwargs) -> R:
73
+ def __call__(*args: P.args, **kwargs: P.kwargs) -> R_co:
74
74
  ...
75
75
 
76
76
  @overload
77
77
  @staticmethod
78
- def __call__(self: T, *args: P.args, **kwargs: P.kwargs) -> R:
78
+ def __call__(self: T_co, *args: P.args, **kwargs: P.kwargs) -> R_co: # type: ignore[misc]
79
79
  ...
80
80
 
81
81
  @overload
82
82
  @staticmethod
83
- def __call__(self: T, _self: T, *args: P.args, **kwargs: P.kwargs) -> R:
83
+ def __call__(cls: type[T_co], *args: P.args, **kwargs: P.kwargs) -> R_co:
84
84
  ...
85
85
 
86
- @overload
87
- @staticmethod
88
- def __call__(cls: type[T], *args: P.args, **kwargs: P.kwargs) -> R:
89
- ...
90
86
 
91
- @overload
92
- @staticmethod
93
- def __call__(cls: type[T], _cls: type[T], *args: P.args, **kwargs: P.kwargs) -> R:
94
- ...
87
+ self_objects_cache = dict[Any, Any]()
95
88
 
96
- @staticmethod
97
- def __call__(*args: Any, **kwds: Any) -> Any:
98
- ...
99
89
 
100
-
101
- self_objects_cache = dict[type, Any]()
102
-
103
-
104
- class inject_self_base(Generic[T, P, R]):
90
+ class inject_self_base(Generic[T_co, P, R_co]):
105
91
  cache: bool | None
106
92
  signature: Signature | None
107
93
  init_kwargs: list[str] | None
108
94
  first_key: str | None
109
95
 
110
- def __init__(self, function: Callable[Concatenate[T, P], R], /, *, cache: bool = False) -> None:
96
+ def __init__(self, function: Callable[Concatenate[T_co, P], R_co], /, *, cache: bool = False) -> None:
111
97
  """
112
98
  Wrap ``function`` to always have a self provided to it.
113
99
 
@@ -130,8 +116,8 @@ class inject_self_base(Generic[T, P, R]):
130
116
  self.clean_kwargs = False
131
117
 
132
118
  def __get__(
133
- self, class_obj: type[T] | T | None, class_type: type[T] | type[type[T]] # type: ignore
134
- ) -> injected_self_func[T, P, R]:
119
+ self, class_obj: type[T] | T | None, class_type: type[T] | type[type[T]] | Any # type: ignore[valid-type]
120
+ ) -> injected_self_func[T_co, P, R_co]:
135
121
  if not self.signature or not self.first_key:
136
122
  self.signature = Signature.from_callable(self.function, eval_str=True)
137
123
  self.first_key = next(iter(list(self.signature.parameters.keys())), None)
@@ -187,8 +173,8 @@ class inject_self_base(Generic[T, P, R]):
187
173
 
188
174
  return _wrapper
189
175
 
190
- def __call__(self, *args: P.args, **kwargs: P.kwargs) -> R:
191
- return self.__get__(None, self)(*args, **kwargs) # type: ignore
176
+ def __call__(self, *args: P.args, **kwargs: P.kwargs) -> R_co:
177
+ return self.__get__(None, self)(*args, **kwargs)
192
178
 
193
179
  @property
194
180
  def __signature__(self) -> Signature:
@@ -197,7 +183,7 @@ class inject_self_base(Generic[T, P, R]):
197
183
  @classmethod
198
184
  def with_args(
199
185
  cls, *args: Any, **kwargs: Any
200
- ) -> Callable[[Callable[Concatenate[T0, P0], R0]], inject_self[T0, P0, R0]]:
186
+ ) -> Callable[[Callable[Concatenate[T0_co, P0], R0_co]], inject_self[T0_co, P0, R0_co]]:
201
187
  """Provide custom args to instantiate the ``self`` object with."""
202
188
 
203
189
  def _wrapper(function: Callable[Concatenate[T0, P0], R0]) -> inject_self[T0, P0, R0]:
@@ -208,69 +194,71 @@ class inject_self_base(Generic[T, P, R]):
208
194
  return _wrapper
209
195
 
210
196
 
211
- class inject_self(Generic[T, P, R], inject_self_base[T, P, R]):
197
+ class inject_self(inject_self_base[T_co, P, R_co]):
212
198
  """Wrap a method so it always has a constructed ``self`` provided to it."""
213
199
 
214
- class cached(Generic[T0, P0, R0], inject_self_base[T0, P0, R0]):
200
+ class cached(inject_self_base[T0_co, P0, R0_co]):
215
201
  """
216
202
  Wrap a method so it always has a constructed ``self`` provided to it.
217
203
  Once ``self`` is constructed, it will be reused.
218
204
  """
219
205
 
220
- class property(Generic[T1, R1]):
221
- def __init__(self, function: Callable[[T1], R1]) -> None:
206
+ class property(Generic[T1_co, R1_co]):
207
+ def __init__(self, function: Callable[[T1_co], R1_co]) -> None:
222
208
  self.function = inject_self(function)
223
209
 
224
210
  def __get__(
225
- self, class_obj: type[T1] | T1 | None, class_type: type[T1] | type[type[T1]] # type: ignore
226
- ) -> R1:
211
+ self, class_obj: type[T1_co] | T1_co | None, class_type: type[T1_co] | T1_co
212
+ ) -> R1_co:
227
213
  return self.function.__get__(class_obj, class_type)()
228
214
 
229
- class init_kwargs(Generic[T0, P0, R0], inject_self_base[T0, P0, R0]):
215
+ class init_kwargs(inject_self_base[T0_co, P0, R0_co]):
230
216
  """
231
217
  Wrap a method so it always has a constructed ``self`` provided to it.
232
218
  When constructed, kwargs to the function will be passed to the constructor.
233
219
  """
234
220
 
235
221
  @classmethod
236
- def clean(cls, function: Callable[Concatenate[T1, P1], R1]) -> inject_self[T1, P1, R1]:
222
+ def clean(cls, function: Callable[Concatenate[T1_co, P1], R1_co]) -> inject_self[T1_co, P1, R1_co]:
237
223
  """Wrap a method, pass kwargs to the constructor and remove them from actual **kwargs."""
238
224
  inj = cls(function) # type: ignore
239
225
  inj.clean_kwargs = True
240
226
  return inj # type: ignore
241
227
 
242
- class property(Generic[T0, R0]):
243
- def __init__(self, function: Callable[[T0], R0]) -> None:
228
+ class property(Generic[T0_co, R0_co]):
229
+ def __init__(self, function: Callable[[T0_co], R0_co]) -> None:
244
230
  self.function = inject_self(function)
245
231
 
246
232
  def __get__(
247
- self, class_obj: type[T0] | T0 | None, class_type: type[T0] | type[type[T0]] # type: ignore
248
- ) -> R0:
233
+ self, class_obj: type[T0_co] | T0_co | None, class_type: type[T0_co] | T0_co
234
+ ) -> R0_co:
249
235
  return self.function.__get__(class_obj, class_type)()
250
236
 
251
237
 
252
- class inject_kwargs_params_base_func(Generic[T, P, R], Callable[Concatenate[T, P], R]): # type: ignore[misc]
253
- def __call__(self: T, *args: P.args, **kwargs: P.kwargs) -> R: # type: ignore
254
- ...
238
+ class inject_kwargs_params_base_func(Generic[T_co, P, R_co]):
239
+ def __call__(self: T_co, *args: P.args, **kwargs: P.kwargs) -> R_co:
240
+ raise NotImplementedError
255
241
 
256
242
 
257
- class inject_kwargs_params_base(Generic[T, P, R]):
243
+ class inject_kwargs_params_base(Generic[T_co, P, R_co]):
244
+ signature: Signature | None
245
+
258
246
  _kwargs_name = 'kwargs'
259
247
 
260
- def __init__(self, function: Callable[Concatenate[T, P], R]) -> None:
248
+ def __init__(self, function: Callable[Concatenate[T_co, P], R_co]) -> None:
261
249
  self.function = function
262
250
 
263
251
  self.signature = None
264
252
 
265
253
  def __get__(
266
254
  self, class_obj: T, class_type: type[T]
267
- ) -> inject_kwargs_params_base_func[T, P, R]:
255
+ ) -> inject_kwargs_params_base_func[T_co, P, R_co]:
268
256
  if not self.signature:
269
- self.signature = Signature.from_callable(self.function, eval_str=True) # type: ignore
257
+ self.signature = Signature.from_callable(self.function, eval_str=True)
270
258
 
271
259
  if (
272
- isinstance(self, inject_kwargs_params.add_to_kwargs) # type: ignore
273
- and (4 not in {x.kind for x in self.signature.parameters.values()}) # type: ignore
260
+ isinstance(self, inject_kwargs_params.add_to_kwargs) # type: ignore[arg-type]
261
+ and (4 not in {x.kind for x in self.signature.parameters.values()})
274
262
  ):
275
263
  from ..exceptions import CustomValueError
276
264
 
@@ -281,10 +269,10 @@ class inject_kwargs_params_base(Generic[T, P, R]):
281
269
  this = self
282
270
 
283
271
  @wraps(self.function)
284
- def _wrapper(self: T, *_args: P.args, **kwargs: P.kwargs) -> R:
272
+ def _wrapper(self: Any, *_args: Any, **kwargs: Any) -> R_co:
285
273
  assert this.signature
286
274
 
287
- if class_obj and not isinstance(self, class_type): # type: ignore
275
+ if class_obj and not isinstance(self, class_type):
288
276
  _args = (self, *_args)
289
277
  self = class_obj
290
278
 
@@ -318,14 +306,14 @@ class inject_kwargs_params_base(Generic[T, P, R]):
318
306
 
319
307
  kwargs[key] = kw_value
320
308
 
321
- if isinstance(this, inject_kwargs_params.add_to_kwargs):
309
+ if isinstance(this, inject_kwargs_params.add_to_kwargs): # type: ignore[arg-type]
322
310
  kwargs |= this_kwargs
323
311
 
324
312
  return this.function(self, *args, **kwargs)
325
313
 
326
314
  return _wrapper # type: ignore
327
315
 
328
- def __call__(self, *args: P.args, **kwargs: P.kwargs) -> R:
316
+ def __call__(self, *args: P.args, **kwargs: P.kwargs) -> R_co:
329
317
  return self.__get__(None, self)(*args, **kwargs) # type: ignore
330
318
 
331
319
  @property
@@ -422,89 +410,55 @@ def get_subclasses(family: type[T], exclude: Sequence[type[T]] = []) -> list[typ
422
410
  return list(set(_subclasses(family)))
423
411
 
424
412
 
425
- class classproperty(Generic[P, R, T, T0, P0]):
413
+ class classproperty(Generic[T, R]):
426
414
  """
427
415
  Make a class property. A combination between classmethod and property.
428
416
  """
429
417
 
430
418
  __isabstractmethod__: bool = False
431
419
 
432
- class metaclass(type):
433
- """This must be set for the decorator to work."""
434
-
435
- def __setattr__(self, key: str, value: Any) -> None:
436
- if key in self.__dict__:
437
- obj = self.__dict__.get(key)
438
-
439
- if obj and isinstance(obj, classproperty):
440
- obj.__set__(self, value)
441
- return
442
-
443
- super(classproperty.metaclass, self).__setattr__(key, value)
444
-
445
420
  def __init__(
446
421
  self,
447
- fget: classmethod[T, P, R] | Callable[P, R],
448
- fset: classmethod[T, P, None] | Callable[[T, T0], None] | None = None,
449
- fdel: classmethod[T, P1, None] | Callable[P1, None] | None = None,
422
+ fget: Callable[[type[T]], R] | classmethod[T, ..., R],
423
+ fset: Callable[[type[T], R], None] | classmethod[T, Concatenate[R, ...], None] | None = None,
424
+ fdel: Callable[[type[T]], None] | classmethod[T, ..., None] | None = None,
450
425
  doc: str | None = None,
451
426
  ) -> None:
452
427
  self.fget = self._wrap(fget)
453
428
  self.fset = self._wrap(fset) if fset is not None else fset
454
429
  self.fdel = self._wrap(fdel) if fdel is not None else fdel
455
430
 
456
- self.doc = doc
431
+ self.__doc__ = doc
457
432
 
458
- def _wrap(self, func: classmethod[T1, P1, R1] | Callable[P1, R1]) -> classmethod[T1, P1, R1]:
459
- if not isinstance(func, (classmethod, staticmethod)):
460
- func = classmethod(func) # type: ignore
433
+ def _wrap(self, func: Callable[..., R1] | classmethod[T, P1, R1]) -> classmethod[T, P1, R1]:
434
+ if not isinstance(func, classmethod):
435
+ func = classmethod(func)
461
436
 
462
- return func # type: ignore
437
+ return func
463
438
 
464
- def getter(self, __fget: classmethod[T, P, R] | Callable[P1, R1]) -> classproperty[P1, R1, T, T0, P0]:
465
- self.fget = self._wrap(__fget) # type: ignore
466
- return self # type: ignore
467
-
468
- def setter(self, __fset: classmethod[T1, P, None] | Callable[[T1, T2], None]) -> classproperty[P, R, T1, T2, P0]:
469
- self.fset = self._wrap(__fset) # type: ignore
470
- return self # type: ignore
471
-
472
- def deleter(self, __fdel: classmethod[T1, P1, None] | Callable[P1, None]) -> classproperty[P, R, T, T0, P1]:
473
- self.fdel = self._wrap(__fdel) # type: ignore
474
- return self # type: ignore
475
-
476
- def __get__(self, __obj: Any, __type: type | None = None) -> R:
439
+ def __get__(self, __obj: T | None, __type: type | None = None) -> R:
477
440
  if __type is None:
478
441
  __type = type(__obj)
479
442
 
480
- return self.fget.__get__(__obj, __type)() # type: ignore
481
-
482
- def __set__(self, __obj: Any, __value: Any) -> None:
483
- from ..exceptions import CustomError
443
+ return self.fget.__get__(__obj, __type)()
484
444
 
445
+ def __set__(self, __obj: T, __value: Any) -> None:
485
446
  if not self.fset:
486
- raise CustomError[AttributeError]("Can't set attribute")
487
-
488
- if isclass(__obj):
489
- type_, __obj = __obj, None
490
- else:
491
- type_ = type(__obj)
492
-
493
- return self.fset.__get__(__obj, type_)(__value)
447
+ raise AttributeError(
448
+ f'classproperty with getter "{self.__name__}" of "{__obj.__class__.__name__}" object has no setter.'
449
+ )
494
450
 
495
- def __delete__(self, __obj: Any) -> None:
496
- from ..exceptions import CustomError
451
+ self.fset.__get__(None, type(__obj))(__value)
497
452
 
453
+ def __delete__(self, __obj: T) -> None:
498
454
  if not self.fdel:
499
- raise CustomError[AttributeError]("Can't delete attribute")
500
-
501
- if isclass(__obj):
502
- type_, __obj = __obj, None
503
- else:
504
- type_ = type(__obj)
455
+ raise AttributeError(
456
+ f'classproperty with getter "{self.__name__}" of "{__obj.__class__.__name__}" object has no deleter.'
457
+ )
505
458
 
506
- return self.fdel.__delete__(__obj, type_)(__obj) # type: ignore
459
+ self.fdel.__get__(None, type(__obj))()
507
460
 
461
+ @property
508
462
  def __name__(self) -> str:
509
463
  return self.fget.__name__
510
464
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: jetpytools
3
- Version: 1.2.8
3
+ Version: 1.4.0
4
4
  Summary: Collection of stuff that's useful in general python programming
5
5
  Author: Jaded Encoding Thaumaturgy
6
6
  Author-email: jaded.encoding.thaumaturgy@gmail.com
@@ -18,6 +18,7 @@ Classifier: Typing :: Typed
18
18
  Requires-Python: >=3.10
19
19
  Description-Content-Type: text/markdown
20
20
  License-File: LICENSE
21
+ Requires-Dist: typing_extensions>=4.12.2
21
22
  Dynamic: author
22
23
  Dynamic: author-email
23
24
  Dynamic: classifier
@@ -27,6 +28,7 @@ Dynamic: license-file
27
28
  Dynamic: maintainer
28
29
  Dynamic: maintainer-email
29
30
  Dynamic: project-url
31
+ Dynamic: requires-dist
30
32
  Dynamic: requires-python
31
33
  Dynamic: summary
32
34
 
@@ -8,6 +8,7 @@ jetpytools/py.typed
8
8
  jetpytools.egg-info/PKG-INFO
9
9
  jetpytools.egg-info/SOURCES.txt
10
10
  jetpytools.egg-info/dependency_links.txt
11
+ jetpytools.egg-info/requires.txt
11
12
  jetpytools.egg-info/top_level.txt
12
13
  jetpytools/enums/__init__.py
13
14
  jetpytools/enums/base.py
@@ -34,4 +35,6 @@ jetpytools/utils/__init__.py
34
35
  jetpytools/utils/file.py
35
36
  jetpytools/utils/funcs.py
36
37
  jetpytools/utils/math.py
37
- jetpytools/utils/ranges.py
38
+ jetpytools/utils/ranges.py
39
+ tests/test_funcs.py
40
+ tests/test_normalize.py
@@ -0,0 +1 @@
1
+ typing_extensions>=4.12.2
@@ -7,6 +7,7 @@ show-source = True
7
7
  statistics = True
8
8
 
9
9
  [mypy]
10
+ python_version = 3.10
10
11
  ignore_missing_imports = False
11
12
  disallow_any_generics = True
12
13
  disallow_untyped_defs = True
@@ -25,6 +25,7 @@ setuptools.setup(
25
25
  'Source Code': 'https://github.com/Jaded-Encoding-Thaumaturgy/jetpytools',
26
26
  'Contact': 'https://discord.gg/XTpc6Fa9eB',
27
27
  },
28
+ install_requires="typing_extensions>=4.12.2",
28
29
  python_requires='>=3.10',
29
30
  packages=[
30
31
  package_name,
@@ -0,0 +1,12 @@
1
+ from __future__ import annotations
2
+
3
+ from jetpytools import fallback, iterate
4
+
5
+
6
+ def test_iterate() -> None:
7
+ assert iterate(5, lambda x: x * 2, 2) == 20
8
+
9
+
10
+ def test_fallback() -> None:
11
+ assert fallback(5, 6) == 5
12
+ assert fallback(None, 6) == 6
@@ -0,0 +1,9 @@
1
+ from __future__ import annotations
2
+
3
+ from jetpytools import normalize_ranges
4
+
5
+
6
+ def test_normalize_ranges() -> None:
7
+ assert normalize_ranges((None, None), end=1000) == [(0, 999)]
8
+ assert normalize_ranges((24, -24), end=1000) == [(24, 975)]
9
+ assert normalize_ranges([(24, 100), (80, 150)], end=1000) == [(24, 150)]
File without changes
File without changes