dycw-utilities 0.125.13__py3-none-any.whl → 0.125.15__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.125.13
3
+ Version: 0.125.15
4
4
  Author-email: Derek Wan <d.wan@icloud.com>
5
5
  License-File: LICENSE
6
6
  Requires-Python: >=3.12
@@ -1,6 +1,6 @@
1
- utilities/__init__.py,sha256=7ZYwhNHFuejRkKzg0MeSvh2I14YxTE-mRj6ie69FmMU,61
1
+ utilities/__init__.py,sha256=o8LjBx2A4acDe22uoFRzAfxBWmfrM93t-mLhWMyL0m0,61
2
2
  utilities/altair.py,sha256=Gpja-flOo-Db0PIPJLJsgzAlXWoKUjPU1qY-DQ829ek,9156
3
- utilities/asyncio.py,sha256=uUVIpmBMP-tAYPnE2Yi7ZyTno7VYImjNp7uA85MQhys,47865
3
+ utilities/asyncio.py,sha256=f0AkOrSdlqiWroCGE3JuyDXO0xXwoPUeonIVCkX4o2Q,50560
4
4
  utilities/atomicwrites.py,sha256=geFjn9Pwn-tTrtoGjDDxWli9NqbYfy3gGL6ZBctiqSo,5393
5
5
  utilities/atools.py,sha256=IYMuFSFGSKyuQmqD6v5IUtDlz8PPw0Sr87Cub_gRU3M,1168
6
6
  utilities/cachetools.py,sha256=C1zqOg7BYz0IfQFK8e3qaDDgEZxDpo47F15RTfJM37Q,2910
@@ -88,7 +88,7 @@ utilities/warnings.py,sha256=un1LvHv70PU-LLv8RxPVmugTzDJkkGXRMZTE2-fTQHw,1771
88
88
  utilities/whenever.py,sha256=jS31ZAY5OMxFxLja_Yo5Fidi87Pd-GoVZ7Vi_teqVDA,16743
89
89
  utilities/zipfile.py,sha256=24lQc9ATcJxHXBPc_tBDiJk48pWyRrlxO2fIsFxU0A8,699
90
90
  utilities/zoneinfo.py,sha256=-5j7IQ9nb7gR43rdgA7ms05im-XuqhAk9EJnQBXxCoQ,1874
91
- dycw_utilities-0.125.13.dist-info/METADATA,sha256=hQ21eoRHxkp3q3Y7wQ3F9fXew2_S1sTHV3hd68qX8e4,12852
92
- dycw_utilities-0.125.13.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
93
- dycw_utilities-0.125.13.dist-info/licenses/LICENSE,sha256=gppZp16M6nSVpBbUBrNL6JuYfvKwZiKgV7XoKKsHzqo,1066
94
- dycw_utilities-0.125.13.dist-info/RECORD,,
91
+ dycw_utilities-0.125.15.dist-info/METADATA,sha256=-hn0kXri9lE8xlAMFZ_Qbfkk57RIrd9BulAR_m5K1os,12852
92
+ dycw_utilities-0.125.15.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
93
+ dycw_utilities-0.125.15.dist-info/licenses/LICENSE,sha256=gppZp16M6nSVpBbUBrNL6JuYfvKwZiKgV7XoKKsHzqo,1066
94
+ dycw_utilities-0.125.15.dist-info/RECORD,,
utilities/__init__.py CHANGED
@@ -1,3 +1,3 @@
1
1
  from __future__ import annotations
2
2
 
3
- __version__ = "0.125.13"
3
+ __version__ = "0.125.15"
utilities/asyncio.py CHANGED
@@ -795,13 +795,9 @@ class Looper(Generic[_T]):
795
795
  assert_never(never)
796
796
 
797
797
  def __await__(self) -> Any:
798
- match self._task:
799
- case None:
800
- raise _LooperNoTaskError(looper=self)
801
- case Task() as task:
802
- return task.__await__()
803
- case _ as never:
804
- assert_never(never)
798
+ if (task := self._task) is None: # cannot use match
799
+ raise _LooperNoTaskError(looper=self)
800
+ return task.__await__()
805
801
 
806
802
  def __len__(self) -> int:
807
803
  return self._queue.qsize()
@@ -825,7 +821,7 @@ class Looper(Generic[_T]):
825
821
  """Remove and return an item from the end of the queue without blocking."""
826
822
  return self._queue.get_right_nowait()
827
823
 
828
- async def initialize(self) -> Exception | None:
824
+ async def initialize(self, *, sleep_if_failure: bool) -> Exception | None:
829
825
  """Initialize the looper."""
830
826
  match self._is_initializing.is_set():
831
827
  case True:
@@ -840,14 +836,26 @@ class Looper(Generic[_T]):
840
836
  try:
841
837
  await self._initialize_core()
842
838
  except Exception as error: # noqa: BLE001
843
- _ = self._logger.warning(
844
- "%s: encountered %s whilst initializing",
845
- self,
846
- repr_error(error),
847
- )
848
839
  async with self._lock:
849
840
  self._initialization_failures += 1
850
841
  ret = error
842
+ match sleep_if_failure:
843
+ case True:
844
+ _ = self._logger.warning(
845
+ "%s: encountered %s whilst initializing; sleeping for %s...",
846
+ self,
847
+ repr_error(error),
848
+ self.backoff,
849
+ )
850
+ await sleep(self._backoff)
851
+ case False:
852
+ _ = self._logger.warning(
853
+ "%s: encountered %s whilst initializing",
854
+ self,
855
+ repr_error(error),
856
+ )
857
+ case _ as never:
858
+ assert_never(never)
851
859
  else:
852
860
  _ = self._debug and self._logger.debug(
853
861
  "%s: finished initializing", self
@@ -939,44 +947,75 @@ class Looper(Generic[_T]):
939
947
  case _ as never:
940
948
  assert_never(never)
941
949
 
942
- async def restart(self) -> None:
950
+ async def restart(self, *, sleep_if_failure: bool) -> None:
943
951
  """Restart the looper."""
944
952
  _ = self._debug and self._logger.debug("%s: restarting...", self)
945
953
  self._is_pending_restart.clear()
946
954
  async with self._lock:
947
955
  self._restart_attempts += 1
948
- tear_down = await self.tear_down()
949
- initialization = await self.initialize()
950
- match tear_down, initialization:
951
- case None, None:
956
+ tear_down = await self.tear_down(sleep_if_failure=False)
957
+ initialization = await self.initialize(sleep_if_failure=False)
958
+ match tear_down, initialization, sleep_if_failure:
959
+ case None, None, bool():
952
960
  _ = self._debug and self._logger.debug("%s: finished restarting", self)
953
961
  async with self._lock:
954
962
  self._restart_successes += 1
955
- case Exception(), None:
963
+ case Exception(), None, True:
964
+ async with self._lock:
965
+ self._restart_failures += 1
966
+ _ = self._logger.warning(
967
+ "%s: encountered %s whilst restarting (tear down); sleeping for %s...",
968
+ self,
969
+ repr_error(tear_down),
970
+ self.backoff,
971
+ )
972
+ await sleep(self._backoff)
973
+ case Exception(), None, False:
974
+ async with self._lock:
975
+ self._restart_failures += 1
956
976
  _ = self._logger.warning(
957
- "%s: encountered %s whilst restarting, during tear down",
977
+ "%s: encountered %s whilst restarting (tear down)",
958
978
  self,
959
979
  repr_error(tear_down),
960
980
  )
981
+ case None, Exception(), True:
961
982
  async with self._lock:
962
983
  self._restart_failures += 1
963
- case None, Exception():
964
984
  _ = self._logger.warning(
965
- "%s: encountered %s whilst restarting, during initialization",
985
+ "%s: encountered %s whilst restarting (initialize); sleeping for %s...",
966
986
  self,
967
987
  repr_error(initialization),
988
+ self.backoff,
968
989
  )
990
+ await sleep(self._backoff)
991
+ case None, Exception(), False:
969
992
  async with self._lock:
970
993
  self._restart_failures += 1
971
- case Exception(), Exception():
972
994
  _ = self._logger.warning(
973
- "%s: encountered %s (tear down) and then %s (initialization) whilst restarting",
995
+ "%s: encountered %s whilst restarting (initialize)",
996
+ self,
997
+ repr_error(initialization),
998
+ )
999
+ case Exception(), Exception(), True:
1000
+ async with self._lock:
1001
+ self._restart_failures += 1
1002
+ _ = self._logger.warning(
1003
+ "%s: encountered %s (tear down) and then %s (initialization) whilst restarting; sleeping for %s...",
974
1004
  self,
975
1005
  repr_error(tear_down),
976
1006
  repr_error(initialization),
1007
+ self.backoff,
977
1008
  )
1009
+ await sleep(self._backoff)
1010
+ case Exception(), Exception(), False:
978
1011
  async with self._lock:
979
1012
  self._restart_failures += 1
1013
+ _ = self._logger.warning(
1014
+ "%s: encountered %s (tear down) and then %s (initialization) whilst restarting",
1015
+ self,
1016
+ repr_error(tear_down),
1017
+ repr_error(initialization),
1018
+ )
980
1019
  case _ as never:
981
1020
  assert_never(never)
982
1021
 
@@ -992,9 +1031,9 @@ class Looper(Generic[_T]):
992
1031
  ):
993
1032
  await self.stop()
994
1033
  elif self._is_pending_restart.is_set():
995
- await self.restart()
1034
+ await self.restart(sleep_if_failure=True)
996
1035
  elif not self._is_initialized.is_set():
997
- _ = await self.initialize()
1036
+ _ = await self.initialize(sleep_if_failure=True)
998
1037
  else:
999
1038
  _ = self._debug and self._logger.debug("%s: running core...", self)
1000
1039
  async with self._lock:
@@ -1051,7 +1090,7 @@ class Looper(Generic[_T]):
1051
1090
  case _ as never:
1052
1091
  assert_never(never)
1053
1092
 
1054
- async def tear_down(self) -> Exception | None:
1093
+ async def tear_down(self, *, sleep_if_failure: bool) -> Exception | None:
1055
1094
  """Tear down the looper."""
1056
1095
  match self._is_tearing_down.is_set():
1057
1096
  case True:
@@ -1065,14 +1104,26 @@ class Looper(Generic[_T]):
1065
1104
  try:
1066
1105
  await self._tear_down_core()
1067
1106
  except Exception as error: # noqa: BLE001
1068
- _ = self._logger.warning(
1069
- "%s: encountered %s whilst tearing down",
1070
- self,
1071
- repr_error(error),
1072
- )
1073
1107
  async with self._lock:
1074
1108
  self._tear_down_failures += 1
1075
1109
  ret = error
1110
+ match sleep_if_failure:
1111
+ case True:
1112
+ _ = self._logger.warning(
1113
+ "%s: encountered %s whilst tearing down; sleeping for %s...",
1114
+ self,
1115
+ repr_error(error),
1116
+ self.backoff,
1117
+ )
1118
+ await sleep(self._backoff)
1119
+ case False:
1120
+ _ = self._logger.warning(
1121
+ "%s: encountered %s whilst tearing down",
1122
+ self,
1123
+ repr_error(error),
1124
+ )
1125
+ case _ as never:
1126
+ assert_never(never)
1076
1127
  else:
1077
1128
  _ = self._debug and self._logger.debug(
1078
1129
  "%s: finished tearing down", self