ducpy 3.3.7__tar.gz → 3.4.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.
- {ducpy-3.3.7 → ducpy-3.4.0}/Cargo.lock +1 -1
- ducpy-3.4.0/PKG-INFO +104 -0
- ducpy-3.4.0/README.md +87 -0
- {ducpy-3.3.7 → ducpy-3.4.0}/packages/ducpy/crate/Cargo.toml +1 -1
- {ducpy-3.3.7 → ducpy-3.4.0}/packages/ducpy/crate/src/lib.rs +45 -0
- {ducpy-3.3.7 → ducpy-3.4.0}/packages/ducrs/Cargo.toml +1 -3
- ducpy-3.4.0/packages/ducrs/README.md +54 -0
- {ducpy-3.3.7 → ducpy-3.4.0}/packages/ducrs/build.rs +20 -16
- {ducpy-3.3.7 → ducpy-3.4.0}/packages/ducrs/src/db/bootstrap.rs +14 -0
- {ducpy-3.3.7 → ducpy-3.4.0}/packages/ducrs/src/db/mod.rs +1 -1
- {ducpy-3.3.7 → ducpy-3.4.0}/pyproject.toml +0 -2
- {ducpy-3.3.7 → ducpy-3.4.0}/src/ducpy/builders/sql_builder.py +129 -65
- {ducpy-3.3.7 → ducpy-3.4.0}/src/ducpy/serialize.py +47 -56
- ducpy-3.4.0/src/ducpy_native/__init__.py +28 -0
- ducpy-3.3.7/PKG-INFO +0 -83
- ducpy-3.3.7/README.md +0 -65
- ducpy-3.3.7/packages/ducrs/README.md +0 -52
- ducpy-3.3.7/src/ducpy/_version.py +0 -3
- ducpy-3.3.7/src/ducpy_native/__init__.py +0 -19
- {ducpy-3.3.7 → ducpy-3.4.0}/Cargo.toml +0 -0
- {ducpy-3.3.7 → ducpy-3.4.0}/LICENSE +0 -0
- {ducpy-3.3.7 → ducpy-3.4.0}/packages/ducrs/LICENSE +0 -0
- {ducpy-3.3.7 → ducpy-3.4.0/packages/ducrs}/schema/duc.sql +0 -0
- {ducpy-3.3.7 → ducpy-3.4.0/packages/ducrs}/schema/migrations/3000000_to_3000001.sql +0 -0
- {ducpy-3.3.7 → ducpy-3.4.0/packages/ducrs}/schema/migrations/3000001_to_3000002.sql +0 -0
- {ducpy-3.3.7 → ducpy-3.4.0/packages/ducrs}/schema/migrations/3000002_to_3000003.sql +0 -0
- {ducpy-3.3.7 → ducpy-3.4.0/packages/ducrs}/schema/migrations/3000003_to_3000004.sql +0 -0
- {ducpy-3.3.7 → ducpy-3.4.0/packages/ducrs}/schema/search.sql +0 -0
- {ducpy-3.3.7 → ducpy-3.4.0/packages/ducrs}/schema/version_control.sql +0 -0
- {ducpy-3.3.7 → ducpy-3.4.0}/packages/ducrs/src/api/document.rs +0 -0
- {ducpy-3.3.7 → ducpy-3.4.0}/packages/ducrs/src/api/meta.rs +0 -0
- {ducpy-3.3.7 → ducpy-3.4.0}/packages/ducrs/src/api/mod.rs +0 -0
- {ducpy-3.3.7 → ducpy-3.4.0}/packages/ducrs/src/api/version_control.rs +0 -0
- {ducpy-3.3.7 → ducpy-3.4.0}/packages/ducrs/src/db/native.rs +0 -0
- {ducpy-3.3.7 → ducpy-3.4.0}/packages/ducrs/src/db/wasm.rs +0 -0
- {ducpy-3.3.7 → ducpy-3.4.0}/packages/ducrs/src/lib.rs +0 -0
- {ducpy-3.3.7 → ducpy-3.4.0}/packages/ducrs/src/parse.rs +0 -0
- {ducpy-3.3.7 → ducpy-3.4.0}/packages/ducrs/src/serde_utils.rs +0 -0
- {ducpy-3.3.7 → ducpy-3.4.0}/packages/ducrs/src/serialize.rs +0 -0
- {ducpy-3.3.7 → ducpy-3.4.0}/packages/ducrs/src/types.rs +0 -0
- {ducpy-3.3.7 → ducpy-3.4.0}/src/ducpy/__init__.py +0 -0
- {ducpy-3.3.7 → ducpy-3.4.0}/src/ducpy/builders/__init__.py +0 -0
- {ducpy-3.3.7 → ducpy-3.4.0}/src/ducpy/builders/block_instance_builder.py +0 -0
- {ducpy-3.3.7 → ducpy-3.4.0}/src/ducpy/builders/block_utils.py +0 -0
- {ducpy-3.3.7 → ducpy-3.4.0}/src/ducpy/builders/element_builders.py +0 -0
- {ducpy-3.3.7 → ducpy-3.4.0}/src/ducpy/builders/mutate_builder.py +0 -0
- {ducpy-3.3.7 → ducpy-3.4.0}/src/ducpy/builders/state_builders.py +0 -0
- {ducpy-3.3.7 → ducpy-3.4.0}/src/ducpy/builders/style_builders.py +0 -0
- {ducpy-3.3.7 → ducpy-3.4.0}/src/ducpy/classes/DataStateClass.py +0 -0
- {ducpy-3.3.7 → ducpy-3.4.0}/src/ducpy/classes/ElementsClass.py +0 -0
- {ducpy-3.3.7 → ducpy-3.4.0}/src/ducpy/classes/__init__.py +0 -0
- {ducpy-3.3.7 → ducpy-3.4.0}/src/ducpy/enums.py +0 -0
- {ducpy-3.3.7 → ducpy-3.4.0}/src/ducpy/parse.py +0 -0
- {ducpy-3.3.7 → ducpy-3.4.0}/src/ducpy/search/__init__.py +0 -0
- {ducpy-3.3.7 → ducpy-3.4.0}/src/ducpy/search/search_elements.py +0 -0
- {ducpy-3.3.7 → ducpy-3.4.0}/src/ducpy/utils/__init__.py +0 -0
- {ducpy-3.3.7 → ducpy-3.4.0}/src/ducpy/utils/constants.py +0 -0
- {ducpy-3.3.7 → ducpy-3.4.0}/src/ducpy/utils/convert.py +0 -0
- {ducpy-3.3.7 → ducpy-3.4.0}/src/ducpy/utils/io.py +0 -0
- {ducpy-3.3.7 → ducpy-3.4.0}/src/ducpy/utils/mutate_utils.py +0 -0
- {ducpy-3.3.7 → ducpy-3.4.0}/src/ducpy/utils/rand_utils.py +0 -0
ducpy-3.4.0/PKG-INFO
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ducpy
|
|
3
|
+
Version: 3.4.0
|
|
4
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
5
|
+
Requires-Dist: nanoid>=2.0.0
|
|
6
|
+
License-File: LICENSE
|
|
7
|
+
Summary: The library for the Duc 2D CAD file format
|
|
8
|
+
Author: Jorge Soares
|
|
9
|
+
Author-email: Ducflair <support@ducflair.com>
|
|
10
|
+
License: MIT
|
|
11
|
+
Requires-Python: >=3.10
|
|
12
|
+
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
|
|
13
|
+
Project-URL: Documentation, https://ducflair.github.io/duc/reference/python/
|
|
14
|
+
Project-URL: Homepage, https://duc.ducflair.com
|
|
15
|
+
Project-URL: Package Index, https://ducflair.github.io/duc/simple/ducpy/
|
|
16
|
+
Project-URL: Source, https://github.com/ducflair/duc/tree/main/packages/ducpy
|
|
17
|
+
|
|
18
|
+
# ducpy
|
|
19
|
+
|
|
20
|
+
<p align="center">
|
|
21
|
+
<br/>
|
|
22
|
+
<a href="https://duc.ducflair.com" target="_blank"><img width="256px" src="https://cdn.jsdelivr.net/gh/ducflair/assets@main/src/duc/duc-extended.png" /></a>
|
|
23
|
+
<p align="center">2D CAD File Format</p>
|
|
24
|
+
<p align="center" style="align: center;">
|
|
25
|
+
<a href="https://pypi.org/project/ducpy/"><img src="https://shields.io/badge/Pip-blue?logo=Pypi&logoColor=white&style=round-square" alt="Pip" /></a>
|
|
26
|
+
<a href="https://github.com/ducflair/duc/releases"><img src="https://img.shields.io/pypi/v/ducpy?style=round-square&label=latest%20stable" alt="PyPI ducpy@latest release" /></a>
|
|
27
|
+
<a href="https://pypi.org/project/ducpy/"><img src="https://img.shields.io/pypi/dm/ducpy?style=round-square&color=salmon" alt="Downloads" /></a>
|
|
28
|
+
<img src="https://shields.io/badge/Python-ffde57?logo=Python&logoColor=646464&style=round-square" alt="Python" />
|
|
29
|
+
</p>
|
|
30
|
+
</p>
|
|
31
|
+
|
|
32
|
+
The `ducpy` package is the official Python implementation of the `.duc` 2D CAD file format. It is built on top of the [`duc`](../ducrs) Rust crate, exposed as the `ducpy_native` extension. A `.duc` file is a zlib-compressed SQLite database — `ducpy` gives you both a high-level builder DSL and direct low-level access to that schema, plus parsing, serialization, and search helpers.
|
|
33
|
+
|
|
34
|
+
## Installation
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
pip install ducpy
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
or with [`uv`](https://docs.astral.sh/uv/):
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
uv add ducpy
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Quick start
|
|
47
|
+
|
|
48
|
+
```python
|
|
49
|
+
import ducpy as duc
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## API overview
|
|
53
|
+
|
|
54
|
+
`ducpy` is organised around four conceptual entry points, matching the structure of the full [API reference](https://duc.ducflair.com):
|
|
55
|
+
|
|
56
|
+
### Builders API (High-level)
|
|
57
|
+
|
|
58
|
+
The easy way to build and manage `.duc` files. Construct elements, apply styles, manage layers, build blocks, and handle document state through the `duc.builders` module.
|
|
59
|
+
|
|
60
|
+
See the worked examples:
|
|
61
|
+
|
|
62
|
+
- [Element creation](src/examples/element_creation_demo.py) — building rectangles, ellipses, polygons, lines, arrows, text, frames and plots with the fluent builder DSL.
|
|
63
|
+
- [Mutating elements](src/examples/mutation_demo.py) — updating element properties in place and observing version changes.
|
|
64
|
+
- [Document elements](src/examples/document_element_demo.py) and [model elements](src/examples/model_element_demo.py) — for the higher-level container / model element types.
|
|
65
|
+
|
|
66
|
+
### SQL Builder (Low-level)
|
|
67
|
+
|
|
68
|
+
A `.duc` file is a zlib-compressed SQLite database. Use `duc.builders.sql_builder` (`DucSQL`) for direct schema access, bulk queries, and low-level manipulation.
|
|
69
|
+
|
|
70
|
+
See the worked example: [SQL Builder](src/examples/sql_builder_demo.py) — `DucSQL.new()` to create a `.duc` from scratch, `DucSQL(path)` to query an existing one.
|
|
71
|
+
|
|
72
|
+
### Search
|
|
73
|
+
|
|
74
|
+
Query and search elements and files programmatically through the `duc.search` API.
|
|
75
|
+
|
|
76
|
+
### File I/O
|
|
77
|
+
|
|
78
|
+
Read and write `.duc` files using the `duc.parse` and `duc.serialize` modules.
|
|
79
|
+
|
|
80
|
+
See the worked examples:
|
|
81
|
+
|
|
82
|
+
- [Parsing](src/examples/parsing_demo.py) — `parse_duc` / `parse_duc_lazy` / `get_external_file` / `list_external_files`.
|
|
83
|
+
- [Serialization](src/examples/serialization_demo.py) — `serialize_duc` from builder-created elements.
|
|
84
|
+
- [External files](src/examples/external_files_demo.py) — attaching binary blobs (images, PDFs) to a `.duc` document.
|
|
85
|
+
|
|
86
|
+
## Documentation
|
|
87
|
+
|
|
88
|
+
For detailed documentation, including the full API reference, schema specification, and end-to-end examples, see:
|
|
89
|
+
|
|
90
|
+
- API reference & guides: [duc.ducflair.com](https://duc.ducflair.com)
|
|
91
|
+
- Source-level reference: [docs/](docs/index.rst)
|
|
92
|
+
- Full example index: [docs/examples.rst](docs/examples.rst)
|
|
93
|
+
|
|
94
|
+
## Tools
|
|
95
|
+
|
|
96
|
+
- [Playground](https://scopture.com): Experiment with the `duc` format in a live environment.
|
|
97
|
+
|
|
98
|
+
## Contributing
|
|
99
|
+
|
|
100
|
+
Feel free to open an issue or contact us at [Ducflair Support](https://www.ducflair.com/support).
|
|
101
|
+
|
|
102
|
+
## License
|
|
103
|
+
|
|
104
|
+
This project is licensed under the MIT License. See the [LICENSE](./LICENSE) file for more details.
|
ducpy-3.4.0/README.md
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# ducpy
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<br/>
|
|
5
|
+
<a href="https://duc.ducflair.com" target="_blank"><img width="256px" src="https://cdn.jsdelivr.net/gh/ducflair/assets@main/src/duc/duc-extended.png" /></a>
|
|
6
|
+
<p align="center">2D CAD File Format</p>
|
|
7
|
+
<p align="center" style="align: center;">
|
|
8
|
+
<a href="https://pypi.org/project/ducpy/"><img src="https://shields.io/badge/Pip-blue?logo=Pypi&logoColor=white&style=round-square" alt="Pip" /></a>
|
|
9
|
+
<a href="https://github.com/ducflair/duc/releases"><img src="https://img.shields.io/pypi/v/ducpy?style=round-square&label=latest%20stable" alt="PyPI ducpy@latest release" /></a>
|
|
10
|
+
<a href="https://pypi.org/project/ducpy/"><img src="https://img.shields.io/pypi/dm/ducpy?style=round-square&color=salmon" alt="Downloads" /></a>
|
|
11
|
+
<img src="https://shields.io/badge/Python-ffde57?logo=Python&logoColor=646464&style=round-square" alt="Python" />
|
|
12
|
+
</p>
|
|
13
|
+
</p>
|
|
14
|
+
|
|
15
|
+
The `ducpy` package is the official Python implementation of the `.duc` 2D CAD file format. It is built on top of the [`duc`](../ducrs) Rust crate, exposed as the `ducpy_native` extension. A `.duc` file is a zlib-compressed SQLite database — `ducpy` gives you both a high-level builder DSL and direct low-level access to that schema, plus parsing, serialization, and search helpers.
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pip install ducpy
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
or with [`uv`](https://docs.astral.sh/uv/):
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
uv add ducpy
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Quick start
|
|
30
|
+
|
|
31
|
+
```python
|
|
32
|
+
import ducpy as duc
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## API overview
|
|
36
|
+
|
|
37
|
+
`ducpy` is organised around four conceptual entry points, matching the structure of the full [API reference](https://duc.ducflair.com):
|
|
38
|
+
|
|
39
|
+
### Builders API (High-level)
|
|
40
|
+
|
|
41
|
+
The easy way to build and manage `.duc` files. Construct elements, apply styles, manage layers, build blocks, and handle document state through the `duc.builders` module.
|
|
42
|
+
|
|
43
|
+
See the worked examples:
|
|
44
|
+
|
|
45
|
+
- [Element creation](src/examples/element_creation_demo.py) — building rectangles, ellipses, polygons, lines, arrows, text, frames and plots with the fluent builder DSL.
|
|
46
|
+
- [Mutating elements](src/examples/mutation_demo.py) — updating element properties in place and observing version changes.
|
|
47
|
+
- [Document elements](src/examples/document_element_demo.py) and [model elements](src/examples/model_element_demo.py) — for the higher-level container / model element types.
|
|
48
|
+
|
|
49
|
+
### SQL Builder (Low-level)
|
|
50
|
+
|
|
51
|
+
A `.duc` file is a zlib-compressed SQLite database. Use `duc.builders.sql_builder` (`DucSQL`) for direct schema access, bulk queries, and low-level manipulation.
|
|
52
|
+
|
|
53
|
+
See the worked example: [SQL Builder](src/examples/sql_builder_demo.py) — `DucSQL.new()` to create a `.duc` from scratch, `DucSQL(path)` to query an existing one.
|
|
54
|
+
|
|
55
|
+
### Search
|
|
56
|
+
|
|
57
|
+
Query and search elements and files programmatically through the `duc.search` API.
|
|
58
|
+
|
|
59
|
+
### File I/O
|
|
60
|
+
|
|
61
|
+
Read and write `.duc` files using the `duc.parse` and `duc.serialize` modules.
|
|
62
|
+
|
|
63
|
+
See the worked examples:
|
|
64
|
+
|
|
65
|
+
- [Parsing](src/examples/parsing_demo.py) — `parse_duc` / `parse_duc_lazy` / `get_external_file` / `list_external_files`.
|
|
66
|
+
- [Serialization](src/examples/serialization_demo.py) — `serialize_duc` from builder-created elements.
|
|
67
|
+
- [External files](src/examples/external_files_demo.py) — attaching binary blobs (images, PDFs) to a `.duc` document.
|
|
68
|
+
|
|
69
|
+
## Documentation
|
|
70
|
+
|
|
71
|
+
For detailed documentation, including the full API reference, schema specification, and end-to-end examples, see:
|
|
72
|
+
|
|
73
|
+
- API reference & guides: [duc.ducflair.com](https://duc.ducflair.com)
|
|
74
|
+
- Source-level reference: [docs/](docs/index.rst)
|
|
75
|
+
- Full example index: [docs/examples.rst](docs/examples.rst)
|
|
76
|
+
|
|
77
|
+
## Tools
|
|
78
|
+
|
|
79
|
+
- [Playground](https://scopture.com): Experiment with the `duc` format in a live environment.
|
|
80
|
+
|
|
81
|
+
## Contributing
|
|
82
|
+
|
|
83
|
+
Feel free to open an issue or contact us at [Ducflair Support](https://www.ducflair.com/support).
|
|
84
|
+
|
|
85
|
+
## License
|
|
86
|
+
|
|
87
|
+
This project is licensed under the MIT License. See the [LICENSE](./LICENSE) file for more details.
|
|
@@ -58,6 +58,45 @@ fn list_external_files(py: Python<'_>, buf: &[u8]) -> PyResult<PyObject> {
|
|
|
58
58
|
.map_err(|e| pyo3::exceptions::PyValueError::new_err(format!("{e}")))
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
+
/// Returns the current DUC schema version as a semver string (e.g. "3.0.0").
|
|
62
|
+
#[pyfunction]
|
|
63
|
+
fn get_schema_version() -> PyResult<String> {
|
|
64
|
+
Ok(duc::db::bootstrap::CURRENT_SCHEMA_VERSION_SEMVER.into())
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/// Returns the raw integer schema version (e.g. 3000000).
|
|
68
|
+
#[pyfunction]
|
|
69
|
+
fn get_schema_version_int() -> PyResult<i64> {
|
|
70
|
+
Ok(duc::db::bootstrap::current_schema_version_int())
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/// Returns the canonical `duc.sql` schema string.
|
|
74
|
+
#[pyfunction]
|
|
75
|
+
fn get_duc_schema_sql() -> PyResult<String> {
|
|
76
|
+
Ok(duc::db::bootstrap::DUC_SCHEMA_SQL.into())
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/// Returns the `version_control.sql` schema string.
|
|
80
|
+
#[pyfunction]
|
|
81
|
+
fn get_version_control_schema_sql() -> PyResult<String> {
|
|
82
|
+
Ok(duc::db::bootstrap::VERSION_CONTROL_SCHEMA_SQL.into())
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/// Returns the `search.sql` schema string.
|
|
86
|
+
#[pyfunction]
|
|
87
|
+
fn get_search_schema_sql() -> PyResult<String> {
|
|
88
|
+
Ok(duc::db::bootstrap::SEARCH_SCHEMA_SQL.into())
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/// Returns all migrations as a list of `(from_version, to_version, sql)` tuples.
|
|
92
|
+
#[pyfunction]
|
|
93
|
+
fn get_migrations(_py: Python<'_>) -> PyResult<Vec<(i64, i64, String)>> {
|
|
94
|
+
Ok(duc::db::bootstrap::MIGRATIONS
|
|
95
|
+
.iter()
|
|
96
|
+
.map(|(f, t, sql)| (*f, *t, sql.to_string()))
|
|
97
|
+
.collect())
|
|
98
|
+
}
|
|
99
|
+
|
|
61
100
|
/// Native duc file format operations.
|
|
62
101
|
#[pymodule]
|
|
63
102
|
fn ducpy_native(m: &Bound<'_, PyModule>) -> PyResult<()> {
|
|
@@ -66,5 +105,11 @@ fn ducpy_native(m: &Bound<'_, PyModule>) -> PyResult<()> {
|
|
|
66
105
|
m.add_function(wrap_pyfunction!(serialize_duc, m)?)?;
|
|
67
106
|
m.add_function(wrap_pyfunction!(get_external_file, m)?)?;
|
|
68
107
|
m.add_function(wrap_pyfunction!(list_external_files, m)?)?;
|
|
108
|
+
m.add_function(wrap_pyfunction!(get_schema_version, m)?)?;
|
|
109
|
+
m.add_function(wrap_pyfunction!(get_schema_version_int, m)?)?;
|
|
110
|
+
m.add_function(wrap_pyfunction!(get_duc_schema_sql, m)?)?;
|
|
111
|
+
m.add_function(wrap_pyfunction!(get_version_control_schema_sql, m)?)?;
|
|
112
|
+
m.add_function(wrap_pyfunction!(get_search_schema_sql, m)?)?;
|
|
113
|
+
m.add_function(wrap_pyfunction!(get_migrations, m)?)?;
|
|
69
114
|
Ok(())
|
|
70
115
|
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# duc (Rust)
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<br/>
|
|
5
|
+
<a href="https://duc.ducflair.com" target="_blank"><img width="256px" src="https://cdn.jsdelivr.net/gh/ducflair/assets@main/src/duc/duc-extended.png" /></a>
|
|
6
|
+
<p align="center">2D CAD File Format</p>
|
|
7
|
+
<p align="center" style="align: center;">
|
|
8
|
+
<a href="https://crates.io/crates/duc"><img src="https://shields.io/badge/Crates-FFC933?logo=Rust&logoColor=646464&style=round-square" alt="Crates" /></a>
|
|
9
|
+
<a href="https://github.com/ducflair/duc/releases"><img src="https://img.shields.io/crates/v/duc?style=round-square&label=latest%20stable" alt="crates.io duc@latest release" /></a>
|
|
10
|
+
<a href="https://crates.io/crates/duc"><img src="https://img.shields.io/crates/d/duc?style=round-square&color=salmon" alt="Downloads" /></a>
|
|
11
|
+
<img src="https://shields.io/badge/Rust-CE412B?logo=Rust&logoColor=fff&style=round-square" alt="Rust" />
|
|
12
|
+
</p>
|
|
13
|
+
</p>
|
|
14
|
+
|
|
15
|
+
The `duc` crate is the canonical Rust implementation of the `.duc` 2D CAD file format and the **root of the entire Duc ecosystem**. [`ducpy`](https://pypi.org/project/ducpy/), [`ducjs`](https://www.npmjs.com/package/ducjs), and the rest of the toolchain are all built on top of the types, parsers and storage layer defined here.
|
|
16
|
+
|
|
17
|
+
A `.duc` file is a standard zlib compressed **SQLite database file** following the schema in `schema/duc.sql`. This crate wraps that database in a strongly-typed Rust API for reading, writing and manipulating `.duc` documents.
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
----
|
|
21
|
+
<br/>
|
|
22
|
+
<br/>
|
|
23
|
+
<br/>
|
|
24
|
+
|
|
25
|
+
## Schema and migrations
|
|
26
|
+
|
|
27
|
+
The canonical SQL lives at `schema/duc.sql` (plus `schema/version_control.sql` and `schema/search.sql`) and is **embedded at compile time** by [`build.rs`](build.rs)
|
|
28
|
+
|
|
29
|
+
Migrations are ran and handled **automatically** upon usage of the library. Each migration is a SQL file named `<from>_to_<to>.sql` in `schema/migrations/`. `build.rs` scans that directory, sorts by `from_version` and emits a static `MIGRATIONS` array. Adding a new migration requires **no Rust changes** — drop the file in and rebuild.
|
|
30
|
+
|
|
31
|
+
## Features
|
|
32
|
+
|
|
33
|
+
| Feature | Default | Description |
|
|
34
|
+
|---------|---------|-------------|
|
|
35
|
+
| `default` | ✅ | Native build with bundled SQLite |
|
|
36
|
+
| `opfs` | ❌ | OPFS SAH-pool VFS for `wasm32-unknown-unknown` (browser persistence) |
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
## Documentation
|
|
40
|
+
|
|
41
|
+
- Full API reference: [docs.rs/duc](https://docs.rs/duc)
|
|
42
|
+
- Format specification, concepts and guides: [duc.ducflair.com](https://duc.ducflair.com)
|
|
43
|
+
|
|
44
|
+
## Tools
|
|
45
|
+
|
|
46
|
+
- [Playground](https://ducflair.com/core): Experiment with the `.duc` format in the browser.
|
|
47
|
+
|
|
48
|
+
## Contributing
|
|
49
|
+
|
|
50
|
+
Feel free to open an issue or contact us at [Ducflair Support](https://www.ducflair.com/support).
|
|
51
|
+
|
|
52
|
+
## License
|
|
53
|
+
|
|
54
|
+
This project is licensed under the MIT License. See the [LICENSE](./LICENSE) file for more details.
|
|
@@ -25,6 +25,7 @@ fn decode_user_version_to_semver(user_version: u32) -> String {
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
fn find_schema_dir(manifest_dir: &Path) -> Result<PathBuf, Box<dyn std::error::Error>> {
|
|
28
|
+
// 1. Explicit override.
|
|
28
29
|
if let Ok(path) = env::var("DUC_SCHEMA_DIR") {
|
|
29
30
|
let candidate = PathBuf::from(path);
|
|
30
31
|
if candidate.join("duc.sql").is_file() {
|
|
@@ -32,22 +33,25 @@ fn find_schema_dir(manifest_dir: &Path) -> Result<PathBuf, Box<dyn std::error::E
|
|
|
32
33
|
}
|
|
33
34
|
}
|
|
34
35
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
if candidate.join("duc.sql").is_file() {
|
|
41
|
-
return Ok(candidate);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
36
|
+
// 2. Schema inside the crate directory (symlink in dev, real files after
|
|
37
|
+
// `cargo publish` dereferences the symlink into the tarball).
|
|
38
|
+
let bundled = manifest_dir.join("schema");
|
|
39
|
+
if bundled.join("duc.sql").is_file() {
|
|
40
|
+
return Ok(bundled);
|
|
44
41
|
}
|
|
45
42
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
43
|
+
// 3. Local workspace: walk up to the repo root `schema/`.
|
|
44
|
+
let source = manifest_dir
|
|
45
|
+
.ancestors()
|
|
46
|
+
.map(|a| a.join("schema"))
|
|
47
|
+
.find(|p| p.join("duc.sql").is_file())
|
|
48
|
+
.ok_or_else(|| {
|
|
49
|
+
format!(
|
|
50
|
+
"Could not locate schema/duc.sql from {}. Set DUC_SCHEMA_DIR to a directory containing duc.sql.",
|
|
51
|
+
manifest_dir.display()
|
|
52
|
+
)
|
|
53
|
+
})?;
|
|
54
|
+
Ok(source)
|
|
51
55
|
}
|
|
52
56
|
|
|
53
57
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
@@ -106,7 +110,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
|
106
110
|
let mut reg = String::from(
|
|
107
111
|
"// Auto-generated by build.rs — do not edit by hand.\n\
|
|
108
112
|
// Each entry: (from_version, to_version, sql).\n\
|
|
109
|
-
pub
|
|
113
|
+
pub static MIGRATIONS: &[(i64, i64, &str)] = &[\n",
|
|
110
114
|
);
|
|
111
115
|
for (from, to, sql) in &migrations {
|
|
112
116
|
reg.push_str(&format!(" ({from}i64, {to}i64, \""));
|
|
@@ -149,4 +153,4 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
|
149
153
|
println!("cargo:rerun-if-changed=build.rs");
|
|
150
154
|
|
|
151
155
|
Ok(())
|
|
152
|
-
}
|
|
156
|
+
}
|
|
@@ -32,10 +32,24 @@ const CURRENT_VERSION: i64 = {
|
|
|
32
32
|
val
|
|
33
33
|
};
|
|
34
34
|
|
|
35
|
+
/// Runtime accessor for the compile-time schema version integer.
|
|
36
|
+
pub fn current_schema_version_int() -> i64 {
|
|
37
|
+
CURRENT_VERSION
|
|
38
|
+
}
|
|
39
|
+
|
|
35
40
|
// Migration registry auto-generated by build.rs from `schema/migrations/*.sql`.
|
|
36
41
|
// Each entry is (from_version, to_version, sql). Sorted ascending by from_version.
|
|
37
42
|
include!(concat!(env!("OUT_DIR"), "/migrations_registry.rs"));
|
|
38
43
|
|
|
44
|
+
// ── Public re-exports for downstream crates ─────────────────────────────
|
|
45
|
+
|
|
46
|
+
/// Current schema version as a semver string (generated at build time).
|
|
47
|
+
pub const CURRENT_SCHEMA_VERSION_SEMVER: &str = env!("DUC_SCHEMA_VERSION");
|
|
48
|
+
|
|
49
|
+
pub const DUC_SCHEMA_SQL: &str = DUC_SCHEMA;
|
|
50
|
+
pub const VERSION_CONTROL_SCHEMA_SQL: &str = VERSION_CONTROL_SCHEMA;
|
|
51
|
+
pub const SEARCH_SCHEMA_SQL: &str = SEARCH_SCHEMA;
|
|
52
|
+
|
|
39
53
|
/// Per-connection PRAGMAs that must be re-applied on every open (they are
|
|
40
54
|
/// either ephemeral or take effect only after the first statement on the
|
|
41
55
|
/// connection).
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
//! Call [`open_file`] or [`open_memory`] instead of calling `rusqlite::Connection`
|
|
4
4
|
//! directly. Internally they dispatch to the correct backend for each compile target.
|
|
5
5
|
|
|
6
|
-
mod bootstrap;
|
|
6
|
+
pub mod bootstrap;
|
|
7
7
|
|
|
8
8
|
#[cfg(not(all(target_family = "wasm", target_os = "unknown")))]
|
|
9
9
|
mod native;
|
|
@@ -34,8 +34,6 @@ python-packages = ["ducpy", "ducpy_native"]
|
|
|
34
34
|
module-name = "ducpy_native"
|
|
35
35
|
include = [
|
|
36
36
|
{ path = "LICENSE", format = "sdist" },
|
|
37
|
-
{ path = "schema/**/*", format = "sdist" },
|
|
38
|
-
{ path = "schema/**/*", format = "wheel" }
|
|
39
37
|
]
|
|
40
38
|
manifest-path = "packages/ducpy/crate/Cargo.toml"
|
|
41
39
|
python-source = "src"
|