tablemaster 2.1.7__tar.gz → 2.1.8__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 (37) hide show
  1. {tablemaster-2.1.7 → tablemaster-2.1.8}/PKG-INFO +1 -1
  2. {tablemaster-2.1.7 → tablemaster-2.1.8}/pyproject.toml +1 -1
  3. {tablemaster-2.1.7 → tablemaster-2.1.8}/tablemaster/schema/diff.py +23 -2
  4. {tablemaster-2.1.7 → tablemaster-2.1.8}/tablemaster.egg-info/PKG-INFO +1 -1
  5. {tablemaster-2.1.7 → tablemaster-2.1.8}/tests/test_schema_core.py +37 -0
  6. {tablemaster-2.1.7 → tablemaster-2.1.8}/LICENSE +0 -0
  7. {tablemaster-2.1.7 → tablemaster-2.1.8}/README.md +0 -0
  8. {tablemaster-2.1.7 → tablemaster-2.1.8}/setup.cfg +0 -0
  9. {tablemaster-2.1.7 → tablemaster-2.1.8}/tablemaster/__init__.py +0 -0
  10. {tablemaster-2.1.7 → tablemaster-2.1.8}/tablemaster/__main__.py +0 -0
  11. {tablemaster-2.1.7 → tablemaster-2.1.8}/tablemaster/cli.py +0 -0
  12. {tablemaster-2.1.7 → tablemaster-2.1.8}/tablemaster/config.py +0 -0
  13. {tablemaster-2.1.7 → tablemaster-2.1.8}/tablemaster/database.py +0 -0
  14. {tablemaster-2.1.7 → tablemaster-2.1.8}/tablemaster/feishu.py +0 -0
  15. {tablemaster-2.1.7 → tablemaster-2.1.8}/tablemaster/gspread.py +0 -0
  16. {tablemaster-2.1.7 → tablemaster-2.1.8}/tablemaster/local.py +0 -0
  17. {tablemaster-2.1.7 → tablemaster-2.1.8}/tablemaster/schema/__init__.py +0 -0
  18. {tablemaster-2.1.7 → tablemaster-2.1.8}/tablemaster/schema/apply.py +0 -0
  19. {tablemaster-2.1.7 → tablemaster-2.1.8}/tablemaster/schema/dialects/__init__.py +0 -0
  20. {tablemaster-2.1.7 → tablemaster-2.1.8}/tablemaster/schema/dialects/base.py +0 -0
  21. {tablemaster-2.1.7 → tablemaster-2.1.8}/tablemaster/schema/dialects/mysql.py +0 -0
  22. {tablemaster-2.1.7 → tablemaster-2.1.8}/tablemaster/schema/dialects/postgresql.py +0 -0
  23. {tablemaster-2.1.7 → tablemaster-2.1.8}/tablemaster/schema/dialects/tidb.py +0 -0
  24. {tablemaster-2.1.7 → tablemaster-2.1.8}/tablemaster/schema/init.py +0 -0
  25. {tablemaster-2.1.7 → tablemaster-2.1.8}/tablemaster/schema/introspect.py +0 -0
  26. {tablemaster-2.1.7 → tablemaster-2.1.8}/tablemaster/schema/loader.py +0 -0
  27. {tablemaster-2.1.7 → tablemaster-2.1.8}/tablemaster/schema/models.py +0 -0
  28. {tablemaster-2.1.7 → tablemaster-2.1.8}/tablemaster/schema/plan.py +0 -0
  29. {tablemaster-2.1.7 → tablemaster-2.1.8}/tablemaster/schema/pull.py +0 -0
  30. {tablemaster-2.1.7 → tablemaster-2.1.8}/tablemaster/sync.py +0 -0
  31. {tablemaster-2.1.7 → tablemaster-2.1.8}/tablemaster/utils.py +0 -0
  32. {tablemaster-2.1.7 → tablemaster-2.1.8}/tablemaster.egg-info/SOURCES.txt +0 -0
  33. {tablemaster-2.1.7 → tablemaster-2.1.8}/tablemaster.egg-info/dependency_links.txt +0 -0
  34. {tablemaster-2.1.7 → tablemaster-2.1.8}/tablemaster.egg-info/entry_points.txt +0 -0
  35. {tablemaster-2.1.7 → tablemaster-2.1.8}/tablemaster.egg-info/requires.txt +0 -0
  36. {tablemaster-2.1.7 → tablemaster-2.1.8}/tablemaster.egg-info/top_level.txt +0 -0
  37. {tablemaster-2.1.7 → tablemaster-2.1.8}/tests/test_error_visibility.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tablemaster
3
- Version: 2.1.7
3
+ Version: 2.1.8
4
4
  Summary: tablemaster is a Python toolkit for moving and managing tabular data across databases, Feishu/Lark, Google Sheets, and local files with one consistent API.
5
5
  Author-email: Livid <livid.su@gmail.com>
6
6
  Project-URL: Homepage, https://github.com/ilivid/tablemaster
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "tablemaster"
7
- version = "2.1.7"
7
+ version = "2.1.8"
8
8
  description = "tablemaster is a Python toolkit for moving and managing tabular data across databases, Feishu/Lark, Google Sheets, and local files with one consistent API."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -1,12 +1,33 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import re
4
+
3
5
  from .dialects.base import BaseDialect
4
6
  from .models import ActualTable, ColumnDef, Plan, PlanAction, TableDef
5
7
 
6
8
 
7
- def _norm_default(value: str | None) -> str | None:
9
+ def _strip_outer_parens(value: str) -> str:
10
+ result = value.strip()
11
+ while result.startswith('(') and result.endswith(')'):
12
+ result = result[1:-1].strip()
13
+ return result
14
+
15
+
16
+ def _normalize_pg_default(value: str) -> str:
17
+ normalized = _strip_outer_parens(value)
18
+ # PostgreSQL introspection often returns defaults like: 'N'::bpchar
19
+ # or ('unknown'::character varying). Strip trailing casts for comparison.
20
+ normalized = re.sub(r"::[a-zA-Z_][a-zA-Z0-9_\[\]\.\s]*$", '', normalized).strip()
21
+ if normalized.startswith("'") and normalized.endswith("'") and len(normalized) >= 2:
22
+ normalized = normalized[1:-1].replace("''", "'")
23
+ return normalized.upper()
24
+
25
+
26
+ def _norm_default(value: str | None, dialect: BaseDialect) -> str | None:
8
27
  if value is None:
9
28
  return None
29
+ if dialect.__class__.__name__ == 'PostgreSQLDialect':
30
+ return _normalize_pg_default(value)
10
31
  return value.strip().strip("'").upper()
11
32
 
12
33
 
@@ -161,7 +182,7 @@ def generate_plan(
161
182
  )
162
183
  )
163
184
 
164
- if _norm_default(desired_col.default) != _norm_default(actual_col.default):
185
+ if _norm_default(desired_col.default, dialect) != _norm_default(actual_col.default, dialect):
165
186
  plan.actions.append(
166
187
  _action(
167
188
  'ALTER_COLUMN_DEFAULT',
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tablemaster
3
- Version: 2.1.7
3
+ Version: 2.1.8
4
4
  Summary: tablemaster is a Python toolkit for moving and managing tabular data across databases, Feishu/Lark, Google Sheets, and local files with one consistent API.
5
5
  Author-email: Livid <livid.su@gmail.com>
6
6
  Project-URL: Homepage, https://github.com/ilivid/tablemaster
@@ -244,6 +244,43 @@ class SchemaCoreTests(unittest.TestCase):
244
244
  )
245
245
  self.assertTrue(any(a.action == 'ADD_PRIMARY_KEY' for a in plan.actions))
246
246
 
247
+ def test_postgresql_default_literal_with_cast_not_repeated(self):
248
+ with TemporaryDirectory() as td:
249
+ root = Path(td)
250
+ schema_dir = root / 'schema' / 'mydb'
251
+ schema_dir.mkdir(parents=True, exist_ok=True)
252
+ (schema_dir / 'orders.yaml').write_text(
253
+ '\n'.join(
254
+ [
255
+ 'table: orders',
256
+ 'columns:',
257
+ ' - name: archive',
258
+ ' type: CHAR(1)',
259
+ ' nullable: false',
260
+ ' default: "\'N\'"',
261
+ ]
262
+ ),
263
+ encoding='utf-8',
264
+ )
265
+ desired = load_schema_definitions(connection='mydb', root_dir=root / 'schema')
266
+ actual = [
267
+ ActualTable(
268
+ table='orders',
269
+ columns=[
270
+ ActualColumn(
271
+ name='archive',
272
+ type='character(1)',
273
+ nullable=False,
274
+ default="'N'::bpchar",
275
+ comment=None,
276
+ )
277
+ ],
278
+ indexes=[],
279
+ )
280
+ ]
281
+ plan = generate_plan('mydb', desired, actual, PostgreSQLDialect())
282
+ self.assertFalse(any(a.action == 'ALTER_COLUMN_DEFAULT' for a in plan.actions))
283
+
247
284
 
248
285
  if __name__ == '__main__':
249
286
  unittest.main()
File without changes
File without changes
File without changes