diff --git a/CLAUDE.md b/CLAUDE.md index 1622c08..5be80c2 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -4,7 +4,7 @@ Python bindings for [libdigidocpp](https://github.com/open-eid/libdigidocpp) via ## Architecture -- `libdigidocpp/` — upstream C++ library as a git submodule (pinned to v4.3.0) +- `libdigidocpp/` — upstream C++ library as a git submodule (pinned to v4.4.0) - `CMakeLists.txt` — builds upstream statically, then builds SWIG Python module - `swig/pydigidoc.i` — thin wrapper: `%rename` for snake_case + `%include "libdigidocpp.i"` - `src/pydigidoc/__init__.py` — re-exports SWIG symbols, wraps `initialize()` to use bundled schema files @@ -13,8 +13,8 @@ Python bindings for [libdigidocpp](https://github.com/open-eid/libdigidocpp) via ## Key decisions - **Static linking** (`BUILD_SHARED_LIBS=OFF`) — self-contained wheels, LGPL-2.1 compliance via RELINKING.md + sdist source -- **`ANDROID=TRUE` hack** in CMake — skips upstream `install(EXPORT)` which fails with static builds -- **Symlinks** (`etc/`, `cmake/`) created at configure time — upstream uses `CMAKE_SOURCE_DIR` which points to our root, not the submodule +- **`install()` override hack** — suppresses upstream install rules that fail on Windows static builds due to `$` on static targets. Remove when [#722](https://github.com/open-eid/libdigidocpp/pull/722) is merged. +- **`digidocpp_EXPORTS` hack** — defines `digidocpp_EXPORTS` on static targets so `Exports.h` doesn't default to `__declspec(dllimport)` on Windows. Remove when [#723](https://github.com/open-eid/libdigidocpp/pull/723) is merged. - **SWIG `%rename` before `%include`** — order matters, upstream `.i` declares `%module(directors="1") digidoc` ## Test diff --git a/CMakeLists.txt b/CMakeLists.txt index 014a94c..3e42e7f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,24 +5,6 @@ set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX_STANDARD_REQUIRED YES) set(CMAKE_POSITION_INDEPENDENT_CODE ON) -# Upstream uses CMAKE_SOURCE_DIR for paths to etc/ and cmake/modules/. -# When included via add_subdirectory(), CMAKE_SOURCE_DIR is our root, -# not the submodule root. Create symlinks (or copies on Windows) so -# those references resolve. -foreach(_DIR etc cmake) - if(NOT EXISTS ${CMAKE_SOURCE_DIR}/${_DIR}) - if(WIN32) - file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/libdigidocpp/${_DIR} - DESTINATION ${CMAKE_SOURCE_DIR}) - else() - file(CREATE_LINK - libdigidocpp/${_DIR} - ${CMAKE_SOURCE_DIR}/${_DIR} - SYMBOLIC) - endif() - endif() -endforeach() - # Suppress upstream's SWIG/tools/framework/docs builds set(CMAKE_DISABLE_FIND_PACKAGE_SWIG TRUE) set(CMAKE_DISABLE_FIND_PACKAGE_Doxygen TRUE) @@ -31,10 +13,6 @@ set(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE) set(BUILD_TOOLS OFF CACHE BOOL "" FORCE) set(FRAMEWORK OFF CACHE BOOL "" FORCE) -# Skip upstream install(EXPORT) — fails with static builds because minizip -# and digidocpp_priv aren't in the export set. We don't need the export config. -set(ANDROID TRUE) - # On macOS, prefer Homebrew's libxml2 over Xcode SDK to avoid ABI mismatches. # Homebrew xmlsec1 links Homebrew libxml2 2.15+, but CMake finds SDK libxml2 2.9; # the ABI difference causes segfaults at runtime. Homebrew libxml2 is keg-only, @@ -72,7 +50,6 @@ if(WIN32 AND NOT BUILD_SHARED_LIBS) target_compile_definitions(digidocpp_util PUBLIC digidocpp_EXPORTS) endif() -unset(ANDROID) set(CMAKE_DISABLE_FIND_PACKAGE_SWIG FALSE) # Verify upstream SWIG interface has the expected module declaration diff --git a/libdigidocpp b/libdigidocpp index 049d848..68ec5bf 160000 --- a/libdigidocpp +++ b/libdigidocpp @@ -1 +1 @@ -Subproject commit 049d84834f6b5cb544c53d055162b38373669cb1 +Subproject commit 68ec5bf6a84d63a48dcfbc891fe1bf21fff4429e diff --git a/tests/conftest.py b/tests/conftest.py index a82c5b5..fea6a63 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -3,9 +3,14 @@ import pydigidoc -@pytest.fixture() +@pytest.fixture(scope="session") def lib(): - """Initialize and terminate pydigidoc around each test.""" + """Initialize pydigidoc once per test session. + + Session-scoped because libdigidocpp segfaults on re-initialize + (init -> terminate -> init) on macOS/Windows with current EU TSL + data. See pydigidoc PR #6 / libdigidocpp upstream. + """ pydigidoc.initialize("pydigidoc-test") yield pydigidoc.terminate() diff --git a/tests/test_basic.py b/tests/test_basic.py index 969de7f..a8fbb28 100644 --- a/tests/test_basic.py +++ b/tests/test_basic.py @@ -1,5 +1,9 @@ """Basic tests for pydigidoc bindings.""" +import sys + +import pytest + import pydigidoc @@ -153,6 +157,11 @@ def test_user_agent(self, lib): assert isinstance(ua, str) assert ua + @pytest.mark.skipif( + not sys.platform.startswith("linux"), + reason="libdigidocpp segfaults on init after a prior terminate " + "on macOS/Windows with current TSL data", + ) def test_initialize_lib_custom_path(self, tmp_path): """Test initialize_lib() with a custom schema directory.""" schema_dir = pydigidoc._SCHEMA_DIR