diff --git a/packages/ducpdf/src/duc2pdf/README.md b/packages/ducpdf/src/duc2pdf/README.md index 3722c59a..c6ea9f59 100644 --- a/packages/ducpdf/src/duc2pdf/README.md +++ b/packages/ducpdf/src/duc2pdf/README.md @@ -79,4 +79,4 @@ To ensure smooth releases with semantic-release, please follow [these guidelines --- -*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!* +*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!* \ No newline at end of file diff --git a/packages/ducpdf/src/duc2pdf/release.config.cjs b/packages/ducpdf/src/duc2pdf/release.config.cjs index 24f52b09..bb74bf0e 100644 --- a/packages/ducpdf/src/duc2pdf/release.config.cjs +++ b/packages/ducpdf/src/duc2pdf/release.config.cjs @@ -23,7 +23,7 @@ module.exports = { // 2. Set the crate version // 3. Build the project prepareCmd: - "node ../../../../scripts/cargo-set-duc-dep-version.js . 2 && cargo set-version ${nextRelease.version} && cargo build --release", + "node ../../../../scripts/cargo-set-duc-dep-version.js . 3 && cargo set-version ${nextRelease.version} && cargo build --release", // Publish step: Publish the crate to crates.io publishCmd: diff --git a/packages/ducpy/src/ducpy/serialize.py b/packages/ducpy/src/ducpy/serialize.py index 068a6406..a4f37b26 100644 --- a/packages/ducpy/src/ducpy/serialize.py +++ b/packages/ducpy/src/ducpy/serialize.py @@ -5,16 +5,56 @@ from __future__ import annotations import logging +import re from dataclasses import asdict, is_dataclass +from pathlib import Path from typing import Any, Dict, List, Optional, Union import ducpy_native -from ducpy._version import DUC_SCHEMA_VERSION from ducpy.utils.convert import (deep_snake_to_camel, snake_to_camel, to_serializable) logger = logging.getLogger(__name__) + +def _decode_user_version_to_semver(user_version: int) -> str: + """Decode sqlite-style schema user_version to semver. + + Encoding convention: + major * 1_000_000 + minor * 1_000 + patch + """ + if user_version < 0: + return "0.0.0" + + major = user_version // 1_000_000 + minor = (user_version % 1_000_000) // 1_000 + patch = user_version % 1_000 + return f"{major}.{minor}.{patch}" + + +def _read_schema_version_fallback() -> str: + """Resolve schema version directly from repository `schema/duc.sql`. + + This is used when `ducpy._version` isn't available (for example, in clean + CI environments before setup-time generation has run). + """ + try: + schema_path = Path(__file__).resolve().parents[4] / "schema" / "duc.sql" + content = schema_path.read_text(encoding="utf-8") + match = re.search(r"PRAGMA\s+user_version\s*=\s*(\d+)\s*;", content) + if match: + return _decode_user_version_to_semver(int(match.group(1))) + except Exception as exc: # pragma: no cover - defensive fallback for CI/runtime variance + logger.warning("Failed to resolve schema version fallback from duc.sql: %s", exc) + + return "0.0.0" + + +try: + from ducpy._version import DUC_SCHEMA_VERSION +except ModuleNotFoundError: + DUC_SCHEMA_VERSION = _read_schema_version_fallback() + # Map Python element class names → Rust serde type tag strings. _ELEMENT_CLASS_TO_TYPE: Dict[str, str] = { "DucRectangleElement": "rectangle",