jetpytools 2.0.0__tar.gz → 2.0.2__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 (34) hide show
  1. {jetpytools-2.0.0 → jetpytools-2.0.2}/PKG-INFO +1 -1
  2. {jetpytools-2.0.0 → jetpytools-2.0.2}/jetpytools/_metadata.py +1 -1
  3. {jetpytools-2.0.0 → jetpytools-2.0.2}/jetpytools/types/supports.py +3 -1
  4. {jetpytools-2.0.0 → jetpytools-2.0.2}/jetpytools/types/utils.py +71 -51
  5. {jetpytools-2.0.0 → jetpytools-2.0.2}/.gitignore +0 -0
  6. {jetpytools-2.0.0 → jetpytools-2.0.2}/LICENSE +0 -0
  7. {jetpytools-2.0.0 → jetpytools-2.0.2}/README.md +0 -0
  8. {jetpytools-2.0.0 → jetpytools-2.0.2}/jetpytools/__init__.py +0 -0
  9. {jetpytools-2.0.0 → jetpytools-2.0.2}/jetpytools/enums/__init__.py +0 -0
  10. {jetpytools-2.0.0 → jetpytools-2.0.2}/jetpytools/enums/base.py +0 -0
  11. {jetpytools-2.0.0 → jetpytools-2.0.2}/jetpytools/enums/other.py +0 -0
  12. {jetpytools-2.0.0 → jetpytools-2.0.2}/jetpytools/exceptions/__init__.py +0 -0
  13. {jetpytools-2.0.0 → jetpytools-2.0.2}/jetpytools/exceptions/base.py +0 -0
  14. {jetpytools-2.0.0 → jetpytools-2.0.2}/jetpytools/exceptions/enum.py +0 -0
  15. {jetpytools-2.0.0 → jetpytools-2.0.2}/jetpytools/exceptions/file.py +0 -0
  16. {jetpytools-2.0.0 → jetpytools-2.0.2}/jetpytools/exceptions/generic.py +0 -0
  17. {jetpytools-2.0.0 → jetpytools-2.0.2}/jetpytools/exceptions/module.py +0 -0
  18. {jetpytools-2.0.0 → jetpytools-2.0.2}/jetpytools/functions/__init__.py +0 -0
  19. {jetpytools-2.0.0 → jetpytools-2.0.2}/jetpytools/functions/funcs.py +0 -0
  20. {jetpytools-2.0.0 → jetpytools-2.0.2}/jetpytools/functions/normalize.py +0 -0
  21. {jetpytools-2.0.0 → jetpytools-2.0.2}/jetpytools/functions/other.py +0 -0
  22. {jetpytools-2.0.0 → jetpytools-2.0.2}/jetpytools/py.typed +0 -0
  23. {jetpytools-2.0.0 → jetpytools-2.0.2}/jetpytools/types/__init__.py +0 -0
  24. {jetpytools-2.0.0 → jetpytools-2.0.2}/jetpytools/types/builtins.py +0 -0
  25. {jetpytools-2.0.0 → jetpytools-2.0.2}/jetpytools/types/check.py +0 -0
  26. {jetpytools-2.0.0 → jetpytools-2.0.2}/jetpytools/types/file.py +0 -0
  27. {jetpytools-2.0.0 → jetpytools-2.0.2}/jetpytools/types/funcs.py +0 -0
  28. {jetpytools-2.0.0 → jetpytools-2.0.2}/jetpytools/types/generic.py +0 -0
  29. {jetpytools-2.0.0 → jetpytools-2.0.2}/jetpytools/utils/__init__.py +0 -0
  30. {jetpytools-2.0.0 → jetpytools-2.0.2}/jetpytools/utils/file.py +0 -0
  31. {jetpytools-2.0.0 → jetpytools-2.0.2}/jetpytools/utils/funcs.py +0 -0
  32. {jetpytools-2.0.0 → jetpytools-2.0.2}/jetpytools/utils/math.py +0 -0
  33. {jetpytools-2.0.0 → jetpytools-2.0.2}/jetpytools/utils/ranges.py +0 -0
  34. {jetpytools-2.0.0 → jetpytools-2.0.2}/pyproject.toml +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: jetpytools
3
- Version: 2.0.0
3
+ Version: 2.0.2
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,6 +1,6 @@
1
1
  """Collection of stuff that's useful in general python programming"""
2
2
 
3
- __version__ = "2.0.0"
3
+ __version__ = "2.0.2"
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__
@@ -113,14 +113,16 @@ class ComparatorFunc(Protocol):
113
113
  ) -> T0 | T1: ...
114
114
 
115
115
 
116
+ @runtime_checkable
116
117
  class SupportsIndexing[T](Protocol):
117
118
  def __getitem__(self, k: int) -> T: ...
118
119
 
119
120
 
121
+ @runtime_checkable
120
122
  class SupportsKeysAndGetItem[KT, VT](Protocol):
121
123
  def keys(self) -> Iterable[KT]: ...
122
124
 
123
125
  def __getitem__(self, k: KT) -> VT: ...
124
126
 
125
127
 
126
- type SupportsFloatOrIndex = SupportsFloat | SupportsIndex
128
+ SupportsFloatOrIndex = SupportsFloat | SupportsIndex
@@ -3,7 +3,7 @@ from __future__ import annotations
3
3
  import sys
4
4
  from contextlib import suppress
5
5
  from functools import wraps
6
- from inspect import Signature
6
+ from inspect import Signature, get_annotations
7
7
  from typing import (
8
8
  TYPE_CHECKING,
9
9
  Any,
@@ -192,10 +192,12 @@ class _InjectSelfBase(Generic[_T_co, _P, _R_co]):
192
192
  self.args = args
193
193
  self.kwargs = kwargs
194
194
 
195
- def __get__[T](self, instance: T | None, owner: type[T]) -> _InjectedSelfFunc[T, _P, _R_co]: # pyright: ignore[reportGeneralTypeIssues]
195
+ def __get__(self, instance: Any | None, owner: type | None = None) -> _InjectedSelfFunc[_T_co, _P, _R_co]: # pyright: ignore[reportGeneralTypeIssues]
196
196
  """
197
197
  Return a wrapped callable that automatically injects an instance as the first argument when called.
198
198
  """
199
+ if owner is None:
200
+ owner = type(instance)
199
201
 
200
202
  @wraps(self._function)
201
203
  def _wrapper(*args: Any, **kwargs: Any) -> _R_co:
@@ -263,6 +265,9 @@ class _InjectSelfBase(Generic[_T_co, _P, _R_co]):
263
265
 
264
266
  return owner(*self.args, **self.kwargs), kwargs
265
267
 
268
+ def __call__(self_, self: _T_co, *args: _P.args, **kwargs: _P.kwargs) -> _R_co: # type: ignore[misc] # noqa: N805
269
+ return self_.__get__(self, type(self))(*args, **kwargs)
270
+
266
271
  @property
267
272
  def __func__(self) -> Callable[Concatenate[_T_co, _P], _R_co]:
268
273
  """Return the original wrapped function."""
@@ -377,10 +382,10 @@ class _InjectKwargsParamsBase(Generic[_T_co, _P, _R_co]):
377
382
  self._signature = None
378
383
 
379
384
  @overload
380
- def __get__(self, instance: None, owner: type[Any]) -> Self: ...
385
+ def __get__(self, instance: None, owner: type) -> Self: ...
381
386
  @overload
382
- def __get__(self, instance: Any, owner: type[Any]) -> Callable[_P, _R_co]: ...
383
- def __get__(self, instance: Any | None, owner: type[Any]) -> Self | Callable[_P, _R_co]:
387
+ def __get__(self, instance: Any, owner: type | None = None) -> Callable[_P, _R_co]: ...
388
+ def __get__(self, instance: Any | None, owner: type | None = None) -> Any:
384
389
  """
385
390
  Descriptor binding logic.
386
391
 
@@ -435,6 +440,9 @@ class _InjectKwargsParamsBase(Generic[_T_co, _P, _R_co]):
435
440
 
436
441
  return wrapper
437
442
 
443
+ def __call__(self_, self: _T_co, *args: _P.args, **kwargs: _P.kwargs) -> _R_co: # type: ignore[misc] # noqa: N805
444
+ return self_.__get__(self, type(self))(*args, **kwargs)
445
+
438
446
  @property
439
447
  def __func__(self) -> Callable[Concatenate[_T_co, _P], _R_co]:
440
448
  """Return the original wrapped function."""
@@ -467,7 +475,7 @@ class _InjectKwargsParamsBase(Generic[_T_co, _P, _R_co]):
467
475
  return _wrapper
468
476
 
469
477
 
470
- class inject_kwargs_params[T, **P, R](_InjectKwargsParamsBase[T, P, R]):
478
+ class inject_kwargs_params(_InjectKwargsParamsBase[_T_co, _P, _R_co]):
471
479
  """
472
480
  Descriptor that injects parameters into functions based on an instance's keyword mapping.
473
481
 
@@ -478,7 +486,7 @@ class inject_kwargs_params[T, **P, R](_InjectKwargsParamsBase[T, P, R]):
478
486
 
479
487
  __slots__ = ()
480
488
 
481
- class add_to_kwargs[T0, **P0, R0](_InjectKwargsParamsBase[T0, P0, R0]):
489
+ class add_to_kwargs(_InjectKwargsParamsBase[_T0_co, _P0, _R0_co]):
482
490
  """
483
491
  Variant of `inject_kwargs_params` that merges unused entries from `self.kwargs` into the keyword arguments
484
492
  passed to the target function.
@@ -490,13 +498,13 @@ class inject_kwargs_params[T, **P, R](_InjectKwargsParamsBase[T, P, R]):
490
498
 
491
499
 
492
500
  class _ComplexHash[**P, R]:
493
- __slots__ = "func"
501
+ __slots__ = "_func"
494
502
 
495
503
  def __init__(self, func: Callable[P, R]) -> None:
496
- self.func = func
504
+ self._func = func
497
505
 
498
506
  def __call__(self, *args: P.args, **kwargs: P.kwargs) -> R:
499
- return self.func(*args, **kwargs)
507
+ return self._func(*args, **kwargs)
500
508
 
501
509
  @staticmethod
502
510
  def hash(*args: Any) -> int:
@@ -507,8 +515,8 @@ class _ComplexHash[**P, R]:
507
515
 
508
516
  :return: Hash of all the combined objects' hashes.
509
517
  """
510
-
511
518
  values = list[str]()
519
+
512
520
  for value in args:
513
521
  try:
514
522
  new_hash = hash(value)
@@ -523,18 +531,21 @@ class _ComplexHash[**P, R]:
523
531
  @_ComplexHash
524
532
  def complex_hash[T](cls: type[T]) -> type[T]:
525
533
  """
526
- Decorator for classes to add a ``__hash__`` method to them.
534
+ Class decorator that automatically adds a ``__hash__`` method to the target class.
535
+
536
+ The generated ``__hash__`` method computes a hash value derived from:
537
+ - the class's name
538
+ - the values of all attributes listed in its type annotations.
527
539
 
528
- Especially useful for NamedTuples.
540
+ This is particularly useful for immutable data structures (e.g., NamedTuples or dataclasses).
529
541
  """
530
542
 
531
543
  def __hash__(self: T) -> int: # noqa: N807
532
- return complex_hash.hash(self.__class__.__name__, *(getattr(self, key) for key in self.__annotations__))
544
+ return complex_hash.hash(self.__class__.__name__, *(getattr(self, key) for key in get_annotations(cls)))
533
545
 
534
- ns = cls.__dict__.copy()
535
- ns["__hash__"] = __hash__
546
+ setattr(cls, __hash__.__name__, __hash__)
536
547
 
537
- return type(cls.__name__, (cls,), ns) # pyright: ignore[reportReturnType]
548
+ return cls
538
549
 
539
550
 
540
551
  def get_subclasses[T](family: type[T], exclude: Sequence[type[T]] = []) -> list[type[T]]:
@@ -584,61 +595,59 @@ class classproperty_base(Generic[_T, _R_co, _T_Any]):
584
595
  def __set_name__(self, owner: object, name: str) -> None:
585
596
  self.__name__ = name
586
597
 
587
- def _get_cache(self, type_: type[_T]) -> dict[str, Any]:
598
+ def _get_cache(self, owner: type[_T]) -> dict[str, Any]:
588
599
  cache_key = getattr(self, "cache_key")
589
600
 
590
- if not hasattr(type_, cache_key):
591
- setattr(type_, cache_key, {})
601
+ if not hasattr(owner, cache_key):
602
+ setattr(owner, cache_key, {})
592
603
 
593
- return getattr(type_, cache_key)
604
+ return getattr(owner, cache_key)
594
605
 
595
- def __get__(self, obj: _T | None, type_: type[_T] | None = None) -> _R_co:
596
- if type_ is None and obj is not None:
597
- type_ = type(obj)
598
- elif type_ is None:
599
- raise NotImplementedError("Both obj and type_ are None")
606
+ def __get__(self, instance: Any | None, owner: type | None = None) -> _R_co:
607
+ if owner is None:
608
+ owner = type(instance)
600
609
 
601
610
  if not isinstance(self, classproperty.cached):
602
- return self.fget(type_)
611
+ return self.fget(owner)
603
612
 
604
- if self.__name__ in (cache := self._get_cache(type_)):
613
+ if self.__name__ in (cache := self._get_cache(owner)):
605
614
  return cache[self.__name__]
606
615
 
607
- value = self.fget(type_)
616
+ value = self.fget(owner)
608
617
  cache[self.__name__] = value
609
618
  return value
610
619
 
611
- def __set__(self, obj: _T, value: _T_Any) -> None:
620
+ def __set__(self, instance: Any, value: _T_Any) -> None:
612
621
  if not self.fset:
613
622
  raise AttributeError(
614
- f'classproperty with getter "{self.__name__}" of "{obj.__class__.__name__}" object has no setter.'
623
+ f'classproperty with getter "{self.__name__}" of "{instance.__class__.__name__}" object has no setter.'
615
624
  )
616
625
 
617
- type_ = type(obj)
626
+ owner = type(instance)
618
627
 
619
628
  if not isinstance(self, classproperty.cached):
620
- return self.fset(type_, value)
629
+ return self.fset(owner, value)
621
630
 
622
- if self.__name__ in (cache := self._get_cache(type_)):
631
+ if self.__name__ in (cache := self._get_cache(owner)):
623
632
  del cache[self.__name__]
624
633
 
625
- self.fset(type_, value)
634
+ self.fset(owner, value)
626
635
 
627
- def __delete__(self, obj: _T) -> None:
636
+ def __delete__(self, instance: Any) -> None:
628
637
  if not self.fdel:
629
638
  raise AttributeError(
630
- f'classproperty with getter "{self.__name__}" of "{obj.__class__.__name__}" object has no deleter.'
639
+ f'classproperty with getter "{self.__name__}" of "{instance.__class__.__name__}" object has no deleter.'
631
640
  )
632
641
 
633
- type_ = type(obj)
642
+ owner = type(instance)
634
643
 
635
644
  if not isinstance(self, classproperty.cached):
636
- return self.fdel(type_)
645
+ return self.fdel(owner)
637
646
 
638
- if self.__name__ in (cache := self._get_cache(type_)):
647
+ if self.__name__ in (cache := self._get_cache(owner)):
639
648
  del cache[self.__name__]
640
649
 
641
- self.fdel(type_)
650
+ self.fdel(owner)
642
651
 
643
652
 
644
653
  class classproperty(classproperty_base[_T, _R_co, _T_Any]):
@@ -788,22 +797,33 @@ class KwargsNotNone(KwargsT):
788
797
 
789
798
 
790
799
  class SingletonMeta(type):
791
- _instances: ClassVar[dict[type[Any], Any]] = {}
800
+ _instances: ClassVar[dict[SingletonMeta, Any]] = {}
792
801
  _singleton_init: bool
793
802
 
794
803
  def __new__[MetaSelf: SingletonMeta](
795
- mcls: type[MetaSelf], name: str, bases: tuple[type, ...], namespace: dict[str, Any], **kwargs: Any
804
+ mcls: type[MetaSelf],
805
+ name: str,
806
+ bases: tuple[type, ...],
807
+ namespace: dict[str, Any],
808
+ *,
809
+ init: bool = False,
810
+ **kwargs: Any,
796
811
  ) -> MetaSelf:
797
- namespace["_singleton_init"] = kwargs.pop("init", False)
798
- return super().__new__(mcls, name, bases, namespace, **kwargs)
812
+ cls = super().__new__(mcls, name, bases, namespace, **kwargs)
813
+ cls._singleton_init = init
814
+ return cls
815
+
816
+ if not TYPE_CHECKING:
817
+
818
+ def __call__(cls, *args: Any, **kwargs: Any) -> Any:
819
+ if cls not in cls._instances:
820
+ cls._instances[cls] = obj = super().__call__(*args, **kwargs)
821
+ return obj
799
822
 
800
- def __call__(cls, *args: Any, **kwargs: Any) -> SingletonMeta:
801
- if cls not in cls._instances:
802
- cls._instances[cls] = super(SingletonMeta, cls).__call__(*args, **kwargs)
803
- elif cls._singleton_init:
804
- cls._instances[cls].__init__(*args, **kwargs)
823
+ if cls._singleton_init:
824
+ cls._instances[cls].__init__(*args, **kwargs)
805
825
 
806
- return cls._instances[cls]
826
+ return cls._instances[cls]
807
827
 
808
828
 
809
829
  class Singleton(metaclass=SingletonMeta):
File without changes
File without changes
File without changes
File without changes