consync 0.1.0__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-0.1.0/.github/CODEOWNERS +2 -0
- consync-0.1.0/.github/copilot-instructions.md +94 -0
- consync-0.1.0/.github/dependabot.yml +18 -0
- consync-0.1.0/.github/workflows/ci.yml +40 -0
- consync-0.1.0/.github/workflows/codeql.yml +40 -0
- consync-0.1.0/.github/workflows/publish.yml +32 -0
- consync-0.1.0/.gitignore +19 -0
- consync-0.1.0/CLAUDE.md +132 -0
- consync-0.1.0/CONTRIBUTING.md +89 -0
- consync-0.1.0/FAQ.md +280 -0
- consync-0.1.0/LICENSE +21 -0
- consync-0.1.0/PKG-INFO +590 -0
- consync-0.1.0/README.md +555 -0
- consync-0.1.0/SECURITY.md +41 -0
- consync-0.1.0/TODO.md +124 -0
- consync-0.1.0/assets/demo.gif +0 -0
- consync-0.1.0/assets/demo.tape +69 -0
- consync-0.1.0/consync/__init__.py +9 -0
- consync-0.1.0/consync/backup.py +188 -0
- consync-0.1.0/consync/cli.py +372 -0
- consync-0.1.0/consync/config.py +200 -0
- consync-0.1.0/consync/hooks.py +81 -0
- consync-0.1.0/consync/lock.py +118 -0
- consync-0.1.0/consync/logging_config.py +273 -0
- consync-0.1.0/consync/models.py +104 -0
- consync-0.1.0/consync/parsers/__init__.py +40 -0
- consync-0.1.0/consync/parsers/c_header.py +96 -0
- consync-0.1.0/consync/parsers/csv_parser.py +133 -0
- consync-0.1.0/consync/parsers/json_parser.py +138 -0
- consync-0.1.0/consync/parsers/toml_parser.py +74 -0
- consync-0.1.0/consync/parsers/xlsx.py +116 -0
- consync-0.1.0/consync/precision.py +148 -0
- consync-0.1.0/consync/renderers/__init__.py +49 -0
- consync-0.1.0/consync/renderers/c_header.py +222 -0
- consync-0.1.0/consync/renderers/csharp.py +174 -0
- consync-0.1.0/consync/renderers/csv_renderer.py +46 -0
- consync-0.1.0/consync/renderers/json_renderer.py +71 -0
- consync-0.1.0/consync/renderers/python_const.py +84 -0
- consync-0.1.0/consync/renderers/rust_const.py +90 -0
- consync-0.1.0/consync/renderers/verilog.py +89 -0
- consync-0.1.0/consync/renderers/vhdl.py +94 -0
- consync-0.1.0/consync/state.py +76 -0
- consync-0.1.0/consync/sync.py +458 -0
- consync-0.1.0/consync/validators.py +233 -0
- consync-0.1.0/consync/watcher.py +176 -0
- consync-0.1.0/examples/fpga/.consync.yaml +17 -0
- consync-0.1.0/examples/fpga/design_params.csv +11 -0
- consync-0.1.0/examples/hardware/.consync.yaml +11 -0
- consync-0.1.0/examples/hardware/constants.csv +8 -0
- consync-0.1.0/examples/multilang/.consync.yaml +21 -0
- consync-0.1.0/examples/multilang/constants.json +7 -0
- consync-0.1.0/pyproject.toml +54 -0
- consync-0.1.0/tests/__init__.py +0 -0
- consync-0.1.0/tests/test_arrays.py +469 -0
- consync-0.1.0/tests/test_cli.py +94 -0
- consync-0.1.0/tests/test_embedded.py +271 -0
- consync-0.1.0/tests/test_parsers.py +148 -0
- consync-0.1.0/tests/test_precision.py +129 -0
- consync-0.1.0/tests/test_renderers.py +210 -0
- consync-0.1.0/tests/test_safety.py +511 -0
- consync-0.1.0/tests/test_sync.py +152 -0
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# Copilot Instructions for consync
|
|
2
|
+
|
|
3
|
+
## What is consync?
|
|
4
|
+
|
|
5
|
+
A Python CLI that bidirectionally syncs constants between spreadsheets (xlsx/csv/json/toml)
|
|
6
|
+
and source code (C, C#, Python, Rust, Verilog, VHDL). Built for embedded/firmware engineers
|
|
7
|
+
who need full IEEE 754 precision (17 significant digits).
|
|
8
|
+
|
|
9
|
+
## Project Structure
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
consync/
|
|
13
|
+
├── cli.py # Click CLI — init, sync, check, watch, diff, recover, log, status
|
|
14
|
+
├── sync.py # Core engine — direction detection, backup, validate, render
|
|
15
|
+
├── config.py # .consync.yaml loader + format auto-detect
|
|
16
|
+
├── models.py # Constant, MappingConfig, ConsyncConfig dataclasses
|
|
17
|
+
├── state.py # SyncState (MD5 hashes for change detection)
|
|
18
|
+
├── watcher.py # File watcher — queues events, retries on lock, startup sync
|
|
19
|
+
├── hooks.py # Git pre-commit hook installer
|
|
20
|
+
├── backup.py # Timestamped snapshots + recovery
|
|
21
|
+
├── lock.py # Advisory .consync.lock with stale-PID detection
|
|
22
|
+
├── validators.py # Range/type/pattern/length checks
|
|
23
|
+
├── logging_config.py # 3-layer: console, rotating file, audit JSONL
|
|
24
|
+
├── parsers/ # xlsx, csv, json, toml, c_header
|
|
25
|
+
└── renderers/ # c_header, csharp, python, rust, verilog, vhdl, json, csv
|
|
26
|
+
tests/
|
|
27
|
+
├── test_parsers.py # Parser unit tests
|
|
28
|
+
├── test_renderers.py # Renderer unit tests
|
|
29
|
+
├── test_sync.py # Sync engine + state tests
|
|
30
|
+
├── test_arrays.py # Array constant support tests
|
|
31
|
+
├── test_safety.py # Backup, recover, validation, lock tests
|
|
32
|
+
└── ...
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Key Patterns
|
|
36
|
+
|
|
37
|
+
- **Universal model**: `Constant(name: str, value: int|float|str|list, unit: str, description: str)`
|
|
38
|
+
- **Every format is a parser AND/OR renderer** — enables bootstrap and round-trip
|
|
39
|
+
- **Safety-first for firmware**: backup before write, validate before render, lock during sync
|
|
40
|
+
- **Watcher queues events** — never drops changes, retries on lock conflict
|
|
41
|
+
- **Audit trail**: JSONL log with every constant value for traceability
|
|
42
|
+
|
|
43
|
+
## When Editing Code
|
|
44
|
+
|
|
45
|
+
1. **Adding a parser/renderer**: Register in `__init__.py` of the package + add to `EXTENSION_TO_FORMAT` in `config.py`
|
|
46
|
+
2. **Adding CLI command**: Use `@main.command()` in `cli.py`, lazy imports inside function
|
|
47
|
+
3. **Modifying sync behavior**: Ensure backup + validation + lock flow is preserved
|
|
48
|
+
4. **Running tests**: `pytest tests/ -v` (151+ tests, takes ~0.5s)
|
|
49
|
+
|
|
50
|
+
## Constraints
|
|
51
|
+
|
|
52
|
+
- Python >=3.10
|
|
53
|
+
- Minimal deps: openpyxl, click, watchdog, pyyaml
|
|
54
|
+
- Precision: 17 significant digits default (IEEE 754 round-trip fidelity)
|
|
55
|
+
- Never drop file changes in watcher (queue + coalesce)
|
|
56
|
+
- Lock must be held during all write operations
|
|
57
|
+
- Backup must exist before overwriting any file
|
|
58
|
+
|
|
59
|
+
## Config Example (.consync.yaml)
|
|
60
|
+
|
|
61
|
+
```yaml
|
|
62
|
+
mappings:
|
|
63
|
+
- source: calibration.xlsx
|
|
64
|
+
target: firmware/config.h
|
|
65
|
+
direction: source_to_target
|
|
66
|
+
precision: 17
|
|
67
|
+
header_guard: CONFIG_H
|
|
68
|
+
static_const: true
|
|
69
|
+
typed_ints: true
|
|
70
|
+
validators:
|
|
71
|
+
BRAKE_PRESSURE:
|
|
72
|
+
min: 0
|
|
73
|
+
max: 300
|
|
74
|
+
TIMEOUT_MS:
|
|
75
|
+
type: int
|
|
76
|
+
min: 100
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## CLI Command Reference
|
|
80
|
+
|
|
81
|
+
| Command | Purpose |
|
|
82
|
+
|---------|---------|
|
|
83
|
+
| `consync init` | Create .consync.yaml template |
|
|
84
|
+
| `consync sync` | Sync all mappings |
|
|
85
|
+
| `consync sync --dry-run` | Show what would be synced |
|
|
86
|
+
| `consync sync --from source` | Force direction |
|
|
87
|
+
| `consync check` | CI gate — exit 1 if out of sync |
|
|
88
|
+
| `consync watch` | File watcher with auto-sync |
|
|
89
|
+
| `consync diff` | Unified diff preview |
|
|
90
|
+
| `consync recover --list` | List backup snapshots |
|
|
91
|
+
| `consync recover --file X --last` | Restore most recent backup |
|
|
92
|
+
| `consync log` | Show audit trail with values |
|
|
93
|
+
| `consync install-hook` | Install git pre-commit hook |
|
|
94
|
+
| `consync status` | Show sync state per mapping |
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
- package-ecosystem: "pip"
|
|
4
|
+
directory: "/"
|
|
5
|
+
schedule:
|
|
6
|
+
interval: "monthly"
|
|
7
|
+
groups:
|
|
8
|
+
all:
|
|
9
|
+
patterns:
|
|
10
|
+
- "*"
|
|
11
|
+
- package-ecosystem: "github-actions"
|
|
12
|
+
directory: "/"
|
|
13
|
+
schedule:
|
|
14
|
+
interval: "monthly"
|
|
15
|
+
groups:
|
|
16
|
+
github-actions:
|
|
17
|
+
patterns:
|
|
18
|
+
- "*"
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
strategy:
|
|
13
|
+
matrix:
|
|
14
|
+
python-version: ["3.10", "3.11", "3.12", "3.13"]
|
|
15
|
+
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
|
+
|
|
19
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
20
|
+
uses: actions/setup-python@v5
|
|
21
|
+
with:
|
|
22
|
+
python-version: ${{ matrix.python-version }}
|
|
23
|
+
|
|
24
|
+
- name: Install dependencies
|
|
25
|
+
run: |
|
|
26
|
+
python -m pip install --upgrade pip
|
|
27
|
+
pip install -e ".[dev]"
|
|
28
|
+
|
|
29
|
+
- name: Lint with ruff
|
|
30
|
+
run: ruff check consync/ tests/
|
|
31
|
+
|
|
32
|
+
- name: Run tests
|
|
33
|
+
run: pytest --cov=consync --cov-report=xml -v
|
|
34
|
+
|
|
35
|
+
- name: Upload coverage
|
|
36
|
+
if: matrix.python-version == '3.12'
|
|
37
|
+
uses: codecov/codecov-action@v4
|
|
38
|
+
with:
|
|
39
|
+
file: ./coverage.xml
|
|
40
|
+
continue-on-error: true
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
name: "CodeQL"
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
schedule:
|
|
9
|
+
- cron: "0 6 * * 1" # Every Monday at 06:00 UTC
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
analyze:
|
|
13
|
+
name: Analyze
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
permissions:
|
|
16
|
+
actions: read
|
|
17
|
+
contents: read
|
|
18
|
+
security-events: write
|
|
19
|
+
|
|
20
|
+
strategy:
|
|
21
|
+
fail-fast: false
|
|
22
|
+
matrix:
|
|
23
|
+
language: [python]
|
|
24
|
+
|
|
25
|
+
steps:
|
|
26
|
+
- name: Checkout repository
|
|
27
|
+
uses: actions/checkout@v4
|
|
28
|
+
|
|
29
|
+
- name: Initialize CodeQL
|
|
30
|
+
uses: github/codeql-action/init@v3
|
|
31
|
+
with:
|
|
32
|
+
languages: ${{ matrix.language }}
|
|
33
|
+
|
|
34
|
+
- name: Autobuild
|
|
35
|
+
uses: github/codeql-action/autobuild@v3
|
|
36
|
+
|
|
37
|
+
- name: Perform CodeQL Analysis
|
|
38
|
+
uses: github/codeql-action/analyze@v3
|
|
39
|
+
with:
|
|
40
|
+
category: "/language:${{ matrix.language }}"
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
publish:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
environment: pypi
|
|
14
|
+
permissions:
|
|
15
|
+
id-token: write # Required for trusted publishing
|
|
16
|
+
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v4
|
|
19
|
+
|
|
20
|
+
- name: Set up Python
|
|
21
|
+
uses: actions/setup-python@v5
|
|
22
|
+
with:
|
|
23
|
+
python-version: "3.12"
|
|
24
|
+
|
|
25
|
+
- name: Install build tools
|
|
26
|
+
run: pip install build
|
|
27
|
+
|
|
28
|
+
- name: Build package
|
|
29
|
+
run: python -m build
|
|
30
|
+
|
|
31
|
+
- name: Publish to PyPI
|
|
32
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
consync-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
.venv/
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.pyc
|
|
4
|
+
*.egg-info/
|
|
5
|
+
dist/
|
|
6
|
+
build/
|
|
7
|
+
.coverage
|
|
8
|
+
.sync_state.json
|
|
9
|
+
*.xlsx
|
|
10
|
+
!examples/**/*.xlsx
|
|
11
|
+
.consync.state.json
|
|
12
|
+
|
|
13
|
+
# consync runtime files
|
|
14
|
+
.consync.log
|
|
15
|
+
.consync.log.*
|
|
16
|
+
.consync.audit.jsonl
|
|
17
|
+
.consync.state.json
|
|
18
|
+
.consync.lock
|
|
19
|
+
.consync/
|
consync-0.1.0/CLAUDE.md
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# consync — AI Assistant Instructions (CLAUDE.md)
|
|
2
|
+
|
|
3
|
+
## Project Overview
|
|
4
|
+
|
|
5
|
+
**consync** is a pip-installable Python CLI for bidirectional synchronisation between
|
|
6
|
+
spreadsheets (xlsx/csv/json/toml) and source code constant declarations (C, C#, Python,
|
|
7
|
+
Rust, Verilog, VHDL). It preserves full IEEE 754 precision (17 significant digits) and
|
|
8
|
+
supports embedded/firmware workflows.
|
|
9
|
+
|
|
10
|
+
**Repo:** https://github.com/naveenkumarbaskaran/consync
|
|
11
|
+
**Author:** Naveen Kumar Baskaran (naveenkb142@gmail.com)
|
|
12
|
+
**Python:** >=3.10
|
|
13
|
+
**Build:** hatchling
|
|
14
|
+
**CLI:** Click
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Architecture
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
.consync.yaml → Config Loader → Sync Engine → State Tracker (.consync.state.json)
|
|
22
|
+
↓ ↓
|
|
23
|
+
┌──────────────┐ ┌──────────────┐
|
|
24
|
+
│ Parsers │ │ Renderers │
|
|
25
|
+
│ xlsx csv json│ │ c_header csv │
|
|
26
|
+
│ toml c_header│ │ csharp python│
|
|
27
|
+
└──────────────┘ │ rust verilog │
|
|
28
|
+
│ vhdl json │
|
|
29
|
+
└──────────────┘
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
**Key design:** Every format can be both parser AND renderer. This enables bootstrap
|
|
33
|
+
(create spreadsheet from existing code) and round-trip (code → spreadsheet → code).
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Module Map
|
|
38
|
+
|
|
39
|
+
| File | Purpose |
|
|
40
|
+
|------|---------|
|
|
41
|
+
| `consync/cli.py` | Click CLI entry point — all commands |
|
|
42
|
+
| `consync/sync.py` | Core sync engine — direction detection, orchestration |
|
|
43
|
+
| `consync/config.py` | YAML config loader, format auto-detection |
|
|
44
|
+
| `consync/models.py` | `Constant`, `MappingConfig`, `ConsyncConfig` dataclasses |
|
|
45
|
+
| `consync/state.py` | `SyncState` — MD5 hashes per-mapping for change detection |
|
|
46
|
+
| `consync/watcher.py` | File watcher with debounce, queue, lock-retry |
|
|
47
|
+
| `consync/hooks.py` | Git hook installer |
|
|
48
|
+
| `consync/backup.py` | Auto-snapshot before every write + recovery |
|
|
49
|
+
| `consync/lock.py` | Advisory `.consync.lock` with stale-PID detection |
|
|
50
|
+
| `consync/validators.py` | User-defined value constraints (range/type/pattern) |
|
|
51
|
+
| `consync/logging_config.py` | 3-layer logging (console, file, audit JSONL) |
|
|
52
|
+
| `consync/parsers/` | One module per input format |
|
|
53
|
+
| `consync/renderers/` | One module per output format |
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## Conventions
|
|
58
|
+
|
|
59
|
+
- **Dataclass-centric**: All data flows through `Constant(name, value, unit, description, metadata)`
|
|
60
|
+
- **No global state**: Config/state passed explicitly; watcher is the only stateful entry point
|
|
61
|
+
- **Format string IDs**: `"xlsx"`, `"csv"`, `"c_header"`, `"csharp"`, `"python"`, `"rust"`, `"verilog"`, `"vhdl"`, `"json"`, `"toml"`
|
|
62
|
+
- **Tests**: pytest, grouped by feature in `tests/`. Run with `pytest tests/ -v`
|
|
63
|
+
- **Logging**: Use `logger = logging.getLogger(__name__)` in every module. Audit via `write_audit_entry()`
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Adding a New Parser
|
|
68
|
+
|
|
69
|
+
1. Create `consync/parsers/my_format.py` with function `parse(filepath: Path) -> list[Constant]`
|
|
70
|
+
2. Register in `consync/parsers/__init__.py` → `PARSERS` dict
|
|
71
|
+
3. Add extension mapping in `consync/config.py` → `EXTENSION_TO_FORMAT`
|
|
72
|
+
4. Add tests in `tests/test_parsers.py`
|
|
73
|
+
|
|
74
|
+
## Adding a New Renderer
|
|
75
|
+
|
|
76
|
+
1. Create `consync/renderers/my_format.py` with function `render(constants: list[Constant], filepath: Path, config: MappingConfig)`
|
|
77
|
+
2. Register in `consync/renderers/__init__.py` → `RENDERERS` dict
|
|
78
|
+
3. Add extension mapping in `consync/config.py` → `EXTENSION_TO_FORMAT`
|
|
79
|
+
4. Add tests in `tests/test_renderers.py`
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## Safety Features (Critical for Embedded)
|
|
84
|
+
|
|
85
|
+
| Feature | Module | Behaviour |
|
|
86
|
+
|---------|--------|-----------|
|
|
87
|
+
| **Backup** | `backup.py` | Copies target to `.consync/backups/` before every write. Retains 20/file. |
|
|
88
|
+
| **Recovery** | `backup.py` + CLI `recover` | Restore any file by timestamp. Creates safety backup before restoring. |
|
|
89
|
+
| **Validation** | `validators.py` | Blocks sync if values violate `validators:` rules in config. |
|
|
90
|
+
| **Lock** | `lock.py` | Advisory PID-based lock prevents concurrent writes. Auto-reclaims stale. |
|
|
91
|
+
| **Audit** | `logging_config.py` | Every sync logged with timestamp, user, direction, all values. |
|
|
92
|
+
| **Queue** | `watcher.py` | Events during debounce are queued (never dropped). Lock conflicts retried 3x. |
|
|
93
|
+
| **Startup sync** | `watcher.py` | On `consync watch`, a full sync runs first to recover any drift. |
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## Common Tasks
|
|
98
|
+
|
|
99
|
+
### Run tests
|
|
100
|
+
```bash
|
|
101
|
+
cd /path/to/consync
|
|
102
|
+
pip install -e ".[dev]"
|
|
103
|
+
pytest tests/ -v
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Run a specific test file
|
|
107
|
+
```bash
|
|
108
|
+
pytest tests/test_safety.py -v
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Test the CLI manually
|
|
112
|
+
```bash
|
|
113
|
+
cd examples/
|
|
114
|
+
consync sync --dry-run
|
|
115
|
+
consync diff
|
|
116
|
+
consync log -n 5
|
|
117
|
+
consync recover --list
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Add a new CLI command
|
|
121
|
+
1. Add function with `@main.command()` decorator in `cli.py`
|
|
122
|
+
2. Follow pattern: import lazily inside function, handle errors, call `sys.exit(1)` on failure
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## Do NOT
|
|
127
|
+
|
|
128
|
+
- Put secrets/credentials in any file (there are none in this project)
|
|
129
|
+
- Modify `pyproject.toml` build config without testing `pip install -e .`
|
|
130
|
+
- Break round-trip precision (17 sig digits must survive parse→render→parse)
|
|
131
|
+
- Remove the lock/backup from sync.py — these are safety-critical for firmware engineers
|
|
132
|
+
- Add heavy dependencies (keep it lightweight: openpyxl, click, watchdog, pyyaml only)
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Contributing to consync
|
|
2
|
+
|
|
3
|
+
Thanks for your interest in contributing! Here's how to get started.
|
|
4
|
+
|
|
5
|
+
## Development Setup
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
git clone https://github.com/naveenkumarbaskaran/consync.git
|
|
9
|
+
cd consync
|
|
10
|
+
python -m venv .venv
|
|
11
|
+
source .venv/bin/activate
|
|
12
|
+
pip install -e ".[dev]"
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Running Tests
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pytest
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
All 77+ tests should pass. Tests cover precision, parsers, renderers, sync engine, and CLI.
|
|
22
|
+
|
|
23
|
+
## Code Style
|
|
24
|
+
|
|
25
|
+
This project uses [ruff](https://docs.astral.sh/ruff/) for linting and formatting:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
ruff check .
|
|
29
|
+
ruff format .
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Making Changes
|
|
33
|
+
|
|
34
|
+
1. Fork the repo and create a feature branch from `main`
|
|
35
|
+
2. Make your changes with clear, descriptive commits
|
|
36
|
+
3. Add or update tests for any new functionality
|
|
37
|
+
4. Ensure all tests pass and linting is clean
|
|
38
|
+
5. Open a pull request against `main`
|
|
39
|
+
|
|
40
|
+
## Commit Messages
|
|
41
|
+
|
|
42
|
+
Follow [Conventional Commits](https://www.conventionalcommits.org/):
|
|
43
|
+
|
|
44
|
+
- `feat: add TOML renderer for constants output`
|
|
45
|
+
- `fix: handle hex values in C header parser`
|
|
46
|
+
- `test: add round-trip precision tests for verilog`
|
|
47
|
+
- `docs: update CLI reference for --from flag`
|
|
48
|
+
|
|
49
|
+
## Architecture Overview
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
Source (xlsx/csv/json/toml) ←→ [consync engine] ←→ Target (C/Python/Rust/Verilog/VHDL)
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Key Modules
|
|
56
|
+
|
|
57
|
+
- `consync/parsers/` — Read constants from various file formats
|
|
58
|
+
- `consync/renderers/` — Write constants to target languages
|
|
59
|
+
- `consync/sync.py` — Core sync engine (direction detection, state management)
|
|
60
|
+
- `consync/precision.py` — IEEE 754 precision formatting
|
|
61
|
+
- `consync/cli.py` — Click-based CLI entry point
|
|
62
|
+
- `consync/watcher.py` — File watcher for continuous sync
|
|
63
|
+
- `consync/state.py` — Hash-based change detection
|
|
64
|
+
|
|
65
|
+
## Adding a New Parser
|
|
66
|
+
|
|
67
|
+
1. Create `consync/parsers/your_format.py`
|
|
68
|
+
2. Implement a function that returns `list[Constant]`
|
|
69
|
+
3. Decorate with `@register("format_name")`
|
|
70
|
+
4. Import in `consync/parsers/__init__.py`
|
|
71
|
+
5. Add tests in `tests/test_parsers.py`
|
|
72
|
+
|
|
73
|
+
## Adding a New Renderer
|
|
74
|
+
|
|
75
|
+
1. Create `consync/renderers/your_format.py`
|
|
76
|
+
2. Implement a function that writes constants to a file
|
|
77
|
+
3. Decorate with `@register("format_name")`
|
|
78
|
+
4. Import in `consync/renderers/__init__.py`
|
|
79
|
+
5. Add tests in `tests/test_renderers.py`
|
|
80
|
+
|
|
81
|
+
## Reporting Issues
|
|
82
|
+
|
|
83
|
+
- Use GitHub Issues with a clear title and reproduction steps
|
|
84
|
+
- Include your Python version, OS, and error output
|
|
85
|
+
- For sync issues, include your `.consync.yaml` (redact any sensitive paths)
|
|
86
|
+
|
|
87
|
+
## License
|
|
88
|
+
|
|
89
|
+
By contributing, you agree that your contributions will be licensed under the MIT License.
|