pgbelt 0.7.2__tar.gz → 0.7.3__tar.gz

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.
Files changed (26) hide show
  1. {pgbelt-0.7.2 → pgbelt-0.7.3}/PKG-INFO +2 -2
  2. {pgbelt-0.7.2 → pgbelt-0.7.3}/pgbelt/cmd/setup.py +2 -16
  3. {pgbelt-0.7.2 → pgbelt-0.7.3}/pgbelt/cmd/status.py +1 -8
  4. {pgbelt-0.7.2 → pgbelt-0.7.3}/pgbelt/cmd/sync.py +2 -16
  5. {pgbelt-0.7.2 → pgbelt-0.7.3}/pgbelt/config/models.py +6 -6
  6. {pgbelt-0.7.2 → pgbelt-0.7.3}/pgbelt/config/remote.py +1 -1
  7. {pgbelt-0.7.2 → pgbelt-0.7.3}/pgbelt/util/pglogical.py +1 -1
  8. {pgbelt-0.7.2 → pgbelt-0.7.3}/pgbelt/util/postgres.py +6 -18
  9. {pgbelt-0.7.2 → pgbelt-0.7.3}/pyproject.toml +7 -7
  10. {pgbelt-0.7.2 → pgbelt-0.7.3}/LICENSE +0 -0
  11. {pgbelt-0.7.2 → pgbelt-0.7.3}/README.md +0 -0
  12. {pgbelt-0.7.2 → pgbelt-0.7.3}/pgbelt/__init__.py +0 -0
  13. {pgbelt-0.7.2 → pgbelt-0.7.3}/pgbelt/cmd/__init__.py +0 -0
  14. {pgbelt-0.7.2 → pgbelt-0.7.3}/pgbelt/cmd/convenience.py +0 -0
  15. {pgbelt-0.7.2 → pgbelt-0.7.3}/pgbelt/cmd/helpers.py +0 -0
  16. {pgbelt-0.7.2 → pgbelt-0.7.3}/pgbelt/cmd/login.py +0 -0
  17. {pgbelt-0.7.2 → pgbelt-0.7.3}/pgbelt/cmd/preflight.py +0 -0
  18. {pgbelt-0.7.2 → pgbelt-0.7.3}/pgbelt/cmd/schema.py +0 -0
  19. {pgbelt-0.7.2 → pgbelt-0.7.3}/pgbelt/cmd/teardown.py +0 -0
  20. {pgbelt-0.7.2 → pgbelt-0.7.3}/pgbelt/config/__init__.py +0 -0
  21. {pgbelt-0.7.2 → pgbelt-0.7.3}/pgbelt/config/config.py +0 -0
  22. {pgbelt-0.7.2 → pgbelt-0.7.3}/pgbelt/main.py +0 -0
  23. {pgbelt-0.7.2 → pgbelt-0.7.3}/pgbelt/util/__init__.py +0 -0
  24. {pgbelt-0.7.2 → pgbelt-0.7.3}/pgbelt/util/asyncfuncs.py +0 -0
  25. {pgbelt-0.7.2 → pgbelt-0.7.3}/pgbelt/util/dump.py +0 -0
  26. {pgbelt-0.7.2 → pgbelt-0.7.3}/pgbelt/util/logs.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pgbelt
3
- Version: 0.7.2
3
+ Version: 0.7.3
4
4
  Summary: A CLI tool used to manage Postgres data migrations from beginning to end, for a single database or a fleet, leveraging pglogical replication.
5
5
  Author: Varjitt Jeeva
6
6
  Author-email: varjitt.jeeva@autodesk.com
@@ -14,7 +14,7 @@ Requires-Dist: aiofiles (>=0.8,<23.3)
14
14
  Requires-Dist: asyncpg (>=0.27,<0.30)
15
15
  Requires-Dist: pydantic (>=2.0,<3.0)
16
16
  Requires-Dist: tabulate (>=0.9.0,<0.10.0)
17
- Requires-Dist: typer (>=0.9.0,<0.10.0)
17
+ Requires-Dist: typer (>=0.9,<0.13)
18
18
  Description-Content-Type: text/markdown
19
19
 
20
20
  # Pgbelt
@@ -41,14 +41,7 @@ async def _setup_src_node(
41
41
 
42
42
  pglogical_tables = pkey_tables
43
43
  if conf.tables:
44
- pglogical_tables = [
45
- t
46
- for t in pkey_tables
47
- if t
48
- in list(
49
- map(str.lower, conf.tables)
50
- ) # Postgres returns table names in lowercase (in analyze_table_pkeys)
51
- ]
44
+ pglogical_tables = [t for t in pkey_tables if t in conf.tables]
52
45
 
53
46
  # Intentionally throw an error if no tables are found, so that the user can correct their config.
54
47
  # When reported by a certain user, errors showed when running the status command, but it was ignored,
@@ -161,14 +154,7 @@ async def setup_back_replication(config_future: Awaitable[DbupgradeConfig]) -> N
161
154
 
162
155
  pglogical_tables = pkeys
163
156
  if conf.tables:
164
- pglogical_tables = [
165
- t
166
- for t in pkeys
167
- if t
168
- in list(
169
- map(str.lower, conf.tables)
170
- ) # Postgres returns table names in lowercase (in analyze_table_pkeys)
171
- ]
157
+ pglogical_tables = [t for t in pkeys if t in conf.tables]
172
158
 
173
159
  await configure_replication_set(
174
160
  dst_root_pool, pglogical_tables, conf.schema_name, dst_logger
@@ -92,14 +92,7 @@ async def status(conf_future: Awaitable[DbupgradeConfig]) -> dict[str, str]:
92
92
  all_tables = pkey_tables + non_pkey_tables
93
93
  target_tables = all_tables
94
94
  if conf.tables:
95
- target_tables = [
96
- t
97
- for t in all_tables
98
- if t
99
- in list(
100
- map(str.lower, conf.tables)
101
- ) # Postgres gave us lowercase table names in analyze_table_pkeys
102
- ]
95
+ target_tables = [t for t in all_tables if t in conf.tables]
103
96
 
104
97
  if not target_tables:
105
98
  raise ValueError(
@@ -77,14 +77,7 @@ async def dump_tables(
77
77
  _, tables, _ = await analyze_table_pkeys(src_pool, conf.schema_name, logger)
78
78
 
79
79
  if conf.tables:
80
- tables = [
81
- t
82
- for t in tables
83
- if t
84
- in list(
85
- map(str.lower, conf.tables)
86
- ) # Postgres returns table names in lowercase (in analyze_table_pkeys)
87
- ]
80
+ tables = [t for t in tables if t in conf.tables]
88
81
 
89
82
  await dump_source_tables(conf, tables, logger)
90
83
 
@@ -192,14 +185,7 @@ async def _dump_and_load_all_tables(
192
185
  ) -> None:
193
186
  _, tables, _ = await analyze_table_pkeys(src_pool, conf.schema_name, src_logger)
194
187
  if conf.tables:
195
- tables = [
196
- t
197
- for t in tables
198
- if t
199
- in list(
200
- map(str.lower, conf.tables)
201
- ) # Postgres returns table names in lowercase (in analyze_table_pkeys)
202
- ]
188
+ tables = [t for t in tables if t in conf.tables]
203
189
  await dump_source_tables(conf, tables, src_logger)
204
190
  await load_dumped_tables(conf, tables, dst_logger)
205
191
 
@@ -9,7 +9,7 @@ from pgbelt.util import get_logger
9
9
  from pgbelt.util.asyncfuncs import makedirs
10
10
  from pydantic import BaseModel
11
11
  from pydantic import ValidationError
12
- from pydantic import validator
12
+ from pydantic import field_validator
13
13
 
14
14
 
15
15
  def config_dir(db: str, dc: str) -> str:
@@ -37,7 +37,7 @@ class User(BaseModel):
37
37
  name: str
38
38
  pw: Optional[str] = None
39
39
 
40
- _not_empty = validator("name", "pw", allow_reuse=True)(not_empty)
40
+ _not_empty = field_validator("name", "pw")(not_empty)
41
41
 
42
42
 
43
43
  class DbConfig(BaseModel):
@@ -64,9 +64,9 @@ class DbConfig(BaseModel):
64
64
  pglogical_user: User
65
65
  other_users: Optional[list[User]] = None
66
66
 
67
- _not_empty = validator("host", "ip", "db", "port", allow_reuse=True)(not_empty)
67
+ _not_empty = field_validator("host", "ip", "db", "port")(not_empty)
68
68
 
69
- @validator("root_user", "owner_user", "pglogical_user")
69
+ @field_validator("root_user", "owner_user", "pglogical_user")
70
70
  def has_password(cls, v) -> User: # noqa: N805
71
71
  if not v.pw:
72
72
  raise ValueError
@@ -118,7 +118,7 @@ class DbupgradeConfig(BaseModel):
118
118
  sequences: Optional[list[str]] = None
119
119
  schema_name: Optional[str] = "public"
120
120
 
121
- _not_empty = validator("db", "dc", allow_reuse=True)(not_empty)
121
+ _not_empty = field_validator("db", "dc")(not_empty)
122
122
 
123
123
  @property
124
124
  def file(self) -> str:
@@ -167,7 +167,7 @@ class DbupgradeConfig(BaseModel):
167
167
  return None
168
168
 
169
169
  try:
170
- out = cls.parse_raw(raw)
170
+ out = cls.model_validate_json(raw)
171
171
  except ValidationError:
172
172
  logger.info("Cached config was not a valid DbupgradeConfig")
173
173
  return None
@@ -79,7 +79,7 @@ async def load_remote_conf_def(
79
79
  async with aopen(config_file, mode="r") as f:
80
80
  raw_json = await f.read()
81
81
 
82
- return RemoteConfigDefinition.parse_raw(raw_json)
82
+ return RemoteConfigDefinition.model_validate_json(raw_json)
83
83
  except FileNotFoundError:
84
84
  logger.error(f"No remote config definition exists at {config_file}")
85
85
  except JSONDecodeError:
@@ -78,7 +78,7 @@ async def grant_pgl(pool: Pool, tables: list[str], schema: str, logger: Logger)
78
78
  async with pool.acquire() as conn:
79
79
  async with conn.transaction():
80
80
  if tables:
81
- tables_with_schema = [f"{schema}.{table}" for table in tables]
81
+ tables_with_schema = [f'{schema}."{table}"' for table in tables]
82
82
  await conn.execute(
83
83
  f"GRANT ALL ON TABLE {','.join(tables_with_schema)} TO pglogical;"
84
84
  )
@@ -100,14 +100,12 @@ async def compare_data(
100
100
  has_run = False
101
101
  for table in set(pkeys):
102
102
  # If specific table list is defined and the iterated table is not in that list, skip.
103
- # Note that the pkeys tables returned from Postgres are all lowercased, so we need to
104
- # map the passed conf tables to lowercase.
105
- if tables and (table not in list(map(str.lower, tables))):
103
+ if tables and (table not in tables):
106
104
  continue
107
105
 
108
106
  has_run = True # If this runs, we have at least one table to compare. We will use this flag to throw an error if no tables are found.
109
107
 
110
- full_table_name = f"{schema}.{table}"
108
+ full_table_name = f'{schema}."{table}"'
111
109
 
112
110
  logger.debug(f"Validating table {full_table_name}...")
113
111
  order_by_pkeys = ",".join(pkeys_dict[table])
@@ -387,15 +385,9 @@ async def precheck_info(
387
385
  )
388
386
 
389
387
  # We filter the table list if the user has specified a list of tables to target.
390
- # Note, from issue #420, the above query will return the table names in lowercase,
391
- # so we need to map the target_tables to lowercase.
392
388
  if target_tables:
393
389
 
394
- result["tables"] = [
395
- t
396
- for t in result["tables"]
397
- if t["Name"] in list(map(str.lower, target_tables))
398
- ]
390
+ result["tables"] = [t for t in result["tables"] if t["Name"] in target_tables]
399
391
 
400
392
  # We will not recapitalize the table names in the result["tables"] list,
401
393
  # to preserve how Postgres sees those tables in its system catalog. Easy
@@ -419,14 +411,10 @@ async def precheck_info(
419
411
  )
420
412
 
421
413
  # We filter the table list if the user has specified a list of tables to target.
422
- # Note, from issue #420, the above query will return the table names in lowercase,
423
- # so we need to map the target_tables to lowercase.
424
414
  if target_sequences:
425
415
 
426
416
  result["sequences"] = [
427
- t
428
- for t in result["sequences"]
429
- if t["Name"] in list(map(str.lower, target_sequences))
417
+ t for t in result["sequences"] if t["Name"] in target_sequences
430
418
  ]
431
419
 
432
420
  # We will not recapitalize the table names in the result["tables"] list,
@@ -485,7 +473,7 @@ async def get_dataset_size(
485
473
 
486
474
  query = f"""
487
475
  SELECT
488
- sum(pg_total_relation_size(schemaname || '.' || tablename)) AS total_relation_size
476
+ sum(pg_total_relation_size(schemaname || '."' || tablename || '"')) AS total_relation_size
489
477
  FROM
490
478
  pg_tables
491
479
  WHERE
@@ -496,7 +484,7 @@ async def get_dataset_size(
496
484
  # Yes it's a duplicate, but it's a pretty one. Rather let Postgres do this than Python.
497
485
  pretty_query = f"""
498
486
  SELECT
499
- pg_size_pretty(sum(pg_total_relation_size(schemaname || '.' || tablename))) AS total_relation_size
487
+ pg_size_pretty(sum(pg_total_relation_size(schemaname || '."' || tablename || '"'))) AS total_relation_size
500
488
  FROM
501
489
  pg_tables
502
490
  WHERE
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "pgbelt"
3
- version = "0.7.2"
3
+ version = "0.7.3"
4
4
  description = "A CLI tool used to manage Postgres data migrations from beginning to end, for a single database or a fleet, leveraging pglogical replication."
5
5
  authors = ["Varjitt Jeeva <varjitt.jeeva@autodesk.com>"]
6
6
  readme = "README.md"
@@ -15,16 +15,16 @@ aiofiles = ">=0.8,<23.3"
15
15
  asyncpg = ">=0.27,<0.30"
16
16
  pydantic = ">=2.0,<3.0"
17
17
  tabulate = "^0.9.0"
18
- typer = "^0.9.0"
18
+ typer = ">=0.9,<0.13"
19
19
 
20
20
  [tool.poetry.dev-dependencies]
21
21
  black = "~24.3.0"
22
- pre-commit = "~3.6.2"
22
+ pre-commit = "~3.7.0"
23
23
  flake8 = "^7.0.0"
24
- pytest-cov = "~4.1.0"
24
+ pytest-cov = "~5.0.0"
25
25
  pytest = "^8.1.1"
26
26
  coverage = {extras = ["toml"], version = "^7.4"}
27
- safety = "^2.3.1"
27
+ safety = "^3.1.0"
28
28
  mypy = "^1.9"
29
29
  xdoctest = {extras = ["colors"], version = "^1.1.3"}
30
30
  flake8-bandit = "~4.1.1"
@@ -36,9 +36,9 @@ darglint = "^1.8.1"
36
36
  reorder-python-imports = "^3.9.0"
37
37
  pre-commit-hooks = "^4.5.0"
38
38
  Pygments = "^2.17.2"
39
- pyupgrade = "^3.15.1"
39
+ pyupgrade = "^3.15.2"
40
40
  pylint = "^3.1.0"
41
- pytest-asyncio = "~0.23.5"
41
+ pytest-asyncio = "~0.23.6"
42
42
 
43
43
  [build-system]
44
44
  requires = ["poetry-core>=1.0.0", "setuptools"]
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes