ry-pg-utils 1.0.9__py3-none-any.whl → 1.0.11__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.
ry_pg_utils/connect.py CHANGED
@@ -5,11 +5,10 @@ import threading
5
5
  import typing as T
6
6
 
7
7
  from ryutils import log
8
- from sqlalchemy import Column, String, create_engine, event
8
+ from sqlalchemy import String, create_engine, event
9
9
  from sqlalchemy.engine.base import Engine
10
10
  from sqlalchemy.exc import OperationalError
11
- from sqlalchemy.orm import declarative_base, declared_attr, scoped_session, sessionmaker
12
- from sqlalchemy.orm.decl_api import DeclarativeMeta
11
+ from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, scoped_session, sessionmaker
13
12
  from sqlalchemy.orm.scoping import ScopedSession
14
13
  from sqlalchemy_utils import database_exists
15
14
  from tenacity import retry, stop_after_attempt, wait_exponential
@@ -22,20 +21,19 @@ BACKEND_ID_VARIABLE = "backend_id"
22
21
  ENGINE: T.Dict[str, Engine] = {}
23
22
  THREAD_SAFE_SESSION_FACTORY: T.Dict[str, ScopedSession] = {}
24
23
 
25
- # Base class with optional backend_id field
24
+
25
+ # Modern SQLAlchemy 2.0 declarative base
26
26
  if config.pg_config.add_backend_to_all:
27
- # Add any common fields here
28
- class CommonBaseModel:
29
- @declared_attr
30
- def backend_id(cls: T.Any) -> Column: # pylint: disable=no-self-argument
31
- return Column(String(256), nullable=False)
32
27
 
33
- Base = declarative_base(name="Base", cls=CommonBaseModel)
28
+ class Base(DeclarativeBase):
29
+ """Base class with automatic backend_id field."""
30
+
31
+ backend_id: Mapped[str] = mapped_column(String(256), nullable=False)
32
+
34
33
  else:
35
- Base = declarative_base(name="Base")
36
34
 
37
- # Add type annotation for Base
38
- Base: DeclarativeMeta # type: ignore
35
+ class Base(DeclarativeBase): # type: ignore[no-redef]
36
+ """Base class for all SQLAlchemy models."""
39
37
 
40
38
 
41
39
  def get_table_name(
@@ -1,11 +1,11 @@
1
1
  from ry_redis_bus.channels import Channel
2
2
 
3
- from ry_pg_utils.pb_types.database_pb2 import DatabaseConfigPb # pylint: disable=no-name-in-module
4
3
  from ry_pg_utils.pb_types.database_pb2 import ( # pylint: disable=no-name-in-module
5
4
  DatabaseNotificationPb,
5
+ PostgresMessagePb,
6
6
  )
7
7
 
8
8
  # Channels
9
- DATABASE_CHANNEL = Channel("DATABASE_CHANNEL", DatabaseConfigPb)
10
- DATABASE_CONFIG_CHANNEL = Channel("DATABASE_CONFIG_CHANNEL", DatabaseConfigPb)
9
+ DATABASE_CHANNEL = Channel("DATABASE_CHANNEL", PostgresMessagePb)
10
+ DATABASE_CONFIG_CHANNEL = Channel("DATABASE_CONFIG_CHANNEL", PostgresMessagePb)
11
11
  DATABASE_NOTIFY_CHANNEL = Channel("DATABASE_NOTIFY_CHANNEL", DatabaseNotificationPb)
@@ -14,25 +14,17 @@ _sym_db = _symbol_database.Default()
14
14
  from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2
15
15
 
16
16
 
17
- DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0e\x64\x61tabase.proto\x12\x08\x64\x61tabase\x1a\x1fgoogle/protobuf/timestamp.proto\"m\n\nPostgresPb\x12\x10\n\x08\x64\x61tabase\x18\x01 \x01(\t\x12\x0c\n\x04user\x18\x02 \x01(\t\x12\x10\n\x08password\x18\x03 \x01(\t\x12\x0c\n\x04host\x18\x04 \x01(\t\x12\x0c\n\x04port\x18\x05 \x01(\x05\x12\x11\n\tbackendId\x18\x06 \x01(\t\"f\n\x11PostgresMessagePb\x12)\n\x05utime\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12&\n\x08postgres\x18\x02 \x01(\x0b\x32\x14.database.PostgresPb\"\xb2\x01\n\x12\x44\x61tabaseSettingsPb\x12\x17\n\x0fprimaryDatabase\x18\x01 \x01(\x08\x12<\n\x08postgres\x18\x02 \x03(\x0b\x32*.database.DatabaseSettingsPb.PostgresEntry\x1a\x45\n\rPostgresEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12#\n\x05value\x18\x02 \x01(\x0b\x32\x14.database.PostgresPb:\x02\x38\x01\"u\n\x10\x44\x61tabaseConfigPb\x12)\n\x05utime\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x10\x64\x61tabaseSettings\x18\x02 \x01(\x0b\x32\x1c.database.DatabaseSettingsPb\"\x8e\x01\n\x16\x44\x61tabaseNotificationPb\x12)\n\x05utime\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x12\n\ntable_name\x18\x02 \x01(\t\x12\x14\n\x0c\x63hannel_name\x18\x03 \x01(\t\x12\x0e\n\x06\x61\x63tion\x18\x04 \x01(\t\x12\x0f\n\x07payload\x18\x05 \x01(\tb\x06proto3')
17
+ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0e\x64\x61tabase.proto\x12\x08\x64\x61tabase\x1a\x1fgoogle/protobuf/timestamp.proto\"m\n\nPostgresPb\x12\x10\n\x08\x64\x61tabase\x18\x01 \x01(\t\x12\x0c\n\x04user\x18\x02 \x01(\t\x12\x10\n\x08password\x18\x03 \x01(\t\x12\x0c\n\x04host\x18\x04 \x01(\t\x12\x0c\n\x04port\x18\x05 \x01(\x05\x12\x11\n\tbackendId\x18\x06 \x01(\t\"f\n\x11PostgresMessagePb\x12)\n\x05utime\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12&\n\x08postgres\x18\x02 \x01(\x0b\x32\x14.database.PostgresPb\"\x8e\x01\n\x16\x44\x61tabaseNotificationPb\x12)\n\x05utime\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x12\n\ntable_name\x18\x02 \x01(\t\x12\x14\n\x0c\x63hannel_name\x18\x03 \x01(\t\x12\x0e\n\x06\x61\x63tion\x18\x04 \x01(\t\x12\x0f\n\x07payload\x18\x05 \x01(\tb\x06proto3')
18
18
 
19
19
  _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
20
20
  _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'database_pb2', globals())
21
21
  if _descriptor._USE_C_DESCRIPTORS == False:
22
22
 
23
23
  DESCRIPTOR._options = None
24
- _DATABASESETTINGSPB_POSTGRESENTRY._options = None
25
- _DATABASESETTINGSPB_POSTGRESENTRY._serialized_options = b'8\001'
26
24
  _POSTGRESPB._serialized_start=61
27
25
  _POSTGRESPB._serialized_end=170
28
26
  _POSTGRESMESSAGEPB._serialized_start=172
29
27
  _POSTGRESMESSAGEPB._serialized_end=274
30
- _DATABASESETTINGSPB._serialized_start=277
31
- _DATABASESETTINGSPB._serialized_end=455
32
- _DATABASESETTINGSPB_POSTGRESENTRY._serialized_start=386
33
- _DATABASESETTINGSPB_POSTGRESENTRY._serialized_end=455
34
- _DATABASECONFIGPB._serialized_start=457
35
- _DATABASECONFIGPB._serialized_end=574
36
- _DATABASENOTIFICATIONPB._serialized_start=577
37
- _DATABASENOTIFICATIONPB._serialized_end=719
28
+ _DATABASENOTIFICATIONPB._serialized_start=277
29
+ _DATABASENOTIFICATIONPB._serialized_end=419
38
30
  # @@protoc_insertion_point(module_scope)
@@ -4,9 +4,7 @@ isort:skip_file
4
4
  """
5
5
 
6
6
  import builtins
7
- import collections.abc
8
7
  import google.protobuf.descriptor
9
- import google.protobuf.internal.containers
10
8
  import google.protobuf.message
11
9
  import google.protobuf.timestamp_pb2
12
10
  import typing
@@ -66,66 +64,6 @@ class PostgresMessagePb(google.protobuf.message.Message):
66
64
 
67
65
  global___PostgresMessagePb = PostgresMessagePb
68
66
 
69
- @typing.final
70
- class DatabaseSettingsPb(google.protobuf.message.Message):
71
- """Message for DatabaseSettings"""
72
-
73
- DESCRIPTOR: google.protobuf.descriptor.Descriptor
74
-
75
- @typing.final
76
- class PostgresEntry(google.protobuf.message.Message):
77
- DESCRIPTOR: google.protobuf.descriptor.Descriptor
78
-
79
- KEY_FIELD_NUMBER: builtins.int
80
- VALUE_FIELD_NUMBER: builtins.int
81
- key: builtins.str
82
- @property
83
- def value(self) -> global___PostgresPb: ...
84
- def __init__(
85
- self,
86
- *,
87
- key: builtins.str = ...,
88
- value: global___PostgresPb | None = ...,
89
- ) -> None: ...
90
- def HasField(self, field_name: typing.Literal["value", b"value"]) -> builtins.bool: ...
91
- def ClearField(self, field_name: typing.Literal["key", b"key", "value", b"value"]) -> None: ...
92
-
93
- PRIMARYDATABASE_FIELD_NUMBER: builtins.int
94
- POSTGRES_FIELD_NUMBER: builtins.int
95
- primaryDatabase: builtins.bool
96
- @property
97
- def postgres(self) -> google.protobuf.internal.containers.MessageMap[builtins.str, global___PostgresPb]: ...
98
- def __init__(
99
- self,
100
- *,
101
- primaryDatabase: builtins.bool = ...,
102
- postgres: collections.abc.Mapping[builtins.str, global___PostgresPb] | None = ...,
103
- ) -> None: ...
104
- def ClearField(self, field_name: typing.Literal["postgres", b"postgres", "primaryDatabase", b"primaryDatabase"]) -> None: ...
105
-
106
- global___DatabaseSettingsPb = DatabaseSettingsPb
107
-
108
- @typing.final
109
- class DatabaseConfigPb(google.protobuf.message.Message):
110
- DESCRIPTOR: google.protobuf.descriptor.Descriptor
111
-
112
- UTIME_FIELD_NUMBER: builtins.int
113
- DATABASESETTINGS_FIELD_NUMBER: builtins.int
114
- @property
115
- def utime(self) -> google.protobuf.timestamp_pb2.Timestamp: ...
116
- @property
117
- def databaseSettings(self) -> global___DatabaseSettingsPb: ...
118
- def __init__(
119
- self,
120
- *,
121
- utime: google.protobuf.timestamp_pb2.Timestamp | None = ...,
122
- databaseSettings: global___DatabaseSettingsPb | None = ...,
123
- ) -> None: ...
124
- def HasField(self, field_name: typing.Literal["databaseSettings", b"databaseSettings", "utime", b"utime"]) -> builtins.bool: ...
125
- def ClearField(self, field_name: typing.Literal["databaseSettings", b"databaseSettings", "utime", b"utime"]) -> None: ...
126
-
127
- global___DatabaseConfigPb = DatabaseConfigPb
128
-
129
67
  @typing.final
130
68
  class DatabaseNotificationPb(google.protobuf.message.Message):
131
69
  DESCRIPTOR: google.protobuf.descriptor.Descriptor
ry_pg_utils/updater.py CHANGED
@@ -11,7 +11,6 @@ from ryutils.verbose import Verbose
11
11
  from ry_pg_utils.connect import close_engine, init_database, is_database_initialized
12
12
  from ry_pg_utils.ipc import channels
13
13
  from ry_pg_utils.pb_types.database_pb2 import ( # pylint: disable=no-name-in-module
14
- DatabaseConfigPb,
15
14
  PostgresMessagePb,
16
15
  PostgresPb,
17
16
  )
@@ -21,28 +20,15 @@ DB_RETRY_TIME = 5.0
21
20
 
22
21
 
23
22
  def get_database_settings(
24
- message_pb: DatabaseConfigPb, backend_id: str, verbose: bool = False
23
+ raw_db_config_pb: PostgresMessagePb | None, verbose: bool = False
25
24
  ) -> T.Optional[PostgresInfo]:
26
- # Access the nested databaseSettings field
27
- if not message_pb.HasField("databaseSettings"):
28
- return None
29
-
30
- database_settings = message_pb.databaseSettings
31
-
32
- # Check if this is the primary database
33
- if not database_settings.primaryDatabase:
34
- return None
35
-
36
- # Get the postgres config for this backend
37
- raw_db_config_pb = database_settings.postgres.get(backend_id, None)
38
-
39
25
  if raw_db_config_pb is None:
40
26
  return None
41
27
 
42
- db_config_pb: PostgresPb = raw_db_config_pb
28
+ db_config_pb: PostgresPb = raw_db_config_pb.postgres
43
29
 
44
30
  if verbose:
45
- log.print_normal(f"Received database settings {backend_id}:\n{db_config_pb}")
31
+ log.print_normal(f"Received database settings:\n{db_config_pb}")
46
32
 
47
33
  database_settings_msg = PostgresInfo(
48
34
  db_name=db_config_pb.database,
@@ -59,14 +45,12 @@ def get_database_settings(
59
45
  class DbUpdater(RedisClientBase):
60
46
  do_publish_db: bool
61
47
  postgres_info: PostgresInfo
62
- backend_id: str
63
48
  logging_error_db_callback: T.Callable[[str, str], None] | None
64
49
 
65
50
  def __init__(
66
51
  self,
67
52
  redis_info: RedisInfo,
68
53
  args: argparse.Namespace,
69
- backend_id: str,
70
54
  verbose: Verbose,
71
55
  logging_error_db_callback: T.Callable[[str, str], None] | None = None,
72
56
  ):
@@ -88,12 +72,11 @@ class DbUpdater(RedisClientBase):
88
72
  self.last_db_init_retry_time = 0.0
89
73
  self.use_local_db_only = args.use_local_db_only if args else True
90
74
  self.database_settings_msg: T.Optional[PostgresInfo] = None
91
- self.backend_id = backend_id
92
75
  self.logging_error_db_callback = logging_error_db_callback
93
76
 
94
77
  @message_handler
95
- def handle_database_config_message(self, message_pb: DatabaseConfigPb) -> None:
96
- database_settings = get_database_settings(message_pb, backend_id=self.backend_id)
78
+ def handle_database_config_message(self, message_pb: PostgresMessagePb) -> None:
79
+ database_settings = get_database_settings(message_pb)
97
80
 
98
81
  if database_settings is not None:
99
82
  self.database_settings_msg = database_settings
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ry-pg-utils
3
- Version: 1.0.9
3
+ Version: 1.0.11
4
4
  Summary: Utility functions for PostgreSQL
5
5
  Author: Ross Yeager
6
6
  Author-email: ryeager12@email.com
@@ -1,22 +1,22 @@
1
1
  ry_pg_utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  ry_pg_utils/config.py,sha256=7W-JLNxZDoursPArtoKyOiEqUABGyO1ZEkTdlVBzdVM,1522
3
- ry_pg_utils/connect.py,sha256=jF-Sj9oySPDfTlOh4_C6c03t4KW5Sef_MLHx_sh52a4,10108
3
+ ry_pg_utils/connect.py,sha256=ECasbbwXCsj1pJwz_er2aKW613X73X30EQyS_TgX5i0,9942
4
4
  ry_pg_utils/dynamic_table.py,sha256=VBkfbATRk_pW3EtAFHvMkGG0fLZMebw_LdWkFaDDugw,6866
5
5
  ry_pg_utils/notify_trigger.py,sha256=_dsuPkoqjnSQqWrsdZK3FqI6zG5UuygVXHwtERwN99Y,12069
6
6
  ry_pg_utils/parse_args.py,sha256=swFYq2-nBggul67C9ibNzsf9goEXDKZkLNSISbJZgOw,751
7
7
  ry_pg_utils/postgres_info.py,sha256=mj9er830jvrJXUFuFKx1EmZMjuEpMDcd901kgYb_Cck,1495
8
8
  ry_pg_utils/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
- ry_pg_utils/updater.py,sha256=nfOR2hpf83buaJc0oyiHf0xfE1pl51CYOz1PuRid198,6103
9
+ ry_pg_utils/updater.py,sha256=qEj1Wc4f-z5ixw_twqvG4vXdlTICSi7fBPZzzbGeafY,5561
10
10
  ry_pg_utils/ipc/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
- ry_pg_utils/ipc/channels.py,sha256=3w88R_BW5wLW7NX4iNAS3akgXo0JFQufdR7y-l_dNGE,499
11
+ ry_pg_utils/ipc/channels.py,sha256=U8MKblm8I-LfokmkC-WuCJmUjr-1KGQJB5Fsdnc1R8M,424
12
12
  ry_pg_utils/pb_types/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
- ry_pg_utils/pb_types/database_pb2.py,sha256=yf__HycGrVoU8pzhYdnOhXhfAkgjeGl80ls_RsLemy4,2780
14
- ry_pg_utils/pb_types/database_pb2.pyi,sha256=svpmlEY_99dA_u3CJqn7CO5D7CH2pAGTOqlhVMZLXC4,5689
13
+ ry_pg_utils/pb_types/database_pb2.py,sha256=j56AaBNQOFHp19O-8egcil3e0x8rujhlnAFuXIyMvx0,1886
14
+ ry_pg_utils/pb_types/database_pb2.pyi,sha256=PtBakRFPx_o9PkpvYgn0doNoaoz6X03eI9TrnpfamkI,3267
15
15
  ry_pg_utils/pb_types/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
16
  ry_pg_utils/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
17
  ry_pg_utils/tools/db_query.py,sha256=sQESUB3zxv3h2bKcodfwJHKHGXdSn6BNaBiyZvg6eNY,19557
18
- ry_pg_utils-1.0.9.dist-info/licenses/LICENSE,sha256=PYnig94SABlde939TWrqvOqQkkfjuHttf8KpWKlPFlA,1068
19
- ry_pg_utils-1.0.9.dist-info/METADATA,sha256=eHg0wS2vfpifjX9vEntJEPSLJOucwhylSfnMgrdpN-s,18039
20
- ry_pg_utils-1.0.9.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
21
- ry_pg_utils-1.0.9.dist-info/top_level.txt,sha256=OruzbmsQHYyPnAw8RichQ5GK1Sxj-MQwWfJ93PEHXIM,12
22
- ry_pg_utils-1.0.9.dist-info/RECORD,,
18
+ ry_pg_utils-1.0.11.dist-info/licenses/LICENSE,sha256=PYnig94SABlde939TWrqvOqQkkfjuHttf8KpWKlPFlA,1068
19
+ ry_pg_utils-1.0.11.dist-info/METADATA,sha256=g4WXkVP-LJbEMceqkOslKguOEoiA8fZaFZV_gRblhWA,18040
20
+ ry_pg_utils-1.0.11.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
21
+ ry_pg_utils-1.0.11.dist-info/top_level.txt,sha256=OruzbmsQHYyPnAw8RichQ5GK1Sxj-MQwWfJ93PEHXIM,12
22
+ ry_pg_utils-1.0.11.dist-info/RECORD,,