consync 0.1.0__py3-none-any.whl
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/__init__.py +9 -0
- consync/backup.py +188 -0
- consync/cli.py +372 -0
- consync/config.py +200 -0
- consync/hooks.py +81 -0
- consync/lock.py +118 -0
- consync/logging_config.py +273 -0
- consync/models.py +104 -0
- consync/parsers/__init__.py +40 -0
- consync/parsers/c_header.py +96 -0
- consync/parsers/csv_parser.py +133 -0
- consync/parsers/json_parser.py +138 -0
- consync/parsers/toml_parser.py +74 -0
- consync/parsers/xlsx.py +116 -0
- consync/precision.py +148 -0
- consync/renderers/__init__.py +49 -0
- consync/renderers/c_header.py +222 -0
- consync/renderers/csharp.py +174 -0
- consync/renderers/csv_renderer.py +46 -0
- consync/renderers/json_renderer.py +71 -0
- consync/renderers/python_const.py +84 -0
- consync/renderers/rust_const.py +90 -0
- consync/renderers/verilog.py +89 -0
- consync/renderers/vhdl.py +94 -0
- consync/state.py +76 -0
- consync/sync.py +458 -0
- consync/validators.py +233 -0
- consync/watcher.py +176 -0
- consync-0.1.0.dist-info/METADATA +590 -0
- consync-0.1.0.dist-info/RECORD +33 -0
- consync-0.1.0.dist-info/WHEEL +4 -0
- consync-0.1.0.dist-info/entry_points.txt +2 -0
- consync-0.1.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,590 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: consync
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Bidirectional sync between spreadsheets and source code constants — with full decimal precision.
|
|
5
|
+
Project-URL: Homepage, https://github.com/naveenkumarbaskaran/consync
|
|
6
|
+
Project-URL: Repository, https://github.com/naveenkumarbaskaran/consync
|
|
7
|
+
Project-URL: Issues, https://github.com/naveenkumarbaskaran/consync/issues
|
|
8
|
+
Author-email: Naveen Kumar Baskaran <naveenkb142@gmail.com>
|
|
9
|
+
License: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: bidirectional,c-header,code-generation,constants,embedded,excel,firmware,hardware,precision,sync,verilog,vhdl
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Intended Audience :: Science/Research
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)
|
|
21
|
+
Classifier: Topic :: Software Development :: Code Generators
|
|
22
|
+
Requires-Python: >=3.10
|
|
23
|
+
Requires-Dist: click>=8.0
|
|
24
|
+
Requires-Dist: openpyxl>=3.1
|
|
25
|
+
Requires-Dist: pyyaml>=6.0
|
|
26
|
+
Requires-Dist: watchdog>=4.0
|
|
27
|
+
Provides-Extra: dev
|
|
28
|
+
Requires-Dist: pytest-cov>=5.0; extra == 'dev'
|
|
29
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
30
|
+
Requires-Dist: ruff>=0.4; extra == 'dev'
|
|
31
|
+
Provides-Extra: toml
|
|
32
|
+
Requires-Dist: tomli-w>=1.0; extra == 'toml'
|
|
33
|
+
Requires-Dist: tomli>=2.0; (python_version < '3.11') and extra == 'toml'
|
|
34
|
+
Description-Content-Type: text/markdown
|
|
35
|
+
|
|
36
|
+
# consync
|
|
37
|
+
|
|
38
|
+
**Bidirectional constant synchronisation between spreadsheets and source code.**
|
|
39
|
+
|
|
40
|
+
Keep a single source of truth for hardware constants (resistor values, timing parameters, frequencies) and automatically generate type-safe declarations for C/C++, C#, Python, Rust, Verilog, and VHDL — or sync changes back from code to your spreadsheet.
|
|
41
|
+
|
|
42
|
+
<p align="center">
|
|
43
|
+
<img src="assets/demo.gif" alt="consync demo" width="720">
|
|
44
|
+
</p>
|
|
45
|
+
|
|
46
|
+
[](https://pypi.org/project/consync/)
|
|
47
|
+
[](https://github.com/naveenkumarbaskaran/consync/actions/workflows/ci.yml)
|
|
48
|
+
[](https://python.org)
|
|
49
|
+
[](LICENSE)
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Architecture
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
┌─────────────────────────────────────────────────────────────────────────┐
|
|
57
|
+
│ .consync.yaml │
|
|
58
|
+
│ (mappings, precision, options) │
|
|
59
|
+
└────────────────────────────────┬────────────────────────────────────────┘
|
|
60
|
+
│
|
|
61
|
+
┌────────────▼────────────┐
|
|
62
|
+
│ Config Loader │
|
|
63
|
+
│ (auto-detect formats) │
|
|
64
|
+
└────────────┬────────────┘
|
|
65
|
+
│
|
|
66
|
+
┌──────────────────┼──────────────────┐
|
|
67
|
+
│ │ │
|
|
68
|
+
┌────────▼───────┐ ┌──────▼──────┐ ┌────────▼───────┐
|
|
69
|
+
│ Parsers │ │ State │ │ Renderers │
|
|
70
|
+
│ │ │ Tracker │ │ │
|
|
71
|
+
│ • xlsx │ │ │ │ • c_header │
|
|
72
|
+
│ • csv │ │ MD5 hashes │ │ • csharp │
|
|
73
|
+
│ • json │ │ per-mapping │ │ • python │
|
|
74
|
+
│ • toml │ │ in .json │ │ • rust │
|
|
75
|
+
│ • c_header │ │ │ │ • verilog │
|
|
76
|
+
└────────┬────────┘ └──────┬──────┘ │ • vhdl │
|
|
77
|
+
│ │ │ • json │
|
|
78
|
+
│ │ │ • csv │
|
|
79
|
+
│ │ └────────┬────────┘
|
|
80
|
+
└──────────────────┼───────────────────┘
|
|
81
|
+
│
|
|
82
|
+
┌────────────▼────────────┐
|
|
83
|
+
│ Sync Engine │
|
|
84
|
+
│ │
|
|
85
|
+
│ 1. Parse source & target │
|
|
86
|
+
│ 2. Compare hashes │
|
|
87
|
+
│ 3. Detect direction │
|
|
88
|
+
│ 4. Render to changed │
|
|
89
|
+
│ side's format │
|
|
90
|
+
│ 5. Update state hashes │
|
|
91
|
+
└────────────┬────────────┘
|
|
92
|
+
│
|
|
93
|
+
┌──────────────────┼──────────────────┐
|
|
94
|
+
│ │ │
|
|
95
|
+
┌────────▼───────┐ ┌──────▼──────┐ ┌────────▼───────┐
|
|
96
|
+
│ CLI (click) │ │ Watcher │ │ Git Hooks │
|
|
97
|
+
│ │ │ (watchdog) │ │ (pre-commit) │
|
|
98
|
+
│ sync/check/ │ │ debounced │ │ consync check │
|
|
99
|
+
│ watch/init/ │ │ auto-sync │ │ exit 1 = block │
|
|
100
|
+
│ status │ │ │ │ │
|
|
101
|
+
└─────────────────┘ └─────────────┘ └────────────────┘
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Data Flow
|
|
105
|
+
|
|
106
|
+
```
|
|
107
|
+
Source file ──parse──► list[Constant] ──render──► Target file
|
|
108
|
+
.xlsx name: str .h
|
|
109
|
+
.csv value: int|float .cs
|
|
110
|
+
.json unit: str .py
|
|
111
|
+
.toml description: str .rs
|
|
112
|
+
.h .v / .vhd
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
**Every format is both a parser and/or a renderer.** This means:
|
|
116
|
+
- **Bootstrap from code**: Have a `.h` file but no spreadsheet? Set `direction: target_to_source` and consync will *create* the CSV/JSON for you.
|
|
117
|
+
- **Multiple targets from one source**: One `.xlsx` can generate `.h` + `.py` + `.v` simultaneously.
|
|
118
|
+
- **Multiple sources**: Track as many source↔target pairs as needed in one config.
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## Why consync?
|
|
123
|
+
|
|
124
|
+
In hardware/firmware projects, constants live in Excel spreadsheets (for EE review) **and** in source code (for compilation). Manual copy-paste introduces:
|
|
125
|
+
|
|
126
|
+
- **Precision loss** — Excel shows 6 digits, your code needs 17 for IEEE 754 fidelity
|
|
127
|
+
- **Drift** — spreadsheet updated, code forgotten (or vice versa)
|
|
128
|
+
- **Format friction** — same value needs different syntax in C, Verilog, Python, VHDL
|
|
129
|
+
|
|
130
|
+
consync eliminates all three: one command syncs constants with full precision in both directions.
|
|
131
|
+
|
|
132
|
+
## Quick Start
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
pip install consync
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### 1. Initialise
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
cd your-project/
|
|
142
|
+
consync init
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Creates `.consync.yaml`:
|
|
146
|
+
|
|
147
|
+
```yaml
|
|
148
|
+
mappings:
|
|
149
|
+
- source: constants.xlsx
|
|
150
|
+
target: constants.h
|
|
151
|
+
direction: both
|
|
152
|
+
precision: 17
|
|
153
|
+
header_guard: HW_CONSTANTS_H
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### 2. Sync
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
consync sync
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Reads `constants.xlsx`, generates `constants.h`:
|
|
163
|
+
|
|
164
|
+
```c
|
|
165
|
+
#ifndef HW_CONSTANTS_H
|
|
166
|
+
#define HW_CONSTANTS_H
|
|
167
|
+
|
|
168
|
+
const double R_SENSE = 1.9999999999910001; /* Ohm | Current sense resistor */
|
|
169
|
+
const double R_PULLUP = 4706; /* Ohm | I2C pull-up resistor */
|
|
170
|
+
const double C_FILTER = 4.783294e-07; /* F | Input filter capacitor */
|
|
171
|
+
const double FREQ_SWITCH = 299872.93847293; /* Hz | Switching frequency */
|
|
172
|
+
|
|
173
|
+
#endif /* HW_CONSTANTS_H */
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### 3. Watch (continuous)
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
consync watch
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Auto-syncs on file change. Edit the spreadsheet → code updates. Edit the code → spreadsheet updates.
|
|
183
|
+
|
|
184
|
+
### 4. CI gate
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
consync check
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
Returns exit code 1 if code and spreadsheet are out of sync. Add to pre-commit hooks:
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
consync install-hook
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## Supported Formats
|
|
197
|
+
|
|
198
|
+
### Sources (input)
|
|
199
|
+
|
|
200
|
+
| Format | Extension | Notes |
|
|
201
|
+
|--------|-----------|-------|
|
|
202
|
+
| Excel | `.xlsx` | Auto-detects column headers |
|
|
203
|
+
| CSV | `.csv`, `.tsv` | Auto-detects delimiter |
|
|
204
|
+
| JSON | `.json` | Flat, array, or nested |
|
|
205
|
+
| TOML | `.toml` | Flat or table-with-metadata |
|
|
206
|
+
| C Header | `.h` | Parses `const`, `#define`, hex/int/float |
|
|
207
|
+
|
|
208
|
+
### Targets (output)
|
|
209
|
+
|
|
210
|
+
| Format | Extension | Features |
|
|
211
|
+
|--------|-----------|----------|
|
|
212
|
+
| C Header | `.h` | `const` or `#define`, `static`, `stdint.h` types, hex |
|
|
213
|
+
| C# | `.cs` | `namespace`, `public static class`, XML doc comments |
|
|
214
|
+
| Python | `.py` | Type annotations (`float`/`int`), inline comments |
|
|
215
|
+
| Rust | `.rs` | `pub const`, `f64`/`i64`, doc comments |
|
|
216
|
+
| Verilog | `.v` | `parameter real`, optional module wrapper |
|
|
217
|
+
| VHDL | `.vhd` | Package with `ieee.math_real`, typed constants |
|
|
218
|
+
| JSON | `.json` | Structured with `_meta` header |
|
|
219
|
+
| CSV | `.csv` | Round-trip back to spreadsheet |
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
## Bootstrap from Existing Code
|
|
224
|
+
|
|
225
|
+
**Don't have a spreadsheet yet?** consync can create one from your existing source files.
|
|
226
|
+
|
|
227
|
+
If you already have a C header with constants and want to start tracking it:
|
|
228
|
+
|
|
229
|
+
```yaml
|
|
230
|
+
# .consync.yaml
|
|
231
|
+
mappings:
|
|
232
|
+
- source: params.csv # doesn't exist yet — will be created
|
|
233
|
+
target: existing_params.h # already exists with const declarations
|
|
234
|
+
direction: target_to_source
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
```bash
|
|
238
|
+
consync sync
|
|
239
|
+
# ✅ params.csv ↔ existing_params.h: 12 constants synced (target → source)
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
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.
|
|
243
|
+
|
|
244
|
+
**Works with any parseable target:** `.h`, `.json`, `.csv`, `.toml` — anything consync has a parser for can bootstrap a new source.
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
## Multiple Mappings (One Source → Many Targets)
|
|
249
|
+
|
|
250
|
+
Track as many source↔target pairs as you need. Each mapping is independent — different directions, precision, and output options:
|
|
251
|
+
|
|
252
|
+
```yaml
|
|
253
|
+
# .consync.yaml
|
|
254
|
+
mappings:
|
|
255
|
+
# EE team's spreadsheet → firmware header
|
|
256
|
+
- source: params.xlsx
|
|
257
|
+
target: firmware/params.h
|
|
258
|
+
direction: source_to_target
|
|
259
|
+
precision: 17
|
|
260
|
+
output_style: const
|
|
261
|
+
typed_ints: true
|
|
262
|
+
|
|
263
|
+
# Same spreadsheet → Python simulation
|
|
264
|
+
- source: params.xlsx
|
|
265
|
+
target: sim/params.py
|
|
266
|
+
direction: source_to_target
|
|
267
|
+
precision: 10
|
|
268
|
+
|
|
269
|
+
# Same spreadsheet → FPGA constraints
|
|
270
|
+
- source: params.xlsx
|
|
271
|
+
target: rtl/params.v
|
|
272
|
+
direction: source_to_target
|
|
273
|
+
module_name: hw_params
|
|
274
|
+
|
|
275
|
+
# Different spreadsheet → C# test harness
|
|
276
|
+
- source: test_vectors.csv
|
|
277
|
+
target: tests/TestConstants.cs
|
|
278
|
+
direction: source_to_target
|
|
279
|
+
namespace: ECU.Tests
|
|
280
|
+
class_name: BrakeParams
|
|
281
|
+
|
|
282
|
+
# Legacy header → bootstrap a TOML config from it
|
|
283
|
+
- source: legacy_config.toml
|
|
284
|
+
target: legacy/old_module.h
|
|
285
|
+
direction: target_to_source
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
`consync sync` processes **all** mappings in one pass. `consync check` verifies them all.
|
|
289
|
+
|
|
290
|
+
---
|
|
291
|
+
|
|
292
|
+
## Embedded / ECU Configuration
|
|
293
|
+
|
|
294
|
+
consync is built for embedded firmware engineers. The C header renderer supports:
|
|
295
|
+
|
|
296
|
+
### Output Styles
|
|
297
|
+
|
|
298
|
+
```yaml
|
|
299
|
+
output_style: const # default: const double X = 1.5;
|
|
300
|
+
output_style: define # preprocessor: #define X 1.5
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
**`const` output (default):**
|
|
304
|
+
```c
|
|
305
|
+
#include <stdint.h>
|
|
306
|
+
|
|
307
|
+
static const uint16_t BRAKE_PRESSURE_MAX = 250;
|
|
308
|
+
static const double BRAKE_GAIN = 1.45;
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
**`#define` output:**
|
|
312
|
+
```c
|
|
313
|
+
#define BRAKE_PRESSURE_MAX 250
|
|
314
|
+
#define BRAKE_GAIN 1.45
|
|
315
|
+
#define HW_VERSION 0x0A03
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
### Static Const
|
|
319
|
+
|
|
320
|
+
```yaml
|
|
321
|
+
static_const: true # adds 'static' keyword (internal linkage, header-safe)
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
### Typed Integers (stdint.h)
|
|
325
|
+
|
|
326
|
+
```yaml
|
|
327
|
+
typed_ints: true # auto-selects smallest stdint type that fits
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
| Value Range | Generated Type |
|
|
331
|
+
|-------------|---------------|
|
|
332
|
+
| 0–255 | `uint8_t` |
|
|
333
|
+
| 0–65535 | `uint16_t` |
|
|
334
|
+
| 0–4294967295 | `uint32_t` |
|
|
335
|
+
| 0+ (larger) | `uint64_t` |
|
|
336
|
+
| -128–127 | `int8_t` |
|
|
337
|
+
| -32768–32767 | `int16_t` |
|
|
338
|
+
| -2147483648–2147483647 | `int32_t` |
|
|
339
|
+
| (larger signed) | `int64_t` |
|
|
340
|
+
|
|
341
|
+
Hex values are preserved: `0xFF03` stays `0xFF03` in output.
|
|
342
|
+
|
|
343
|
+
### Full Embedded Example
|
|
344
|
+
|
|
345
|
+
```yaml
|
|
346
|
+
mappings:
|
|
347
|
+
- source: ecu_params.csv
|
|
348
|
+
target: src/ecu_params.h
|
|
349
|
+
direction: source_to_target
|
|
350
|
+
precision: 17
|
|
351
|
+
header_guard: ECU_PARAMS_H
|
|
352
|
+
output_style: const
|
|
353
|
+
static_const: true
|
|
354
|
+
typed_ints: true
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
Generates:
|
|
358
|
+
```c
|
|
359
|
+
#ifndef ECU_PARAMS_H
|
|
360
|
+
#define ECU_PARAMS_H
|
|
361
|
+
|
|
362
|
+
#include <stdint.h>
|
|
363
|
+
|
|
364
|
+
static const uint8_t BRAKE_PRESSURE_MAX = 250; /* bar | Max hydraulic pressure */
|
|
365
|
+
static const uint16_t CAN_MSG_ID = 0x1A3; /* – | Brake status CAN ID */
|
|
366
|
+
static const double FILTER_CUTOFF = 1200.5; /* Hz | Low-pass filter cutoff */
|
|
367
|
+
static const int16_t TEMP_OFFSET = -40; /* °C | Temperature sensor offset */
|
|
368
|
+
|
|
369
|
+
#endif /* ECU_PARAMS_H */
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
---
|
|
373
|
+
|
|
374
|
+
## Precision Guarantee
|
|
375
|
+
|
|
376
|
+
consync uses **17 significant digits** by default — the minimum needed for IEEE 754 double-precision round-trip fidelity:
|
|
377
|
+
|
|
378
|
+
```
|
|
379
|
+
Excel value: 1.9999999999910001
|
|
380
|
+
C output: 1.9999999999910001
|
|
381
|
+
Parse back: 1.9999999999910001 ← identical bits
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
Configure per mapping:
|
|
385
|
+
```yaml
|
|
386
|
+
precision: 6 # fewer digits for display-only targets
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
---
|
|
390
|
+
|
|
391
|
+
## Bidirectional Sync
|
|
392
|
+
|
|
393
|
+
consync tracks file hashes in `.consync.state.json` to detect which side changed:
|
|
394
|
+
|
|
395
|
+
| Source changed | Target changed | Action |
|
|
396
|
+
|:-:|:-:|---|
|
|
397
|
+
| ✓ | — | Source → Target |
|
|
398
|
+
| — | ✓ | Target → Source |
|
|
399
|
+
| ✓ | ✓ | Conflict (configurable: `source_wins`, `target_wins`, `fail`) |
|
|
400
|
+
| — | — | No-op |
|
|
401
|
+
|
|
402
|
+
---
|
|
403
|
+
|
|
404
|
+
## Configuration Reference
|
|
405
|
+
|
|
406
|
+
```yaml
|
|
407
|
+
# .consync.yaml
|
|
408
|
+
mappings:
|
|
409
|
+
- source: constants.xlsx # source file path (xlsx/csv/json/toml/h)
|
|
410
|
+
target: hw_constants.h # target file path (h/cs/py/rs/v/vhd/json/csv)
|
|
411
|
+
direction: both # source_to_target | target_to_source | both
|
|
412
|
+
precision: 17 # significant digits (1-17, default: 17)
|
|
413
|
+
|
|
414
|
+
# ─── C Header options ───
|
|
415
|
+
header_guard: HW_CONSTANTS_H # #ifndef guard name
|
|
416
|
+
output_style: const # const (default) | define
|
|
417
|
+
static_const: true # adds 'static' keyword (default: false)
|
|
418
|
+
typed_ints: true # use stdint.h types (default: false)
|
|
419
|
+
|
|
420
|
+
# ─── C# options ───
|
|
421
|
+
namespace: MyCompany.Firmware # C# namespace
|
|
422
|
+
class_name: EcuConstants # C# class name (default: Constants)
|
|
423
|
+
|
|
424
|
+
# ─── Verilog/VHDL options ───
|
|
425
|
+
module_name: design_params # Verilog module / VHDL package name
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
---
|
|
429
|
+
|
|
430
|
+
## Safety & Recovery
|
|
431
|
+
|
|
432
|
+
consync is designed for safety-critical embedded systems. Every sync is protected by:
|
|
433
|
+
|
|
434
|
+
### Automatic Backups
|
|
435
|
+
|
|
436
|
+
Before every write, the previous version is saved to `.consync/backups/`:
|
|
437
|
+
|
|
438
|
+
```
|
|
439
|
+
.consync/backups/
|
|
440
|
+
├── config.h.20260505_083012.bak
|
|
441
|
+
├── config.h.20260505_091045.bak
|
|
442
|
+
└── params.v.20260505_083012.bak
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
Retention: keeps last 20 backups per file (auto-trimmed).
|
|
446
|
+
|
|
447
|
+
### Recovery
|
|
448
|
+
|
|
449
|
+
Restore any file to a previous state:
|
|
450
|
+
|
|
451
|
+
```bash
|
|
452
|
+
# List all available snapshots
|
|
453
|
+
consync recover --list
|
|
454
|
+
|
|
455
|
+
# List snapshots for a specific file
|
|
456
|
+
consync recover --file config.h --list
|
|
457
|
+
|
|
458
|
+
# Restore most recent backup
|
|
459
|
+
consync recover --file config.h --last
|
|
460
|
+
|
|
461
|
+
# Restore to a specific timestamp
|
|
462
|
+
consync recover --file config.h --at 2026-05-05T08:30:12
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
Recovery creates a safety backup of the *current* state before restoring, so you can always undo an undo.
|
|
466
|
+
|
|
467
|
+
### Diff Preview
|
|
468
|
+
|
|
469
|
+
See exactly what would change before committing:
|
|
470
|
+
|
|
471
|
+
```bash
|
|
472
|
+
consync diff
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
Shows a colorized unified diff for each mapping that would be modified. Pair with `--from source` or `--from target` to preview forced-direction syncs.
|
|
476
|
+
|
|
477
|
+
### Validation Hooks
|
|
478
|
+
|
|
479
|
+
Define value constraints in `.consync.yaml` to reject out-of-range values **before** they reach your firmware:
|
|
480
|
+
|
|
481
|
+
```yaml
|
|
482
|
+
mappings:
|
|
483
|
+
- source: calibration.xlsx
|
|
484
|
+
target: brake_params.h
|
|
485
|
+
direction: source_to_target
|
|
486
|
+
validators:
|
|
487
|
+
BRAKE_MAX_PRESSURE:
|
|
488
|
+
min: 0
|
|
489
|
+
max: 300
|
|
490
|
+
TIMEOUT_MS:
|
|
491
|
+
type: int
|
|
492
|
+
min: 100
|
|
493
|
+
max: 60000
|
|
494
|
+
DEVICE_NAME:
|
|
495
|
+
pattern: "^[A-Z]{3}-\\d{4}$"
|
|
496
|
+
LOOKUP_TABLE:
|
|
497
|
+
min_length: 4
|
|
498
|
+
max_length: 256
|
|
499
|
+
min: 0
|
|
500
|
+
max: 1023
|
|
501
|
+
```
|
|
502
|
+
|
|
503
|
+
Supported validator rules:
|
|
504
|
+
|
|
505
|
+
| Rule | Applies to | Description |
|
|
506
|
+
|------|-----------|-------------|
|
|
507
|
+
| `min` / `max` | int, float, array elements | Numeric range (inclusive) |
|
|
508
|
+
| `type` | all | Expected type: `int`, `float`, `string` |
|
|
509
|
+
| `pattern` | string | Regex pattern (Python `re.match`) |
|
|
510
|
+
| `min_length` / `max_length` | arrays, strings | Length bounds |
|
|
511
|
+
| `not_empty` | all | Reject `""` or `[]` |
|
|
512
|
+
|
|
513
|
+
If validation fails, sync is **blocked** and the error is reported:
|
|
514
|
+
|
|
515
|
+
```
|
|
516
|
+
❌ calibration.xlsx ↔ brake_params.h: Validation failed: BRAKE_MAX_PRESSURE = 999 exceeds maximum 300
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
### Concurrency Lock
|
|
520
|
+
|
|
521
|
+
An advisory lock (`.consync.lock`) prevents concurrent writes:
|
|
522
|
+
- Detects stale locks from crashed processes (PID check + timeout)
|
|
523
|
+
- Auto-reclaims dead locks
|
|
524
|
+
- Prevents file corruption from parallel `consync sync` + `consync watch`
|
|
525
|
+
|
|
526
|
+
### Audit Log
|
|
527
|
+
|
|
528
|
+
Every sync is logged with full values to `.consync.audit.jsonl`:
|
|
529
|
+
|
|
530
|
+
```bash
|
|
531
|
+
# Show recent syncs with values
|
|
532
|
+
consync log
|
|
533
|
+
|
|
534
|
+
# Show last 5 entries as raw JSON
|
|
535
|
+
consync log -n 5 --json
|
|
536
|
+
```
|
|
537
|
+
|
|
538
|
+
Each entry records: timestamp, user, direction, files, all constant names+values — enabling full traceability for ISO 26262 / IEC 61508 compliance workflows.
|
|
539
|
+
|
|
540
|
+
---
|
|
541
|
+
|
|
542
|
+
## CLI Reference
|
|
543
|
+
|
|
544
|
+
| Command | Description |
|
|
545
|
+
|---------|-------------|
|
|
546
|
+
| `consync init` | Create `.consync.yaml` in current directory |
|
|
547
|
+
| `consync sync` | Sync all mappings |
|
|
548
|
+
| `consync sync --dry-run` | Preview changes without writing |
|
|
549
|
+
| `consync sync --from source` | Force source → target regardless of state |
|
|
550
|
+
| `consync sync --from target` | Force target → source (bootstrap) |
|
|
551
|
+
| `consync check` | Verify sync (exit 1 if out of sync) |
|
|
552
|
+
| `consync watch` | Watch files and auto-sync on change |
|
|
553
|
+
| `consync diff` | Show unified diff of what would change |
|
|
554
|
+
| `consync recover --list` | List available snapshots |
|
|
555
|
+
| `consync recover --file X --last` | Restore most recent backup |
|
|
556
|
+
| `consync log` | Show audit log with values |
|
|
557
|
+
| `consync install-hook` | Install git pre-commit hook |
|
|
558
|
+
| `consync status` | Show current sync state |
|
|
559
|
+
| `-v` / `--verbose` | Show INFO-level details |
|
|
560
|
+
| `--debug` | Show DEBUG-level details |
|
|
561
|
+
|
|
562
|
+
---
|
|
563
|
+
|
|
564
|
+
## Target Audiences
|
|
565
|
+
|
|
566
|
+
| Domain | Source | Targets | Key Features |
|
|
567
|
+
|--------|--------|---------|--------------|
|
|
568
|
+
| **Embedded/ECU firmware** | Excel/CSV from EE team | C headers | `typed_ints`, `static_const`, `#define` |
|
|
569
|
+
| **FPGA/ASIC design** | Excel from systems team | Verilog + VHDL | `module_name`, `parameter real` |
|
|
570
|
+
| **Automotive (AUTOSAR)** | CSV with calibration data | C headers | Hex preservation, stdint.h |
|
|
571
|
+
| **.NET test harnesses** | CSV/JSON | C# classes | `namespace`, `class_name`, XML docs |
|
|
572
|
+
| **Control systems** | Excel with tuning params | Python + C | Full precision, bidirectional |
|
|
573
|
+
| **Multi-language libs** | JSON master | C + Python + Rust | One source, many targets |
|
|
574
|
+
|
|
575
|
+
---
|
|
576
|
+
|
|
577
|
+
## Development
|
|
578
|
+
|
|
579
|
+
```bash
|
|
580
|
+
git clone https://github.com/naveenkumarbaskaran/consync.git
|
|
581
|
+
cd consync
|
|
582
|
+
pip install -e ".[dev]"
|
|
583
|
+
pytest # 151 tests
|
|
584
|
+
```
|
|
585
|
+
|
|
586
|
+
---
|
|
587
|
+
|
|
588
|
+
## License
|
|
589
|
+
|
|
590
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
consync/__init__.py,sha256=jBxockseZOwiTIqCOHD8XTaW4NgdmdJYLP9KnC8YfyE,324
|
|
2
|
+
consync/backup.py,sha256=m6wGzXlMzD4B7EQRFdOlsIJVA4e-ZSnAzGlMpzu_bE8,6209
|
|
3
|
+
consync/cli.py,sha256=KJ1mv3lu45eGuEr2pZef4_3qasuznOAeG3EjLoUnKb4,13740
|
|
4
|
+
consync/config.py,sha256=uvUtxU2Oz00eVw_ao1uLrfrVrqZTzbWOeSX6WKyZptU,6561
|
|
5
|
+
consync/hooks.py,sha256=xL-RnkeZC47Dxy5cqKuZ4fYBxKc9Sj5j9ENQqe97r9k,2441
|
|
6
|
+
consync/lock.py,sha256=PQY99ucOjlJDzl32-w6fU_kT_k0mzKJcjbalphmM5JM,3802
|
|
7
|
+
consync/logging_config.py,sha256=foR_OcRIP6Wf4Wu2k7vJ99b57VlRODhIhb5SdgrCjXg,8892
|
|
8
|
+
consync/models.py,sha256=EwTgEIQLqfaqpeGca8oY5p3QfHjXJhQh7fU30HrKFDk,3446
|
|
9
|
+
consync/precision.py,sha256=lJjChgPuXdMfHMW5zkBjWUS8Tk2Lu2gDtb0WPcWgqBs,3958
|
|
10
|
+
consync/state.py,sha256=go2gibo4ft9QiCVnupyTSuVLUSynLDcdAl4PuKAWfyw,2381
|
|
11
|
+
consync/sync.py,sha256=O5frP6aL30yyo-T64ywB5uUiwLrhHEwDkjzNLJJpVOE,16375
|
|
12
|
+
consync/validators.py,sha256=8GQi6_qRVnzk47HthnQpzPlQHEerqkYAXOpTq21rq4g,7673
|
|
13
|
+
consync/watcher.py,sha256=JONwJ7w4EYwz1T46OV7P3V8-5unNsF_mLKDqaHA3L04,6614
|
|
14
|
+
consync/parsers/__init__.py,sha256=ROCEx1UHa9oFL8OJgMcsWpBnayphgg_uhVvoZibC4h4,1150
|
|
15
|
+
consync/parsers/c_header.py,sha256=ab17NuBSrda9tUMjq2nNDOPZ-Vhb87ZpUzJE6bSUQ7Q,2960
|
|
16
|
+
consync/parsers/csv_parser.py,sha256=ce6adRD9ieIi1QgZb3PoWD5pAtTuaL3UBWIzVeisAVA,3911
|
|
17
|
+
consync/parsers/json_parser.py,sha256=pQpdH0U2QvQ2vj6w27sjG2ifzUGeYZBvPfAUoUMDSgM,4117
|
|
18
|
+
consync/parsers/toml_parser.py,sha256=GOUPrBM3vqontXxpym2EZ4B-xYGNtuqE_Ad2L4mIYEs,2129
|
|
19
|
+
consync/parsers/xlsx.py,sha256=efXNqYFmawl5tQvk8cprDSADNqRJbki2-BQqoiF3H2Y,3485
|
|
20
|
+
consync/renderers/__init__.py,sha256=r5-N5eOecklbUoctzBAbhvSyeNZrHb32wsWojwkK_2Q,1244
|
|
21
|
+
consync/renderers/c_header.py,sha256=IRj-CKdewaBlxO6v1LgrKwUwVZg7iHSPVJaAaTKC530,7345
|
|
22
|
+
consync/renderers/csharp.py,sha256=5twWeTQBrzVq38ruDSW9mC5Wt7kn7nPEVJj7bKCe8Do,5278
|
|
23
|
+
consync/renderers/csv_renderer.py,sha256=EVP5_GypEhSmIkUwgOk41Yzc0YfQV59wdDRIugtt1DM,1699
|
|
24
|
+
consync/renderers/json_renderer.py,sha256=AHVJPAGIVgvMXZVZXSCb3hCnnt2Q2Wexj3IS9B-_vmg,1843
|
|
25
|
+
consync/renderers/python_const.py,sha256=u0lh0Ez4FEvDuQjhbPGOG86Z3asdWNO8XUXbzO1c3lM,2983
|
|
26
|
+
consync/renderers/rust_const.py,sha256=A8E2StgENQ2uGN82lPRKd_xfwYKl93-GE65-5LuNQOU,3209
|
|
27
|
+
consync/renderers/verilog.py,sha256=_u5X5pvr1qe_e2SyboGTPsYia4MhjeVxFnlV7OttpOA,2919
|
|
28
|
+
consync/renderers/vhdl.py,sha256=gf2YQwctE8rHddHd_vHQXBXbQAWQQN24jFwutVUGzBA,3058
|
|
29
|
+
consync-0.1.0.dist-info/METADATA,sha256=weuKJ2G8RzRaSN9j7L3w5z7fUeIe4XaY3koY6Zxwkgg,20198
|
|
30
|
+
consync-0.1.0.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
|
|
31
|
+
consync-0.1.0.dist-info/entry_points.txt,sha256=2MhLwDg0rAMvc25XYemTnEhJMa6PcSUFHg5kUs9yeaM,45
|
|
32
|
+
consync-0.1.0.dist-info/licenses/LICENSE,sha256=WMRZzthkxX0W8YTz3TR1ecBkTHzyxuOJq1HKfIvAFo4,1078
|
|
33
|
+
consync-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Naveen Kumar Baskaran
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|