From 140fb6463f7a4ee9beb3298f1b041470b6f051b7 Mon Sep 17 00:00:00 2001 From: Tania Mathern Date: Thu, 21 Aug 2025 20:06:13 -0700 Subject: [PATCH 01/16] feat: wheel for mac is universal wheel now --- .github/workflows/build-wheel.yml | 8 +-- .github/workflows/build.yml | 22 ++++--- setup.py | 22 ++----- src/c2pa/lib.py | 98 ++++++++++++++++--------------- 4 files changed, 75 insertions(+), 75 deletions(-) diff --git a/.github/workflows/build-wheel.yml b/.github/workflows/build-wheel.yml index d7b5fcaf..0bebed04 100644 --- a/.github/workflows/build-wheel.yml +++ b/.github/workflows/build-wheel.yml @@ -109,8 +109,8 @@ jobs: # Build wheel python setup.py bdist_wheel --plat-name win_amd64 - - name: Build macOS wheel (Apple Silicon) - if: runner.os == 'macOS' && runner.arch == 'arm64' + - name: Build macOS wheel (Universal) + if: runner == 'macos-latest' run: | # Create necessary directories mkdir -p artifacts @@ -126,12 +126,12 @@ jobs: python scripts/download_artifacts.py $C2PA_VERSION # Build wheel - python setup.py bdist_wheel --plat-name macosx_11_0_arm64 + python setup.py bdist_wheel --plat-name macosx_10_9_universal2 # Rename wheel to ensure unique filename cd dist for wheel in *.whl; do - mv "$wheel" "${wheel/macosx_11_0_arm64/macosx_11_0_arm64}" + mv "$wheel" "${wheel/macosx_10_9_universal2/macosx_10_9_universal2}" done cd .. diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6978367a..37d3e791 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -51,7 +51,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ macos-latest, ubuntu-latest, ubuntu-24.04-arm ] + os: [ macos-latest, ubuntu-latest, ubuntu-24.04-arm] steps: - name: Checkout repository @@ -105,7 +105,7 @@ jobs: github.event.pull_request.user.login == 'dependabot[bot]' || contains(github.event.pull_request.labels.*.name, 'safe to test') - runs-on: windows-latest + runs-on: [windows-latest, windows-2022] steps: - name: Checkout repository @@ -326,19 +326,22 @@ jobs: .\venv\Scripts\pytest .\tests\test_unit_tests.py -v build-macos-wheel: - name: Build macOS wheel + name: Build macOS wheel (Universal) uses: ./.github/workflows/build-wheel.yml needs: [tests-unix, read-version] with: python-version: "3.10" artifact-name: wheels-macos-${{ matrix.target }} - runs-on: macos-latest + architecture: ${{ matrix.target }} c2pa-version: ${{ needs.read-version.outputs.c2pa-native-version }} secrets: github-token: ${{ secrets.GITHUB_TOKEN }} strategy: matrix: - target: [aarch64] + include: + - target: universal2 + runs-on: macos-latest + if: | github.event_name != 'pull_request' || github.event.pull_request.author_association == 'COLLABORATOR' || @@ -347,12 +350,15 @@ jobs: contains(github.event.pull_request.labels.*.name, 'safe to test') test-built-macos-wheel: - name: Test macOS built wheel + name: Test macOS built wheel (Universal) needs: build-macos-wheel runs-on: macos-latest strategy: matrix: - target: [aarch64] + include: + - target: universal2 + runs-on: macos-latest + if: | github.event_name != 'pull_request' || github.event.pull_request.author_association == 'COLLABORATOR' || @@ -452,7 +458,7 @@ jobs: run: | echo "Downloaded Artifacts" ls -la dist/ - - name: Publish to PyPI + - name: Publish to TestPyPI uses: pypa/gh-action-pypi-publish@release/v1 with: packages-dir: dist diff --git a/setup.py b/setup.py index 1216abdc..03fccaa2 100644 --- a/setup.py +++ b/setup.py @@ -17,8 +17,7 @@ def get_version(): PLATFORM_EXTENSIONS = { 'win_amd64': 'dll', 'win_arm64': 'dll', - 'macosx_x86_64': 'dylib', - 'apple-darwin': 'dylib', # we need to update the published keys + 'apple-darwin': 'dylib', # universal 'linux_x86_64': 'so', 'linux_aarch64': 'so', } @@ -26,11 +25,9 @@ def get_version(): # Based on what c2pa-rs repo publishes PLATFORM_FOLDERS = { 'universal-apple-darwin': 'dylib', - 'aarch64-apple-darwin': 'dylib', - 'x86_64-apple-darwin': 'dylib', 'x86_64-pc-windows-msvc': 'dll', 'x86_64-unknown-linux-gnu': 'so', - 'aarch64-unknown-linux-gnu': 'so', # Add ARM Linux support + 'aarch64-unknown-linux-gnu': 'so', } # Directory structure @@ -38,7 +35,7 @@ def get_version(): PACKAGE_LIBS_DIR = Path('src/c2pa/libs') # Where libraries will be copied for the wheel -def get_platform_identifier(cpu_arch = None) -> str: +def get_platform_identifier() -> str: """Get a platform identifier (arch-os) for the current system, matching downloaded identifiers used by the Github publisher. @@ -47,9 +44,7 @@ def get_platform_identifier(cpu_arch = None) -> str: cpu_arch: Optional CPU architecture for macOS. If not provided, returns universal build. Returns one of: - - universal-apple-darwin (for Mac, when cpu_arch is None, fallback) - - aarch64-apple-darwin (for Mac ARM64) - - x86_64-apple-darwin (for Mac x86_64) + - universal-apple-darwin (for macOS) - x86_64-pc-windows-msvc (for Windows 64-bit) - x86_64-unknown-linux-gnu (for Linux 64-bit) - aarch64-unknown-linux-gnu (for Linux ARM64) @@ -57,14 +52,7 @@ def get_platform_identifier(cpu_arch = None) -> str: system = platform.system().lower() if system == "darwin": - if cpu_arch is None: - return "universal-apple-darwin" - elif cpu_arch == "arm64": - return "aarch64-apple-darwin" - elif cpu_arch == "x86_64": - return "x86_64-apple-darwin" - else: - raise ValueError(f"Unsupported CPU architecture for macOS: {cpu_arch}") + return "universal-apple-darwin" elif system == "windows": return "x86_64-pc-windows-msvc" elif system == "linux": diff --git a/src/c2pa/lib.py b/src/c2pa/lib.py index 186c8d3a..255e4cc4 100644 --- a/src/c2pa/lib.py +++ b/src/c2pa/lib.py @@ -10,15 +10,19 @@ import logging import platform from pathlib import Path -from typing import Optional, Tuple +from typing import Optional from enum import Enum # Debug flag for library loading DEBUG_LIBRARY_LOADING = False -# Create a module-specific logger with NullHandler to avoid interfering with global configuration -logger = logging.getLogger("c2pa") -logger.addHandler(logging.NullHandler()) +# Configure logging +logging.basicConfig( + level=logging.INFO, + format='%(asctime)s - %(levelname)s - %(message)s', + force=True # Force configuration even if already configured +) +logger = logging.getLogger(__name__) class CPUArchitecture(Enum): @@ -27,34 +31,20 @@ class CPUArchitecture(Enum): X86_64 = "x86_64" -def get_platform_identifier(cpu_arch: Optional[CPUArchitecture] = None) -> str: - """Get the full platform identifier (arch-os) for the current system, +def get_platform_identifier() -> str: + """Get the platform identifier (arch-os) for the current system, matching the downloaded identifiers used by the Github publisher. - Args: - cpu_arch: Optional CPU architecture for macOS. - If not provided, returns universal build. - Only used on macOS systems. - Returns one of: - - universal-apple-darwin (for Mac, when cpu_arch is None) - - aarch64-apple-darwin (for Mac ARM64) - - x86_64-apple-darwin (for Mac x86_64) + - universal-apple-darwin (for Mac, ARM or Intel) - x86_64-pc-windows-msvc (for Windows 64-bit) - x86_64-unknown-linux-gnu (for Linux 64-bit) + - aarch64-unknown-linux-gnu (for Linux ARM) """ system = platform.system().lower() if system == "darwin": - if cpu_arch is None: - return "universal-apple-darwin" - elif cpu_arch == CPUArchitecture.AARCH64: - return "aarch64-apple-darwin" - elif cpu_arch == CPUArchitecture.X86_64: - return "x86_64-apple-darwin" - else: - raise ValueError( - f"Unsupported CPU architecture for macOS: {cpu_arch}") + return "universal-apple-darwin" elif system == "windows": return "x86_64-pc-windows-msvc" elif system == "linux": @@ -81,7 +71,8 @@ def _get_architecture() -> str: elif sys.platform == "linux": return platform.machine() elif sys.platform == "win32": - # win32 will cover all Windows versions (the 32 is a historical quirk) + # win32 will cover all Windows versions + # (the 32 is a historical quirk) return platform.machine() else: raise RuntimeError(f"Unsupported platform: {sys.platform}") @@ -99,7 +90,8 @@ def _get_platform_dir() -> str: elif sys.platform == "linux": return "unknown-linux-gnu" elif sys.platform == "win32": - # win32 will cover all Windows versions (the 32 is a historical quirk) + # win32 will cover all Windows versions + # (the 32 is a historical quirk) return "pc-windows-msvc" else: raise RuntimeError(f"Unsupported platform: {sys.platform}") @@ -117,28 +109,31 @@ def _load_single_library(lib_name: str, Returns: The loaded library or None if loading failed """ - if DEBUG_LIBRARY_LOADING: - logger.info(f"Searching for library '{lib_name}' in paths: {[str(p) for p in search_paths]}") + if DEBUG_LIBRARY_LOADING: # pragma: no cover + logger.info( + f"Searching for library '{lib_name}' in paths: {[str(p) for p in search_paths]}") current_arch = _get_architecture() - if DEBUG_LIBRARY_LOADING: + if DEBUG_LIBRARY_LOADING: # pragma: no cover logger.info(f"Current architecture: {current_arch}") for path in search_paths: lib_path = path / lib_name - if DEBUG_LIBRARY_LOADING: + if DEBUG_LIBRARY_LOADING: # pragma: no cover logger.info(f"Checking path: {lib_path}") if lib_path.exists(): - if DEBUG_LIBRARY_LOADING: + if DEBUG_LIBRARY_LOADING: # pragma: no cover logger.info(f"Found library at: {lib_path}") try: return ctypes.CDLL(str(lib_path)) except Exception as e: error_msg = str(e) if "incompatible architecture" in error_msg: - logger.error(f"Architecture mismatch: Library at {lib_path} is not compatible with current architecture {current_arch}") + logger.error( + f"Architecture mismatch: Library at {lib_path} is not compatible with current architecture {current_arch}") logger.error(f"Error details: {error_msg}") else: - logger.error(f"Failed to load library from {lib_path}: {e}") + logger.error( + f"Failed to load library from {lib_path}: {e}") else: logger.debug(f"Library not found at: {lib_path}") return None @@ -155,7 +150,7 @@ def _get_possible_search_paths() -> list[Path]: platform_dir = _get_platform_dir() platform_id = get_platform_identifier() - if DEBUG_LIBRARY_LOADING: + if DEBUG_LIBRARY_LOADING: # pragma: no cover logger.info(f"Using platform directory: {platform_dir}") logger.info(f"Using platform identifier: {platform_id}") @@ -196,9 +191,12 @@ def dynamically_load_library( Load the dynamic library containing the C-API based on the platform. Args: - lib_name: Optional specific library name to load. If provided, only this library will be loaded. - This enables to potentially load wrapper libraries of the C-API that may have an other name - (the presence of required symbols will nevertheless be verified once the library is loaded). + lib_name: Optional specific library name to load. + If provided, only this library will be loaded. + This enables to potentially load wrapper libraries + of the C-API that may have an other name + (the presence of required symbols will nevertheless + be verified once the library is loaded). Returns: The loaded library or None if loading failed @@ -212,7 +210,7 @@ def dynamically_load_library( else: raise RuntimeError(f"Unsupported platform: {sys.platform}") - if DEBUG_LIBRARY_LOADING: + if DEBUG_LIBRARY_LOADING: # pragma: no cover logger.info(f"Current working directory: {Path.cwd()}") logger.info(f"Package directory: {Path(__file__).parent}") logger.info(f"System architecture: {_get_architecture()}") @@ -220,7 +218,7 @@ def dynamically_load_library( # Check for C2PA_LIBRARY_NAME environment variable env_lib_name = os.environ.get("C2PA_LIBRARY_NAME") if env_lib_name: - if DEBUG_LIBRARY_LOADING: + if DEBUG_LIBRARY_LOADING: # pragma: no cover logger.info( f"Using library name from env var C2PA_LIBRARY_NAME: {env_lib_name}") try: @@ -229,13 +227,14 @@ def dynamically_load_library( if lib: return lib else: - logger.error(f"Could not find library {env_lib_name} in any of the search paths") + logger.error( + f"Could not find library {env_lib_name} in any of the search paths") # Continue with normal loading if environment variable library # name fails except Exception as e: logger.error(f"Failed to load library from C2PA_LIBRARY_NAME: {e}") - # Continue with normal loading if environment variable library name - # fails + # Continue with normal loading if + # environment variable library name fails possible_paths = _get_possible_search_paths() @@ -245,15 +244,22 @@ def dynamically_load_library( if not lib: platform_id = get_platform_identifier() current_arch = _get_architecture() - logger.error(f"Could not find {lib_name} in any of the search paths: {[str(p) for p in possible_paths]}") - logger.error(f"Platform: {platform_id}, Architecture: {current_arch}") - raise RuntimeError(f"Could not find {lib_name} in any of the search paths (Platform: {platform_id}, Architecture: {current_arch})") + logger.error( + f"Could not find {lib_name} in any of the search paths: {[str(p) for p in possible_paths]}") + logger.error( + f"Platform: {platform_id}, Architecture: {current_arch}") + raise RuntimeError( + f"Could not find {lib_name} in any of the search paths (Platform: {platform_id}, Architecture: {current_arch})") return lib # Default path (no library name provided in the environment) c2pa_lib = _load_single_library(c2pa_lib_name, possible_paths) if not c2pa_lib: - logger.error(f"Could not find {c2pa_lib_name} in any of the search paths: {[str(p) for p in possible_paths]}") - raise RuntimeError(f"Could not find {c2pa_lib_name} in any of the search paths") + logger.error( + f"Could not find {c2pa_lib_name} in any of the search paths: { + [ + str(p) for p in possible_paths]}") + raise RuntimeError( + f"Could not find {c2pa_lib_name} in any of the search paths") return c2pa_lib From 51ad041b4e236e88d7933091af6f993c2a2705b7 Mon Sep 17 00:00:00 2001 From: Tania Mathern Date: Thu, 21 Aug 2025 20:07:07 -0700 Subject: [PATCH 02/16] chore: Clean up --- .github/workflows/upload-test.yml | 98 ------------------------------- 1 file changed, 98 deletions(-) delete mode 100644 .github/workflows/upload-test.yml diff --git a/.github/workflows/upload-test.yml b/.github/workflows/upload-test.yml deleted file mode 100644 index 8bacc094..00000000 --- a/.github/workflows/upload-test.yml +++ /dev/null @@ -1,98 +0,0 @@ -name: Upload Test for Pypi. - -on: - workflow_dispatch: - -jobs: - linux: - runs-on: ubuntu-latest - - strategy: - matrix: - target: [aarch64] - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 - with: - python-version: "3.10" - cache: "pip" - - run: pip install -r requirements.txt - - name: Setup QEMU - uses: docker/setup-qemu-action@v1 - if: ${{ matrix.target == 'aarch64' }} - - name: Build wheels - uses: PyO3/maturin-action@v1 - with: - target: ${{ matrix.target }} - maturin-version: "1.2.0" - args: --release --out dist --find-interpreter - sccache: "true" - manylinux: ${{ matrix.target == 'aarch64' && 'manylinux_2_28' || 'auto' }} - before-script-linux: | - pip install uniffi-bindgen==0.24.1 - - # ISSUE: https://github.com/sfackler/rust-openssl/issues/2036#issuecomment-1724324145 - # If we're running on rhel centos, install needed packages. - if command -v yum &> /dev/null; then - yum update -y && yum install -y perl-core openssl openssl-devel pkgconfig libatomic - - # If we're running on i686 we need to symlink libatomic - # in order to build openssl with -latomic flag. - if [[ ! -d "/usr/lib64" ]]; then - ln -s /usr/lib/libatomic.so.1 /usr/lib/libatomic.so - fi - else - # If we're running on debian-based system. - apt update -y && apt-get install -y libssl-dev openssl pkg-config - fi - - name: Upload wheels - uses: actions/upload-artifact@v4 - with: - name: wheels-${{ matrix.target }} - path: dist - - sdist: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - name: Build sdist - uses: PyO3/maturin-action@v1 - with: - command: sdist - args: --out dist - - name: Upload sdist - uses: actions/upload-artifact@v4 - with: - name: wheels - path: dist - - pypi-publish: - name: upload release to PyPI - runs-on: ubuntu-latest - needs: [linux, sdist] - - # Specifying a GitHub environment is optional, but strongly encouraged - environment: testpublish - permissions: - # IMPORTANT: this permission is mandatory for Trusted Publishing - id-token: write - steps: - # retrieve your distributions here - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Download aarch64 wheels artifact - uses: actions/download-artifact@v4 - with: - name: wheels-aarch64 - - - name: Download sdist artifact - uses: actions/download-artifact@v4 - with: - name: sdist - - - name: Publish package distributions to PyPI - uses: pypa/gh-action-pypi-publish@release/v1 - with: - repository-url: https://test.pypi.org/legacy/ \ No newline at end of file From 4df0620f518f5fbfb8cf99a0275a27e767306641 Mon Sep 17 00:00:00 2001 From: Tania Mathern Date: Thu, 21 Aug 2025 20:11:21 -0700 Subject: [PATCH 03/16] fix: Universal pipeline --- .github/workflows/build.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 37d3e791..0aeb8b24 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -51,7 +51,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ macos-latest, ubuntu-latest, ubuntu-24.04-arm] + os: [ macos-latest, ubuntu-latest, ubuntu-24.04-arm ] steps: - name: Checkout repository @@ -105,7 +105,7 @@ jobs: github.event.pull_request.user.login == 'dependabot[bot]' || contains(github.event.pull_request.labels.*.name, 'safe to test') - runs-on: [windows-latest, windows-2022] + runs-on: [ windows-latest, windows-2022 ] steps: - name: Checkout repository @@ -331,6 +331,7 @@ jobs: needs: [tests-unix, read-version] with: python-version: "3.10" + runs-on: macos-latest artifact-name: wheels-macos-${{ matrix.target }} architecture: ${{ matrix.target }} c2pa-version: ${{ needs.read-version.outputs.c2pa-native-version }} @@ -458,7 +459,7 @@ jobs: run: | echo "Downloaded Artifacts" ls -la dist/ - - name: Publish to TestPyPI + - name: Publish to PyPI uses: pypa/gh-action-pypi-publish@release/v1 with: packages-dir: dist From 660e15981135b7781ba6199b5a25f561a002dce9 Mon Sep 17 00:00:00 2001 From: Tania Mathern Date: Thu, 21 Aug 2025 20:12:56 -0700 Subject: [PATCH 04/16] fix: Universal pipeline --- src/c2pa/lib.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/c2pa/lib.py b/src/c2pa/lib.py index 255e4cc4..cab14324 100644 --- a/src/c2pa/lib.py +++ b/src/c2pa/lib.py @@ -255,11 +255,7 @@ def dynamically_load_library( # Default path (no library name provided in the environment) c2pa_lib = _load_single_library(c2pa_lib_name, possible_paths) if not c2pa_lib: - logger.error( - f"Could not find {c2pa_lib_name} in any of the search paths: { - [ - str(p) for p in possible_paths]}") - raise RuntimeError( - f"Could not find {c2pa_lib_name} in any of the search paths") + logger.error(f"Could not find {c2pa_lib_name} in any of the search paths: {[str(p) for p in possible_paths]}") + raise RuntimeError(f"Could not find {c2pa_lib_name} in any of the search paths") return c2pa_lib From 5c8ac0f608b489982275bb0f051b94e5b9940cf5 Mon Sep 17 00:00:00 2001 From: Tania Mathern Date: Thu, 21 Aug 2025 20:18:06 -0700 Subject: [PATCH 05/16] fix: Universal pipeline --- .github/workflows/build-wheel.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-wheel.yml b/.github/workflows/build-wheel.yml index 0bebed04..8f73d2ad 100644 --- a/.github/workflows/build-wheel.yml +++ b/.github/workflows/build-wheel.yml @@ -110,7 +110,7 @@ jobs: python setup.py bdist_wheel --plat-name win_amd64 - name: Build macOS wheel (Universal) - if: runner == 'macos-latest' + if: runner.os == 'macOS' run: | # Create necessary directories mkdir -p artifacts From 407a423a87d0d54af959ffa9720f5c05a39f82d6 Mon Sep 17 00:00:00 2001 From: Tania Mathern Date: Thu, 21 Aug 2025 20:19:02 -0700 Subject: [PATCH 06/16] fix: Universal pipeline --- src/c2pa/lib.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/c2pa/lib.py b/src/c2pa/lib.py index cab14324..2f22a3f0 100644 --- a/src/c2pa/lib.py +++ b/src/c2pa/lib.py @@ -16,13 +16,9 @@ # Debug flag for library loading DEBUG_LIBRARY_LOADING = False -# Configure logging -logging.basicConfig( - level=logging.INFO, - format='%(asctime)s - %(levelname)s - %(message)s', - force=True # Force configuration even if already configured -) -logger = logging.getLogger(__name__) +# Create a module-specific logger with NullHandler to avoid interfering with global configuration +logger = logging.getLogger("c2pa") +logger.addHandler(logging.NullHandler()) class CPUArchitecture(Enum): From 6cf92098dbc8912abb56e4ee7c0a37167ed583ed Mon Sep 17 00:00:00 2001 From: Tania Mathern Date: Thu, 21 Aug 2025 20:22:28 -0700 Subject: [PATCH 07/16] fix: Universal pipeline --- .github/workflows/build.yml | 2 +- pyproject.toml | 2 +- src/c2pa/lib.py | 6 ------ 3 files changed, 2 insertions(+), 8 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0aeb8b24..dd16ffdb 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -105,7 +105,7 @@ jobs: github.event.pull_request.user.login == 'dependabot[bot]' || contains(github.event.pull_request.labels.*.name, 'safe to test') - runs-on: [ windows-latest, windows-2022 ] + runs-on: windows-latest steps: - name: Checkout repository diff --git a/pyproject.toml b/pyproject.toml index ea41c1b3..d0e45cb7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "c2pa-python" -version = "0.12.1" +version = "0.13.0" requires-python = ">=3.10" description = "Python bindings for the C2PA Content Authenticity Initiative (CAI) library" readme = { file = "README.md", content-type = "text/markdown" } diff --git a/src/c2pa/lib.py b/src/c2pa/lib.py index 2f22a3f0..a5af902e 100644 --- a/src/c2pa/lib.py +++ b/src/c2pa/lib.py @@ -21,12 +21,6 @@ logger.addHandler(logging.NullHandler()) -class CPUArchitecture(Enum): - """CPU architecture enum for platform-specific identifiers.""" - AARCH64 = "aarch64" - X86_64 = "x86_64" - - def get_platform_identifier() -> str: """Get the platform identifier (arch-os) for the current system, matching the downloaded identifiers used by the Github publisher. From cdf685caf3202b33abb76bec46b23ba18e37386c Mon Sep 17 00:00:00 2001 From: Tania Mathern Date: Thu, 21 Aug 2025 20:25:53 -0700 Subject: [PATCH 08/16] fix: Universal pipeline --- src/c2pa/lib.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/c2pa/lib.py b/src/c2pa/lib.py index a5af902e..e0884467 100644 --- a/src/c2pa/lib.py +++ b/src/c2pa/lib.py @@ -21,6 +21,13 @@ logger.addHandler(logging.NullHandler()) +class CPUArchitecture(Enum): + """CPU architecture enum for platform-specific identifiers.""" + AARCH64 = "aarch64" + X86_64 = "x86_64" + ARM64 = "arm64" + + def get_platform_identifier() -> str: """Get the platform identifier (arch-os) for the current system, matching the downloaded identifiers used by the Github publisher. @@ -38,7 +45,7 @@ def get_platform_identifier() -> str: elif system == "windows": return "x86_64-pc-windows-msvc" elif system == "linux": - if _get_architecture() in ['arm64', 'aarch64']: + if _get_architecture() in [CPUArchitecture.ARM64, CPUArchitecture.AARCH64]: return "aarch64-unknown-linux-gnu" return "x86_64-unknown-linux-gnu" else: @@ -55,9 +62,9 @@ def _get_architecture() -> str: if sys.platform == "darwin": # On macOS, we need to check if we're running under Rosetta if platform.processor() == 'arm': - return 'arm64' + return CPUArchitecture.ARM64 else: - return 'x86_64' + return CPUArchitecture.ARM64.X86_64 elif sys.platform == "linux": return platform.machine() elif sys.platform == "win32": From 2373248d2f7185c248a088568826f07decf44d74 Mon Sep 17 00:00:00 2001 From: Tania Mathern Date: Thu, 21 Aug 2025 20:29:51 -0700 Subject: [PATCH 09/16] fix: Universal pipeline --- .github/workflows/build-wheel.yml | 5 +++++ src/c2pa/lib.py | 6 +++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-wheel.yml b/.github/workflows/build-wheel.yml index 8f73d2ad..490ef365 100644 --- a/.github/workflows/build-wheel.yml +++ b/.github/workflows/build-wheel.yml @@ -72,6 +72,9 @@ jobs: rm -f /io/dist/*-linux_*.whl " + # Install twine to verify wheels + pip install twine + # Verify the wheel was built echo "Contents of dist directory:" ls -la dist/ @@ -94,6 +97,7 @@ jobs: pip install -r requirements.txt pip install -r requirements-dev.txt pip install wheel + pip install twine # Download native artifacts Write-Host "Starting artifact download process..." @@ -121,6 +125,7 @@ jobs: pip install -r requirements.txt pip install -r requirements-dev.txt pip install wheel + pip install twine # Download native artifacts python scripts/download_artifacts.py $C2PA_VERSION diff --git a/src/c2pa/lib.py b/src/c2pa/lib.py index e0884467..af324b93 100644 --- a/src/c2pa/lib.py +++ b/src/c2pa/lib.py @@ -45,7 +45,7 @@ def get_platform_identifier() -> str: elif system == "windows": return "x86_64-pc-windows-msvc" elif system == "linux": - if _get_architecture() in [CPUArchitecture.ARM64, CPUArchitecture.AARCH64]: + if _get_architecture() in [CPUArchitecture.ARM64.value, CPUArchitecture.AARCH64.value]: return "aarch64-unknown-linux-gnu" return "x86_64-unknown-linux-gnu" else: @@ -62,9 +62,9 @@ def _get_architecture() -> str: if sys.platform == "darwin": # On macOS, we need to check if we're running under Rosetta if platform.processor() == 'arm': - return CPUArchitecture.ARM64 + return CPUArchitecture.ARM64.value else: - return CPUArchitecture.ARM64.X86_64 + return CPUArchitecture.X86_64.value elif sys.platform == "linux": return platform.machine() elif sys.platform == "win32": From 8f8fec1ebed05a1cf45b20cfa55ac32fe1c86061 Mon Sep 17 00:00:00 2001 From: Tania Mathern Date: Thu, 21 Aug 2025 20:33:40 -0700 Subject: [PATCH 10/16] fix: Universal pipeline --- .github/workflows/build-wheel.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/build-wheel.yml b/.github/workflows/build-wheel.yml index 490ef365..191e0b2f 100644 --- a/.github/workflows/build-wheel.yml +++ b/.github/workflows/build-wheel.yml @@ -82,6 +82,8 @@ jobs: find dist -name "*.whl" | wc -l echo "Wheel filenames:" find dist -name "*.whl" -exec basename {} \; + echo "Verifying wheelsusing twine check" + twine check dist/* - name: Build Windows wheel (x64) if: runner.os == 'Windows' @@ -140,6 +142,9 @@ jobs: done cd .. + echo "Verifying wheelsusing twine check" + twine check dist/* + - name: Log wheel filename if: runner.os == 'Linux' || runner.os == 'macOS' shell: bash From 97a48e39d4d333fafa185025700fd848048656f7 Mon Sep 17 00:00:00 2001 From: Tania Mathern Date: Thu, 21 Aug 2025 20:37:02 -0700 Subject: [PATCH 11/16] fix: Universal pipeline --- .github/workflows/build-wheel.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-wheel.yml b/.github/workflows/build-wheel.yml index 191e0b2f..59d0172a 100644 --- a/.github/workflows/build-wheel.yml +++ b/.github/workflows/build-wheel.yml @@ -82,7 +82,9 @@ jobs: find dist -name "*.whl" | wc -l echo "Wheel filenames:" find dist -name "*.whl" -exec basename {} \; - echo "Verifying wheelsusing twine check" + + # Verify wheel structure + echo "Verifying wheels using twine check" twine check dist/* - name: Build Windows wheel (x64) @@ -115,6 +117,9 @@ jobs: # Build wheel python setup.py bdist_wheel --plat-name win_amd64 + # Verify wheel structure + twine check dist/* + - name: Build macOS wheel (Universal) if: runner.os == 'macOS' run: | @@ -142,7 +147,8 @@ jobs: done cd .. - echo "Verifying wheelsusing twine check" + # Verify wheel structure + echo "Verifying wheels using twine check" twine check dist/* - name: Log wheel filename From ad06a621842cdee6e81ffd6f2cbff6ca5579014d Mon Sep 17 00:00:00 2001 From: Tania Mathern Date: Thu, 21 Aug 2025 21:19:53 -0700 Subject: [PATCH 12/16] fix: Run universal mac wheel build also on mac Intel --- .github/workflows/build.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index dd16ffdb..ba888f71 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -359,6 +359,8 @@ jobs: include: - target: universal2 runs-on: macos-latest + - target: universal2 + runs-on: macos-13 if: | github.event_name != 'pull_request' || From c4632ada039b30c68799e00128ac4ac606f363b5 Mon Sep 17 00:00:00 2001 From: Tania Mathern Date: Tue, 26 Aug 2025 19:41:57 -0700 Subject: [PATCH 13/16] fix: Proper build check --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ba888f71..cbdb3a1c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -353,7 +353,7 @@ jobs: test-built-macos-wheel: name: Test macOS built wheel (Universal) needs: build-macos-wheel - runs-on: macos-latest + runs-on: ${{ matrix.runs-on }} strategy: matrix: include: From 86aa780e321e3736021a4ee8c82b9a3d8548df50 Mon Sep 17 00:00:00 2001 From: Tania Mathern Date: Thu, 28 Aug 2025 08:51:32 -0700 Subject: [PATCH 14/16] fix: Bump version number --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 85e5560c..f178c63f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "c2pa-python" -version = "0.14.0" +version = "0.15.0" requires-python = ">=3.10" description = "Python bindings for the C2PA Content Authenticity Initiative (CAI) library" readme = { file = "README.md", content-type = "text/markdown" } From 7a1614b682c8df41acdf9e0d3c31e2e33a6aa719 Mon Sep 17 00:00:00 2001 From: Tania Mathern Date: Thu, 28 Aug 2025 09:04:09 -0700 Subject: [PATCH 15/16] fix: Push to test PYPI --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index cbdb3a1c..f6bc138d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -465,8 +465,8 @@ jobs: uses: pypa/gh-action-pypi-publish@release/v1 with: packages-dir: dist - # Uncomment to use TestPyPI - # repository-url: https://test.pypi.org/legacy/ + #Uncomment to use TestPyPI + repository-url: https://test.pypi.org/legacy/ verbose: true # Uncomment below for test runs, otherwise fails on existing packages being reuploaded skip-existing: true From 19553596b7a42454de6e2fb7e4ad726ae9aa7ef6 Mon Sep 17 00:00:00 2001 From: Tania Mathern Date: Thu, 28 Aug 2025 09:16:42 -0700 Subject: [PATCH 16/16] fix: Prepare to publish to PyPI --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f6bc138d..cbdb3a1c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -465,8 +465,8 @@ jobs: uses: pypa/gh-action-pypi-publish@release/v1 with: packages-dir: dist - #Uncomment to use TestPyPI - repository-url: https://test.pypi.org/legacy/ + # Uncomment to use TestPyPI + # repository-url: https://test.pypi.org/legacy/ verbose: true # Uncomment below for test runs, otherwise fails on existing packages being reuploaded skip-existing: true