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.
- {tablemaster-2.1.7 → tablemaster-2.1.8}/PKG-INFO +1 -1
- {tablemaster-2.1.7 → tablemaster-2.1.8}/pyproject.toml +1 -1
- {tablemaster-2.1.7 → tablemaster-2.1.8}/tablemaster/schema/diff.py +23 -2
- {tablemaster-2.1.7 → tablemaster-2.1.8}/tablemaster.egg-info/PKG-INFO +1 -1
- {tablemaster-2.1.7 → tablemaster-2.1.8}/tests/test_schema_core.py +37 -0
- {tablemaster-2.1.7 → tablemaster-2.1.8}/LICENSE +0 -0
- {tablemaster-2.1.7 → tablemaster-2.1.8}/README.md +0 -0
- {tablemaster-2.1.7 → tablemaster-2.1.8}/setup.cfg +0 -0
- {tablemaster-2.1.7 → tablemaster-2.1.8}/tablemaster/__init__.py +0 -0
- {tablemaster-2.1.7 → tablemaster-2.1.8}/tablemaster/__main__.py +0 -0
- {tablemaster-2.1.7 → tablemaster-2.1.8}/tablemaster/cli.py +0 -0
- {tablemaster-2.1.7 → tablemaster-2.1.8}/tablemaster/config.py +0 -0
- {tablemaster-2.1.7 → tablemaster-2.1.8}/tablemaster/database.py +0 -0
- {tablemaster-2.1.7 → tablemaster-2.1.8}/tablemaster/feishu.py +0 -0
- {tablemaster-2.1.7 → tablemaster-2.1.8}/tablemaster/gspread.py +0 -0
- {tablemaster-2.1.7 → tablemaster-2.1.8}/tablemaster/local.py +0 -0
- {tablemaster-2.1.7 → tablemaster-2.1.8}/tablemaster/schema/__init__.py +0 -0
- {tablemaster-2.1.7 → tablemaster-2.1.8}/tablemaster/schema/apply.py +0 -0
- {tablemaster-2.1.7 → tablemaster-2.1.8}/tablemaster/schema/dialects/__init__.py +0 -0
- {tablemaster-2.1.7 → tablemaster-2.1.8}/tablemaster/schema/dialects/base.py +0 -0
- {tablemaster-2.1.7 → tablemaster-2.1.8}/tablemaster/schema/dialects/mysql.py +0 -0
- {tablemaster-2.1.7 → tablemaster-2.1.8}/tablemaster/schema/dialects/postgresql.py +0 -0
- {tablemaster-2.1.7 → tablemaster-2.1.8}/tablemaster/schema/dialects/tidb.py +0 -0
- {tablemaster-2.1.7 → tablemaster-2.1.8}/tablemaster/schema/init.py +0 -0
- {tablemaster-2.1.7 → tablemaster-2.1.8}/tablemaster/schema/introspect.py +0 -0
- {tablemaster-2.1.7 → tablemaster-2.1.8}/tablemaster/schema/loader.py +0 -0
- {tablemaster-2.1.7 → tablemaster-2.1.8}/tablemaster/schema/models.py +0 -0
- {tablemaster-2.1.7 → tablemaster-2.1.8}/tablemaster/schema/plan.py +0 -0
- {tablemaster-2.1.7 → tablemaster-2.1.8}/tablemaster/schema/pull.py +0 -0
- {tablemaster-2.1.7 → tablemaster-2.1.8}/tablemaster/sync.py +0 -0
- {tablemaster-2.1.7 → tablemaster-2.1.8}/tablemaster/utils.py +0 -0
- {tablemaster-2.1.7 → tablemaster-2.1.8}/tablemaster.egg-info/SOURCES.txt +0 -0
- {tablemaster-2.1.7 → tablemaster-2.1.8}/tablemaster.egg-info/dependency_links.txt +0 -0
- {tablemaster-2.1.7 → tablemaster-2.1.8}/tablemaster.egg-info/entry_points.txt +0 -0
- {tablemaster-2.1.7 → tablemaster-2.1.8}/tablemaster.egg-info/requires.txt +0 -0
- {tablemaster-2.1.7 → tablemaster-2.1.8}/tablemaster.egg-info/top_level.txt +0 -0
- {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.
|
|
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
|
+
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
|
|
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.
|
|
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
|
|
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
|
|
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
|