dycw-utilities 0.162.7__py3-none-any.whl → 0.162.9__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dycw-utilities
3
- Version: 0.162.7
3
+ Version: 0.162.9
4
4
  Author-email: Derek Wan <d.wan@icloud.com>
5
5
  License-File: LICENSE
6
6
  Requires-Python: >=3.12
@@ -1,4 +1,4 @@
1
- utilities/__init__.py,sha256=Dcz0z6bhNKqyHot7MCQfuWzE8TliQJMNyt--tNT0EAs,60
1
+ utilities/__init__.py,sha256=yIzdXMHAz9NOoXJ_vYb10qb8XxfKwv3K-9tpKq1xLb4,60
2
2
  utilities/aeventkit.py,sha256=ddoleSwW9zdc2tjX5Ge0pMKtYwV_JMxhHYOxnWX2AGM,12609
3
3
  utilities/altair.py,sha256=92E2lCdyHY4Zb-vCw6rEJIsWdKipuu-Tu2ab1ufUfAk,9079
4
4
  utilities/asyncio.py,sha256=PUedzQ5deqlSECQ33sam9cRzI9TnygHz3FdOqWJWPTM,15288
@@ -57,7 +57,7 @@ utilities/pytest.py,sha256=M-Om6b3hpF9W_bEB7UFY2IzBCubSxzVQleGrgRXHtxY,7741
57
57
  utilities/pytest_regressions.py,sha256=ocjHTtfOeiGfQAKIei8pKNd61sxN9dawrJJ9gPt2wzA,4097
58
58
  utilities/random.py,sha256=hZlH4gnAtoaofWswuJYjcygejrY8db4CzP-z_adO2Mo,4165
59
59
  utilities/re.py,sha256=S4h-DLL6ScMPqjboZ_uQ1BVTJajrqV06r_81D--_HCE,4573
60
- utilities/redis.py,sha256=pgdiHynm3unF8w7DxF2GVVvKNbxIBWJ-3VOvmGKKItQ,28526
60
+ utilities/redis.py,sha256=FYCxeQxkVNwNLGyIUJTV-tefDa72ehjILzhhJvR7cM4,30449
61
61
  utilities/reprlib.py,sha256=ssYTcBW-TeRh3fhCJv57sopTZHF5FrPyyUg9yp5XBlo,3953
62
62
  utilities/scipy.py,sha256=wZJM7fEgBAkLSYYvSmsg5ac-QuwAI0BGqHVetw1_Hb0,947
63
63
  utilities/sentinel.py,sha256=A_p5jX2K0Yc5XBfoYHyBLqHsEWzE1ByOdDuzzA2pZnE,1434
@@ -88,8 +88,8 @@ utilities/zoneinfo.py,sha256=tdIScrTB2-B-LH0ukb1HUXKooLknOfJNwHk10MuMYvA,3619
88
88
  utilities/pytest_plugins/__init__.py,sha256=U4S_2y3zgLZVfMenHRaJFBW8yqh2mUBuI291LGQVOJ8,35
89
89
  utilities/pytest_plugins/pytest_randomly.py,sha256=B1qYVlExGOxTywq2r1SMi5o7btHLk2PNdY_b1p98dkE,409
90
90
  utilities/pytest_plugins/pytest_regressions.py,sha256=9v8kAXDM2ycIXJBimoiF4EgrwbUvxTycFWJiGR_GHhM,1466
91
- dycw_utilities-0.162.7.dist-info/METADATA,sha256=SbAYx4H3pjMZFKDEgFhfeTghXPl6wnH3GNC6ILRaIN4,1696
92
- dycw_utilities-0.162.7.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
93
- dycw_utilities-0.162.7.dist-info/entry_points.txt,sha256=BOD_SoDxwsfJYOLxhrSXhHP_T7iw-HXI9f2WVkzYxvQ,135
94
- dycw_utilities-0.162.7.dist-info/licenses/LICENSE,sha256=gppZp16M6nSVpBbUBrNL6JuYfvKwZiKgV7XoKKsHzqo,1066
95
- dycw_utilities-0.162.7.dist-info/RECORD,,
91
+ dycw_utilities-0.162.9.dist-info/METADATA,sha256=99Cp_EH9oX7AopXh2VjQKU7VbbsYeUU0Zzgds3gie-c,1696
92
+ dycw_utilities-0.162.9.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
93
+ dycw_utilities-0.162.9.dist-info/entry_points.txt,sha256=BOD_SoDxwsfJYOLxhrSXhHP_T7iw-HXI9f2WVkzYxvQ,135
94
+ dycw_utilities-0.162.9.dist-info/licenses/LICENSE,sha256=gppZp16M6nSVpBbUBrNL6JuYfvKwZiKgV7XoKKsHzqo,1066
95
+ dycw_utilities-0.162.9.dist-info/RECORD,,
utilities/__init__.py CHANGED
@@ -1,3 +1,3 @@
1
1
  from __future__ import annotations
2
2
 
3
- __version__ = "0.162.7"
3
+ __version__ = "0.162.9"
utilities/redis.py CHANGED
@@ -639,9 +639,11 @@ def subscribe(
639
639
  /,
640
640
  *,
641
641
  timeout: Delta | None = _SUBSCRIBE_TIMEOUT,
642
- sleep: Delta = _SUBSCRIBE_SLEEP,
643
642
  output: Literal["raw"],
644
- filter_: Callable[[_RedisMessage], bool] | None = None,
643
+ error_transform: Callable[[_RedisMessage, Exception], None] | None = None,
644
+ filter_: Callable[[bytes], bool] | None = None,
645
+ error_filter: Callable[[bytes, Exception], None] | None = None,
646
+ sleep: Delta = _SUBSCRIBE_SLEEP,
645
647
  ) -> AsyncIterator[Task[None]]: ...
646
648
  @overload
647
649
  @enhanced_async_context_manager
@@ -652,9 +654,11 @@ def subscribe(
652
654
  /,
653
655
  *,
654
656
  timeout: Delta | None = _SUBSCRIBE_TIMEOUT,
655
- sleep: Delta = _SUBSCRIBE_SLEEP,
656
657
  output: Literal["bytes"],
658
+ error_transform: Callable[[_RedisMessage, Exception], None] | None = None,
657
659
  filter_: Callable[[bytes], bool] | None = None,
660
+ error_filter: Callable[[bytes, Exception], None] | None = None,
661
+ sleep: Delta = _SUBSCRIBE_SLEEP,
658
662
  ) -> AsyncIterator[Task[None]]: ...
659
663
  @overload
660
664
  @enhanced_async_context_manager
@@ -665,9 +669,11 @@ def subscribe(
665
669
  /,
666
670
  *,
667
671
  timeout: Delta | None = _SUBSCRIBE_TIMEOUT,
668
- sleep: Delta = _SUBSCRIBE_SLEEP,
669
672
  output: Literal["text"] = "text",
673
+ error_transform: Callable[[_RedisMessage, Exception], None] | None = None,
670
674
  filter_: Callable[[str], bool] | None = None,
675
+ error_filter: Callable[[str, Exception], None] | None = None,
676
+ sleep: Delta = _SUBSCRIBE_SLEEP,
671
677
  ) -> AsyncIterator[Task[None]]: ...
672
678
  @overload
673
679
  @enhanced_async_context_manager
@@ -678,9 +684,11 @@ def subscribe[T](
678
684
  /,
679
685
  *,
680
686
  timeout: Delta | None = _SUBSCRIBE_TIMEOUT,
681
- sleep: Delta = _SUBSCRIBE_SLEEP,
682
687
  output: Callable[[bytes], T],
688
+ error_transform: Callable[[_RedisMessage, Exception], None] | None = None,
683
689
  filter_: Callable[[T], bool] | None = None,
690
+ error_filter: Callable[[T, Exception], None] | None = None,
691
+ sleep: Delta = _SUBSCRIBE_SLEEP,
684
692
  ) -> AsyncIterator[Task[None]]: ...
685
693
  @enhanced_async_context_manager
686
694
  async def subscribe[T](
@@ -690,22 +698,21 @@ async def subscribe[T](
690
698
  /,
691
699
  *,
692
700
  timeout: Delta | None = _SUBSCRIBE_TIMEOUT,
693
- sleep: Delta = _SUBSCRIBE_SLEEP,
694
701
  output: Literal["raw", "bytes", "text"] | Callable[[bytes], T] = "text",
695
- filter_: Callable[[Any], bool] | None = None,
702
+ error_transform: Callable[[_RedisMessage, Exception], None] | None = None,
703
+ filter_: Callable[[T], bool] | None = None,
704
+ error_filter: Callable[[T, Exception], None] | None = None,
705
+ sleep: Delta = _SUBSCRIBE_SLEEP,
696
706
  ) -> AsyncIterator[Task[None]]:
697
707
  """Subscribe to the data of a given channel(s)."""
698
708
  channels = list(always_iterable(channels)) # skipif-ci-and-not-linux
699
709
  match output: # skipif-ci-and-not-linux
700
710
  case "raw":
701
- transform = cast("Any", identity)
711
+ transform = cast("Callable[[_RedisMessage], T]", identity)
702
712
  case "bytes":
703
- transform = cast("Any", itemgetter("data"))
713
+ transform = cast("Callable[[_RedisMessage], T]", itemgetter("data"))
704
714
  case "text":
705
-
706
- def transform(message: _RedisMessage, /) -> str: # pyright: ignore[reportRedeclaration]
707
- return message["data"].decode()
708
-
715
+ transform = cast("Callable[[_RedisMessage], T]", _decoded_data)
709
716
  case Callable() as deserialize:
710
717
 
711
718
  def transform(message: _RedisMessage, /) -> T:
@@ -721,8 +728,10 @@ async def subscribe[T](
721
728
  transform,
722
729
  queue,
723
730
  timeout=timeout,
724
- sleep=sleep,
731
+ error_transform=error_transform,
725
732
  filter_=filter_,
733
+ error_filter=error_filter,
734
+ sleep=sleep,
726
735
  )
727
736
  )
728
737
  try: # skipif-ci-and-not-linux
@@ -737,16 +746,22 @@ async def subscribe[T](
737
746
  await task
738
747
 
739
748
 
740
- async def _subscribe_core(
749
+ def _decoded_data(message: _RedisMessage, /) -> str:
750
+ return message["data"].decode()
751
+
752
+
753
+ async def _subscribe_core[T](
741
754
  redis: Redis,
742
755
  channels: MaybeIterable[str],
743
- transform: Callable[[_RedisMessage], Any],
756
+ transform: Callable[[_RedisMessage], T],
744
757
  queue: Queue[Any],
745
758
  /,
746
759
  *,
747
760
  timeout: Delta | None = _SUBSCRIBE_TIMEOUT,
761
+ error_transform: Callable[[_RedisMessage, Exception], None] | None = None,
762
+ filter_: Callable[[T], bool] | None = None,
763
+ error_filter: Callable[[T, Exception], None] | None = None,
748
764
  sleep: Delta = _SUBSCRIBE_SLEEP,
749
- filter_: Callable[[Any], bool] | None = None,
750
765
  ) -> None:
751
766
  timeout_use = ( # skipif-ci-and-not-linux
752
767
  None if timeout is None else to_seconds(timeout)
@@ -758,11 +773,15 @@ async def _subscribe_core(
758
773
  while True:
759
774
  message = await pubsub.get_message(timeout=timeout_use)
760
775
  if is_subscribe_message(message):
761
- transformed = transform(message)
762
- if (filter_ is None) or filter_(transformed):
763
- queue.put_nowait(transformed)
764
- else:
765
- await sleep_td(sleep)
776
+ _handle_message(
777
+ message,
778
+ transform,
779
+ queue,
780
+ error_transform=error_transform,
781
+ filter_=filter_,
782
+ error_filter=error_filter,
783
+ )
784
+ await sleep_td(sleep)
766
785
 
767
786
 
768
787
  def _is_message(
@@ -781,6 +800,33 @@ def _is_message(
781
800
  )
782
801
 
783
802
 
803
+ def _handle_message[T](
804
+ message: _RedisMessage,
805
+ transform: Callable[[_RedisMessage], T],
806
+ queue: Queue[Any],
807
+ /,
808
+ *,
809
+ error_transform: Callable[[_RedisMessage, Exception], None] | None = None,
810
+ filter_: Callable[[T], bool] | None = None,
811
+ error_filter: Callable[[T, Exception], None] | None = None,
812
+ ) -> None:
813
+ try:
814
+ transformed = transform(message)
815
+ except Exception as error: # noqa: BLE001
816
+ if error_transform is not None:
817
+ error_transform(message, error)
818
+ return
819
+ if filter_ is None:
820
+ queue.put_nowait(transformed)
821
+ return
822
+ try:
823
+ if filter_(transformed):
824
+ queue.put_nowait(transformed)
825
+ except Exception as error: # noqa: BLE001
826
+ if error_filter is not None:
827
+ error_filter(transformed, error)
828
+
829
+
784
830
  class _RedisMessage(TypedDict):
785
831
  type: Literal["subscribe", "psubscribe", "message", "pmessage"]
786
832
  pattern: str | None