arpakitlib 1.8.267__py3-none-any.whl → 1.8.269__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.
@@ -75,8 +75,10 @@ class BaseWorker(ABC):
75
75
  def sync_on_error(self, exception: Exception, **kwargs):
76
76
  pass
77
77
 
78
- def sync_safe_run(self):
78
+ def sync_safe_run(self, *, timeout_before_run: timedelta | None = None):
79
79
  self._logger.info("start")
80
+ if timeout_before_run is not None:
81
+ sync_safe_sleep(timeout_before_run)
80
82
  try:
81
83
  self.sync_on_startup()
82
84
  except Exception as exception:
@@ -117,8 +119,10 @@ class BaseWorker(ABC):
117
119
  async def async_on_error(self, exception: Exception, **kwargs):
118
120
  pass
119
121
 
120
- async def async_safe_run(self):
122
+ async def async_safe_run(self, *, timeout_before_run: timedelta | None = None):
121
123
  self._logger.info("start async_safe_run")
124
+ if timeout_before_run is not None:
125
+ await async_safe_sleep(timeout_before_run)
122
126
  try:
123
127
  await self.async_on_startup()
124
128
  except Exception as exception:
@@ -0,0 +1,82 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Optional
4
+
5
+ import sqlalchemy
6
+ from sqlalchemy.engine import Engine
7
+ from sqlalchemy.orm import DeclarativeBase
8
+
9
+
10
+ def _quote_ident_pg(ident: str) -> str:
11
+ # простое кавычирование для PG (экранируем двойные кавычки)
12
+ return '"' + ident.replace('"', '""') + '"'
13
+
14
+
15
+ def _quote_ident_mysql(ident: str) -> str:
16
+ # простое кавычирование для MySQL/MariaDB (экранируем обратные апострофы)
17
+ return '`' + ident.replace('`', '``') + '`'
18
+
19
+
20
+ def _qualified_name(
21
+ schema: Optional[str], table: str, dialect_name: str
22
+ ) -> str:
23
+ if dialect_name == "postgresql":
24
+ q = _quote_ident_pg
25
+ elif dialect_name in {"mysql", "mariadb"}:
26
+ q = _quote_ident_mysql
27
+ else:
28
+ # по умолчанию без кавычек — но мы не должны сюда попасть,
29
+ # поскольку ниже ограничиваем поддержанные диалекты.
30
+ q = lambda x: x
31
+
32
+ if schema:
33
+ return f"{q(schema)}.{q(table)}"
34
+ return q(table)
35
+
36
+
37
+ def drop_sqlalchemy_check_constraints(*, base_: type[DeclarativeBase], engine: Engine) -> None:
38
+ """
39
+ Удаляет ВСЕ существующие в БД CHECK-ограничения для таблиц из base_.metadata,
40
+ выполняя прямые SQL-запросы (без SQLAlchemy DDL-объектов).
41
+
42
+ Поддерживаемые диалекты:
43
+ - PostgreSQL: ALTER TABLE <sch>.<tbl> DROP CONSTRAINT <name>
44
+ - MySQL 8.0.16+/MariaDB 10.2+: ALTER TABLE <sch>.<tbl> DROP CHECK <name>
45
+
46
+ Для SQLite кидает NotImplementedError.
47
+ """
48
+
49
+ if engine.dialect.name == "sqlite":
50
+ raise NotImplementedError(
51
+ "Удаление CHECK-констреинтов прямыми запросами для SQLite не поддержано: "
52
+ "в большинстве версий требуется пересоздание таблицы."
53
+ )
54
+ if engine.dialect.name not in {"postgresql", "mysql", "mariadb"}:
55
+ raise NotImplementedError(f"Пока не реализовано для диалекта: {engine.dialect.name}")
56
+
57
+ with engine.begin() as conn:
58
+ conn_inspection_ = sqlalchemy.inspect(conn)
59
+
60
+ for table in base_.metadata.tables.values():
61
+ fqtn = _qualified_name(table.schema, table.name, engine.dialect.name)
62
+
63
+ # берём ВСЕ реальные CHECK-и из базы
64
+ checks = conn_inspection_.get_check_constraints(table.name, schema=table.schema)
65
+
66
+ for check_ in checks:
67
+ name = check_.get("name")
68
+ if not name:
69
+ # На всякий случай: без имени нам нечего дропать безопасно
70
+ # (в PG/ MySQL синтаксис требует имя).
71
+ continue
72
+
73
+ if engine.dialect.name == "postgresql":
74
+ ident = _quote_ident_pg(name)
75
+ sql = f"ALTER TABLE {fqtn} DROP CONSTRAINT {ident}"
76
+ else: # mysql / mariadb
77
+ ident = _quote_ident_mysql(name)
78
+ # В MySQL/MariaDB именно DROP CHECK <name>
79
+ sql = f"ALTER TABLE {fqtn} DROP CHECK {ident}"
80
+
81
+ # выполняем прямой SQL-запрос
82
+ conn.exec_driver_sql(sql)
@@ -305,6 +305,10 @@ class SQLAlchemyDb:
305
305
  from arpakitlib.ar_ensure_sqlalchemy_check_constraints import ensure_sqlalchemy_check_constraints
306
306
  ensure_sqlalchemy_check_constraints(base_=self.base_dbm, engine=self.engine)
307
307
 
308
+ def drop_check_constraints(self):
309
+ from arpakitlib.ar_sqlalchemy_drop_check_constraints import drop_sqlalchemy_check_constraints
310
+ drop_sqlalchemy_check_constraints(base_=self.base_dbm, engine=self.engine)
311
+
308
312
  def init(self, ensure_check_constraints: bool = True):
309
313
  self.base_dbm.metadata.create_all(bind=self.engine, checkfirst=True)
310
314
  if ensure_check_constraints:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: arpakitlib
3
- Version: 1.8.267
3
+ Version: 1.8.269
4
4
  Summary: arpakitlib
5
5
  License: Apache-2.0
6
6
  Keywords: arpakitlib,arpakit,arpakit-company,arpakitcompany,arpakit_company
@@ -384,7 +384,7 @@ arpakitlib/ar_arpakit_schedule_uust_api_client_util.py,sha256=MRPaF31CRhYA45ldPn
384
384
  arpakitlib/ar_arpakit_schedule_uust_site_util.py,sha256=8wLct9Gd4MWkXzB6nSmETAwTPLw8lfpWgx0LoWSAOvg,1643
385
385
  arpakitlib/ar_arpakitlib_cli_util.py,sha256=RJGcfEZ_q74FJ4tqdXvt7xQpShTszOvKu1mbp3D8qzw,2599
386
386
  arpakitlib/ar_base64_util.py,sha256=udSSpeXMZx0JgQknl4hQgZ8kr1Ps_aQOloIXu4T9dMQ,1286
387
- arpakitlib/ar_base_worker_util.py,sha256=e-Vj9w1D-59KN3Zz7TQlOB2lW4fZphJlsPpFkmX-gtY,5982
387
+ arpakitlib/ar_base_worker_util.py,sha256=QXrk_bnxgxtbmz8YhfShxuLMMJEz2HK2KZpYeFcRm1I,6267
388
388
  arpakitlib/ar_blank_util.py,sha256=qFUdY8usL_pRYamz8Rw1fW3fzNIgrLmpdYP8q-_PQvw,2281
389
389
  arpakitlib/ar_cache_file_util.py,sha256=Fo2pH-Zqm966KWFBHG_pbiySGZvhIFCYqy7k1weRfJ0,3476
390
390
  arpakitlib/ar_class_util.py,sha256=i76pQW_7k_S2m_DlQh6xNjtggv9Col3WSx9W_bwk98E,722
@@ -426,12 +426,13 @@ arpakitlib/ar_schedule_uust_api_client_util.py,sha256=rXI2_3OTaIBgR-GixM1Ti-Ue1f
426
426
  arpakitlib/ar_settings_util.py,sha256=Y5wi_cmsjDjfJpM0VJHjbo0NoVPKfypKaD1USowwDtQ,1327
427
427
  arpakitlib/ar_sleep_util.py,sha256=ggaj7ML6QK_ADsHMcyu6GUmUpQ_9B9n-SKYH17h-9lM,1045
428
428
  arpakitlib/ar_sqladmin_util.py,sha256=SEoaowAPF3lhxPsNjwmOymNJ55Ty9rmzvsDm7gD5Ceo,861
429
- arpakitlib/ar_sqlalchemy_util.py,sha256=FDva9onjtCPrYZYIHHb93NMwD1WlmaORjiWgPRJQKoU,16180
429
+ arpakitlib/ar_sqlalchemy_drop_check_constraints.py,sha256=XEqnMrIwSYasW_UOJ8xU-JhsVrcYeyehalFuSvmJMak,3518
430
+ arpakitlib/ar_sqlalchemy_util.py,sha256=EMMaoVerrDaFXCCwH2BbbpaVr_oKp4nDlbnoJRJg_84,16404
430
431
  arpakitlib/ar_str_util.py,sha256=2lGpnXDf2h1cBZpVf5i1tX_HCv5iBd6IGnrCw4QWWlY,4350
431
432
  arpakitlib/ar_type_util.py,sha256=Cs_tef-Fc5xeyAF54KgISCsP11NHyzIsglm4S3Xx7iM,4049
432
433
  arpakitlib/ar_yookassa_api_client_util.py,sha256=VozuZeCJjmLd1zj2BdC9WfiAQ3XYOrIMsdpNK-AUlm0,5347
433
- arpakitlib-1.8.267.dist-info/LICENSE,sha256=GPEDQMam2r7FSTYqM1mm7aKnxLaWcBotH7UvQtea-ec,11355
434
- arpakitlib-1.8.267.dist-info/METADATA,sha256=5U0ksCQqqwNpyS6KXV0K1iN-BCW2u_pV-oOQrhmSBOc,3919
435
- arpakitlib-1.8.267.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
436
- arpakitlib-1.8.267.dist-info/entry_points.txt,sha256=36xqR3PJFT2kuwjkM_EqoIy0qFUDPKSm_mJaI7emewE,87
437
- arpakitlib-1.8.267.dist-info/RECORD,,
434
+ arpakitlib-1.8.269.dist-info/LICENSE,sha256=GPEDQMam2r7FSTYqM1mm7aKnxLaWcBotH7UvQtea-ec,11355
435
+ arpakitlib-1.8.269.dist-info/METADATA,sha256=bA31Hw4OoYrLzkLSB8hVlkHmS77vA_TS00PKwkJe28g,3919
436
+ arpakitlib-1.8.269.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
437
+ arpakitlib-1.8.269.dist-info/entry_points.txt,sha256=36xqR3PJFT2kuwjkM_EqoIy0qFUDPKSm_mJaI7emewE,87
438
+ arpakitlib-1.8.269.dist-info/RECORD,,