consync 2.2.0__tar.gz → 2.2.2__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 (73) hide show
  1. {consync-2.2.0 → consync-2.2.2}/PKG-INFO +53 -5
  2. {consync-2.2.0 → consync-2.2.2}/README.md +52 -4
  3. {consync-2.2.0 → consync-2.2.2}/consync/cli.py +3 -3
  4. {consync-2.2.0 → consync-2.2.2}/consync/config.py +15 -7
  5. {consync-2.2.0 → consync-2.2.2}/consync/hooks.py +2 -2
  6. {consync-2.2.0 → consync-2.2.2}/consync/lock.py +2 -2
  7. {consync-2.2.0 → consync-2.2.2}/consync/state.py +2 -2
  8. {consync-2.2.0 → consync-2.2.2}/pyproject.toml +1 -1
  9. {consync-2.2.0 → consync-2.2.2}/.github/CODEOWNERS +0 -0
  10. {consync-2.2.0 → consync-2.2.2}/.github/copilot-instructions.md +0 -0
  11. {consync-2.2.0 → consync-2.2.2}/.github/dependabot.yml +0 -0
  12. {consync-2.2.0 → consync-2.2.2}/.github/workflows/ci.yml +0 -0
  13. {consync-2.2.0 → consync-2.2.2}/.github/workflows/codeql.yml +0 -0
  14. {consync-2.2.0 → consync-2.2.2}/.github/workflows/publish.yml +0 -0
  15. {consync-2.2.0 → consync-2.2.2}/.github/workflows/release.yml +0 -0
  16. {consync-2.2.0 → consync-2.2.2}/.gitignore +0 -0
  17. {consync-2.2.0 → consync-2.2.2}/CLAUDE.md +0 -0
  18. {consync-2.2.0 → consync-2.2.2}/CONTRIBUTING.md +0 -0
  19. {consync-2.2.0 → consync-2.2.2}/FAQ.md +0 -0
  20. {consync-2.2.0 → consync-2.2.2}/LICENSE +0 -0
  21. {consync-2.2.0 → consync-2.2.2}/SECURITY.md +0 -0
  22. {consync-2.2.0 → consync-2.2.2}/TODO.md +0 -0
  23. {consync-2.2.0 → consync-2.2.2}/assets/demo.gif +0 -0
  24. {consync-2.2.0 → consync-2.2.2}/assets/demo.tape +0 -0
  25. {consync-2.2.0 → consync-2.2.2}/consync/__init__.py +0 -0
  26. {consync-2.2.0 → consync-2.2.2}/consync/backup.py +0 -0
  27. {consync-2.2.0 → consync-2.2.2}/consync/logging_config.py +0 -0
  28. {consync-2.2.0 → consync-2.2.2}/consync/models.py +0 -0
  29. {consync-2.2.0 → consync-2.2.2}/consync/parsers/__init__.py +0 -0
  30. {consync-2.2.0 → consync-2.2.2}/consync/parsers/c_header.py +0 -0
  31. {consync-2.2.0 → consync-2.2.2}/consync/parsers/c_struct_table.py +0 -0
  32. {consync-2.2.0 → consync-2.2.2}/consync/parsers/csv_parser.py +0 -0
  33. {consync-2.2.0 → consync-2.2.2}/consync/parsers/json_parser.py +0 -0
  34. {consync-2.2.0 → consync-2.2.2}/consync/parsers/toml_parser.py +0 -0
  35. {consync-2.2.0 → consync-2.2.2}/consync/parsers/xlsx.py +0 -0
  36. {consync-2.2.0 → consync-2.2.2}/consync/precision.py +0 -0
  37. {consync-2.2.0 → consync-2.2.2}/consync/renderers/__init__.py +0 -0
  38. {consync-2.2.0 → consync-2.2.2}/consync/renderers/c_header.py +0 -0
  39. {consync-2.2.0 → consync-2.2.2}/consync/renderers/c_struct_table.py +0 -0
  40. {consync-2.2.0 → consync-2.2.2}/consync/renderers/csharp.py +0 -0
  41. {consync-2.2.0 → consync-2.2.2}/consync/renderers/csv_renderer.py +0 -0
  42. {consync-2.2.0 → consync-2.2.2}/consync/renderers/json_renderer.py +0 -0
  43. {consync-2.2.0 → consync-2.2.2}/consync/renderers/python_const.py +0 -0
  44. {consync-2.2.0 → consync-2.2.2}/consync/renderers/rust_const.py +0 -0
  45. {consync-2.2.0 → consync-2.2.2}/consync/renderers/verilog.py +0 -0
  46. {consync-2.2.0 → consync-2.2.2}/consync/renderers/vhdl.py +0 -0
  47. {consync-2.2.0 → consync-2.2.2}/consync/sync.py +0 -0
  48. {consync-2.2.0 → consync-2.2.2}/consync/validators.py +0 -0
  49. {consync-2.2.0 → consync-2.2.2}/consync/watcher.py +0 -0
  50. {consync-2.2.0 → consync-2.2.2}/examples/fpga/.consync.yaml +0 -0
  51. {consync-2.2.0 → consync-2.2.2}/examples/fpga/design_params.csv +0 -0
  52. {consync-2.2.0 → consync-2.2.2}/examples/hardware/.consync.yaml +0 -0
  53. {consync-2.2.0 → consync-2.2.2}/examples/hardware/constants.csv +0 -0
  54. {consync-2.2.0 → consync-2.2.2}/examples/multilang/.consync.yaml +0 -0
  55. {consync-2.2.0 → consync-2.2.2}/examples/multilang/constants.json +0 -0
  56. {consync-2.2.0 → consync-2.2.2}/npm/.npmrc +0 -0
  57. {consync-2.2.0 → consync-2.2.2}/npm/LICENSE +0 -0
  58. {consync-2.2.0 → consync-2.2.2}/npm/README.md +0 -0
  59. {consync-2.2.0 → consync-2.2.2}/npm/bin/consync.js +0 -0
  60. {consync-2.2.0 → consync-2.2.2}/npm/package.json +0 -0
  61. {consync-2.2.0 → consync-2.2.2}/npm/scripts/install.js +0 -0
  62. {consync-2.2.0 → consync-2.2.2}/tests/__init__.py +0 -0
  63. {consync-2.2.0 → consync-2.2.2}/tests/test_arrays.py +0 -0
  64. {consync-2.2.0 → consync-2.2.2}/tests/test_bidirectional.py +0 -0
  65. {consync-2.2.0 → consync-2.2.2}/tests/test_c_struct_table.py +0 -0
  66. {consync-2.2.0 → consync-2.2.2}/tests/test_cli.py +0 -0
  67. {consync-2.2.0 → consync-2.2.2}/tests/test_comprehensive_sync.py +0 -0
  68. {consync-2.2.0 → consync-2.2.2}/tests/test_embedded.py +0 -0
  69. {consync-2.2.0 → consync-2.2.2}/tests/test_parsers.py +0 -0
  70. {consync-2.2.0 → consync-2.2.2}/tests/test_precision.py +0 -0
  71. {consync-2.2.0 → consync-2.2.2}/tests/test_renderers.py +0 -0
  72. {consync-2.2.0 → consync-2.2.2}/tests/test_safety.py +0 -0
  73. {consync-2.2.0 → consync-2.2.2}/tests/test_sync.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: consync
3
- Version: 2.2.0
3
+ Version: 2.2.2
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
@@ -153,6 +153,12 @@ mappings:
153
153
  direction: both
154
154
  precision: 17
155
155
  header_guard: HW_CONSTANTS_H
156
+
157
+ # Or for C struct tables → Excel:
158
+ # - source: MotorParams.c
159
+ # target: MotorParams.xlsx
160
+ # direction: both
161
+ # format: c_struct_table
156
162
  ```
157
163
 
158
164
  ### 2. Sync
@@ -229,7 +235,36 @@ consync install-hook
229
235
 
230
236
  **Don't have a spreadsheet yet?** consync can create one from your existing source files.
231
237
 
232
- If you already have a C header with constants and want to start tracking it:
238
+ ### C Struct Table Excel (multi-variant motor parameters)
239
+
240
+ Have a complex C file with `#if`/`#elif` struct arrays and want an Excel for your team to review/edit?
241
+
242
+ ```yaml
243
+ # .consync.yaml
244
+ mappings:
245
+ - source: RBPSC_HWVariantParameter.c # Existing C file with struct arrays
246
+ target: RBPSC_HWVariantParameter.xlsx # Excel will be created on first sync
247
+ direction: both # Edit C or Excel — both stay in sync
248
+ format: c_struct_table # Parses #if/#elif multi-variant tables
249
+ precision: 17
250
+ ```
251
+
252
+ ```bash
253
+ consync sync
254
+ # ✅ RBPSC_HWVariantParameter.c ↔ RBPSC_HWVariantParameter.xlsx: 160 constants synced (source → target)
255
+ ```
256
+
257
+ consync parses the C file — handling nested `{{...}}` initializers, `#if`/`#elif` variant blocks, float suffixes (`1.0F`), hex (`0xFF`), expressions — and generates a multi-sheet Excel with one sheet per variant (BWA, EMB, DPB, etc.).
258
+
259
+ After that, edit either side:
260
+ - **Edit Excel** → values sync back into the C file (in-place, minimal diffs)
261
+ - **Edit C file** → Excel updates on next `consync sync`
262
+
263
+ > **Note:** The `format: c_struct_table` field tells consync to use the struct-table parser for the `.c` file instead of the default `c_header` parser. The `.xlsx` target format is auto-detected.
264
+
265
+ ### C Header → CSV/JSON (simple constants)
266
+
267
+ If you have a simpler C header with `const`/`#define` declarations:
233
268
 
234
269
  ```yaml
235
270
  # .consync.yaml
@@ -246,7 +281,7 @@ consync sync
246
281
 
247
282
  consync parses the existing `.h` file, extracts all constants (name, value, unit, description from comments), and writes a fresh CSV. From that point forward, you have a spreadsheet to share with your EE team.
248
283
 
249
- **Works with any parseable target:** `.h`, `.json`, `.csv`, `.toml` — anything consync has a parser for can bootstrap a new source.
284
+ **Works with any parseable format:** `.h`, `.c`, `.json`, `.csv`, `.toml` — anything consync has a parser for can bootstrap a new source.
250
285
 
251
286
  ---
252
287
 
@@ -411,17 +446,30 @@ consync tracks file hashes in `.consync.state.json` to detect which side changed
411
446
  ```yaml
412
447
  # .consync.yaml
413
448
  mappings:
414
- - source: constants.xlsx # source file path (xlsx/csv/json/toml/h)
415
- target: hw_constants.h # target file path (h/cs/py/rs/v/vhd/json/csv)
449
+ - source: constants.xlsx # source file path (xlsx/csv/json/toml/h/c)
450
+ target: hw_constants.h # target file path (h/cs/py/rs/v/vhd/json/csv/xlsx)
416
451
  direction: both # source_to_target | target_to_source | both
417
452
  precision: 17 # significant digits (1-17, default: 17)
418
453
 
454
+ # ─── Format override ───
455
+ # format: c_struct_table # Override auto-detected format for the matching side.
456
+ # # Useful when .c needs c_struct_table instead of c_header.
457
+ # # Auto-assigned to whichever side's extension matches.
458
+ # source_format: xlsx # Explicit source format (overrides auto-detect)
459
+ # target_format: c_header # Explicit target format (overrides auto-detect)
460
+
419
461
  # ─── C Header options ───
420
462
  header_guard: HW_CONSTANTS_H # #ifndef guard name
421
463
  output_style: const # const (default) | define
422
464
  static_const: true # adds 'static' keyword (default: false)
423
465
  typed_ints: true # use stdint.h types (default: false)
424
466
 
467
+ # ─── C Struct Table options ───
468
+ # parser_options:
469
+ # variant: DPB # Select specific #elif variant (or "all")
470
+ # table_var: PSC_HWVarParLUT # Struct array variable name (auto-detected)
471
+ # fields: [R_Phase, L_d, L_q, Psi, J, Imax, Tmax] # Field names (auto-detected)
472
+
425
473
  # ─── C# options ───
426
474
  namespace: MyCompany.Firmware # C# namespace
427
475
  class_name: EcuConstants # C# class name (default: Constants)
@@ -118,6 +118,12 @@ mappings:
118
118
  direction: both
119
119
  precision: 17
120
120
  header_guard: HW_CONSTANTS_H
121
+
122
+ # Or for C struct tables → Excel:
123
+ # - source: MotorParams.c
124
+ # target: MotorParams.xlsx
125
+ # direction: both
126
+ # format: c_struct_table
121
127
  ```
122
128
 
123
129
  ### 2. Sync
@@ -194,7 +200,36 @@ consync install-hook
194
200
 
195
201
  **Don't have a spreadsheet yet?** consync can create one from your existing source files.
196
202
 
197
- If you already have a C header with constants and want to start tracking it:
203
+ ### C Struct Table Excel (multi-variant motor parameters)
204
+
205
+ Have a complex C file with `#if`/`#elif` struct arrays and want an Excel for your team to review/edit?
206
+
207
+ ```yaml
208
+ # .consync.yaml
209
+ mappings:
210
+ - source: RBPSC_HWVariantParameter.c # Existing C file with struct arrays
211
+ target: RBPSC_HWVariantParameter.xlsx # Excel will be created on first sync
212
+ direction: both # Edit C or Excel — both stay in sync
213
+ format: c_struct_table # Parses #if/#elif multi-variant tables
214
+ precision: 17
215
+ ```
216
+
217
+ ```bash
218
+ consync sync
219
+ # ✅ RBPSC_HWVariantParameter.c ↔ RBPSC_HWVariantParameter.xlsx: 160 constants synced (source → target)
220
+ ```
221
+
222
+ consync parses the C file — handling nested `{{...}}` initializers, `#if`/`#elif` variant blocks, float suffixes (`1.0F`), hex (`0xFF`), expressions — and generates a multi-sheet Excel with one sheet per variant (BWA, EMB, DPB, etc.).
223
+
224
+ After that, edit either side:
225
+ - **Edit Excel** → values sync back into the C file (in-place, minimal diffs)
226
+ - **Edit C file** → Excel updates on next `consync sync`
227
+
228
+ > **Note:** The `format: c_struct_table` field tells consync to use the struct-table parser for the `.c` file instead of the default `c_header` parser. The `.xlsx` target format is auto-detected.
229
+
230
+ ### C Header → CSV/JSON (simple constants)
231
+
232
+ If you have a simpler C header with `const`/`#define` declarations:
198
233
 
199
234
  ```yaml
200
235
  # .consync.yaml
@@ -211,7 +246,7 @@ consync sync
211
246
 
212
247
  consync parses the existing `.h` file, extracts all constants (name, value, unit, description from comments), and writes a fresh CSV. From that point forward, you have a spreadsheet to share with your EE team.
213
248
 
214
- **Works with any parseable target:** `.h`, `.json`, `.csv`, `.toml` — anything consync has a parser for can bootstrap a new source.
249
+ **Works with any parseable format:** `.h`, `.c`, `.json`, `.csv`, `.toml` — anything consync has a parser for can bootstrap a new source.
215
250
 
216
251
  ---
217
252
 
@@ -376,17 +411,30 @@ consync tracks file hashes in `.consync.state.json` to detect which side changed
376
411
  ```yaml
377
412
  # .consync.yaml
378
413
  mappings:
379
- - source: constants.xlsx # source file path (xlsx/csv/json/toml/h)
380
- target: hw_constants.h # target file path (h/cs/py/rs/v/vhd/json/csv)
414
+ - source: constants.xlsx # source file path (xlsx/csv/json/toml/h/c)
415
+ target: hw_constants.h # target file path (h/cs/py/rs/v/vhd/json/csv/xlsx)
381
416
  direction: both # source_to_target | target_to_source | both
382
417
  precision: 17 # significant digits (1-17, default: 17)
383
418
 
419
+ # ─── Format override ───
420
+ # format: c_struct_table # Override auto-detected format for the matching side.
421
+ # # Useful when .c needs c_struct_table instead of c_header.
422
+ # # Auto-assigned to whichever side's extension matches.
423
+ # source_format: xlsx # Explicit source format (overrides auto-detect)
424
+ # target_format: c_header # Explicit target format (overrides auto-detect)
425
+
384
426
  # ─── C Header options ───
385
427
  header_guard: HW_CONSTANTS_H # #ifndef guard name
386
428
  output_style: const # const (default) | define
387
429
  static_const: true # adds 'static' keyword (default: false)
388
430
  typed_ints: true # use stdint.h types (default: false)
389
431
 
432
+ # ─── C Struct Table options ───
433
+ # parser_options:
434
+ # variant: DPB # Select specific #elif variant (or "all")
435
+ # table_var: PSC_HWVarParLUT # Struct array variable name (auto-detected)
436
+ # fields: [R_Phase, L_d, L_q, Psi, J, Imax, Tmax] # Field names (auto-detected)
437
+
390
438
  # ─── C# options ───
391
439
  namespace: MyCompany.Firmware # C# namespace
392
440
  class_name: EcuConstants # C# class name (default: Constants)
@@ -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
 
@@ -209,23 +209,31 @@ def generate_default_config() -> str:
209
209
  # Sync constants between spreadsheets and source code with full decimal precision.
210
210
 
211
211
  mappings:
212
+ # ─── Pattern 1: Spreadsheet → Code ───
213
+ # Excel is the source of truth, code is generated from it.
212
214
  - source: constants.xlsx # Where constants are defined (spreadsheet)
213
215
  target: include/constants.h # Generated code file
214
216
  direction: both # source_to_target | target_to_source | both
215
217
  precision: 17 # Significant digits (17 = full IEEE 754 double)
216
218
  header_guard: HW_CONSTANTS_H # C header include guard
217
219
 
220
+ # ─── Pattern 2: C struct table → Excel ───
221
+ # Existing C file with struct arrays — generate Excel for review/editing.
222
+ # - source: MotorParams.c # Existing C file with struct array
223
+ # target: MotorParams.xlsx # Excel generated from C (created if missing)
224
+ # direction: both # Edit either side, sync keeps them matched
225
+ # format: c_struct_table # Parser for #if/#elif struct arrays
226
+ # precision: 17
227
+
228
+ # ─── Pattern 3: Code → Spreadsheet (bootstrap) ───
229
+ # - source: params.csv # Will be created from your existing code
230
+ # target: legacy/params.h # Already exists
231
+ # direction: target_to_source # First sync creates the CSV from the .h
232
+
218
233
  # Optional:
219
234
  # prefix: "" # Prefix all constant names (e.g., "HW_")
220
235
  # uppercase_names: true # Force UPPER_CASE names in output
221
236
 
222
- # Add more mappings as needed:
223
- # - source: parameters.xlsx
224
- # target: src/params.v
225
- # direction: source_to_target
226
- # precision: 12
227
- # module_name: design_params
228
-
229
237
  # Global settings:
230
238
  # state_file: .consync.state.json # Track sync state (gitignore this)
231
239
  # watch_debounce: 2.0 # Seconds to wait before re-syncing
@@ -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.0"
7
+ version = "2.2.2"
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