consync 2.2.1__tar.gz → 2.2.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.
- {consync-2.2.1 → consync-2.2.3}/PKG-INFO +1 -1
- {consync-2.2.1 → consync-2.2.3}/consync/cli.py +3 -3
- {consync-2.2.1 → consync-2.2.3}/consync/config.py +16 -4
- {consync-2.2.1 → consync-2.2.3}/consync/hooks.py +2 -2
- {consync-2.2.1 → consync-2.2.3}/consync/lock.py +2 -2
- {consync-2.2.1 → consync-2.2.3}/consync/state.py +2 -2
- {consync-2.2.1 → consync-2.2.3}/pyproject.toml +1 -1
- {consync-2.2.1 → consync-2.2.3}/.github/CODEOWNERS +0 -0
- {consync-2.2.1 → consync-2.2.3}/.github/copilot-instructions.md +0 -0
- {consync-2.2.1 → consync-2.2.3}/.github/dependabot.yml +0 -0
- {consync-2.2.1 → consync-2.2.3}/.github/workflows/ci.yml +0 -0
- {consync-2.2.1 → consync-2.2.3}/.github/workflows/codeql.yml +0 -0
- {consync-2.2.1 → consync-2.2.3}/.github/workflows/publish.yml +0 -0
- {consync-2.2.1 → consync-2.2.3}/.github/workflows/release.yml +0 -0
- {consync-2.2.1 → consync-2.2.3}/.gitignore +0 -0
- {consync-2.2.1 → consync-2.2.3}/CLAUDE.md +0 -0
- {consync-2.2.1 → consync-2.2.3}/CONTRIBUTING.md +0 -0
- {consync-2.2.1 → consync-2.2.3}/FAQ.md +0 -0
- {consync-2.2.1 → consync-2.2.3}/LICENSE +0 -0
- {consync-2.2.1 → consync-2.2.3}/README.md +0 -0
- {consync-2.2.1 → consync-2.2.3}/SECURITY.md +0 -0
- {consync-2.2.1 → consync-2.2.3}/TODO.md +0 -0
- {consync-2.2.1 → consync-2.2.3}/assets/demo.gif +0 -0
- {consync-2.2.1 → consync-2.2.3}/assets/demo.tape +0 -0
- {consync-2.2.1 → consync-2.2.3}/consync/__init__.py +0 -0
- {consync-2.2.1 → consync-2.2.3}/consync/backup.py +0 -0
- {consync-2.2.1 → consync-2.2.3}/consync/logging_config.py +0 -0
- {consync-2.2.1 → consync-2.2.3}/consync/models.py +0 -0
- {consync-2.2.1 → consync-2.2.3}/consync/parsers/__init__.py +0 -0
- {consync-2.2.1 → consync-2.2.3}/consync/parsers/c_header.py +0 -0
- {consync-2.2.1 → consync-2.2.3}/consync/parsers/c_struct_table.py +0 -0
- {consync-2.2.1 → consync-2.2.3}/consync/parsers/csv_parser.py +0 -0
- {consync-2.2.1 → consync-2.2.3}/consync/parsers/json_parser.py +0 -0
- {consync-2.2.1 → consync-2.2.3}/consync/parsers/toml_parser.py +0 -0
- {consync-2.2.1 → consync-2.2.3}/consync/parsers/xlsx.py +0 -0
- {consync-2.2.1 → consync-2.2.3}/consync/precision.py +0 -0
- {consync-2.2.1 → consync-2.2.3}/consync/renderers/__init__.py +0 -0
- {consync-2.2.1 → consync-2.2.3}/consync/renderers/c_header.py +0 -0
- {consync-2.2.1 → consync-2.2.3}/consync/renderers/c_struct_table.py +0 -0
- {consync-2.2.1 → consync-2.2.3}/consync/renderers/csharp.py +0 -0
- {consync-2.2.1 → consync-2.2.3}/consync/renderers/csv_renderer.py +0 -0
- {consync-2.2.1 → consync-2.2.3}/consync/renderers/json_renderer.py +0 -0
- {consync-2.2.1 → consync-2.2.3}/consync/renderers/python_const.py +0 -0
- {consync-2.2.1 → consync-2.2.3}/consync/renderers/rust_const.py +0 -0
- {consync-2.2.1 → consync-2.2.3}/consync/renderers/verilog.py +0 -0
- {consync-2.2.1 → consync-2.2.3}/consync/renderers/vhdl.py +0 -0
- {consync-2.2.1 → consync-2.2.3}/consync/sync.py +0 -0
- {consync-2.2.1 → consync-2.2.3}/consync/validators.py +0 -0
- {consync-2.2.1 → consync-2.2.3}/consync/watcher.py +0 -0
- {consync-2.2.1 → consync-2.2.3}/examples/fpga/.consync.yaml +0 -0
- {consync-2.2.1 → consync-2.2.3}/examples/fpga/design_params.csv +0 -0
- {consync-2.2.1 → consync-2.2.3}/examples/hardware/.consync.yaml +0 -0
- {consync-2.2.1 → consync-2.2.3}/examples/hardware/constants.csv +0 -0
- {consync-2.2.1 → consync-2.2.3}/examples/multilang/.consync.yaml +0 -0
- {consync-2.2.1 → consync-2.2.3}/examples/multilang/constants.json +0 -0
- {consync-2.2.1 → consync-2.2.3}/npm/.npmrc +0 -0
- {consync-2.2.1 → consync-2.2.3}/npm/LICENSE +0 -0
- {consync-2.2.1 → consync-2.2.3}/npm/README.md +0 -0
- {consync-2.2.1 → consync-2.2.3}/npm/bin/consync.js +0 -0
- {consync-2.2.1 → consync-2.2.3}/npm/package.json +0 -0
- {consync-2.2.1 → consync-2.2.3}/npm/scripts/install.js +0 -0
- {consync-2.2.1 → consync-2.2.3}/tests/__init__.py +0 -0
- {consync-2.2.1 → consync-2.2.3}/tests/test_arrays.py +0 -0
- {consync-2.2.1 → consync-2.2.3}/tests/test_bidirectional.py +0 -0
- {consync-2.2.1 → consync-2.2.3}/tests/test_c_struct_table.py +0 -0
- {consync-2.2.1 → consync-2.2.3}/tests/test_cli.py +0 -0
- {consync-2.2.1 → consync-2.2.3}/tests/test_comprehensive_sync.py +0 -0
- {consync-2.2.1 → consync-2.2.3}/tests/test_embedded.py +0 -0
- {consync-2.2.1 → consync-2.2.3}/tests/test_parsers.py +0 -0
- {consync-2.2.1 → consync-2.2.3}/tests/test_precision.py +0 -0
- {consync-2.2.1 → consync-2.2.3}/tests/test_renderers.py +0 -0
- {consync-2.2.1 → consync-2.2.3}/tests/test_safety.py +0 -0
- {consync-2.2.1 → consync-2.2.3}/tests/test_sync.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: consync
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.3
|
|
4
4
|
Summary: Bidirectional sync between spreadsheets and source code constants — with full decimal precision.
|
|
5
5
|
Project-URL: Homepage, https://github.com/naveenkumarbaskaran/consync
|
|
6
6
|
Project-URL: Repository, https://github.com/naveenkumarbaskaran/consync
|
|
@@ -46,7 +46,7 @@ def init(path: str):
|
|
|
46
46
|
click.echo(f"⚠️ {target} already exists. Delete it first to regenerate.")
|
|
47
47
|
sys.exit(1)
|
|
48
48
|
|
|
49
|
-
target.write_text(generate_default_config())
|
|
49
|
+
target.write_text(generate_default_config(), encoding="utf-8")
|
|
50
50
|
click.echo(f"✅ Created {target}")
|
|
51
51
|
click.echo(" Edit it to configure your source ↔ target mappings.")
|
|
52
52
|
click.echo(" Then run: consync sync")
|
|
@@ -329,13 +329,13 @@ def diff_cmd(config_path: str | None, from_side: str | None, color: bool):
|
|
|
329
329
|
|
|
330
330
|
try:
|
|
331
331
|
_render_file(constants, tmp_path, mapping.target_format if direction == "source" else mapping.source_format, mapping)
|
|
332
|
-
new_content = tmp_path.read_text().splitlines(keepends=True)
|
|
332
|
+
new_content = tmp_path.read_text(encoding="utf-8").splitlines(keepends=True)
|
|
333
333
|
finally:
|
|
334
334
|
tmp_path.unlink(missing_ok=True)
|
|
335
335
|
|
|
336
336
|
# Get current content
|
|
337
337
|
if dest_path.exists():
|
|
338
|
-
old_content = dest_path.read_text().splitlines(keepends=True)
|
|
338
|
+
old_content = dest_path.read_text(encoding="utf-8").splitlines(keepends=True)
|
|
339
339
|
else:
|
|
340
340
|
old_content = []
|
|
341
341
|
|
|
@@ -132,6 +132,14 @@ def _parse_mapping(raw: dict[str, Any], config_dir: Path) -> MappingConfig:
|
|
|
132
132
|
|
|
133
133
|
direction = _parse_direction(raw.get("direction", "source_to_target"))
|
|
134
134
|
|
|
135
|
+
# Normalize parser_options — handle None (empty YAML value) and promote
|
|
136
|
+
# common parser keys (variant, table_var, fields) from mapping level
|
|
137
|
+
parser_options = raw.get("parser_options") or {}
|
|
138
|
+
_PROMOTABLE_PARSER_KEYS = ("variant", "table_var", "fields")
|
|
139
|
+
for key in _PROMOTABLE_PARSER_KEYS:
|
|
140
|
+
if key not in parser_options and key in raw:
|
|
141
|
+
parser_options[key] = raw[key]
|
|
142
|
+
|
|
135
143
|
return MappingConfig(
|
|
136
144
|
source=source,
|
|
137
145
|
target=target,
|
|
@@ -147,9 +155,9 @@ def _parse_mapping(raw: dict[str, Any], config_dir: Path) -> MappingConfig:
|
|
|
147
155
|
output_style=raw.get("output_style", "const"),
|
|
148
156
|
static_const=raw.get("static_const", False),
|
|
149
157
|
typed_ints=raw.get("typed_ints", True),
|
|
150
|
-
parser_options=
|
|
151
|
-
renderer_options=raw.get("renderer_options"
|
|
152
|
-
validators=raw.get("validators"
|
|
158
|
+
parser_options=parser_options,
|
|
159
|
+
renderer_options=raw.get("renderer_options") or {},
|
|
160
|
+
validators=raw.get("validators") or {},
|
|
153
161
|
)
|
|
154
162
|
|
|
155
163
|
|
|
@@ -223,7 +231,11 @@ mappings:
|
|
|
223
231
|
# target: MotorParams.xlsx # Excel generated from C (created if missing)
|
|
224
232
|
# direction: both # Edit either side, sync keeps them matched
|
|
225
233
|
# format: c_struct_table # Parser for #if/#elif struct arrays
|
|
226
|
-
#
|
|
234
|
+
# variant: all # Extract ALL #if/#elif variants (one sheet each)
|
|
235
|
+
# # table_var: MyStructLUT # Optional: struct array name (auto-detected)
|
|
236
|
+
# # fields: [R_Phase, L_d, Psi] # Optional: field names (auto-detected)
|
|
237
|
+
# # parser_options: # Alternative: nest parser keys here
|
|
238
|
+
# # variant: all
|
|
227
239
|
|
|
228
240
|
# ─── Pattern 3: Code → Spreadsheet (bootstrap) ───
|
|
229
241
|
# - source: params.csv # Will be created from your existing code
|
|
@@ -49,7 +49,7 @@ def install_git_hook(hook_type: str = "pre-commit"):
|
|
|
49
49
|
|
|
50
50
|
# Check for existing hook
|
|
51
51
|
if hook_file.exists():
|
|
52
|
-
existing = hook_file.read_text()
|
|
52
|
+
existing = hook_file.read_text(encoding="utf-8")
|
|
53
53
|
if "consync" in existing:
|
|
54
54
|
click.echo(f"✔️ consync hook already installed in .git/hooks/{hook_type}")
|
|
55
55
|
return
|
|
@@ -61,7 +61,7 @@ def install_git_hook(hook_type: str = "pre-commit"):
|
|
|
61
61
|
f.write(HOOK_TEMPLATE.format(hook_type=hook_type, git_cmd=git_cmd))
|
|
62
62
|
else:
|
|
63
63
|
# Create new hook
|
|
64
|
-
hook_file.write_text(HOOK_TEMPLATE.format(hook_type=hook_type, git_cmd=git_cmd))
|
|
64
|
+
hook_file.write_text(HOOK_TEMPLATE.format(hook_type=hook_type, git_cmd=git_cmd), encoding="utf-8")
|
|
65
65
|
|
|
66
66
|
hook_file.chmod(0o755)
|
|
67
67
|
click.echo(f"✅ Installed consync check in .git/hooks/{hook_type}")
|
|
@@ -66,7 +66,7 @@ class SyncLock:
|
|
|
66
66
|
"created": datetime.now(timezone.utc).isoformat(timespec="seconds"),
|
|
67
67
|
"hostname": platform.node(),
|
|
68
68
|
}
|
|
69
|
-
self.lock_path.write_text(json.dumps(lock_info, indent=2))
|
|
69
|
+
self.lock_path.write_text(json.dumps(lock_info, indent=2), encoding="utf-8")
|
|
70
70
|
self._acquired = True
|
|
71
71
|
logger.debug("Lock acquired: %s", self.lock_path)
|
|
72
72
|
|
|
@@ -80,7 +80,7 @@ class SyncLock:
|
|
|
80
80
|
def _read_lock(self) -> dict | None:
|
|
81
81
|
"""Read lock file contents."""
|
|
82
82
|
try:
|
|
83
|
-
return json.loads(self.lock_path.read_text())
|
|
83
|
+
return json.loads(self.lock_path.read_text(encoding="utf-8"))
|
|
84
84
|
except (json.JSONDecodeError, OSError):
|
|
85
85
|
return None
|
|
86
86
|
|
|
@@ -43,14 +43,14 @@ class SyncState:
|
|
|
43
43
|
def _load(self):
|
|
44
44
|
if self.state_file.exists():
|
|
45
45
|
try:
|
|
46
|
-
self._data = json.loads(self.state_file.read_text())
|
|
46
|
+
self._data = json.loads(self.state_file.read_text(encoding="utf-8"))
|
|
47
47
|
except (json.JSONDecodeError, OSError):
|
|
48
48
|
self._data = {}
|
|
49
49
|
else:
|
|
50
50
|
self._data = {}
|
|
51
51
|
|
|
52
52
|
def _save(self):
|
|
53
|
-
self.state_file.write_text(json.dumps(self._data, indent=2) + "\n")
|
|
53
|
+
self.state_file.write_text(json.dumps(self._data, indent=2) + "\n", encoding="utf-8")
|
|
54
54
|
|
|
55
55
|
def get_hash(self, mapping_key: str, side: str) -> str | None:
|
|
56
56
|
"""Get the stored hash for a mapping side ('source' or 'target')."""
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "consync"
|
|
7
|
-
version = "2.2.
|
|
7
|
+
version = "2.2.3"
|
|
8
8
|
description = "Bidirectional sync between spreadsheets and source code constants — with full decimal precision."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = {text = "MIT"}
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|