dycw-utilities 0.125.25__py3-none-any.whl → 0.125.26__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.25
3
+ Version: 0.125.26
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=3MYZAqKLfaJb4ielcVRGJ7gJj-yObA5kgfPLoc-wN1Q,61
1
+ utilities/__init__.py,sha256=Q_deKUGgT21jjkI5E7MKTAtXWcqWJotIcZmKdq_5394,61
2
2
  utilities/altair.py,sha256=Gpja-flOo-Db0PIPJLJsgzAlXWoKUjPU1qY-DQ829ek,9156
3
3
  utilities/asyncio.py,sha256=K5Kj7rsM0nA17-b7d7mrNgPR1U_NbkfQmTruq5LBLRA,51778
4
4
  utilities/atomicwrites.py,sha256=geFjn9Pwn-tTrtoGjDDxWli9NqbYfy3gGL6ZBctiqSo,5393
@@ -68,7 +68,7 @@ utilities/sentinel.py,sha256=3jIwgpMekWgDAxPDA_hXMP2St43cPhciKN3LWiZ7kv0,1248
68
68
  utilities/shelve.py,sha256=HZsMwK4tcIfg3sh0gApx4-yjQnrY4o3V3ZRimvRhoW0,738
69
69
  utilities/slack_sdk.py,sha256=h2DiVkcFyYcT5zzZOAo6CSith5BBlHUbXeOJSL1neK8,5948
70
70
  utilities/socket.py,sha256=K77vfREvzoVTrpYKo6MZakol0EYu2q1sWJnnZqL0So0,118
71
- utilities/sqlalchemy.py,sha256=p8vsHaNRoeq5zJouIKyp9piFM26wtm5yR4DkzCMFDSw,35471
71
+ utilities/sqlalchemy.py,sha256=KraI3PGrIs8ZpTQi0rZzBMjlcPbgWNipXlLySeu4aiY,36765
72
72
  utilities/sqlalchemy_polars.py,sha256=s7hQNep2O5DTgIRXyN_JRQma7a4DAtNd25tshaZW8iw,15490
73
73
  utilities/statsmodels.py,sha256=koyiBHvpMcSiBfh99wFUfSggLNx7cuAw3rwyfAhoKpQ,3410
74
74
  utilities/streamlit.py,sha256=U9PJBaKP1IdSykKhPZhIzSPTZsmLsnwbEPZWzNhJPKk,2955
@@ -90,7 +90,7 @@ utilities/warnings.py,sha256=un1LvHv70PU-LLv8RxPVmugTzDJkkGXRMZTE2-fTQHw,1771
90
90
  utilities/whenever.py,sha256=jS31ZAY5OMxFxLja_Yo5Fidi87Pd-GoVZ7Vi_teqVDA,16743
91
91
  utilities/zipfile.py,sha256=24lQc9ATcJxHXBPc_tBDiJk48pWyRrlxO2fIsFxU0A8,699
92
92
  utilities/zoneinfo.py,sha256=-5j7IQ9nb7gR43rdgA7ms05im-XuqhAk9EJnQBXxCoQ,1874
93
- dycw_utilities-0.125.25.dist-info/METADATA,sha256=TYTHhscXtNic_ikhuiW7WQN30GUx2y-ay4RXYCt3qFI,12852
94
- dycw_utilities-0.125.25.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
95
- dycw_utilities-0.125.25.dist-info/licenses/LICENSE,sha256=gppZp16M6nSVpBbUBrNL6JuYfvKwZiKgV7XoKKsHzqo,1066
96
- dycw_utilities-0.125.25.dist-info/RECORD,,
93
+ dycw_utilities-0.125.26.dist-info/METADATA,sha256=KvzlW9sc8xXbF0-RtEA4gzn8H_mkvGM1pgby4iC-u4A,12852
94
+ dycw_utilities-0.125.26.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
95
+ dycw_utilities-0.125.26.dist-info/licenses/LICENSE,sha256=gppZp16M6nSVpBbUBrNL6JuYfvKwZiKgV7XoKKsHzqo,1066
96
+ dycw_utilities-0.125.26.dist-info/RECORD,,
utilities/__init__.py CHANGED
@@ -1,3 +1,3 @@
1
1
  from __future__ import annotations
2
2
 
3
- __version__ = "0.125.25"
3
+ __version__ = "0.125.26"
utilities/sqlalchemy.py CHANGED
@@ -57,7 +57,8 @@ from sqlalchemy.orm import (
57
57
  from sqlalchemy.orm.exc import UnmappedClassError
58
58
  from sqlalchemy.pool import NullPool, Pool
59
59
 
60
- from utilities.asyncio import InfiniteQueueLooper, timeout_dur
60
+ from utilities.asyncio import InfiniteQueueLooper, Looper, timeout_dur
61
+ from utilities.datetime import SECOND
61
62
  from utilities.functions import (
62
63
  ensure_str,
63
64
  get_class_name,
@@ -654,6 +655,42 @@ class UpserterError(Exception):
654
655
  return f"Error running {get_class_name(self.upserter)!r}"
655
656
 
656
657
 
658
+ @dataclass(kw_only=True)
659
+ class UpsertService(Looper[_InsertItem]):
660
+ """Service to upsert items to a database."""
661
+
662
+ # base
663
+ freq: Duration = field(default=SECOND, repr=False)
664
+ backoff: Duration = field(default=SECOND, repr=False)
665
+ empty_upon_exit: bool = field(default=True, repr=False)
666
+ # self
667
+ engine: AsyncEngine
668
+ snake: bool = False
669
+ selected_or_all: _SelectedOrAll = "selected"
670
+ chunk_size_frac: float = CHUNK_SIZE_FRAC
671
+ assume_tables_exist: bool = False
672
+ timeout_create: Duration | None = None
673
+ error_create: type[Exception] = TimeoutError
674
+ timeout_insert: Duration | None = None
675
+ error_insert: type[Exception] = TimeoutError
676
+
677
+ @override
678
+ async def core(self) -> None:
679
+ await super().core()
680
+ await upsert_items(
681
+ self.engine,
682
+ *self.get_all_nowait(),
683
+ snake=self.snake,
684
+ selected_or_all=self.selected_or_all,
685
+ chunk_size_frac=self.chunk_size_frac,
686
+ assume_tables_exist=self.assume_tables_exist,
687
+ timeout_create=self.timeout_create,
688
+ error_create=self.error_create,
689
+ timeout_insert=self.timeout_insert,
690
+ error_insert=self.error_insert,
691
+ )
692
+
693
+
657
694
  ##
658
695
 
659
696
 
@@ -1109,6 +1146,7 @@ __all__ = [
1109
1146
  "InsertItemsError",
1110
1147
  "TablenameMixin",
1111
1148
  "UpsertItemsError",
1149
+ "UpsertService",
1112
1150
  "Upserter",
1113
1151
  "UpserterError",
1114
1152
  "check_engine",