jetpytools 1.6.4__py3-none-any.whl → 1.7.0__py3-none-any.whl
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.
- jetpytools/_metadata.py +1 -1
- jetpytools/exceptions/base.py +1 -1
- jetpytools/types/utils.py +129 -60
- {jetpytools-1.6.4.dist-info → jetpytools-1.7.0.dist-info}/METADATA +1 -1
- {jetpytools-1.6.4.dist-info → jetpytools-1.7.0.dist-info}/RECORD +7 -7
- {jetpytools-1.6.4.dist-info → jetpytools-1.7.0.dist-info}/WHEEL +0 -0
- {jetpytools-1.6.4.dist-info → jetpytools-1.7.0.dist-info}/licenses/LICENSE +0 -0
jetpytools/_metadata.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""Collection of stuff that's useful in general python programming"""
|
|
2
2
|
|
|
3
|
-
__version__ = "1.
|
|
3
|
+
__version__ = "1.7.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__
|
jetpytools/exceptions/base.py
CHANGED
jetpytools/types/utils.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from
|
|
3
|
+
from contextlib import suppress
|
|
4
|
+
from functools import wraps
|
|
4
5
|
from inspect import Signature
|
|
5
6
|
from inspect import _empty as empty_param
|
|
6
7
|
from typing import (
|
|
@@ -21,9 +22,9 @@ from typing import (
|
|
|
21
22
|
overload,
|
|
22
23
|
)
|
|
23
24
|
|
|
24
|
-
from typing_extensions import Self
|
|
25
|
+
from typing_extensions import Self, deprecated
|
|
25
26
|
|
|
26
|
-
from .builtins import F0, F1, P0, P1, R0, R1, T0,
|
|
27
|
+
from .builtins import F0, F1, P0, P1, R0, R1, T0, KwargsT, P, R, R0_co, R1_co, R_co, T, T0_co, T1_co, T_co
|
|
27
28
|
|
|
28
29
|
__all__ = [
|
|
29
30
|
"KwargsNotNone",
|
|
@@ -400,17 +401,15 @@ def get_subclasses(family: type[T], exclude: Sequence[type[T]] = []) -> list[typ
|
|
|
400
401
|
return list(set(_subclasses(family)))
|
|
401
402
|
|
|
402
403
|
|
|
403
|
-
class
|
|
404
|
-
"""
|
|
405
|
-
Make a class property. A combination between classmethod and property.
|
|
406
|
-
"""
|
|
407
|
-
|
|
404
|
+
class classproperty_base(Generic[T, R_co]):
|
|
408
405
|
__isabstractmethod__: bool = False
|
|
409
406
|
|
|
410
407
|
def __init__(
|
|
411
408
|
self,
|
|
412
|
-
fget: Callable[[type[T]],
|
|
413
|
-
fset: Callable[[type[T],
|
|
409
|
+
fget: Callable[[type[T]], R_co] | classmethod[T, ..., R_co],
|
|
410
|
+
fset: Callable[Concatenate[type[T], Any, ...], None]
|
|
411
|
+
| classmethod[T, Concatenate[Any, ...], None]
|
|
412
|
+
| None = None,
|
|
414
413
|
fdel: Callable[[type[T]], None] | classmethod[T, ..., None] | None = None,
|
|
415
414
|
doc: str | None = None,
|
|
416
415
|
) -> None:
|
|
@@ -419,6 +418,7 @@ class classproperty(Generic[T, R]):
|
|
|
419
418
|
self.fdel = self._wrap(fdel) if fdel is not None else fdel
|
|
420
419
|
|
|
421
420
|
self.__doc__ = doc
|
|
421
|
+
self.__name__ = self.fget.__name__
|
|
422
422
|
|
|
423
423
|
def _wrap(self, func: Callable[..., R1] | classmethod[T, P1, R1]) -> classmethod[T, P1, R1]:
|
|
424
424
|
if not isinstance(func, classmethod):
|
|
@@ -426,11 +426,30 @@ class classproperty(Generic[T, R]):
|
|
|
426
426
|
|
|
427
427
|
return func
|
|
428
428
|
|
|
429
|
-
def
|
|
429
|
+
def __set_name__(self, owner: object, name: str) -> None:
|
|
430
|
+
self.__name__ = name
|
|
431
|
+
|
|
432
|
+
def _get_cache(self, type_: type) -> dict[str, Any]:
|
|
433
|
+
cache_key = getattr(self, "cache_key")
|
|
434
|
+
|
|
435
|
+
if not hasattr(type_, cache_key):
|
|
436
|
+
setattr(type_, cache_key, {})
|
|
437
|
+
|
|
438
|
+
return getattr(type_, cache_key)
|
|
439
|
+
|
|
440
|
+
def __get__(self, obj: T | None, type_: type | None = None) -> R_co:
|
|
430
441
|
if type_ is None:
|
|
431
442
|
type_ = type(obj)
|
|
432
443
|
|
|
433
|
-
|
|
444
|
+
if not isinstance(self, classproperty.cached):
|
|
445
|
+
return self.fget.__get__(obj, type_)()
|
|
446
|
+
|
|
447
|
+
if self.__name__ in (cache := self._get_cache(type_)):
|
|
448
|
+
return cache[self.__name__]
|
|
449
|
+
|
|
450
|
+
value = self.fget.__get__(obj, type_)()
|
|
451
|
+
cache[self.__name__] = value
|
|
452
|
+
return value
|
|
434
453
|
|
|
435
454
|
def __set__(self, obj: T, value: Any) -> None:
|
|
436
455
|
if not self.fset:
|
|
@@ -438,7 +457,12 @@ class classproperty(Generic[T, R]):
|
|
|
438
457
|
f'classproperty with getter "{self.__name__}" of "{obj.__class__.__name__}" object has no setter.'
|
|
439
458
|
)
|
|
440
459
|
|
|
441
|
-
|
|
460
|
+
type_ = type(obj)
|
|
461
|
+
|
|
462
|
+
if self.__name__ in (cache := self._get_cache(type_)):
|
|
463
|
+
del cache[self.__name__]
|
|
464
|
+
|
|
465
|
+
self.fset.__get__(None, type_)(value)
|
|
442
466
|
|
|
443
467
|
def __delete__(self, obj: T) -> None:
|
|
444
468
|
if not self.fdel:
|
|
@@ -446,88 +470,133 @@ class classproperty(Generic[T, R]):
|
|
|
446
470
|
f'classproperty with getter "{self.__name__}" of "{obj.__class__.__name__}" object has no deleter.'
|
|
447
471
|
)
|
|
448
472
|
|
|
449
|
-
|
|
473
|
+
type_ = type(obj)
|
|
450
474
|
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
475
|
+
if self.__name__ in (cache := self._get_cache(type_)):
|
|
476
|
+
del cache[self.__name__]
|
|
477
|
+
|
|
478
|
+
self.fdel.__get__(None, type_)()
|
|
454
479
|
|
|
455
480
|
|
|
456
|
-
class
|
|
481
|
+
class classproperty(classproperty_base[T, R_co]):
|
|
457
482
|
"""
|
|
458
|
-
|
|
483
|
+
A combination of `classmethod` and `property`.
|
|
484
|
+
"""
|
|
485
|
+
|
|
486
|
+
class cached(classproperty_base[T0, R0_co]):
|
|
487
|
+
"""
|
|
488
|
+
A combination of `classmethod` and `property`.
|
|
489
|
+
|
|
490
|
+
The value is computed once and then cached in a dictionary (under `cache_key`)
|
|
491
|
+
attached to the class type. If a setter or deleter is defined and invoked,
|
|
492
|
+
the cache is cleared.
|
|
493
|
+
"""
|
|
459
494
|
|
|
460
|
-
|
|
495
|
+
cache_key = "_jetpt_classproperty_cached"
|
|
496
|
+
|
|
497
|
+
@classmethod
|
|
498
|
+
def clear_cache(cls, type_: type, names: str | Iterable[str] | None = None) -> None:
|
|
499
|
+
"""
|
|
500
|
+
Clear cached properties of an type instance.
|
|
461
501
|
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
502
|
+
:param type_: The type whose cache should be cleared.
|
|
503
|
+
:param names: Specific property names to clear. If None, all cached properties are cleared.
|
|
504
|
+
"""
|
|
505
|
+
if names is None:
|
|
506
|
+
with suppress(AttributeError):
|
|
507
|
+
getattr(type_, cls.cache_key).clear()
|
|
508
|
+
return None
|
|
509
|
+
|
|
510
|
+
from ..functions import to_arr
|
|
511
|
+
|
|
512
|
+
cache = getattr(type_, cls.cache_key, {})
|
|
513
|
+
|
|
514
|
+
for name in to_arr(names):
|
|
515
|
+
with suppress(KeyError):
|
|
516
|
+
del cache[name]
|
|
517
|
+
|
|
518
|
+
|
|
519
|
+
class cachedproperty(property, Generic[R_co]):
|
|
520
|
+
"""
|
|
521
|
+
Wrapper for a one-time get property, that will be cached.
|
|
522
|
+
|
|
523
|
+
You shouldn't hold a reference to itself or it will never get garbage collected.
|
|
465
524
|
"""
|
|
466
525
|
|
|
467
526
|
__isabstractmethod__: bool = False
|
|
468
527
|
|
|
469
528
|
cache_key = "_jetpt_cachedproperty_cache"
|
|
470
529
|
|
|
530
|
+
@deprecated(
|
|
531
|
+
"The cache dict is now set automatically. You no longer need to inherit from it", category=DeprecationWarning
|
|
532
|
+
)
|
|
471
533
|
class baseclass:
|
|
472
534
|
"""Inherit from this class to automatically set the cache dict."""
|
|
473
535
|
|
|
474
|
-
if not TYPE_CHECKING:
|
|
475
|
-
|
|
476
|
-
def __new__(cls, *args: Any, **kwargs: Any) -> None:
|
|
477
|
-
try:
|
|
478
|
-
self = super().__new__(cls, *args, **kwargs)
|
|
479
|
-
except TypeError:
|
|
480
|
-
self = super().__new__(cls)
|
|
481
|
-
self.__dict__.__setitem__(cachedproperty.cache_key, dict[str, Any]())
|
|
482
|
-
return self
|
|
483
|
-
|
|
484
536
|
if TYPE_CHECKING:
|
|
485
537
|
|
|
486
538
|
def __init__(
|
|
487
539
|
self,
|
|
488
|
-
fget: Callable[
|
|
489
|
-
fset: Callable[[
|
|
490
|
-
fdel: Callable[
|
|
540
|
+
fget: Callable[[Any], R_co],
|
|
541
|
+
fset: Callable[[Any, Any], None] | None = None,
|
|
542
|
+
fdel: Callable[[Any], None] | None = None,
|
|
491
543
|
doc: str | None = None,
|
|
492
544
|
) -> None: ...
|
|
493
545
|
|
|
494
|
-
def getter(self, fget: Callable[
|
|
546
|
+
def getter(self, fget: Callable[..., R_co]) -> cachedproperty[R_co]: ...
|
|
495
547
|
|
|
496
|
-
def setter(self, fset: Callable[[
|
|
548
|
+
def setter(self, fset: Callable[[Any, Any], None]) -> cachedproperty[R_co]: ...
|
|
497
549
|
|
|
498
|
-
def deleter(self, fdel: Callable[
|
|
550
|
+
def deleter(self, fdel: Callable[..., None]) -> cachedproperty[R_co]: ...
|
|
499
551
|
|
|
500
552
|
@overload
|
|
501
|
-
def __get__(self,
|
|
553
|
+
def __get__(self, instance: None, owner: type | None = None) -> Self: ...
|
|
502
554
|
|
|
503
555
|
@overload
|
|
504
|
-
def __get__(self,
|
|
556
|
+
def __get__(self, instance: Any, owner: type | None = None) -> R_co: ...
|
|
505
557
|
|
|
506
|
-
def __get__(self,
|
|
507
|
-
if
|
|
508
|
-
|
|
509
|
-
obj = type_
|
|
558
|
+
def __get__(self, instance: Any, owner: type | None = None) -> Any:
|
|
559
|
+
if instance is None:
|
|
560
|
+
return self
|
|
510
561
|
|
|
511
|
-
|
|
512
|
-
|
|
562
|
+
if self.__name__ in (cache := instance.__dict__.setdefault(self.cache_key, {})):
|
|
563
|
+
return cache[self.__name__]
|
|
513
564
|
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
assert self.fget
|
|
518
|
-
function = self.fget.__get__(obj, type_)
|
|
519
|
-
cache = obj.__dict__.get(cachedproperty.cache_key)
|
|
520
|
-
name = function.__name__
|
|
565
|
+
value = super().__get__(instance, owner)
|
|
566
|
+
cache[self.__name__] = value
|
|
567
|
+
return value
|
|
521
568
|
|
|
522
|
-
|
|
523
|
-
|
|
569
|
+
def __set__(self, instance: Any, value: Any) -> None:
|
|
570
|
+
if self.__name__ in (cache := instance.__dict__.setdefault(self.cache_key, {})):
|
|
571
|
+
del cache[self.__name__]
|
|
524
572
|
|
|
525
|
-
return
|
|
573
|
+
return super().__set__(instance, value)
|
|
526
574
|
|
|
527
|
-
|
|
575
|
+
def __delete__(self, instance: Any) -> None:
|
|
576
|
+
if self.__name__ in (cache := instance.__dict__.setdefault(self.cache_key, {})):
|
|
577
|
+
del cache[self.__name__]
|
|
578
|
+
|
|
579
|
+
return super().__delete__(instance)
|
|
580
|
+
|
|
581
|
+
@classmethod
|
|
582
|
+
def clear_cache(cls, obj: object, names: str | Iterable[str] | None = None) -> None:
|
|
583
|
+
"""
|
|
584
|
+
Clear cached properties of an object instance.
|
|
585
|
+
|
|
586
|
+
:param obj: The object whose cache should be cleared.
|
|
587
|
+
:param names: Specific property names to clear. If None, all cached properties are cleared.
|
|
588
|
+
"""
|
|
589
|
+
if names is None:
|
|
590
|
+
obj.__dict__.get(cls.cache_key, {}).clear()
|
|
591
|
+
return None
|
|
592
|
+
|
|
593
|
+
from ..functions import to_arr
|
|
594
|
+
|
|
595
|
+
cache = obj.__dict__.get(cls.cache_key, {})
|
|
528
596
|
|
|
529
|
-
|
|
530
|
-
|
|
597
|
+
for name in to_arr(names):
|
|
598
|
+
with suppress(KeyError):
|
|
599
|
+
del cache[name]
|
|
531
600
|
|
|
532
601
|
|
|
533
602
|
class KwargsNotNone(KwargsT):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: jetpytools
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.7.0
|
|
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
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
jetpytools/__init__.py,sha256=ha_pCOMqfeIbipDRrtqKOqH3NQEpX4KwN2SskpsCGb4,114
|
|
2
|
-
jetpytools/_metadata.py,sha256=
|
|
2
|
+
jetpytools/_metadata.py,sha256=3W5CtWRlEtbGoTDF01K0zcMyjXfrii4o8Rdz1tDvRKE,414
|
|
3
3
|
jetpytools/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
4
|
jetpytools/enums/__init__.py,sha256=TvEt3TWmnzf2TWS_Gd6llyyXAGDKxdhdJsDgSvT7xys,41
|
|
5
5
|
jetpytools/enums/base.py,sha256=L5dk6UAsQ3V6GVj0vulKaiJsholnh0Ftyh1FZFM9zwI,2034
|
|
6
6
|
jetpytools/enums/other.py,sha256=9GGRS4P-P589C1HqNpDDBhLdphID1trwCJi7pbXT0iM,1317
|
|
7
7
|
jetpytools/exceptions/__init__.py,sha256=0rNEfnOuoSRUyKsutGzHFWQkgiFaK7diOT4VbRVKt9c,105
|
|
8
|
-
jetpytools/exceptions/base.py,sha256=
|
|
8
|
+
jetpytools/exceptions/base.py,sha256=cCVT-v-mJoWzLvOxB5SG5dkeGAM_allXAuRgjfI9H6E,7649
|
|
9
9
|
jetpytools/exceptions/enum.py,sha256=euR6cyMetVWSfTgO5rkblhQyEgusdwhx6Rd9I5ZoFbA,293
|
|
10
10
|
jetpytools/exceptions/file.py,sha256=7Eh4aPo4r1W-ppnf6XLwWaStOSjIxw9JfzOCa4W7m8E,1105
|
|
11
11
|
jetpytools/exceptions/generic.py,sha256=5LYQHdSLM2wu5fv40PTrjkW9v0iq8R-QlQzhVsiLLpE,1509
|
|
@@ -21,13 +21,13 @@ jetpytools/types/file.py,sha256=LbOwMAwDALWxAZZ2i7ZNexoN3GHWD-uUoIhVvUy95Vo,6539
|
|
|
21
21
|
jetpytools/types/funcs.py,sha256=U5tBmTtLS5CLp3ZtOiA5101PQiCWQOBsmf0bj1pRwgY,2778
|
|
22
22
|
jetpytools/types/generic.py,sha256=SFnUqDAVehKZ36HmLrs9PN4Ze0BLcabPjwC7hJsGp4w,1102
|
|
23
23
|
jetpytools/types/supports.py,sha256=woMTv62HpcRiC5TG18U8NU5v2Q6iqcrHzQgXl7QYEws,3516
|
|
24
|
-
jetpytools/types/utils.py,sha256=
|
|
24
|
+
jetpytools/types/utils.py,sha256=oISv8o8xD1BS-MjsEDpDBitDQPfkGou1FoyN4EsHYa8,22614
|
|
25
25
|
jetpytools/utils/__init__.py,sha256=_rJ-mY5PsGjBfy8Fihx_FYJfAIGSrYAYzI6Td9oFh9A,83
|
|
26
26
|
jetpytools/utils/file.py,sha256=um4ow7_UEH1UxOV74w6F1u4s0wC4zh98LrcwBYjed50,10578
|
|
27
27
|
jetpytools/utils/funcs.py,sha256=2qhFyLD0OLvenjzOu2wu1ZWoZGzQ8aPmvbkAI1i9Gvk,914
|
|
28
28
|
jetpytools/utils/math.py,sha256=I56OeHDDJl3X8EFXMWVEiXGAD16AKcn8KVnFuP5fFes,3445
|
|
29
29
|
jetpytools/utils/ranges.py,sha256=glxypgmuzauV6KCSNujNHOdWkNEUNylOUAPS618jnIg,2559
|
|
30
|
-
jetpytools-1.
|
|
31
|
-
jetpytools-1.
|
|
32
|
-
jetpytools-1.
|
|
33
|
-
jetpytools-1.
|
|
30
|
+
jetpytools-1.7.0.dist-info/METADATA,sha256=iB6mPlOU_lgtyaIwSz1RM-NSe77g-P9r3FepRPCgrI8,1198
|
|
31
|
+
jetpytools-1.7.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
32
|
+
jetpytools-1.7.0.dist-info/licenses/LICENSE,sha256=l0PN-qDtXcgOB5aXP_nSUsvCK5V3o9pQCGsTzyZhKL0,1071
|
|
33
|
+
jetpytools-1.7.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|