ducpy 3.3.8__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.8 → 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.8 → ducpy-3.4.0}/packages/ducpy/crate/Cargo.toml +1 -1
- ducpy-3.4.0/packages/ducrs/README.md +54 -0
- {ducpy-3.3.8 → ducpy-3.4.0}/src/ducpy/builders/sql_builder.py +118 -14
- {ducpy-3.3.8 → ducpy-3.4.0}/src/ducpy/serialize.py +45 -1
- ducpy-3.3.8/PKG-INFO +0 -83
- ducpy-3.3.8/README.md +0 -65
- ducpy-3.3.8/packages/ducrs/README.md +0 -52
- {ducpy-3.3.8 → ducpy-3.4.0}/Cargo.toml +0 -0
- {ducpy-3.3.8 → ducpy-3.4.0}/LICENSE +0 -0
- {ducpy-3.3.8 → ducpy-3.4.0}/packages/ducpy/crate/src/lib.rs +0 -0
- {ducpy-3.3.8 → ducpy-3.4.0}/packages/ducrs/Cargo.toml +0 -0
- {ducpy-3.3.8 → ducpy-3.4.0}/packages/ducrs/LICENSE +0 -0
- {ducpy-3.3.8 → ducpy-3.4.0}/packages/ducrs/build.rs +0 -0
- {ducpy-3.3.8 → ducpy-3.4.0}/packages/ducrs/schema/duc.sql +0 -0
- {ducpy-3.3.8 → ducpy-3.4.0}/packages/ducrs/schema/migrations/3000000_to_3000001.sql +0 -0
- {ducpy-3.3.8 → ducpy-3.4.0}/packages/ducrs/schema/migrations/3000001_to_3000002.sql +0 -0
- {ducpy-3.3.8 → ducpy-3.4.0}/packages/ducrs/schema/migrations/3000002_to_3000003.sql +0 -0
- {ducpy-3.3.8 → ducpy-3.4.0}/packages/ducrs/schema/migrations/3000003_to_3000004.sql +0 -0
- {ducpy-3.3.8 → ducpy-3.4.0}/packages/ducrs/schema/search.sql +0 -0
- {ducpy-3.3.8 → ducpy-3.4.0}/packages/ducrs/schema/version_control.sql +0 -0
- {ducpy-3.3.8 → ducpy-3.4.0}/packages/ducrs/src/api/document.rs +0 -0
- {ducpy-3.3.8 → ducpy-3.4.0}/packages/ducrs/src/api/meta.rs +0 -0
- {ducpy-3.3.8 → ducpy-3.4.0}/packages/ducrs/src/api/mod.rs +0 -0
- {ducpy-3.3.8 → ducpy-3.4.0}/packages/ducrs/src/api/version_control.rs +0 -0
- {ducpy-3.3.8 → ducpy-3.4.0}/packages/ducrs/src/db/bootstrap.rs +0 -0
- {ducpy-3.3.8 → ducpy-3.4.0}/packages/ducrs/src/db/mod.rs +0 -0
- {ducpy-3.3.8 → ducpy-3.4.0}/packages/ducrs/src/db/native.rs +0 -0
- {ducpy-3.3.8 → ducpy-3.4.0}/packages/ducrs/src/db/wasm.rs +0 -0
- {ducpy-3.3.8 → ducpy-3.4.0}/packages/ducrs/src/lib.rs +0 -0
- {ducpy-3.3.8 → ducpy-3.4.0}/packages/ducrs/src/parse.rs +0 -0
- {ducpy-3.3.8 → ducpy-3.4.0}/packages/ducrs/src/serde_utils.rs +0 -0
- {ducpy-3.3.8 → ducpy-3.4.0}/packages/ducrs/src/serialize.rs +0 -0
- {ducpy-3.3.8 → ducpy-3.4.0}/packages/ducrs/src/types.rs +0 -0
- {ducpy-3.3.8 → ducpy-3.4.0}/pyproject.toml +0 -0
- {ducpy-3.3.8 → ducpy-3.4.0}/src/ducpy/__init__.py +0 -0
- {ducpy-3.3.8 → ducpy-3.4.0}/src/ducpy/builders/__init__.py +0 -0
- {ducpy-3.3.8 → ducpy-3.4.0}/src/ducpy/builders/block_instance_builder.py +0 -0
- {ducpy-3.3.8 → ducpy-3.4.0}/src/ducpy/builders/block_utils.py +0 -0
- {ducpy-3.3.8 → ducpy-3.4.0}/src/ducpy/builders/element_builders.py +0 -0
- {ducpy-3.3.8 → ducpy-3.4.0}/src/ducpy/builders/mutate_builder.py +0 -0
- {ducpy-3.3.8 → ducpy-3.4.0}/src/ducpy/builders/state_builders.py +0 -0
- {ducpy-3.3.8 → ducpy-3.4.0}/src/ducpy/builders/style_builders.py +0 -0
- {ducpy-3.3.8 → ducpy-3.4.0}/src/ducpy/classes/DataStateClass.py +0 -0
- {ducpy-3.3.8 → ducpy-3.4.0}/src/ducpy/classes/ElementsClass.py +0 -0
- {ducpy-3.3.8 → ducpy-3.4.0}/src/ducpy/classes/__init__.py +0 -0
- {ducpy-3.3.8 → ducpy-3.4.0}/src/ducpy/enums.py +0 -0
- {ducpy-3.3.8 → ducpy-3.4.0}/src/ducpy/parse.py +0 -0
- {ducpy-3.3.8 → ducpy-3.4.0}/src/ducpy/search/__init__.py +0 -0
- {ducpy-3.3.8 → ducpy-3.4.0}/src/ducpy/search/search_elements.py +0 -0
- {ducpy-3.3.8 → ducpy-3.4.0}/src/ducpy/utils/__init__.py +0 -0
- {ducpy-3.3.8 → ducpy-3.4.0}/src/ducpy/utils/constants.py +0 -0
- {ducpy-3.3.8 → ducpy-3.4.0}/src/ducpy/utils/convert.py +0 -0
- {ducpy-3.3.8 → ducpy-3.4.0}/src/ducpy/utils/io.py +0 -0
- {ducpy-3.3.8 → ducpy-3.4.0}/src/ducpy/utils/mutate_utils.py +0 -0
- {ducpy-3.3.8 → ducpy-3.4.0}/src/ducpy/utils/rand_utils.py +0 -0
- {ducpy-3.3.8 → ducpy-3.4.0}/src/ducpy_native/__init__.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.
|
|
@@ -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.
|
|
@@ -31,12 +31,71 @@ from __future__ import annotations
|
|
|
31
31
|
import os
|
|
32
32
|
import sqlite3
|
|
33
33
|
import tempfile
|
|
34
|
+
import zlib
|
|
34
35
|
from pathlib import Path
|
|
35
|
-
from typing import Any, List, Optional, Union
|
|
36
|
+
from typing import Any, List, Optional, Sequence, Union
|
|
36
37
|
|
|
37
38
|
import ducpy_native
|
|
38
39
|
|
|
39
|
-
__all__ = ["DucSQL"]
|
|
40
|
+
__all__ = ["DucSQL", "quote_sql_identifier"]
|
|
41
|
+
SQLITE_HEADER_MAGIC = b"SQLite format 3\x00"
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def quote_sql_identifier(value: str) -> str:
|
|
45
|
+
"""Quote a SQLite identifier such as an attached database alias."""
|
|
46
|
+
if not value:
|
|
47
|
+
raise ValueError("SQLite identifier cannot be empty.")
|
|
48
|
+
return '"' + value.replace('"', '""') + '"'
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def _is_sqlite_bytes(data: bytes) -> bool:
|
|
52
|
+
return data.startswith(SQLITE_HEADER_MAGIC)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def _normalize_sqlite_image(data: bytes) -> bytes:
|
|
56
|
+
image = bytearray(data)
|
|
57
|
+
if len(image) > 19:
|
|
58
|
+
if image[18] == 2:
|
|
59
|
+
image[18] = 1
|
|
60
|
+
if image[19] == 2:
|
|
61
|
+
image[19] = 1
|
|
62
|
+
return bytes(image)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def _inflate_duc_bytes(data: bytes) -> bytes:
|
|
66
|
+
if _is_sqlite_bytes(data):
|
|
67
|
+
return _normalize_sqlite_image(data)
|
|
68
|
+
inflated = zlib.decompress(data, -zlib.MAX_WBITS)
|
|
69
|
+
if not _is_sqlite_bytes(inflated):
|
|
70
|
+
raise ValueError("decompressed .duc payload does not start with a SQLite header")
|
|
71
|
+
return _normalize_sqlite_image(inflated)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def _deflate_duc_bytes(data: bytes) -> bytes:
|
|
75
|
+
compressor = zlib.compressobj(level=-1, wbits=-zlib.MAX_WBITS)
|
|
76
|
+
return compressor.compress(data) + compressor.flush()
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def _write_temp_sqlite(data: bytes) -> str:
|
|
80
|
+
tmp = tempfile.NamedTemporaryFile(suffix=".duc", delete=False)
|
|
81
|
+
try:
|
|
82
|
+
tmp.write(_inflate_duc_bytes(data))
|
|
83
|
+
tmp.close()
|
|
84
|
+
return tmp.name
|
|
85
|
+
except Exception:
|
|
86
|
+
tmp.close()
|
|
87
|
+
os.unlink(tmp.name)
|
|
88
|
+
raise
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def _sqlite_path_for_duc(path: Union[str, Path]) -> tuple[str, Optional[str]]:
|
|
92
|
+
path = str(path)
|
|
93
|
+
with open(path, "rb") as f:
|
|
94
|
+
data = f.read()
|
|
95
|
+
if _is_sqlite_bytes(data):
|
|
96
|
+
return path, None
|
|
97
|
+
temp_path = _write_temp_sqlite(data)
|
|
98
|
+
return temp_path, temp_path
|
|
40
99
|
|
|
41
100
|
|
|
42
101
|
def _get_current_schema_version() -> int:
|
|
@@ -105,12 +164,14 @@ class DucSQL:
|
|
|
105
164
|
path = str(path)
|
|
106
165
|
if not os.path.exists(path):
|
|
107
166
|
raise FileNotFoundError(f"File not found: {path}")
|
|
108
|
-
|
|
167
|
+
sqlite_path, temp_path = _sqlite_path_for_duc(path)
|
|
168
|
+
self.conn: sqlite3.Connection = sqlite3.connect(sqlite_path)
|
|
109
169
|
self.conn.row_factory = sqlite3.Row
|
|
110
170
|
_apply_pragmas(self.conn)
|
|
111
171
|
_apply_migrations(self.conn)
|
|
112
|
-
self._path: Optional[str] =
|
|
113
|
-
self._temp: Optional[str] =
|
|
172
|
+
self._path: Optional[str] = sqlite_path
|
|
173
|
+
self._temp: Optional[str] = temp_path
|
|
174
|
+
self._attached_temps: list[str] = []
|
|
114
175
|
self._closed = False
|
|
115
176
|
|
|
116
177
|
@classmethod
|
|
@@ -126,29 +187,68 @@ class DucSQL:
|
|
|
126
187
|
inst.conn.executescript(_read_schema_sql())
|
|
127
188
|
inst._path = target if path else None
|
|
128
189
|
inst._temp = None
|
|
190
|
+
inst._attached_temps = []
|
|
129
191
|
inst._closed = False
|
|
130
192
|
return inst
|
|
131
193
|
|
|
132
194
|
@classmethod
|
|
133
195
|
def from_bytes(cls, data: bytes) -> DucSQL:
|
|
134
196
|
"""Open a ``.duc`` from raw bytes (temp file, cleaned up on close)."""
|
|
135
|
-
|
|
197
|
+
temp_path = _write_temp_sqlite(data)
|
|
136
198
|
try:
|
|
137
|
-
tmp.write(data)
|
|
138
|
-
tmp.close()
|
|
139
199
|
inst = object.__new__(cls)
|
|
140
|
-
inst.conn = sqlite3.connect(
|
|
200
|
+
inst.conn = sqlite3.connect(temp_path)
|
|
141
201
|
inst.conn.row_factory = sqlite3.Row
|
|
142
202
|
_apply_pragmas(inst.conn)
|
|
143
203
|
_apply_migrations(inst.conn)
|
|
144
|
-
inst._path =
|
|
145
|
-
inst._temp =
|
|
204
|
+
inst._path = temp_path
|
|
205
|
+
inst._temp = temp_path
|
|
206
|
+
inst._attached_temps = []
|
|
146
207
|
inst._closed = False
|
|
147
208
|
return inst
|
|
148
209
|
except Exception:
|
|
149
|
-
os.unlink(
|
|
210
|
+
os.unlink(temp_path)
|
|
150
211
|
raise
|
|
151
212
|
|
|
213
|
+
@classmethod
|
|
214
|
+
def attach_many(
|
|
215
|
+
cls,
|
|
216
|
+
paths: Sequence[Union[str, Path]],
|
|
217
|
+
aliases: Optional[Sequence[str]] = None,
|
|
218
|
+
read_only: bool = True,
|
|
219
|
+
) -> DucSQL:
|
|
220
|
+
"""Open an in-memory SQLite connection with multiple ``.duc`` files attached.
|
|
221
|
+
|
|
222
|
+
This is useful for querying multiple drawings in one SQL statement. The
|
|
223
|
+
returned ``DucSQL`` owns only the in-memory connection; attached files are
|
|
224
|
+
not deleted on close.
|
|
225
|
+
"""
|
|
226
|
+
if aliases is not None and len(aliases) != len(paths):
|
|
227
|
+
raise ValueError("aliases must have the same length as paths.")
|
|
228
|
+
|
|
229
|
+
inst = object.__new__(cls)
|
|
230
|
+
inst.conn = sqlite3.connect(":memory:")
|
|
231
|
+
inst.conn.row_factory = sqlite3.Row
|
|
232
|
+
inst._path = None
|
|
233
|
+
inst._temp = None
|
|
234
|
+
inst._attached_temps = []
|
|
235
|
+
inst._closed = False
|
|
236
|
+
|
|
237
|
+
for index, path in enumerate(paths):
|
|
238
|
+
alias = aliases[index] if aliases is not None else f"d{index}"
|
|
239
|
+
sqlite_path, temp_path = _sqlite_path_for_duc(path)
|
|
240
|
+
if temp_path:
|
|
241
|
+
inst._attached_temps.append(temp_path)
|
|
242
|
+
inst.conn.execute(
|
|
243
|
+
f"ATTACH DATABASE ? AS {quote_sql_identifier(alias)}",
|
|
244
|
+
(sqlite_path,),
|
|
245
|
+
)
|
|
246
|
+
|
|
247
|
+
if read_only:
|
|
248
|
+
inst.conn.execute("PRAGMA query_only = ON")
|
|
249
|
+
|
|
250
|
+
return inst
|
|
251
|
+
|
|
152
252
|
# ------------------------------------------------------------------
|
|
153
253
|
# SQL execution
|
|
154
254
|
# ------------------------------------------------------------------
|
|
@@ -186,7 +286,7 @@ class DucSQL:
|
|
|
186
286
|
finally:
|
|
187
287
|
dst.close()
|
|
188
288
|
|
|
189
|
-
def to_bytes(self) -> bytes:
|
|
289
|
+
def to_bytes(self, compressed: bool = False) -> bytes:
|
|
190
290
|
"""Export the database as raw bytes."""
|
|
191
291
|
self.commit()
|
|
192
292
|
tmp = tempfile.NamedTemporaryFile(suffix=".duc", delete=False)
|
|
@@ -196,7 +296,8 @@ class DucSQL:
|
|
|
196
296
|
self.conn.backup(dst)
|
|
197
297
|
dst.close()
|
|
198
298
|
with open(tmp.name, "rb") as f:
|
|
199
|
-
|
|
299
|
+
data = f.read()
|
|
300
|
+
return _deflate_duc_bytes(data) if compressed else data
|
|
200
301
|
finally:
|
|
201
302
|
os.unlink(tmp.name)
|
|
202
303
|
|
|
@@ -210,6 +311,9 @@ class DucSQL:
|
|
|
210
311
|
self._closed = True
|
|
211
312
|
if self._temp and os.path.exists(self._temp):
|
|
212
313
|
os.unlink(self._temp)
|
|
314
|
+
for temp_path in getattr(self, "_attached_temps", []):
|
|
315
|
+
if os.path.exists(temp_path):
|
|
316
|
+
os.unlink(temp_path)
|
|
213
317
|
|
|
214
318
|
def __enter__(self) -> DucSQL:
|
|
215
319
|
return self
|
|
@@ -5,11 +5,15 @@ Serialize DUC data using the Rust native extension (ducpy_native).
|
|
|
5
5
|
from __future__ import annotations
|
|
6
6
|
|
|
7
7
|
import logging
|
|
8
|
+
import builtins
|
|
9
|
+
import contextlib
|
|
10
|
+
import io
|
|
8
11
|
import os
|
|
9
12
|
import re
|
|
10
13
|
import subprocess
|
|
11
14
|
import sys
|
|
12
15
|
import tempfile
|
|
16
|
+
import traceback
|
|
13
17
|
from dataclasses import asdict, is_dataclass
|
|
14
18
|
from pathlib import Path
|
|
15
19
|
from typing import Any, Dict, List, Optional, Tuple
|
|
@@ -256,6 +260,8 @@ builtins.resolve_external_file = resolve_external_file
|
|
|
256
260
|
)
|
|
257
261
|
except subprocess.TimeoutExpired as exc:
|
|
258
262
|
return f"{label}: Python validation timed out after {timeout_seconds:g}s"
|
|
263
|
+
except PermissionError:
|
|
264
|
+
return _run_python_validation_in_process(code, label, tmp_path, resolved_files)
|
|
259
265
|
except OSError as exc:
|
|
260
266
|
return f"{label}: failed to start Python validation: {exc}"
|
|
261
267
|
|
|
@@ -266,6 +272,44 @@ builtins.resolve_external_file = resolve_external_file
|
|
|
266
272
|
return f"{label}: Python validation failed\n{output}"
|
|
267
273
|
|
|
268
274
|
|
|
275
|
+
def _run_python_validation_in_process(
|
|
276
|
+
code: str,
|
|
277
|
+
label: str,
|
|
278
|
+
project_dir: Path,
|
|
279
|
+
resolved_files: Dict[str, str],
|
|
280
|
+
) -> Optional[str]:
|
|
281
|
+
previous_cwd = os.getcwd()
|
|
282
|
+
had_resolver = hasattr(builtins, "resolve_external_file")
|
|
283
|
+
previous_resolver = getattr(builtins, "resolve_external_file", None)
|
|
284
|
+
|
|
285
|
+
def resolve_external_file(file_id: str) -> str:
|
|
286
|
+
if file_id in resolved_files:
|
|
287
|
+
return resolved_files[file_id]
|
|
288
|
+
if callable(previous_resolver):
|
|
289
|
+
return os.fspath(previous_resolver(file_id))
|
|
290
|
+
raise FileNotFoundError(f"External file '{file_id}' not found in validation sandbox.")
|
|
291
|
+
|
|
292
|
+
try:
|
|
293
|
+
os.chdir(project_dir)
|
|
294
|
+
builtins.resolve_external_file = resolve_external_file
|
|
295
|
+
globals_dict = {
|
|
296
|
+
"__name__": "__main__",
|
|
297
|
+
"resolve_external_file": resolve_external_file,
|
|
298
|
+
}
|
|
299
|
+
with contextlib.redirect_stdout(io.StringIO()), contextlib.redirect_stderr(io.StringIO()):
|
|
300
|
+
exec(compile(code, "<ducpy-embedded-model>", "exec"), globals_dict)
|
|
301
|
+
except Exception:
|
|
302
|
+
return f"{label}: Python validation failed\n{traceback.format_exc().strip()}"
|
|
303
|
+
finally:
|
|
304
|
+
os.chdir(previous_cwd)
|
|
305
|
+
if had_resolver:
|
|
306
|
+
builtins.resolve_external_file = previous_resolver
|
|
307
|
+
elif hasattr(builtins, "resolve_external_file"):
|
|
308
|
+
delattr(builtins, "resolve_external_file")
|
|
309
|
+
|
|
310
|
+
return None
|
|
311
|
+
|
|
312
|
+
|
|
269
313
|
def _write_typst_external_files(project_dir: Path, files_meta: Optional[Dict[str, Any]], files_data: Optional[Dict[str, bytes]]) -> None:
|
|
270
314
|
if not files_meta or not files_data:
|
|
271
315
|
return
|
|
@@ -324,7 +368,7 @@ def _validate_embedded_code(
|
|
|
324
368
|
elements: List[Any],
|
|
325
369
|
files_meta: Optional[Dict[str, Any]],
|
|
326
370
|
files_data: Optional[Dict[str, bytes]],
|
|
327
|
-
timeout_seconds: float,
|
|
371
|
+
timeout_seconds: Optional[float],
|
|
328
372
|
) -> None:
|
|
329
373
|
failures: List[str] = []
|
|
330
374
|
|
ducpy-3.3.8/PKG-INFO
DELETED
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: ducpy
|
|
3
|
-
Version: 3.3.8
|
|
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
|
-
|
|
33
|
-
The `ducpy` package provides a robust Python implementation for the `duc` 2D CAD file format, a cornerstone of our advanced design system. Designed for professionals seeking precision and efficiency, this package ensures seamless integration and manipulation of `duc` files within your Python projects.
|
|
34
|
-
|
|
35
|
-
## Introduction
|
|
36
|
-
|
|
37
|
-
The `ducpy` package offers comprehensive Python types and helper functions to work effortlessly with the `duc` CAD file format. Built with efficiency and performance in mind, this package enables you to parse, validate, and manipulate `duc` files with ease.
|
|
38
|
-
|
|
39
|
-
## Features
|
|
40
|
-
|
|
41
|
-
- **Python Support:** Strongly-typed interfaces for all aspects of the `duc` file format, ensuring type safety and IDE support.
|
|
42
|
-
- **Utility Functions:** Easy-to-use functions for parsing, validating, and manipulating `duc` files.
|
|
43
|
-
- **Extensible Architecture:** Designed to integrate seamlessly with other `ducflair` packages and your custom tools.
|
|
44
|
-
- **Performance Optimized:** Efficient processing to handle complex CAD data with ease.
|
|
45
|
-
|
|
46
|
-
## Installation
|
|
47
|
-
|
|
48
|
-
Install the package using pip:
|
|
49
|
-
|
|
50
|
-
```bash
|
|
51
|
-
pip install ducpy
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
## Usage
|
|
55
|
-
|
|
56
|
-
```python
|
|
57
|
-
import ducpy as duc
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
## Documentation
|
|
61
|
-
|
|
62
|
-
For detailed documentation, including all available types and utility functions, visit our [Documentation](https://duc.ducflair.com).
|
|
63
|
-
|
|
64
|
-
## Tools
|
|
65
|
-
|
|
66
|
-
- [Playground](https://scopture.com): Experiment with the `duc` format in a live environment.
|
|
67
|
-
|
|
68
|
-
## Contributing
|
|
69
|
-
|
|
70
|
-
At the moment we are not accepting contributions to this package. However, we welcome feedback and suggestions for future improvements. Feel free to open an issue or contact us at [Ducflair Support](https://www.ducflair.com/support).
|
|
71
|
-
|
|
72
|
-
## License
|
|
73
|
-
|
|
74
|
-
This project is licensed under the MIT License. See the [LICENSE](./LICENSE) file for more details.
|
|
75
|
-
|
|
76
|
-
## Commit Message Guidelines
|
|
77
|
-
|
|
78
|
-
To ensure smooth releases with semantic-release, please follow [these guidelines](https://semantic-release.gitbook.io/semantic-release#how-does-it-work).
|
|
79
|
-
|
|
80
|
-
---
|
|
81
|
-
|
|
82
|
-
*The duc format and libraries are constantly evolving, aiming to set new standards in the 2D CAD industry. Be a part of this transformation and help shape the future of design technology!*
|
|
83
|
-
|
ducpy-3.3.8/README.md
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
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
|
-
|
|
16
|
-
The `ducpy` package provides a robust Python implementation for the `duc` 2D CAD file format, a cornerstone of our advanced design system. Designed for professionals seeking precision and efficiency, this package ensures seamless integration and manipulation of `duc` files within your Python projects.
|
|
17
|
-
|
|
18
|
-
## Introduction
|
|
19
|
-
|
|
20
|
-
The `ducpy` package offers comprehensive Python types and helper functions to work effortlessly with the `duc` CAD file format. Built with efficiency and performance in mind, this package enables you to parse, validate, and manipulate `duc` files with ease.
|
|
21
|
-
|
|
22
|
-
## Features
|
|
23
|
-
|
|
24
|
-
- **Python Support:** Strongly-typed interfaces for all aspects of the `duc` file format, ensuring type safety and IDE support.
|
|
25
|
-
- **Utility Functions:** Easy-to-use functions for parsing, validating, and manipulating `duc` files.
|
|
26
|
-
- **Extensible Architecture:** Designed to integrate seamlessly with other `ducflair` packages and your custom tools.
|
|
27
|
-
- **Performance Optimized:** Efficient processing to handle complex CAD data with ease.
|
|
28
|
-
|
|
29
|
-
## Installation
|
|
30
|
-
|
|
31
|
-
Install the package using pip:
|
|
32
|
-
|
|
33
|
-
```bash
|
|
34
|
-
pip install ducpy
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
## Usage
|
|
38
|
-
|
|
39
|
-
```python
|
|
40
|
-
import ducpy as duc
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
## Documentation
|
|
44
|
-
|
|
45
|
-
For detailed documentation, including all available types and utility functions, visit our [Documentation](https://duc.ducflair.com).
|
|
46
|
-
|
|
47
|
-
## Tools
|
|
48
|
-
|
|
49
|
-
- [Playground](https://scopture.com): Experiment with the `duc` format in a live environment.
|
|
50
|
-
|
|
51
|
-
## Contributing
|
|
52
|
-
|
|
53
|
-
At the moment we are not accepting contributions to this package. However, we welcome feedback and suggestions for future improvements. Feel free to open an issue or contact us at [Ducflair Support](https://www.ducflair.com/support).
|
|
54
|
-
|
|
55
|
-
## License
|
|
56
|
-
|
|
57
|
-
This project is licensed under the MIT License. See the [LICENSE](./LICENSE) file for more details.
|
|
58
|
-
|
|
59
|
-
## Commit Message Guidelines
|
|
60
|
-
|
|
61
|
-
To ensure smooth releases with semantic-release, please follow [these guidelines](https://semantic-release.gitbook.io/semantic-release#how-does-it-work).
|
|
62
|
-
|
|
63
|
-
---
|
|
64
|
-
|
|
65
|
-
*The duc format and libraries are constantly evolving, aiming to set new standards in the 2D CAD industry. Be a part of this transformation and help shape the future of design technology!*
|
|
@@ -1,52 +0,0 @@
|
|
|
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 provides a robust Rust implementation for the `duc` 2D CAD file format, a cornerstone of our advanced design system. Designed for professionals seeking precision and efficiency, this crate ensures seamless integration and manipulation of `duc` files within your Rust projects.
|
|
16
|
-
|
|
17
|
-
## Introduction
|
|
18
|
-
|
|
19
|
-
The `duc` crate offers comprehensive Rust types and helper functions to work effortlessly with the `duc` CAD file format. Built with efficiency and performance in mind, this crate enables you to parse, validate, and manipulate `duc` files with ease.
|
|
20
|
-
|
|
21
|
-
## Features
|
|
22
|
-
|
|
23
|
-
- **Rust Support:** Strongly-typed interfaces for all aspects of the `duc` file format, ensuring type safety and IDE support.
|
|
24
|
-
- **Utility Functions:** Easy-to-use functions for parsing, validating, and manipulating `duc` files.
|
|
25
|
-
- **Extensible Architecture:** Designed to integrate seamlessly with other `ducflair` packages and your custom tools.
|
|
26
|
-
- **Performance Optimized:** Efficient processing to handle complex CAD data with ease.
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
## Documentation
|
|
30
|
-
|
|
31
|
-
For detailed documentation, including all available types and utility functions, visit our [Documentation](https://duc.ducflair.com).
|
|
32
|
-
|
|
33
|
-
## Tools
|
|
34
|
-
|
|
35
|
-
- [Playground](https://ducflair.com/core): Experiment with the `duc` format in a live environment.
|
|
36
|
-
- [Documentation](https://duc.ducflair.com): Comprehensive guides and API references.
|
|
37
|
-
|
|
38
|
-
## Contributing
|
|
39
|
-
|
|
40
|
-
At the moment we are not accepting contributions to this crate. However, we welcome feedback and suggestions for future improvements. Feel free to open an issue or contact us at [Ducflair Support](https://www.ducflair.com/support).
|
|
41
|
-
|
|
42
|
-
## License
|
|
43
|
-
|
|
44
|
-
This project is licensed under the MIT License. See the [LICENSE](./LICENSE) file for more details.
|
|
45
|
-
|
|
46
|
-
## Commit Message Guidelines
|
|
47
|
-
|
|
48
|
-
To ensure smooth releases with semantic-release, please follow [these guidelines](https://semantic-release.gitbook.io/semantic-release#how-does-it-work).
|
|
49
|
-
|
|
50
|
-
---
|
|
51
|
-
|
|
52
|
-
*The duc format and libraries are constantly evolving, aiming to set new standards in the 2D CAD industry. Be a part of this transformation and help shape the future of design technology!*
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|