From a8b19f3761457079bcd9d4fb233b2ad0b783ca5b Mon Sep 17 00:00:00 2001 From: Hans Johnson Date: Fri, 3 Apr 2026 15:51:15 -0500 Subject: [PATCH 01/27] ENH: Add ITK commit message hooks (prepare-commit-msg and kw-commit-msg) Add pre-commit hooks in Utilities/Hooks/ matching ITK's directory structure and commit message enforcement: - prepare-commit-msg: Inserts ITK prefix instructions into the commit message editor so developers see valid prefixes while composing. - kw-commit-msg.py: Validates commit messages with the same rules as upstream ITK: prefix check (BUG/COMP/DOC/ENH/PERF/STYLE/WIP), subject line max 78 chars, no leading/trailing whitespace, empty second line, and Merge/Revert exemptions. Co-Authored-By: Claude Opus 4.6 (1M context) --- .pre-commit-config.yaml | 13 +++ Utilities/Hooks/kw-commit-msg.py | 153 +++++++++++++++++++++++++++++ Utilities/Hooks/prepare-commit-msg | 53 ++++++++++ 3 files changed, 219 insertions(+) create mode 100644 .pre-commit-config.yaml create mode 100755 Utilities/Hooks/kw-commit-msg.py create mode 100755 Utilities/Hooks/prepare-commit-msg diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..b15a4760 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,13 @@ +repos: + - repo: local + hooks: + - id: local-prepare-commit-msg + name: 'local prepare-commit-msg' + entry: 'Utilities/Hooks/prepare-commit-msg' + language: system + stages: [prepare-commit-msg] + - id: kw-commit-msg + name: 'kw commit-msg' + entry: 'python3 Utilities/Hooks/kw-commit-msg.py' + language: system + stages: [commit-msg] diff --git a/Utilities/Hooks/kw-commit-msg.py b/Utilities/Hooks/kw-commit-msg.py new file mode 100755 index 00000000..0d6b0af8 --- /dev/null +++ b/Utilities/Hooks/kw-commit-msg.py @@ -0,0 +1,153 @@ +#!/usr/bin/env python3 +# ========================================================================== +# +# Copyright NumFOCUS +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0.txt +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ========================================================================== + +import os +import re +import subprocess +import sys + +from pathlib import Path + + +DEFAULT_LINE_LENGTH: int = 78 + + +def die(message, commit_msg_path): + print("commit-msg hook failure", file=sys.stderr) + print("-----------------------", file=sys.stderr) + print(message, file=sys.stderr) + print("-----------------------", file=sys.stderr) + print( + f""" +To continue editing, run the command + git commit -e -F "{commit_msg_path}" +(assuming your working directory is at the top).""", + file=sys.stderr, + ) + sys.exit(1) + + +def get_max_length(): + try: + result = subprocess.run( + ["git", "config", "--get", "hooks.commit-msg.ITKCommitSubjectMaxLength"], + capture_output=True, + text=True, + check=True, + ) + return int(result.stdout.strip()) + except (subprocess.CalledProcessError, ValueError): + return DEFAULT_LINE_LENGTH + + +def main(): + git_dir_path: Path = Path(os.environ.get("GIT_DIR", ".git")).resolve() + commit_msg_path: Path = git_dir_path / "COMMIT_MSG" + + if len(sys.argv) < 2: + die(f"Usage: {sys.argv[0]} ", commit_msg_path) + + input_file: Path = Path(sys.argv[1]) + if not input_file.exists(): + die( + f"Missing input_file {sys.argv[1]} for {sys.argv[0]} processing", + commit_msg_path, + ) + max_subjectline_length: int = get_max_length() + + original_input_file_lines: list[str] = [] + with open(input_file) as f_in: + original_input_file_lines = f_in.readlines() + + input_file_lines: list[str] = [] + for test_line in original_input_file_lines: + test_line = test_line.strip() + is_empty_line_before_subject: bool = ( + len(input_file_lines) == 0 and len(test_line) == 0 + ) + if test_line.startswith("#") or is_empty_line_before_subject: + continue + input_file_lines.append(f"{test_line}\n") + + with open(commit_msg_path, "w") as f_out: + f_out.writelines(input_file_lines) + + subject_line: str = input_file_lines[0] + + if len(subject_line) < 8: + die( + f"The first line must be at least 8 characters:\n--------\n{subject_line}\n--------", + commit_msg_path, + ) + if ( + len(subject_line) > max_subjectline_length + and not subject_line.startswith("Merge ") + and not subject_line.startswith("Revert ") + ): + die( + f"The first line may be at most {max_subjectline_length} characters:\n" + + "-" * max_subjectline_length + + f"\n{subject_line}\n" + + "-" * max_subjectline_length, + commit_msg_path, + ) + if re.match(r"^[ \t]|[ \t]$", subject_line): + die( + f"The first line may not have leading or trailing space:\n[{subject_line}]", + commit_msg_path, + ) + if not re.match( + r"^(Merge|Revert|BUG:|COMP:|DOC:|ENH:|PERF:|STYLE:|WIP:)\s", subject_line + ): + die( + f"""Start ITK commit messages with a standard prefix (and a space): + BUG: - fix for runtime crash or incorrect result + COMP: - compiler error or warning fix + DOC: - documentation change + ENH: - new functionality + PERF: - performance improvement + STYLE: - no logic impact (indentation, comments) + WIP: - Work In Progress not ready for merge +To reference GitHub issue XXXX, add "Issue #XXXX" to the commit message. +If the issue addresses an open issue, add "Closes #XXXX" to the message.""", + commit_msg_path, + ) + if re.match(r"^BUG: [0-9]+\.", subject_line): + die( + f'Do not put a "." after the bug number:\n\n {subject_line}', + commit_msg_path, + ) + del subject_line + + if len(input_file_lines) > 1: + second_line: str = input_file_lines[ + 1 + ].strip() # Remove whitespace at beginning and end + if len(second_line) == 0: + input_file_lines[1] = "\n" # Replace line with only newline + else: + die( + f'The second line of the commit message must be empty:\n"{second_line}" with length {len(second_line)}', + commit_msg_path, + ) + del second_line + + +if __name__ == "__main__": + main() diff --git a/Utilities/Hooks/prepare-commit-msg b/Utilities/Hooks/prepare-commit-msg new file mode 100755 index 00000000..276fd093 --- /dev/null +++ b/Utilities/Hooks/prepare-commit-msg @@ -0,0 +1,53 @@ +#!/usr/bin/env bash +#========================================================================== +# +# Copyright NumFOCUS +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0.txt +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +#========================================================================== + +egrep-q() { + egrep "$@" >/dev/null 2>/dev/null +} + +# First argument is file containing commit message. +commit_msg="$1" + +# Check for our extra instructions. +egrep-q "^# Start ITK commit messages" -- "$commit_msg" && return 0 + +# Insert our extra instructions. +commit_msg_tmp="$commit_msg.$$" +instructions='#\ +# Start ITK commit messages with a standard prefix (and a space):\ +# BUG: - fix for runtime crash or incorrect result\ +# COMP: - compiler error or warning fix\ +# DOC: - documentation change\ +# ENH: - new functionality\ +# PERF: - performance improvement\ +# STYLE: - no logic impact (indentation, comments)\ +# WIP: - Work In Progress not ready for merge\ +#\ +# The first line of the commit message should preferably be 72 characters\ +# or less; the maximum allowed is 78 characters.\ +#\ +# Follow the first line commit summary with an empty line, then a detailed\ +# description in one or more paragraphs.\ +#' && +sed '/^# On branch.*$/ a\ +'"$instructions"' +/^# Not currently on any branch.*$/ a\ +'"$instructions"' +' "$commit_msg" > "$commit_msg_tmp" && +mv "$commit_msg_tmp" "$commit_msg" From 6e670a40c011e93e4dd42db2df89ec7c9049781d Mon Sep 17 00:00:00 2001 From: Cavan Riley Date: Tue, 17 Mar 2026 15:33:07 -0500 Subject: [PATCH 02/27] ENH: Transition build system from shell scripts to consolidated Python scripts Replaces the primary build orchestration layer with a Python-based system. Adds core abstractions including BuildManager for step-wise build persistence/resumption, CMakeArgumentBuilder for managing CMake definitions, cross-platform venv utilities, subprocess helpers, and pixi environment integration. Establishes platform-specific base classes that Linux, macOS, and Windows implementations extend. Restructures CMake layout into modular BuildWheelsSupport and SuperbuildSupport components. Shell scripts remain where still required. Co-authored-by: Hans J. Johnson --- BuildWheelsSupport/CMakeLists.txt | 7 + LICENSE => BuildWheelsSupport/LICENSE | 0 .../WHEEL_NAMES.txt | 2 +- CMakeLists.txt | 571 - SuperbuildSupport/CMakeLists.txt | 7 + cmake/ITKPythonPackage.cmake | 240 - cmake/ITKPythonPackage_BuildWheels.cmake | 250 + cmake/ITKPythonPackage_SuperBuild.cmake | 366 + cmake/ITKPythonPackage_Utils.cmake | 252 + itkVersion.py | 31 - pixi.lock | 11190 ++++++++++++++++ pixi.toml | 183 + pyproject.toml | 21 + requirements-dev.txt | 6 - scripts/BuildManager.py | 134 + scripts/build_python_instance_base.py | 1029 ++ scripts/build_wheels.py | 607 + scripts/cmake_argument_builder.py | 107 + scripts/install_pixi.py | 153 + scripts/internal/Support.cmake | 2749 ---- ...not-needed-symbols-exported-by-interpreter | 0 scripts/internal/wheel_builder_utils.py | 95 - scripts/pyproject.toml.in | 6 +- scripts/pyproject_configure.py | 513 +- scripts/wheel_builder_utils.py | 752 ++ 25 files changed, 15438 insertions(+), 3833 deletions(-) create mode 100644 BuildWheelsSupport/CMakeLists.txt rename LICENSE => BuildWheelsSupport/LICENSE (100%) rename {scripts => BuildWheelsSupport}/WHEEL_NAMES.txt (89%) delete mode 100644 CMakeLists.txt create mode 100644 SuperbuildSupport/CMakeLists.txt delete mode 100644 cmake/ITKPythonPackage.cmake create mode 100644 cmake/ITKPythonPackage_BuildWheels.cmake create mode 100644 cmake/ITKPythonPackage_SuperBuild.cmake create mode 100644 cmake/ITKPythonPackage_Utils.cmake delete mode 100644 itkVersion.py create mode 100644 pixi.lock create mode 100644 pixi.toml create mode 100644 pyproject.toml delete mode 100644 requirements-dev.txt create mode 100644 scripts/BuildManager.py create mode 100644 scripts/build_python_instance_base.py create mode 100755 scripts/build_wheels.py create mode 100644 scripts/cmake_argument_builder.py create mode 100755 scripts/install_pixi.py delete mode 100644 scripts/internal/Support.cmake delete mode 100644 scripts/internal/libpython-not-needed-symbols-exported-by-interpreter delete mode 100644 scripts/internal/wheel_builder_utils.py create mode 100644 scripts/wheel_builder_utils.py diff --git a/BuildWheelsSupport/CMakeLists.txt b/BuildWheelsSupport/CMakeLists.txt new file mode 100644 index 00000000..dbaa4a66 --- /dev/null +++ b/BuildWheelsSupport/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 3.26.6 FATAL_ERROR) +# NOTE: 3.26.6 is the first cmake version to support Development.SABIModule + +project(ITKPythonPackageWheels CXX) + +include(${CMAKE_CURRENT_SOURCE_DIR}/../cmake/ITKPythonPackage_Utils.cmake) +include(${CMAKE_CURRENT_SOURCE_DIR}/../cmake/ITKPythonPackage_BuildWheels.cmake) diff --git a/LICENSE b/BuildWheelsSupport/LICENSE similarity index 100% rename from LICENSE rename to BuildWheelsSupport/LICENSE diff --git a/scripts/WHEEL_NAMES.txt b/BuildWheelsSupport/WHEEL_NAMES.txt similarity index 89% rename from scripts/WHEEL_NAMES.txt rename to BuildWheelsSupport/WHEEL_NAMES.txt index 94ff00af..434c06c1 100644 --- a/scripts/WHEEL_NAMES.txt +++ b/BuildWheelsSupport/WHEEL_NAMES.txt @@ -4,4 +4,4 @@ itk-io itk-filtering itk-registration itk-segmentation -itk-meta \ No newline at end of file +itk-meta diff --git a/CMakeLists.txt b/CMakeLists.txt deleted file mode 100644 index 6908545c..00000000 --- a/CMakeLists.txt +++ /dev/null @@ -1,571 +0,0 @@ -cmake_minimum_required(VERSION 3.26.6 FATAL_ERROR) -# NOTE: 3.26.6 is the first cmake vesion to support Development.SABIModule - -project(ITKPythonPackage CXX) - -set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH}) -include(ITKPythonPackage) - -if(NOT DEFINED ITKPythonPackage_SUPERBUILD) - set(ITKPythonPackage_SUPERBUILD 1) -endif() - -if(NOT DEFINED ITKPythonPackage_WHEEL_NAME) - set(ITKPythonPackage_WHEEL_NAME "itk") -endif() -message(STATUS "SuperBuild - ITKPythonPackage_WHEEL_NAME:${ITKPythonPackage_WHEEL_NAME}") - -option(ITKPythonPackage_USE_TBB "Build and use oneTBB in the ITK python package" ON) - -if(ITKPythonPackage_SUPERBUILD) - - #----------------------------------------------------------------------------- - #------------------------------------------------------ - #---------------------------------- - # ITKPythonPackage_SUPERBUILD: ON - #---------------------------------- - #------------------------------------------------------ - #----------------------------------------------------------------------------- - - # Avoid "Manually-specified variables were not used by the project" warnings. - ipp_unused_vars(${PYTHON_VERSION_STRING} ${SKBUILD}) - - set(ep_common_cmake_cache_args ) - if(NOT CMAKE_CONFIGURATION_TYPES) - list(APPEND ep_common_cmake_cache_args - -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} - ) - endif() - set(ep_download_extract_timestamp_arg ) - if(CMAKE_VERSION VERSION_EQUAL "3.24" OR CMAKE_VERSION VERSION_GREATER "3.24") - # See https://cmake.org/cmake/help/latest/policy/CMP0135.html - set(ep_download_extract_timestamp_arg DOWNLOAD_EXTRACT_TIMESTAMP 1) - endif() - - #----------------------------------------------------------------------------- - # Options - - # When building different "flavor" of ITK python packages on a given platform, - # explicitly setting the following options allow to speed up package generation by - # re-using existing resources. - # - # ITK_SOURCE_DIR: Path to an existing source directory - # - - option(ITKPythonPackage_BUILD_PYTHON "Build ITK python module" ON) - mark_as_advanced(ITKPythonPackage_BUILD_PYTHON) - - if(CMAKE_OSX_DEPLOYMENT_TARGET) - list(APPEND ep_common_cmake_cache_args - -DCMAKE_OSX_DEPLOYMENT_TARGET:STRING=${CMAKE_OSX_DEPLOYMENT_TARGET}) - endif() - if(CMAKE_OSX_ARCHITECTURES) - list(APPEND ep_common_cmake_cache_args - -DCMAKE_OSX_ARCHITECTURES:STRING=${CMAKE_OSX_ARCHITECTURES}) - endif() - - if(CMAKE_MAKE_PROGRAM) - list(APPEND ep_common_cmake_cache_args - -DCMAKE_MAKE_PROGRAM:FILEPATH=${CMAKE_MAKE_PROGRAM}) - endif() - - #----------------------------------------------------------------------------- - # compile with multiple processors - include(ProcessorCount) - ProcessorCount(NPROC) - if(NOT NPROC EQUAL 0) - set( ENV{MAKEFLAGS} "-j${NPROC}" ) - endif() - - #----------------------------------------------------------------------------- - include(ExternalProject) - - set(ITK_REPOSITORY "https://github.com/InsightSoftwareConsortium/ITK.git") - - # release branch, 2026-03-10 - set(ITK_GIT_TAG "c6e1c1be6a86236cbb812bd71eec5a4df9b1353c") - - #----------------------------------------------------------------------------- - # A separate project is used to download ITK, so that it can reused - # when building different "flavor" of ITK python packages - - message(STATUS "SuperBuild -") - message(STATUS "SuperBuild - ITK-source-download") - - # Sanity checks - if(DEFINED ITK_SOURCE_DIR AND NOT EXISTS ${ITK_SOURCE_DIR}) - message(FATAL_ERROR "ITK_SOURCE_DIR variable is defined but corresponds to nonexistent directory") - endif() - - if(ITKPythonPackage_USE_TBB) - if(ITK_SOURCE_DIR) - set(TBB_DIR "${ITK_SOURCE_DIR}/../oneTBB-prefix/lib/cmake/TBB") - else() - set(TBB_DIR "${CMAKE_BINARY_DIR}/../oneTBB-prefix/lib/cmake/TBB") - endif() - set(tbb_args ) - if(ITKPythonPackage_USE_TBB) - set(tbb_args - -DModule_ITKTBB:BOOL=ON - -DTBB_DIR:PATH=${TBB_DIR} - ) - endif() - - set(tbb_cmake_cache_args) - if(CMAKE_OSX_DEPLOYMENT_TARGET) - list(APPEND tbb_cmake_cache_args - -DCMAKE_CXX_OSX_DEPLOYMENT_TARGET_FLAG:STRING="-mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}" - -DCMAKE_C_OSX_DEPLOYMENT_TARGET_FLAG:STRING="-mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}" - ) - endif() - - ExternalProject_add(oneTBB - URL https://github.com/oneapi-src/oneTBB/archive/refs/tags/v2022.2.0.tar.gz - URL_HASH SHA256=f0f78001c8c8edb4bddc3d4c5ee7428d56ae313254158ad1eec49eced57f6a5b - CMAKE_ARGS - -DTBB_TEST:BOOL=OFF - -DCMAKE_BUILD_TYPE:STRING=Release - -DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_BINARY_DIR}/../oneTBB-prefix - -DCMAKE_INSTALL_LIBDIR:STRING=lib # Skip default initialization by GNUInstallDirs CMake module - ${ep_common_cmake_cache_args} - ${tbb_cmake_cache_args} - ${ep_download_extract_timestamp_arg} - -DCMAKE_BUILD_TYPE:STRING=Release - BUILD_BYPRODUCTS "${TBB_DIR}/TBBConfig.cmake" - USES_TERMINAL_DOWNLOAD 1 - USES_TERMINAL_UPDATE 1 - USES_TERMINAL_CONFIGURE 1 - USES_TERMINAL_BUILD 1 - ) - message(STATUS "SuperBuild - TBB: Enabled") - message(STATUS "SuperBuild - TBB_DIR: ${TBB_DIR}") - endif() - set(tbb_depends "") - if(ITKPythonPackage_USE_TBB) - set(tbb_depends oneTBB) - endif() - - - if(NOT DEFINED ITK_SOURCE_DIR) - - set(ITK_SOURCE_DIR ${CMAKE_BINARY_DIR}/ITK) - - ExternalProject_add(ITK-source-download - SOURCE_DIR ${ITK_SOURCE_DIR} - GIT_REPOSITORY ${ITK_REPOSITORY} - GIT_TAG ${ITK_GIT_TAG} - USES_TERMINAL_DOWNLOAD 1 - CONFIGURE_COMMAND "" - BUILD_COMMAND "" - INSTALL_COMMAND "" - DEPENDS "${tbb_depends}" - ) - set(proj_status "") - - else() - - ipp_ExternalProject_Add_Empty( - ITK-source-download - "" - ) - set(proj_status " (REUSE)") - - endif() - - message(STATUS "SuperBuild - ITK_SOURCE_DIR: ${ITK_SOURCE_DIR}") - message(STATUS "SuperBuild - ITK-source-download[OK]${proj_status}") - - #----------------------------------------------------------------------------- - if(NOT ITKPythonPackage_BUILD_PYTHON) - return() - endif() - - #----------------------------------------------------------------------------- - # Search for python interpreter and libraries - - message(STATUS "SuperBuild -") - message(STATUS "SuperBuild - Searching for python") - - # Sanity checks - if(DEFINED Python3_INCLUDE_DIR AND NOT EXISTS ${Python3_INCLUDE_DIR}) - message(FATAL_ERROR "Python3_INCLUDE_DIR variable is defined but corresponds to nonexistent directory") - endif() - if(DEFINED Python3_LIBRARY AND NOT EXISTS ${Python3_LIBRARY}) - message(FATAL_ERROR "Python3_LIBRARY variable is defined but corresponds to nonexistent file") - endif() - if(DEFINED Python3_EXECUTABLE AND NOT EXISTS ${Python3_EXECUTABLE}) - message(FATAL_ERROR "Python3_EXECUTABLE variable is defined but corresponds to nonexistent file") - endif() - if(DEFINED DOXYGEN_EXECUTABLE AND NOT EXISTS ${DOXYGEN_EXECUTABLE}) - message(FATAL_ERROR "DOXYGEN_EXECUTABLE variable is defined but corresponds to nonexistent file") - endif() - - if(NOT DEFINED Python3_INCLUDE_DIR - OR NOT DEFINED Python3_LIBRARY - OR NOT DEFINED Python3_EXECUTABLE) - - find_package(Python3 COMPONENTS Interpreter Development) - if(NOT Python3_EXECUTABLE AND _Python3_EXECUTABLE) - set(Python3_EXECUTABLE ${_Python3_EXECUTABLE} CACHE INTERNAL - "Path to the Python interpreter" FORCE) - endif() - endif() - if(NOT DEFINED DOXYGEN_EXECUTABLE) - find_package(Doxygen REQUIRED) - endif() - - message(STATUS "SuperBuild - Python3_INCLUDE_DIR: ${Python3_INCLUDE_DIR}") - message(STATUS "SuperBuild - Python3_INCLUDE_DIRS: ${Python3_INCLUDE_DIRS}") - message(STATUS "SuperBuild - Python3_LIBRARY: ${Python3_LIBRARY}") - message(STATUS "SuperBuild - Python3_EXECUTABLE: ${Python3_EXECUTABLE}") - message(STATUS "SuperBuild - Searching for python[OK]") - message(STATUS "SuperBuild - DOXYGEN_EXECUTABLE: ${DOXYGEN_EXECUTABLE}") - - # CMake configuration variables to pass to ITK's build - set(ep_itk_cmake_cache_args "") - foreach(var - BUILD_SHARED_LIBS - ITK_BUILD_DEFAULT_MODULES - ) - if(DEFINED ${var}) - list(APPEND ep_itk_cmake_cache_args "-D${var}=${${var}}") - endif() - endforeach() - function(cached_variables RESULTVAR PATTERN) - get_cmake_property(variables CACHE_VARIABLES) - set(result) - foreach(variable ${variables}) - if(${variable} AND variable MATCHES "${PATTERN}") - list(APPEND result "-D${variable}=${${variable}}") - endif() - endforeach() - set(${RESULTVAR} ${result} PARENT_SCOPE) - endfunction() - cached_variables(itk_pattern_cached_vars "^(ITK_WRAP_)|(ITKGroup_)|(Module_)") - list(APPEND ep_itk_cmake_cache_args ${itk_pattern_cached_vars}) - # Todo, also pass all Module_* variables - message(STATUS "ITK CMake Cache Args - ${ep_itk_cmake_cache_args}") - #----------------------------------------------------------------------------- - # ITK: This project builds ITK and associated Python modules - - option(ITKPythonPackage_ITK_BINARY_REUSE "Reuse provided ITK_BINARY_DIR without configuring or building ITK" OFF) - - set(ITK_BINARY_DIR "${CMAKE_BINARY_DIR}/ITKb" CACHE PATH "ITK build directory") - - message(STATUS "SuperBuild -") - message(STATUS "SuperBuild - ITK => Requires ITK-source-download") - message(STATUS "SuperBuild - ITK_BINARY_DIR: ${ITK_BINARY_DIR}") - - if(NOT ITKPythonPackage_ITK_BINARY_REUSE) - - set(_stamp "${CMAKE_BINARY_DIR}/ITK-prefix/src/ITK-stamp/ITK-configure") - if(EXISTS ${_stamp}) - execute_process(COMMAND ${CMAKE_COMMAND} -E remove ${_stamp}) - message(STATUS "SuperBuild - Force re-configure removing ${_stamp}") - endif() - - set(install_component_per_module OFF) - if(NOT ITKPythonPackage_WHEEL_NAME STREQUAL "itk") - set(install_component_per_module ON) - endif() - - ExternalProject_add(ITK - DOWNLOAD_COMMAND "" - SOURCE_DIR ${ITK_SOURCE_DIR} - BINARY_DIR ${ITK_BINARY_DIR} - PREFIX "ITKp" - CMAKE_ARGS - -DBUILD_TESTING:BOOL=OFF - -DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_INSTALL_PREFIX} - -DPY_SITE_PACKAGES_PATH:PATH=${CMAKE_INSTALL_PREFIX} - -DWRAP_ITK_INSTALL_COMPONENT_IDENTIFIER:STRING=PythonWheel - -DWRAP_ITK_INSTALL_COMPONENT_PER_MODULE:BOOL=${install_component_per_module} - -DITK_LEGACY_SILENT:BOOL=ON - -DITK_WRAP_PYTHON:BOOL=ON - -DDOXYGEN_EXECUTABLE:FILEPATH=${DOXYGEN_EXECUTABLE} - -DPython3_INCLUDE_DIR:PATH=${Python3_INCLUDE_DIR} - -DPython3_LIBRARY:FILEPATH=${Python3_LIBRARY} - -DPython3_EXECUTABLE:FILEPATH=${Python3_EXECUTABLE} - ${ep_common_cmake_cache_args} - ${tbb_args} - ${ep_itk_cmake_cache_args} - ${ep_download_extract_timestamp_arg} - USES_TERMINAL_DOWNLOAD 1 - USES_TERMINAL_UPDATE 1 - USES_TERMINAL_CONFIGURE 1 - USES_TERMINAL_BUILD 1 - INSTALL_COMMAND "" - ) - set(proj_status "") - - else() - - # Sanity checks - if(NOT EXISTS "${ITK_BINARY_DIR}/CMakeCache.txt") - message(FATAL_ERROR "ITKPythonPackage_ITK_BINARY_REUSE is ON but ITK_BINARY_DIR variable is not associated with an ITK build directory. [ITK_BINARY_DIR:${ITK_BINARY_DIR}]") - endif() - - ipp_ExternalProject_Add_Empty( - ITK - "" - ) - set(proj_status " (REUSE)") - - endif() - ExternalProject_Add_StepDependencies(ITK download ITK-source-download) - - message(STATUS "SuperBuild - ITK[OK]${proj_status}") - - #----------------------------------------------------------------------------- - # ITKPythonPackage: This project adds install rules for the "RuntimeLibraries" - # components associated with the ITK project. - - message(STATUS "SuperBuild -") - message(STATUS "SuperBuild - ${PROJECT_NAME} => Requires ITK") - - ExternalProject_add(${PROJECT_NAME} - SOURCE_DIR ${CMAKE_SOURCE_DIR} - BINARY_DIR ${CMAKE_BINARY_DIR}/${PROJECT_NAME}-build - DOWNLOAD_COMMAND "" - UPDATE_COMMAND "" - CMAKE_CACHE_ARGS - -DITKPythonPackage_SUPERBUILD:BOOL=0 - -DITK_BINARY_DIR:PATH=${ITK_BINARY_DIR} - -DITK_SOURCE_DIR:PATH=${ITK_SOURCE_DIR} - -DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_INSTALL_PREFIX} - -DITKPythonPackage_WHEEL_NAME:STRING=${ITKPythonPackage_WHEEL_NAME} - -DITKPythonPackage_USE_TBB:BOOL=${ITKPythonPackage_USE_TBB} - ${ep_common_cmake_cache_args} - USES_TERMINAL_CONFIGURE 1 - INSTALL_COMMAND "" - DEPENDS ITK - ) - - install(SCRIPT ${CMAKE_BINARY_DIR}/${PROJECT_NAME}-build/cmake_install.cmake) - - message(STATUS "SuperBuild - ${PROJECT_NAME}[OK]") - -else() - - #----------------------------------------------------------------------------- - #------------------------------------------------------ - #---------------------------------- - # ITKPythonPackage_SUPERBUILD: OFF - #---------------------------------- - #------------------------------------------------------ - #----------------------------------------------------------------------------- - - set(components "PythonWheelRuntimeLibraries") - if(NOT ITKPythonPackage_WHEEL_NAME STREQUAL "itk") - - message(STATUS "ITKPythonPackage_WHEEL_NAME: ${ITKPythonPackage_WHEEL_NAME}") - - # Extract ITK group name from wheel name - message(STATUS "") - set(msg "Extracting ITK_WHEEL_GROUP") - message(STATUS ${msg}) - ipp_wheel_to_group(${ITKPythonPackage_WHEEL_NAME} ITK_WHEEL_GROUP) - message(STATUS "${msg} - done [${ITK_WHEEL_GROUP}]") - - # - # Considering that - # - # * Every ITK module is associated with exactly one ITK group. - # * ITK module dependencies are specified independently of ITK groups - # - # we semi-arbitrarily defined a collection of wheels (see ``ITK_WHEEL_GROUPS``) - # that will roughly bundle the modules associated with each group. - # - # Based on the module dependency graph, the code below will determine which module - # should be packaged in which wheel. - # - - # List of ITK wheel groups - set(ITK_WHEEL_GROUPS "") - file(STRINGS "${CMAKE_SOURCE_DIR}/scripts/WHEEL_NAMES.txt" ITK_WHEELS REGEX "^itk-.+") - foreach(wheel_name IN LISTS ITK_WHEELS) - ipp_wheel_to_group(${wheel_name} group) - list(APPEND ITK_WHEEL_GROUPS ${group}) - endforeach() - - # Define below a reasonable dependency graph for ITK groups - set(ITK_GROUP_Core_DEPENDS) - set(ITK_GROUP_IO_DEPENDS Core) - set(ITK_GROUP_Numerics_DEPENDS Core) - set(ITK_GROUP_Filtering_DEPENDS Numerics) - set(ITK_GROUP_Segmentation_DEPENDS Filtering) - set(ITK_GROUP_Registration_DEPENDS Filtering) - set(ITK_GROUP_Video_DEPENDS Core) - - # ITK is needed to retrieve ITK module information - set(ITK_DIR ${ITK_BINARY_DIR}) - find_package(ITK REQUIRED) - set(CMAKE_MODULE_PATH ${ITK_CMAKE_DIR} ${CMAKE_MODULE_PATH}) - - # Sort wheel groups - include(TopologicalSort) - topological_sort(ITK_WHEEL_GROUPS ITK_GROUP_ _DEPENDS) - - # Set ``ITK_MODULE__DEPENDS`` variables - # - # Notes: - # - # * ``_DEPENDS`` variables are set after calling ``find_package(ITK REQUIRED)`` - # - # * This naming convention corresponds to what is used internally in ITK and allow - # to differentiate with variable like ``ITK_GROUP__DEPENDS`` set above. - # - foreach(module IN LISTS ITK_MODULES_ENABLED) - set(ITK_MODULE_${module}_DEPENDS "${${module}_DEPENDS}") - endforeach() - - # Set ``ITK_MODULE__DEPENDEES`` variables - foreach(module IN LISTS ITK_MODULES_ENABLED) - ipp_get_module_dependees(${module} ITK_MODULE_${module}_DEPENDEES) - endforeach() - - # Set ``ITK_GROUPS`` variable - file(GLOB group_dirs "${ITK_SOURCE_DIR}/Modules/*") - set(ITK_GROUPS ) - foreach(dir IN LISTS group_dirs) - file(RELATIVE_PATH group "${ITK_SOURCE_DIR}/Modules" "${dir}") - if(NOT IS_DIRECTORY "${dir}" OR "${group}" MATCHES "^External$") - continue() - endif() - list(APPEND ITK_GROUPS ${group}) - endforeach() - message(STATUS "") - message(STATUS "ITK_GROUPS:${ITK_GROUPS}") - - # Set ``ITK_MODULE__GROUP`` variables - foreach(group IN LISTS ITK_GROUPS) - file( GLOB_RECURSE _${group}_module_files ${ITK_SOURCE_DIR}/Modules/${group}/itk-module.cmake ) - foreach( _module_file ${_${group}_module_files} ) - file(READ ${_module_file} _module_file_content) - string( REGEX MATCH "itk_module[ \n]*(\\([ \n]*)([A-Za-z0-9]*)" _module_name ${_module_file_content} ) - set(_module_name ${CMAKE_MATCH_2}) - list( APPEND _${group}_module_list ${_module_name} ) - set(ITK_MODULE_${_module_name}_GROUP ${group}) - endforeach() - endforeach() - - # Initialize ``ITK_WHEEL__MODULES`` variables that will contain list of modules - # to package in each wheel. - foreach(group IN LISTS ITK_WHEEL_GROUPS) - set(ITK_WHEEL_${group}_MODULES "") - endforeach() - - # Configure table display - set(row_widths 40 20 20 10 90 12) - set(row_headers MODULE_NAME MODULE_GROUP WHEEL_GROUP IS_LEAF MODULE_DEPENDEES_GROUPS IS_WRAPPED) - message(STATUS "") - ipp_display_table_row("${row_headers}" "${row_widths}") - - # Update ``ITK_WHEEL__MODULES`` variables - foreach(module IN LISTS ITK_MODULES_ENABLED) - - ipp_is_module_leaf(${module} leaf) - set(dependees_groups) - if(NOT leaf) - set(dependees "") - ipp_recursive_module_dependees(${module} dependees) - foreach(dep IN LISTS dependees) - list(APPEND dependees_groups ${ITK_MODULE_${dep}_GROUP}) - endforeach() - if(dependees_groups) - list(REMOVE_DUPLICATES dependees_groups) - endif() - endif() - - # Filter out group not associated with a wheel - set(dependees_wheel_groups) - foreach(group IN LISTS dependees_groups) - list(FIND ITK_WHEEL_GROUPS ${group} _index) - if(_index EQUAL -1) - continue() - endif() - list(APPEND dependees_wheel_groups ${group}) - endforeach() - - set(wheel_group) - list(LENGTH dependees_wheel_groups _length) - - # Sanity check - if(leaf AND _length GREATER 0) - message(FATAL_ERROR "leaf module should not module depending on them !") - endif() - - if(_length EQUAL 0) - set(wheel_group "${ITK_MODULE_${module}_GROUP}") - elseif(_length EQUAL 1) - # Since packages depending on this module belong to one group, also package this module - set(wheel_group "${dependees_wheel_groups}") - elseif(_length GREATER 1) - # If more than one group is associated with the dependees, package the module in the - # "common ancestor" group. - set(common_ancestor_index 999999) - foreach(g IN LISTS dependees_wheel_groups) - list(FIND ITK_WHEEL_GROUPS ${g} _index) - if(NOT _index EQUAL -1 AND _index LESS common_ancestor_index) - set(common_ancestor_index ${_index}) - endif() - endforeach() - list(GET ITK_WHEEL_GROUPS ${common_ancestor_index} wheel_group) - endif() - - set(wheel_group_display ${wheel_group}) - - # XXX Hard-coded dispatch - if(module STREQUAL "ITKBridgeNumPy") - set(new_wheel_group "Core") - set(wheel_group_display "${new_wheel_group} (was ${wheel_group})") - set(wheel_group ${new_wheel_group}) - endif() - if(module STREQUAL "ITKVTK") - set(new_wheel_group "Core") - set(wheel_group_display "${new_wheel_group} (was ${wheel_group})") - set(wheel_group ${new_wheel_group}) - endif() - - # Associate module with a wheel - list(APPEND ITK_WHEEL_${wheel_group}_MODULES ${module}) - - # Display module info - ipp_is_module_python_wrapped(${module} is_wrapped) - ipp_list_to_string("^^" "${dependees_groups}" dependees_groups_str) - set(row_values "${module};${ITK_MODULE_${module}_GROUP};${wheel_group_display};${leaf};${dependees_groups_str};${is_wrapped}") - ipp_display_table_row("${row_values}" "${row_widths}") - - endforeach() - - # Set list of components to install - set(components "") - foreach(module IN LISTS ITK_WHEEL_${ITK_WHEEL_GROUP}_MODULES) - list(APPEND components ${module}PythonWheelRuntimeLibraries) - endforeach() - - endif() - - if(MSVC AND ITKPythonPackage_WHEEL_NAME STREQUAL "itk-core") - message(STATUS "Adding install rules for compiler runtime libraries") - # Put the runtime libraries next to the "itk/_*.pyd" C-extensions so they - # are found. - set(CMAKE_INSTALL_SYSTEM_RUNTIME_DESTINATION "itk") - include(InstallRequiredSystemLibraries) - endif() - - #----------------------------------------------------------------------------- - # Install ITK components - message(STATUS "Adding install rules for components:") - foreach(component IN LISTS components) - message(STATUS " ${component}") - install(CODE " -unset(CMAKE_INSTALL_COMPONENT) -set(COMPONENT \"${component}\") -set(CMAKE_INSTALL_DO_STRIP 1) -include(\"${ITK_BINARY_DIR}/cmake_install.cmake\") -unset(CMAKE_INSTALL_COMPONENT) -") - endforeach() - -endif() diff --git a/SuperbuildSupport/CMakeLists.txt b/SuperbuildSupport/CMakeLists.txt new file mode 100644 index 00000000..25311ae9 --- /dev/null +++ b/SuperbuildSupport/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 3.26.6 FATAL_ERROR) +# NOTE: 3.26.6 is the first cmake version to support Development.SABIModule + +project(ITKPythonPackageSuperbuild CXX) + +include(${CMAKE_CURRENT_SOURCE_DIR}/../cmake/ITKPythonPackage_Utils.cmake) +include(${CMAKE_CURRENT_SOURCE_DIR}/../cmake/ITKPythonPackage_SuperBuild.cmake) diff --git a/cmake/ITKPythonPackage.cmake b/cmake/ITKPythonPackage.cmake deleted file mode 100644 index 4190c4e4..00000000 --- a/cmake/ITKPythonPackage.cmake +++ /dev/null @@ -1,240 +0,0 @@ - -# ipp_ExternalProject_Add_Empty( ) -# -# Add an empty external project -# -function(ipp_ExternalProject_Add_Empty proj depends) - set(depends_args) - if(NOT depends STREQUAL "") - set(depends_args DEPENDS ${depends}) - endif() - ExternalProject_add(${proj} - SOURCE_DIR ${CMAKE_BINARY_DIR}/${proj} - DOWNLOAD_COMMAND "" - UPDATE_COMMAND "" - CONFIGURE_COMMAND "" - BUILD_COMMAND "" - BUILD_IN_SOURCE 1 - BUILD_ALWAYS 1 - INSTALL_COMMAND "" - ${depends_args} - ) -endfunction() - -# ipp_get_module_dependees( ) -# -# Collect all modules depending on ````. -# -function(ipp_get_module_dependees itk-module output_var) - set(dependees "") - foreach(m_enabled IN LISTS ITK_MODULES_ENABLED) - list(FIND ITK_MODULE_${m_enabled}_DEPENDS ${itk-module} _index) - if(NOT _index EQUAL -1) - list(APPEND dependees ${m_enabled}) - endif() - endforeach() - list(REMOVE_DUPLICATES dependees) - set(${output_var} ${dependees} PARENT_SCOPE) -endfunction() - -function(_recursive_deps item-type item-category itk-item output_var) - set(_${itk-item}_deps ) - foreach(dep IN LISTS ITK_${item-type}_${itk-item}_${item-category}) - list(APPEND _${itk-item}_deps ${dep}) - _recursive_deps(${item-type} ${item-category} ${dep} _${itk-item}_deps) - endforeach() - list(APPEND ${output_var} ${_${itk-item}_deps}) - list(REMOVE_DUPLICATES ${output_var}) - set(${output_var} ${${output_var}} PARENT_SCOPE) -endfunction() - -# ipp_recursive_module_dependees( ) -# -# Recursively collect all modules depending on ````. -# -function(ipp_recursive_module_dependees itk-module output_var) - set(_${itk-module}_deps ) - _recursive_deps("MODULE" "DEPENDEES" ${itk-module} ${output_var}) - set(${output_var} ${${output_var}} PARENT_SCOPE) -endfunction() - -# ipp_is_module_leaf( ) -# -# If ```` has no dependencies, set `` to 1 -# otherwise set `` to 0. -# -function(ipp_is_module_leaf itk-module output_var) - set(leaf 1) - foreach(m_enabled IN LISTS ITK_MODULES_ENABLED) - list(FIND ITK_MODULE_${m_enabled}_DEPENDS ${itk-module} _index) - if(NOT _index EQUAL -1) - set(leaf 0) - break() - endif() - endforeach() - set(${output_var} ${leaf} PARENT_SCOPE) -endfunction() - -# ipp_is_module_python_wrapped( ) -# -# If ```` is wrapped in python, set `` to 1 -# otherwise set `` to 0. -# -function(ipp_is_module_python_wrapped itk-module output_var) - set(wrapped 0) - if(NOT DEFINED ITK_MODULE_${itk-module}_GROUP) - message(AUTHOR_WARNING "Variable ITK_MODULE_${itk-module}_GROUP is not defined") - else() - set(group ${ITK_MODULE_${itk-module}_GROUP}) - set(module_folder ${itk-module}) - # if any, strip ITK prefix - if(module_folder MATCHES "^ITK.+$") - string(REGEX REPLACE "^ITK(.+)$" "\\1" module_folder ${module_folder}) - endif() - if(EXISTS ${ITK_SOURCE_DIR}/Modules/${group}/${itk-module}/wrapping/CMakeLists.txt - OR EXISTS ${ITK_SOURCE_DIR}/Modules/${group}/${module_folder}/wrapping/CMakeLists.txt) - set(wrapped 1) - endif() - endif() - set(${output_var} ${wrapped} PARENT_SCOPE) -endfunction() - -# ipp_wheel_to_group( ) -# -# Extract ITK group name from wheel name (e.g 'itk-core' -> 'Core'). -# -# If the group name has less than 3 characters, take the uppercase -# value (e.g 'itk-io' -> 'IO'). -# -function(ipp_wheel_to_group wheel_name group_name_var) - string(REPLACE "itk-" "" _group ${wheel_name}) - string(SUBSTRING ${_group} 0 1 _first) - string(TOUPPER ${_first} _first_uc) - string(SUBSTRING ${_group} 1 -1 _remaining) - set(group_name "${_first_uc}${_remaining}") - # Convert to upper case if length <= 2 - string(LENGTH ${group_name} _length) - if(_length LESS 3) - string(TOUPPER ${group_name} group_name) - endif() - set(${group_name_var} ${group_name} PARENT_SCOPE) -endfunction() - -# ipp_pad_text( ) -# -# Example: -# -# set(row "Apple") -# ipp_pad_text(${row} 20 row) -# -# set(row "${row}Banana") -# ipp_pad_text(${row} 40 row) -# -# set(row "${row}Kiwi") -# ipp_pad_text(${row} 60 row) -# -# message(${row}) -# -# Output: -# -# Apple Banana Kiwi -# -function(ipp_pad_text text text_right_jusitfy_length output_var) - set(fill_char " ") - string(LENGTH "${text}" text_length) - math(EXPR pad_length "${text_right_jusitfy_length} - ${text_length} - 1") - if(pad_length GREATER 0) - string(RANDOM LENGTH ${pad_length} ALPHABET ${fill_char} text_dots) - set(${output_var} "${text} ${text_dots}" PARENT_SCOPE) - else() - set(${output_var} "${text}" PARENT_SCOPE) - endif() -endfunction() - -# ipp_display_table_row( ) -# -# Example: -# -# ipp_display_table_row("Apple^^Banana^^Kiwi" "20;20;20") -# ipp_display_table_row("Eiger^^Rainer^^Sajama" "20;20;20") -# -# Output: -# -# Apple Banana Kiwi -# Eiger Rainer Sajama -# -function(ipp_display_table_row values widths) - list(LENGTH values length) - set(text "") - math(EXPR range "${length} - 1") - foreach(index RANGE ${range}) - list(GET widths ${index} width) - list(GET values ${index} value) - string(REPLACE "^^" ";" value "${value}") - ipp_pad_text("${value}" ${width} value) - set(text "${text}${value}") - endforeach() - message(STATUS "${text}") -endfunction() - -# ipp_list_to_string( ) -# -# Example: -# -# set(values Foo Bar Oof) -# message("${values}") -# ipp_list_to_string("^^" "${values}" values) -# message("${values}") -# -# Output: -# -# Foo;Bar;Oof -# Foo^^Bar^^Oof -# -# Copied from Slicer/CMake/ListToString.cmake -# -function(ipp_list_to_string separator input_list output_string_var) - set(_string "") - # Get list length - list(LENGTH input_list list_length) - # If the list has 0 or 1 element, there is no need to loop over. - if(list_length LESS 2) - set(_string "${input_list}") - else() - math(EXPR last_element_index "${list_length} - 1") - foreach(index RANGE ${last_element_index}) - # Get current item_value - list(GET input_list ${index} item_value) - if(NOT item_value STREQUAL "") - # .. and append non-empty value to output string - set(_string "${_string}${item_value}") - # Append separator if current element is NOT the last one. - if(NOT index EQUAL last_element_index) - set(_string "${_string}${separator}") - endif() - endif() - endforeach() - endif() - set(${output_string_var} ${_string} PARENT_SCOPE) -endfunction() - -# No-op function allowing to shut-up "Manually-specified variables were not used by the project" -# warnings. -function(ipp_unused_vars) -endfunction() - -# -# Unused -# - -function(recursive_module_deps itk-module output_var) - set(_${itk-module}_deps ) - _recursive_deps("MODULE" "DEPENDS" ${itk-module} ${output_var}) - set(${output_var} ${${output_var}} PARENT_SCOPE) -endfunction() - -function(recursive_group_deps itk-group output_var) - set(_${itk-group}_deps ) - _recursive_deps("GROUP" "DEPENDS" ${itk-group} ${output_var}) - set(${output_var} ${${output_var}} PARENT_SCOPE) -endfunction() diff --git a/cmake/ITKPythonPackage_BuildWheels.cmake b/cmake/ITKPythonPackage_BuildWheels.cmake new file mode 100644 index 00000000..94fa89d9 --- /dev/null +++ b/cmake/ITKPythonPackage_BuildWheels.cmake @@ -0,0 +1,250 @@ +#----------------------------------------------------------------------------- +#------------------------------------------------------ +#---------------------------------- +# ITKPythonPackage_SUPERBUILD: OFF +#---------------------------------- +#------------------------------------------------------ +#----------------------------------------------------------------------------- +if(NOT DEFINED ITKPythonPackage_WHEEL_NAME) + message(FATAL_ERROR "ITKPythonPackage_WHEEL_NAME must be defined") +endif() + +message( + STATUS + "SuperBuild - ITKPythonPackage_WHEEL_NAME:${ITKPythonPackage_WHEEL_NAME}" +) + +set(components "PythonWheelRuntimeLibraries") + +message(STATUS "ITKPythonPackage_WHEEL_NAME: ${ITKPythonPackage_WHEEL_NAME}") + +# Extract ITK group name from wheel name +message(STATUS "") +set(msg "Extracting ITK_WHEEL_GROUP") +message(STATUS ${msg}) +ipp_wheel_to_group(${ITKPythonPackage_WHEEL_NAME} ITK_WHEEL_GROUP) +message(STATUS "${msg} - done [${ITK_WHEEL_GROUP}]") + +# +# Considering that +# +# * Every ITK module is associated with exactly one ITK group. +# * ITK module dependencies are specified independently of ITK groups +# +# we semi-arbitrarily defined a collection of wheels (see ``ITK_WHEEL_GROUPS``) +# that will roughly bundle the modules associated with each group. +# +# Based on the module dependency graph, the code below will determine which module +# should be packaged in which wheel. +# + +# List of ITK wheel groups +set(ITK_WHEEL_GROUPS "") +file(STRINGS "${CMAKE_SOURCE_DIR}/WHEEL_NAMES.txt" ITK_WHEELS REGEX "^itk-.+") +foreach(wheel_name IN LISTS ITK_WHEELS) + ipp_wheel_to_group(${wheel_name} group) + list(APPEND ITK_WHEEL_GROUPS ${group}) +endforeach() + +# Define below a reasonable dependency graph for ITK groups +set(ITK_GROUP_Core_DEPENDS) +set(ITK_GROUP_IO_DEPENDS Core) +set(ITK_GROUP_Numerics_DEPENDS Core) +set(ITK_GROUP_Filtering_DEPENDS Numerics) +set(ITK_GROUP_Segmentation_DEPENDS Filtering) +set(ITK_GROUP_Registration_DEPENDS Filtering) +set(ITK_GROUP_Video_DEPENDS Core) + +# ITK is needed to retrieve ITK module information +set(ITK_DIR ${ITK_BINARY_DIR}) +find_package(ITK REQUIRED) +set(CMAKE_MODULE_PATH ${ITK_CMAKE_DIR} ${CMAKE_MODULE_PATH}) + +# Sort wheel groups +include(TopologicalSort) +topological_sort(ITK_WHEEL_GROUPS ITK_GROUP_ _DEPENDS) + +# Set ``ITK_MODULE__DEPENDS`` variables +# +# Notes: +# +# * ``_DEPENDS`` variables are set after calling ``find_package(ITK REQUIRED)`` +# +# * This naming convention corresponds to what is used internally in ITK and allow +# to differentiate with variable like ``ITK_GROUP__DEPENDS`` set above. +# +foreach(module IN LISTS ITK_MODULES_ENABLED) + set(ITK_MODULE_${module}_DEPENDS "${${module}_DEPENDS}") +endforeach() + +# Set ``ITK_MODULE__DEPENDEES`` variables +foreach(module IN LISTS ITK_MODULES_ENABLED) + ipp_get_module_dependees(${module} ITK_MODULE_${module}_DEPENDEES) +endforeach() + +# Set ``ITK_GROUPS`` variable +file(GLOB group_dirs "${ITK_SOURCE_DIR}/Modules/*") +set(ITK_GROUPS) +foreach(dir IN LISTS group_dirs) + file(RELATIVE_PATH group "${ITK_SOURCE_DIR}/Modules" "${dir}") + if(NOT IS_DIRECTORY "${dir}" OR "${group}" MATCHES "^External$") + continue() + endif() + list(APPEND ITK_GROUPS ${group}) +endforeach() +message(STATUS "") +message(STATUS "ITK_GROUPS:${ITK_GROUPS}") + +# Set ``ITK_MODULE__GROUP`` variables +foreach(group IN LISTS ITK_GROUPS) + file( + GLOB_RECURSE _${group}_module_files + ${ITK_SOURCE_DIR}/Modules/${group}/itk-module.cmake + ) + foreach(_module_file ${_${group}_module_files}) + file(READ ${_module_file} _module_file_content) + string( + REGEX MATCH + "itk_module[ \n]*(\\([ \n]*)([A-Za-z0-9]*)" + _module_name + ${_module_file_content} + ) + set(_module_name ${CMAKE_MATCH_2}) + list(APPEND _${group}_module_list ${_module_name}) + set(ITK_MODULE_${_module_name}_GROUP ${group}) + endforeach() +endforeach() + +# Initialize ``ITK_WHEEL__MODULES`` variables that will contain list of modules +# to package in each wheel. +foreach(group IN LISTS ITK_WHEEL_GROUPS) + set(ITK_WHEEL_${group}_MODULES "") +endforeach() + +# Configure table display +set(row_widths + 40 + 20 + 20 + 10 + 90 + 12 +) +set(row_headers + MODULE_NAME + MODULE_GROUP + WHEEL_GROUP + IS_LEAF + MODULE_DEPENDEES_GROUPS + IS_WRAPPED +) +message(STATUS "") +ipp_display_table_row("${row_headers}" "${row_widths}") + +# Update ``ITK_WHEEL__MODULES`` variables +foreach(module IN LISTS ITK_MODULES_ENABLED) + ipp_is_module_leaf(${module} leaf) + set(dependees_groups) + if(NOT leaf) + set(dependees "") + ipp_recursive_module_dependees(${module} dependees) + foreach(dep IN LISTS dependees) + list(APPEND dependees_groups ${ITK_MODULE_${dep}_GROUP}) + endforeach() + if(dependees_groups) + list(REMOVE_DUPLICATES dependees_groups) + endif() + endif() + + # Filter out group not associated with a wheel + set(dependees_wheel_groups) + foreach(group IN LISTS dependees_groups) + list(FIND ITK_WHEEL_GROUPS ${group} _index) + if(_index EQUAL -1) + continue() + endif() + list(APPEND dependees_wheel_groups ${group}) + endforeach() + + set(wheel_group) + list(LENGTH dependees_wheel_groups _length) + + # Sanity check + if(leaf AND _length GREATER 0) + message(FATAL_ERROR "leaf module should not module depending on them !") + endif() + + if(_length EQUAL 0) + set(wheel_group "${ITK_MODULE_${module}_GROUP}") + elseif(_length EQUAL 1) + # Since packages depending on this module belong to one group, also package this module + set(wheel_group "${dependees_wheel_groups}") + elseif(_length GREATER 1) + # If more than one group is associated with the dependees, package the module in the + # "common ancestor" group. + set(common_ancestor_index 999999) + foreach(g IN LISTS dependees_wheel_groups) + list(FIND ITK_WHEEL_GROUPS ${g} _index) + if(NOT _index EQUAL -1 AND _index LESS common_ancestor_index) + set(common_ancestor_index ${_index}) + endif() + endforeach() + list(GET ITK_WHEEL_GROUPS ${common_ancestor_index} wheel_group) + endif() + + set(wheel_group_display ${wheel_group}) + + # XXX Hard-coded dispatch + if(module STREQUAL "ITKBridgeNumPy") + set(new_wheel_group "Core") + set(wheel_group_display "${new_wheel_group} (was ${wheel_group})") + set(wheel_group ${new_wheel_group}) + endif() + if(module STREQUAL "ITKVTK") + set(new_wheel_group "Core") + set(wheel_group_display "${new_wheel_group} (was ${wheel_group})") + set(wheel_group ${new_wheel_group}) + endif() + + # Associate module with a wheel + list(APPEND ITK_WHEEL_${wheel_group}_MODULES ${module}) + + # Display module info + ipp_is_module_python_wrapped(${module} is_wrapped) + ipp_list_to_string("^^" "${dependees_groups}" dependees_groups_str) + set(row_values + "${module};${ITK_MODULE_${module}_GROUP};${wheel_group_display};${leaf};${dependees_groups_str};${is_wrapped}" + ) + ipp_display_table_row("${row_values}" "${row_widths}") +endforeach() + +# Set list of components to install +set(components "") +foreach(module IN LISTS ITK_WHEEL_${ITK_WHEEL_GROUP}_MODULES) + list(APPEND components ${module}PythonWheelRuntimeLibraries) +endforeach() + +if(MSVC AND ITKPythonPackage_WHEEL_NAME STREQUAL "itk-core") + message(STATUS "Adding install rules for compiler runtime libraries") + # Put the runtime libraries next to the "itk/_*.pyd" C-extensions so they + # are found. + set(CMAKE_INSTALL_SYSTEM_RUNTIME_DESTINATION "itk") + include(InstallRequiredSystemLibraries) +endif() + +#----------------------------------------------------------------------------- +# Install ITK components +message(STATUS "Adding install rules for components:") +foreach(component IN LISTS components) + message(STATUS " ${component}") + install( + CODE + " +unset(CMAKE_INSTALL_COMPONENT) +set(COMPONENT \"${component}\") +set(CMAKE_INSTALL_DO_STRIP 1) +include(\"${ITK_BINARY_DIR}/cmake_install.cmake\") +unset(CMAKE_INSTALL_COMPONENT) +" + ) +endforeach() diff --git a/cmake/ITKPythonPackage_SuperBuild.cmake b/cmake/ITKPythonPackage_SuperBuild.cmake new file mode 100644 index 00000000..8f418bcd --- /dev/null +++ b/cmake/ITKPythonPackage_SuperBuild.cmake @@ -0,0 +1,366 @@ +#----------------------------------------------------------------------------- +#------------------------------------------------------ +#---------------------------------- +# ITKPythonPackage_SUPERBUILD: ON +#---------------------------------- +#------------------------------------------------------ +#----------------------------------------------------------------------------- + +option( + ITKPythonPackage_USE_TBB + "Build and use oneTBB in the ITK python package" + ON +) + +# Avoid "Manually-specified variables were not used by the project" warnings. +ipp_unused_vars(${PYTHON_VERSION_STRING} ${SKBUILD}) + +set(ep_download_extract_timestamp_arg) +if(CMAKE_VERSION VERSION_EQUAL "3.24" OR CMAKE_VERSION VERSION_GREATER "3.24") + # See https://cmake.org/cmake/help/latest/policy/CMP0135.html + set(ep_download_extract_timestamp_arg DOWNLOAD_EXTRACT_TIMESTAMP 1) +endif() + +#----------------------------------------------------------------------------- +# Options + +# When building different "flavor" of ITK python packages on a given platform, +# explicitly setting the following options allow to speed up package generation by +# re-using existing resources. +# +# ITK_SOURCE_DIR: Path to an existing source directory +# + +option(ITKPythonPackage_BUILD_PYTHON "Build ITK python module" ON) +mark_as_advanced(ITKPythonPackage_BUILD_PYTHON) + +set(ep_common_cmake_cache_args) +if(NOT CMAKE_CONFIGURATION_TYPES) + if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE "Release") + endif() + list( + APPEND ep_common_cmake_cache_args + -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} + ) +endif() + +if(CMAKE_OSX_DEPLOYMENT_TARGET) + list( + APPEND ep_common_cmake_cache_args + -DCMAKE_OSX_DEPLOYMENT_TARGET:STRING=${CMAKE_OSX_DEPLOYMENT_TARGET} + ) +endif() +if(CMAKE_OSX_ARCHITECTURES) + list( + APPEND ep_common_cmake_cache_args + -DCMAKE_OSX_ARCHITECTURES:STRING=${CMAKE_OSX_ARCHITECTURES} + ) +endif() + +if(CMAKE_MAKE_PROGRAM) + list( + APPEND ep_common_cmake_cache_args + -DCMAKE_MAKE_PROGRAM:FILEPATH=${CMAKE_MAKE_PROGRAM} + ) +endif() + +if(CMAKE_CXX_COMPILER) + list( + APPEND ep_common_cmake_cache_args + -DCMAKE_CXX_COMPILER:PATH=${CMAKE_CXX_COMPILER} + ) +elseif(ENV{CXX}) + list(APPEND ep_common_cmake_cache_args -DCMAKE_CXX_COMPILER:PATH=$ENV{CXX}) +endif() + +if(CMAKE_C_COMPILER) + list( + APPEND ep_common_cmake_cache_args + -DCMAKE_C_COMPILER:PATH=${CMAKE_C_COMPILER} + ) +elseif(ENV{CC}) + list(APPEND ep_common_cmake_cache_args -DCMAKE_C_COMPILER:PATH=$ENV{CC}) +endif() + +#----------------------------------------------------------------------------- +# compile with multiple processors +include(ProcessorCount) +ProcessorCount(NPROC) +if(NOT NPROC EQUAL 0) + set(ENV{MAKEFLAGS} "-j${NPROC}") +endif() + +#----------------------------------------------------------------------------- +include(ExternalProject) + +#----------------------------------------------------------------------------- +# A separate project is used to download ITK, so that it can reused +# when building different "flavor" of ITK python packages + +message(STATUS "SuperBuild -") +message(STATUS "SuperBuild - ITK-source-download") + +if(NOT ITK_SOURCE_DIR AND ENV{ITK_SOURCE_DIR}) + set(ITK_SOURCE_DIR "$ENV{ITK_SOURCE_DIR}") +endif() + +set(tbb_depends "") +set(tbb_args -DModule_ITKTBB:BOOL=OFF) +if(ITKPythonPackage_USE_TBB) + set(TBB_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/../oneTBB-prefix") + set(TBB_DIR "${TBB_INSTALL_PREFIX}/lib/cmake/TBB") + set(tbb_args -DModule_ITKTBB:BOOL=ON -DTBB_DIR:PATH=${TBB_DIR}) + + set(tbb_cmake_cache_args) + if(CMAKE_OSX_DEPLOYMENT_TARGET) + list( + APPEND tbb_cmake_cache_args + -DCMAKE_CXX_OSX_DEPLOYMENT_TARGET_FLAG:STRING="-mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}" + -DCMAKE_C_OSX_DEPLOYMENT_TARGET_FLAG:STRING="-mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}" + ) + endif() + + ExternalProject_Add( + oneTBB + URL + https://github.com/oneapi-src/oneTBB/archive/refs/tags/v2022.2.0.tar.gz + URL_HASH + SHA256=f0f78001c8c8edb4bddc3d4c5ee7428d56ae313254158ad1eec49eced57f6a5b + CMAKE_ARGS + -DTBB_TEST:BOOL=OFF + -DCMAKE_INSTALL_PREFIX:PATH=${TBB_INSTALL_PREFIX} + -DCMAKE_INSTALL_LIBDIR:STRING=lib # Skip default initialization by GNUInstallDirs CMake module + ${ep_common_cmake_cache_args} ${tbb_cmake_cache_args} + ${ep_download_extract_timestamp_arg} + BUILD_BYPRODUCTS "${TBB_DIR}/TBBConfig.cmake" + USES_TERMINAL_DOWNLOAD 1 + USES_TERMINAL_UPDATE 1 + USES_TERMINAL_CONFIGURE 1 + USES_TERMINAL_BUILD 1 + ) + message(STATUS "SuperBuild - TBB: Enabled") + message(STATUS "SuperBuild - TBB_DIR: ${TBB_DIR}") + set(tbb_depends oneTBB) +endif() + +# Only add ITK-source-download ExternalProject if directory does not +# already exist +if(NOT EXISTS ${ITK_SOURCE_DIR}) + set(ITK_REPOSITORY "https://github.com/InsightSoftwareConsortium/ITK.git") + + if(NOT DEFINED ITK_GIT_TAG AND DEFINED ENV{ITK_GIT_TAG}) + set(ITK_GIT_TAG "$ENV{ITK_GIT_TAG}") + endif() + + if(NOT DEFINED ITK_GIT_TAG) + message( + FATAL_ERROR + "ITK_GIT_TAG must be defined when configuring cmake" + ) + endif() + ExternalProject_Add( + ITK-source-download + SOURCE_DIR ${ITK_SOURCE_DIR} + GIT_REPOSITORY ${ITK_REPOSITORY} + GIT_TAG ${ITK_GIT_TAG} + USES_TERMINAL_DOWNLOAD 1 + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + DEPENDS "${tbb_depends}" + ) + set(proj_status "") +else() + # Suppress unused variable warning + set(_unused "${ITK_GIT_TAG}") + ipp_externalproject_add_empty( + ITK-source-download + "" + ) + set(proj_status " (REUSE)") +endif() + +message(STATUS "SuperBuild - ITK_SOURCE_DIR: ${ITK_SOURCE_DIR}") +message(STATUS "SuperBuild - ITK-source-download[OK]${proj_status}") + +#----------------------------------------------------------------------------- +if(NOT ITKPythonPackage_BUILD_PYTHON) + return() +endif() + +#----------------------------------------------------------------------------- +# Search for python interpreter and libraries + +message(STATUS "SuperBuild -") +message(STATUS "SuperBuild - Searching for python") + +# Sanity checks +if(DEFINED Python3_INCLUDE_DIR AND NOT EXISTS ${Python3_INCLUDE_DIR}) + message( + FATAL_ERROR + "Python3_INCLUDE_DIR=${Python3_INCLUDE_DIR}: variable is defined but corresponds to nonexistent directory" + ) +endif() +if(DEFINED Python3_LIBRARY AND NOT EXISTS ${Python3_LIBRARY}) + message( + FATAL_ERROR + "Python3_LIBRARY=${Python3_LIBRARY}: variable is defined but corresponds to nonexistent file" + ) +endif() +if(DEFINED Python3_EXECUTABLE AND NOT EXISTS ${Python3_EXECUTABLE}) + message( + FATAL_ERROR + "Python3_EXECUTABLE=${Python3_EXECUTABLE}: variable is defined but corresponds to nonexistent file" + ) +endif() +if(DEFINED DOXYGEN_EXECUTABLE AND NOT EXISTS ${DOXYGEN_EXECUTABLE}) + message( + FATAL_ERROR + "DOXYGEN_EXECUTABLE=${DOXYGEN_EXECUTABLE}: variable is defined but corresponds to nonexistent file" + ) +endif() + +if( + NOT DEFINED Python3_INCLUDE_DIR + OR NOT DEFINED Python3_LIBRARY + OR NOT DEFINED Python3_EXECUTABLE +) + find_package(Python3 COMPONENTS Interpreter Development) + if(NOT Python3_EXECUTABLE AND _Python3_EXECUTABLE) + set(Python3_EXECUTABLE + ${_Python3_EXECUTABLE} + CACHE INTERNAL + "Path to the Python interpreter" + FORCE + ) + endif() +endif() +if(NOT DEFINED DOXYGEN_EXECUTABLE) + find_package(Doxygen REQUIRED) +endif() + +message(STATUS "SuperBuild - Python3_INCLUDE_DIR: ${Python3_INCLUDE_DIR}") +message(STATUS "SuperBuild - Python3_INCLUDE_DIRS: ${Python3_INCLUDE_DIRS}") +message(STATUS "SuperBuild - Python3_LIBRARY: ${Python3_LIBRARY}") +message(STATUS "SuperBuild - Python3_EXECUTABLE: ${Python3_EXECUTABLE}") +message(STATUS "SuperBuild - Searching for python[OK]") +message(STATUS "SuperBuild - DOXYGEN_EXECUTABLE: ${DOXYGEN_EXECUTABLE}") + +# CMake configuration variables to pass to ITK's build +set(ep_itk_cmake_cache_args "") +foreach(var BUILD_SHARED_LIBS ITK_BUILD_DEFAULT_MODULES) + if(DEFINED ${var}) + list(APPEND ep_itk_cmake_cache_args "-D${var}=${${var}}") + endif() +endforeach() +function(cached_variables RESULTVAR PATTERN) + get_cmake_property(variables CACHE_VARIABLES) + set(result) + foreach(variable ${variables}) + if(${variable} AND variable MATCHES "${PATTERN}") + list(APPEND result "-D${variable}=${${variable}}") + endif() + endforeach() + set(${RESULTVAR} ${result} PARENT_SCOPE) +endfunction() +cached_variables(itk_pattern_cached_vars "^(ITK_WRAP_)|(ITKGroup_)|(Module_)") +list(APPEND ep_itk_cmake_cache_args ${itk_pattern_cached_vars}) +# Todo, also pass all Module_* variables +message(STATUS "ITK CMake Cache Args - ${ep_itk_cmake_cache_args}") +#----------------------------------------------------------------------------- +# ITK: This project builds ITK and associated Python modules + +option( + ITKPythonPackage_ITK_BINARY_REUSE + "Reuse provided ITK_BINARY_DIR without configuring or building ITK" + OFF +) + +set(ITK_BINARY_DIR "${CMAKE_BINARY_DIR}/ITKb" CACHE PATH "ITK build directory") + +message(STATUS "SuperBuild -") +message(STATUS "SuperBuild - ITK => Requires ITK-source-download") +message(STATUS "SuperBuild - ITK_BINARY_DIR: ${ITK_BINARY_DIR}") + +if(NOT ITKPythonPackage_ITK_BINARY_REUSE) + set(_stamp "${CMAKE_BINARY_DIR}/ITK-prefix/src/ITK-stamp/ITK-configure") + if(EXISTS ${_stamp}) + execute_process(COMMAND ${CMAKE_COMMAND} -E remove ${_stamp}) + message(STATUS "SuperBuild - Force re-configure removing ${_stamp}") + endif() + + ExternalProject_Add( + ITK + DOWNLOAD_COMMAND "" + SOURCE_DIR ${ITK_SOURCE_DIR} + BINARY_DIR ${ITK_BINARY_DIR} + PREFIX "ITKp" + CMAKE_ARGS + -DBUILD_TESTING:BOOL=OFF + -DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_INSTALL_PREFIX} + -DPY_SITE_PACKAGES_PATH:PATH=${CMAKE_INSTALL_PREFIX} + -DWRAP_ITK_INSTALL_COMPONENT_IDENTIFIER:STRING=PythonWheel + -DWRAP_ITK_INSTALL_COMPONENT_PER_MODULE:BOOL=ON + -DITK_LEGACY_SILENT:BOOL=ON -DITK_WRAP_PYTHON:BOOL=ON + -DDOXYGEN_EXECUTABLE:FILEPATH=${DOXYGEN_EXECUTABLE} + -DPython3_INCLUDE_DIR:PATH=${Python3_INCLUDE_DIR} + -DPython3_LIBRARY:FILEPATH=${Python3_LIBRARY} + -DPython3_EXECUTABLE:FILEPATH=${Python3_EXECUTABLE} + ${ep_common_cmake_cache_args} ${tbb_args} ${ep_itk_cmake_cache_args} + ${ep_download_extract_timestamp_arg} + USES_TERMINAL_DOWNLOAD 1 + USES_TERMINAL_UPDATE 1 + USES_TERMINAL_CONFIGURE 1 + USES_TERMINAL_BUILD 1 + INSTALL_COMMAND "" + ) + set(proj_status "") +else() + # Sanity checks + if(NOT EXISTS "${ITK_BINARY_DIR}/CMakeCache.txt") + message( + FATAL_ERROR + "ITKPythonPackage_ITK_BINARY_REUSE is ON but ITK_BINARY_DIR variable is not associated with an ITK build directory. [ITK_BINARY_DIR:${ITK_BINARY_DIR}]" + ) + endif() + + ipp_externalproject_add_empty( + ITK + "" + ) + set(proj_status " (REUSE)") +endif() +ExternalProject_Add_StepDependencies(ITK download ITK-source-download) + +message(STATUS "SuperBuild - ITK[OK]${proj_status}") + +#----------------------------------------------------------------------------- +# ITKPythonPackage: This project adds install rules for the "RuntimeLibraries" +# components associated with the ITK project. + +message(STATUS "SuperBuild -") +message(STATUS "SuperBuild - ${PROJECT_NAME} => Requires ITK") + +ExternalProject_Add( + ${PROJECT_NAME} + SOURCE_DIR ${CMAKE_SOURCE_DIR} + BINARY_DIR ${CMAKE_BINARY_DIR}/${PROJECT_NAME}-build + DOWNLOAD_COMMAND "" + UPDATE_COMMAND "" + CMAKE_CACHE_ARGS + -DITKPythonPackage_SUPERBUILD:BOOL=0 + -DITK_BINARY_DIR:PATH=${ITK_BINARY_DIR} + -DITK_SOURCE_DIR:PATH=${ITK_SOURCE_DIR} + -DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_INSTALL_PREFIX} + -DITKPythonPackage_WHEEL_NAME:STRING=${ITKPythonPackage_WHEEL_NAME} + -DITKPythonPackage_USE_TBB:BOOL=${ITKPythonPackage_USE_TBB} + ${ep_common_cmake_cache_args} + USES_TERMINAL_CONFIGURE 1 + INSTALL_COMMAND "" + DEPENDS ITK +) + +install(SCRIPT ${CMAKE_BINARY_DIR}/${PROJECT_NAME}-build/cmake_install.cmake) + +message(STATUS "SuperBuild - ${PROJECT_NAME}[OK]") diff --git a/cmake/ITKPythonPackage_Utils.cmake b/cmake/ITKPythonPackage_Utils.cmake new file mode 100644 index 00000000..5282b416 --- /dev/null +++ b/cmake/ITKPythonPackage_Utils.cmake @@ -0,0 +1,252 @@ +# ipp_ExternalProject_Add_Empty( ) +# +# Add an empty external project +# +function(ipp_ExternalProject_Add_Empty proj depends) + set(depends_args) + if(NOT depends STREQUAL "") + set(depends_args DEPENDS ${depends}) + endif() + ExternalProject_Add( + ${proj} + SOURCE_DIR ${CMAKE_BINARY_DIR}/${proj} + DOWNLOAD_COMMAND "" + UPDATE_COMMAND "" + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + BUILD_IN_SOURCE 1 + BUILD_ALWAYS 1 + INSTALL_COMMAND "" ${depends_args} + ) +endfunction() + +# ipp_get_module_dependees( ) +# +# Collect all modules depending on ````. +# +function(ipp_get_module_dependees itk-module output_var) + set(dependees "") + foreach(m_enabled IN LISTS ITK_MODULES_ENABLED) + list(FIND ITK_MODULE_${m_enabled}_DEPENDS ${itk-module} _index) + if(NOT _index EQUAL -1) + list(APPEND dependees ${m_enabled}) + endif() + endforeach() + list(REMOVE_DUPLICATES dependees) + set(${output_var} ${dependees} PARENT_SCOPE) +endfunction() + +function(_recursive_deps item-type item-category itk-item output_var) + set(_${itk-item}_deps) + foreach(dep IN LISTS ITK_${item-type}_${itk-item}_${item-category}) + list(APPEND _${itk-item}_deps ${dep}) + _recursive_deps(${item-type} ${item-category} ${dep} _${itk-item}_deps) + endforeach() + list(APPEND ${output_var} ${_${itk-item}_deps}) + list(REMOVE_DUPLICATES ${output_var}) + set(${output_var} ${${output_var}} PARENT_SCOPE) +endfunction() + +# ipp_recursive_module_dependees( ) +# +# Recursively collect all modules depending on ````. +# +function(ipp_recursive_module_dependees itk-module output_var) + set(_${itk-module}_deps) + _recursive_deps("MODULE" "DEPENDEES" ${itk-module} ${output_var}) + set(${output_var} ${${output_var}} PARENT_SCOPE) +endfunction() + +# ipp_is_module_leaf( ) +# +# If ```` has no dependencies, set `` to 1 +# otherwise set `` to 0. +# +function(ipp_is_module_leaf itk-module output_var) + set(leaf 1) + foreach(m_enabled IN LISTS ITK_MODULES_ENABLED) + list(FIND ITK_MODULE_${m_enabled}_DEPENDS ${itk-module} _index) + if(NOT _index EQUAL -1) + set(leaf 0) + break() + endif() + endforeach() + set(${output_var} ${leaf} PARENT_SCOPE) +endfunction() + +# ipp_is_module_python_wrapped( ) +# +# If ```` is wrapped in python, set `` to 1 +# otherwise set `` to 0. +# +function(ipp_is_module_python_wrapped itk-module output_var) + set(wrapped 0) + if(NOT DEFINED ITK_MODULE_${itk-module}_GROUP) + message( + AUTHOR_WARNING + "Variable ITK_MODULE_${itk-module}_GROUP is not defined" + ) + else() + set(group ${ITK_MODULE_${itk-module}_GROUP}) + set(module_folder ${itk-module}) + # if any, strip ITK prefix + if(module_folder MATCHES "^ITK.+$") + string( + REGEX REPLACE + "^ITK(.+)$" + "\\1" + module_folder + ${module_folder} + ) + endif() + if( + EXISTS + ${ITK_SOURCE_DIR}/Modules/${group}/${itk-module}/wrapping/CMakeLists.txt + OR EXISTS + ${ITK_SOURCE_DIR}/Modules/${group}/${module_folder}/wrapping/CMakeLists.txt + ) + set(wrapped 1) + endif() + endif() + set(${output_var} ${wrapped} PARENT_SCOPE) +endfunction() + +# ipp_wheel_to_group( ) +# +# Extract ITK group name from wheel name (e.g 'itk-core' -> 'Core'). +# +# If the group name has less than 3 characters, take the uppercase +# value (e.g 'itk-io' -> 'IO'). +# +function(ipp_wheel_to_group wheel_name group_name_var) + string(REPLACE "itk-" "" _group ${wheel_name}) + string(SUBSTRING ${_group} 0 1 _first) + string(TOUPPER ${_first} _first_uc) + string(SUBSTRING ${_group} 1 -1 _remaining) + set(group_name "${_first_uc}${_remaining}") + # Convert to upper case if length <= 2 + string(LENGTH ${group_name} _length) + if(_length LESS 3) + string(TOUPPER ${group_name} group_name) + endif() + set(${group_name_var} ${group_name} PARENT_SCOPE) +endfunction() + +# ipp_pad_text( ) +# +# Example: +# +# set(row "Apple") +# ipp_pad_text(${row} 20 row) +# +# set(row "${row}Banana") +# ipp_pad_text(${row} 40 row) +# +# set(row "${row}Kiwi") +# ipp_pad_text(${row} 60 row) +# +# message(${row}) +# +# Output: +# +# Apple Banana Kiwi +# +function(ipp_pad_text text text_right_jusitfy_length output_var) + set(fill_char " ") + string(LENGTH "${text}" text_length) + math(EXPR pad_length "${text_right_jusitfy_length} - ${text_length} - 1") + if(pad_length GREATER 0) + string(RANDOM LENGTH ${pad_length} ALPHABET ${fill_char} text_dots) + set(${output_var} "${text} ${text_dots}" PARENT_SCOPE) + else() + set(${output_var} "${text}" PARENT_SCOPE) + endif() +endfunction() + +# ipp_display_table_row( ) +# +# Example: +# +# ipp_display_table_row("Apple^^Banana^^Kiwi" "20;20;20") +# ipp_display_table_row("Eiger^^Rainer^^Sajama" "20;20;20") +# +# Output: +# +# Apple Banana Kiwi +# Eiger Rainer Sajama +# +function(ipp_display_table_row values widths) + list(LENGTH values length) + set(text "") + math(EXPR range "${length} - 1") + foreach(index RANGE ${range}) + list(GET widths ${index} width) + list(GET values ${index} value) + string(REPLACE "^^" ";" value "${value}") + ipp_pad_text("${value}" ${width} value) + set(text "${text}${value}") + endforeach() + message(STATUS "${text}") +endfunction() + +# ipp_list_to_string( ) +# +# Example: +# +# set(values Foo Bar Oof) +# message("${values}") +# ipp_list_to_string("^^" "${values}" values) +# message("${values}") +# +# Output: +# +# Foo;Bar;Oof +# Foo^^Bar^^Oof +# +# Copied from Slicer/CMake/ListToString.cmake +# +function(ipp_list_to_string separator input_list output_string_var) + set(_string "") + # Get list length + list(LENGTH input_list list_length) + # If the list has 0 or 1 element, there is no need to loop over. + if(list_length LESS 2) + set(_string "${input_list}") + else() + math(EXPR last_element_index "${list_length} - 1") + foreach(index RANGE ${last_element_index}) + # Get current item_value + list(GET input_list ${index} item_value) + if(NOT item_value STREQUAL "") + # .. and append non-empty value to output string + set(_string "${_string}${item_value}") + # Append separator if current element is NOT the last one. + if(NOT index EQUAL last_element_index) + set(_string "${_string}${separator}") + endif() + endif() + endforeach() + endif() + set(${output_string_var} ${_string} PARENT_SCOPE) +endfunction() + +# No-op function allowing to shut-up "Manually-specified variables were not used by the project" +# warnings. +function(ipp_unused_vars) +endfunction() + +# +# Unused +# + +function(recursive_module_deps itk-module output_var) + set(_${itk-module}_deps) + _recursive_deps("MODULE" "DEPENDS" ${itk-module} ${output_var}) + set(${output_var} ${${output_var}} PARENT_SCOPE) +endfunction() + +function(recursive_group_deps itk-group output_var) + set(_${itk-group}_deps) + _recursive_deps("GROUP" "DEPENDS" ${itk-group} ${output_var}) + set(${output_var} ${${output_var}} PARENT_SCOPE) +endfunction() diff --git a/itkVersion.py b/itkVersion.py deleted file mode 100644 index acf9bffb..00000000 --- a/itkVersion.py +++ /dev/null @@ -1,31 +0,0 @@ -from packaging.version import Version - -# Version needs to be python PEP 440 compliant (no leading v) -VERSION = '6.0b2'.removeprefix("v") - -def get_versions(): - """Returns versions for the ITK Python package. - - from itkVersion import get_versions - - # Returns the ITK repository version - get_versions()['version'] - - # Returns the package version. Since GitHub Releases do not support the '+' - # character in file names, this does not contain the local version - # identifier in nightly builds, i.e. - # - # '4.11.0.dev20170208' - # - # instead of - # - # '4.11.0.dev20170208+139.g922f2d9' - get_versions()['package-version'] - """ - - Version(VERSION) # Raise InvalidVersion exception if not PEP 440 compliant - - versions = {} - versions['version'] = VERSION - versions['package-version'] = VERSION.split('+')[0] - return versions diff --git a/pixi.lock b/pixi.lock new file mode 100644 index 00000000..94039c9e --- /dev/null +++ b/pixi.lock @@ -0,0 +1,11190 @@ +version: 6 +environments: + default: + channels: + - url: https://conda.anaconda.org/conda-forge/ + options: + pypi-prerelease-mode: if-necessary-or-explicit + packages: + linux-64: + - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/archspec-0.2.5-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.3.0-py314h680f03e_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/boltons-25.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.2.0-py314h3de4e8d_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_9.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.34.6-hb03c661_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.2.25-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-2.0.0-py314h4a8dc5f_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.5-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/conda-26.1.1-py314hdafbbf9_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-libmamba-solver-25.11.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-handling-2.4.0-pyh7900ff3_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-streaming-0.12.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cpp-expected-1.3.1-h171cf75_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/distro-1.9.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/fmt-12.1.0-hff5e90c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/frozendict-2.4.7-py314h5bd0f2a_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.2-h33c6efd_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpatch-1.33-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpointer-3.0.0-pyhcf101f3_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.22.2-ha1258a1_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_101.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libarchive-3.8.6-gpl_hc2c16d8_100.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcurl-8.19.0-hcf29cc6_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libev-4.33-hd590300_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.4-hecca717_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.18-h3b78370_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.2-hb03c661_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libmamba-2.5.0-hd28c85e_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libmamba-spdlog-2.5.0-h12fcf84_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libmambapy-2.5.0-py314hcbd71af_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb03c661_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.67.0-had1ee68_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsolv-0.7.35-h9463b59_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.52.0-hf4e2dac_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libssh2-1.11.1-hcf80075_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.41.3-h5347b49_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-16-2.15.2-hca6bf5a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.15.2-he237659_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/lz4-c-1.10.0-h5888daf_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/lzo-2.10-h280c20c_1002.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/menuinst-2.4.2-py314hdafbbf9_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/msgpack-python-1.1.2-py314h9891dd4_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nlohmann_json-abi-3.12.0-h0f90c79_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.1-h35e630c_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pixi-pycharm-0.0.10-unix_hf108a03_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pybind11-abi-11-hc364b38_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pycosat-0.6.6-py314h5bd0f2a_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.14.3-h32b2ec7_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/reproc-14.2.5.post0-hb9d3cd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/reproc-cpp-14.2.5.post0-h5888daf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.32.5-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ruamel.yaml-0.18.17-py314h0f05182_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ruamel.yaml.clib-0.2.15-py314h0f05182_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/simdjson-4.2.4-hb700be7_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/spdlog-1.17.0-hab81395_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/taplo-0.10.0-h2d22210_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/truststore-0.10.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-cpp-0.8.0-h3f2d84a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstandard-0.25.0-py314h0f05182_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda + linux-aarch64: + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-20_gnu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/archspec-0.2.5-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.3.0-py314h680f03e_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/boltons-25.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/brotli-python-1.2.0-py314h352cb57_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/bzip2-1.0.8-h4777abc_9.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/c-ares-1.34.6-he30d5cf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.2.25-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cffi-2.0.0-py314h0bd77cf_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.5-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/conda-26.1.1-py314h28a4750_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-libmamba-solver-25.11.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-handling-2.4.0-pyh7900ff3_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-streaming-0.12.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cpp-expected-1.3.1-hdc560ac_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/distro-1.9.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/fmt-12.1.0-h20c602a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/frozendict-2.4.7-py314h51f160d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/icu-78.2-hcab7f73_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpatch-1.33-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpointer-3.0.0-pyhcf101f3_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/keyutils-1.6.3-h86ecc28_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/krb5-1.22.2-hfd895c2_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.45.1-default_h1979696_101.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libarchive-3.8.6-gpl_hbe7d12b_100.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcurl-8.19.0-hc57f145_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libedit-3.1.20250104-pl5321h976ea20_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libev-4.33-h31becfc_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.7.4-hfae3067_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libffi-3.5.2-h376a255_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-15.2.0-h8acb6b2_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-ng-15.2.0-he9431aa_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-15.2.0-h8acb6b2_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libiconv-1.18-h90929bb_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblzma-5.8.2-he30d5cf_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libmamba-2.5.0-hc712cdd_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libmamba-spdlog-2.5.0-h3ad78e7_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libmambapy-2.5.0-py314h709e558_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libmpdec-4.0.0-he30d5cf_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libnghttp2-1.67.0-ha888d0e_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsolv-0.7.35-hdda61c4_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.52.0-h10b116e_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libssh2-1.11.1-h18c354c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-15.2.0-hef695bb_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.41.3-h1022ec0_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxml2-16-2.15.2-h79dcc73_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxml2-2.15.2-h825857f_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.3.1-h86ecc28_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lz4-c-1.10.0-h5ad3122_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lzo-2.10-h80f16a2_1002.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/menuinst-2.4.2-py314h28a4750_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/msgpack-python-1.1.2-py314hd7d8586_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.5-ha32ae93_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nlohmann_json-abi-3.12.0-h0f90c79_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.6.1-h546c87b_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pixi-pycharm-0.0.10-unix_hf108a03_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pybind11-abi-11-hc364b38_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pycosat-0.6.6-py314h51f160d_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.14.3-hb06a95a_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/readline-8.3-hb682ff5_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/reproc-14.2.5.post0-h86ecc28_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/reproc-cpp-14.2.5.post0-h5ad3122_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.32.5-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ruamel.yaml-0.18.17-py314h2e8dab5_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ruamel.yaml.clib-0.2.15-py314h2e8dab5_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/simdjson-4.2.4-hfefdfc9_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/spdlog-1.17.0-h9f97df7_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/taplo-0.10.0-h3618846_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tk-8.6.13-noxft_h0dc03b3_103.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/truststore-0.10.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/yaml-cpp-0.8.0-h5ad3122_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstandard-0.25.0-py314h2e8dab5_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.7-h85ac4a6_6.conda + osx-64: + - conda: https://conda.anaconda.org/conda-forge/noarch/archspec-0.2.5-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.3.0-py314h680f03e_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/boltons-25.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/brotli-python-1.2.0-py314h3262eb8_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/bzip2-1.0.8-h500dc9f_9.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/c-ares-1.34.6-hb5e19a0_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.2.25-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/cffi-2.0.0-py314h8ca4d5a_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.5-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/conda-26.1.1-py314hee6578b_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-libmamba-solver-25.11.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-handling-2.4.0-pyh7900ff3_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-streaming-0.12.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/cpp-expected-1.3.1-h0ba0a54_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/distro-1.9.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/fmt-12.1.0-hda137b5_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/frozendict-2.4.7-py314h6482030_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/icu-78.2-h14c5de8_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpatch-1.33-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpointer-3.0.0-pyhcf101f3_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/krb5-1.22.2-h207b36a_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libarchive-3.8.6-gpl_h2bf6321_100.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcurl-8.19.0-h8f0b9e4_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcxx-22.1.1-h19cb2f5_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libedit-3.1.20250104-pl5321ha958ccf_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libev-4.33-h10d778d_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libexpat-2.7.4-h991f03e_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libffi-3.5.2-hd1f9c09_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libiconv-1.18-h57a12c2_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/liblzma-5.8.2-h11316ed_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libmamba-2.5.0-h7fe6c55_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libmamba-spdlog-2.5.0-hb923e0c_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libmambapy-2.5.0-py314haca2e77_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libmpdec-4.0.0-hf3981d6_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libnghttp2-1.67.0-h3338091_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libsolv-0.7.35-h6fd32b5_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.52.0-h77d7759_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libssh2-1.11.1-hed3591d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libxml2-16-2.15.2-h7a90416_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libxml2-2.15.2-hd552753_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.3.1-hd23fc13_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/lz4-c-1.10.0-h240833e_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/lzo-2.10-h4132b18_1002.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/menuinst-2.4.2-py314hee6578b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/msgpack-python-1.1.2-py314h00ed6fe_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.5-h0622a9a_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nlohmann_json-abi-3.12.0-h0f90c79_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/openssl-3.6.1-hb6871ef_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pixi-pycharm-0.0.10-unix_hf108a03_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pybind11-abi-11-hc364b38_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/pycosat-0.6.6-py314h03d016b_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.14.3-h4f44bb5_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/readline-8.3-h68b038d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/reproc-14.2.5.post0-h6e16a3a_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/reproc-cpp-14.2.5.post0-h240833e_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.32.5-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ruamel.yaml-0.18.17-py314hd330473_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ruamel.yaml.clib-0.2.15-py314hd330473_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/simdjson-4.2.4-hcb651aa_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/spdlog-1.17.0-h30f01e4_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/taplo-0.10.0-hffa81eb_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-h7142dee_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/truststore-0.10.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/yaml-cpp-0.8.0-h92383a6_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/zstandard-0.25.0-py314hd1e8ddb_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.7-h3eecb57_6.conda + osx-arm64: + - conda: https://conda.anaconda.org/conda-forge/noarch/archspec-0.2.5-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.3.0-py314h680f03e_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/boltons-25.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-python-1.2.0-py314h3daef5d_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-hd037594_9.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-ares-1.34.6-hc919400_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.2.25-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cffi-2.0.0-py314h44086f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.5-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/conda-26.1.1-py314h4dc9dd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-libmamba-solver-25.11.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-handling-2.4.0-pyh7900ff3_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-streaming-0.12.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cpp-expected-1.3.1-h4f10f1e_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/distro-1.9.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/fmt-12.1.0-h403dcb5_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/frozendict-2.4.7-py314h0612a62_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.2-hef89b57_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpatch-1.33-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpointer-3.0.0-pyhcf101f3_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.22.2-h385eeb1_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarchive-3.8.6-gpl_h6fbacd7_100.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcurl-8.19.0-hd5a2499_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-22.1.1-h55c6f16_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libedit-3.1.20250104-pl5321hafb1f1b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libev-4.33-h93a5062_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.7.4-hf6b4638_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-hcf2aa1b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libiconv-1.18-h23cfdf5_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.2-h8088a28_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmamba-2.5.0-h7950639_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmamba-spdlog-2.5.0-h85b9800_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmambapy-2.5.0-py314hf8f60b7_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmpdec-4.0.0-h84a0fba_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libnghttp2-1.67.0-hc438710_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsolv-0.7.35-h5f525b2_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.52.0-h1ae2325_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libssh2-1.11.1-h1590b86_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-16-2.15.2-h5ef1a60_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-2.15.2-h8d039ee_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.1-h8359307_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/lz4-c-1.10.0-h286801f_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/lzo-2.10-h925e9cb_1002.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/menuinst-2.4.2-py314h4dc9dd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/msgpack-python-1.1.2-py314h784bc60_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.5-h5e97a16_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nlohmann_json-abi-3.12.0-h0f90c79_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.1-hd24854e_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pixi-pycharm-0.0.10-unix_hf108a03_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pybind11-abi-11-hc364b38_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pycosat-0.6.6-py314hb84d1df_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.14.3-h4c637c5_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/reproc-14.2.5.post0-h5505292_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/reproc-cpp-14.2.5.post0-h286801f_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.32.5-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ruamel.yaml-0.18.17-py314ha14b1ff_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ruamel.yaml.clib-0.2.15-py314ha14b1ff_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/simdjson-4.2.4-ha7d2532_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/spdlog-1.17.0-ha0f8610_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/taplo-0.10.0-h2b2570c_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h010d191_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/truststore-0.10.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/yaml-cpp-0.8.0-ha1acc90_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstandard-0.25.0-py314h9d33bd4_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda + win-64: + - conda: https://conda.anaconda.org/conda-forge/noarch/archspec-0.2.5-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.3.0-py314h680f03e_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/boltons-25.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/brotli-python-1.2.0-py314he701e3d_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-h0ad9c76_9.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-h4c7d964_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.2.25-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cffi-2.0.0-py314h5a2d7ad_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.5-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/conda-26.1.1-py314h86ab7b2_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-libmamba-solver-25.11.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-handling-2.4.0-pyh7900ff3_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-streaming-0.12.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cpp-expected-1.3.1-h477610d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/distro-1.9.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/fmt-12.1.0-h7f4e812_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/frozendict-2.4.7-py314h5a2d7ad_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpatch-1.33-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpointer-3.0.0-pyhcf101f3_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/krb5-1.22.2-h0ea6238_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libarchive-3.8.6-gpl_he24518a_100.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libcurl-8.19.0-h8206538_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.7.4-hac47afa_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libffi-3.5.2-h3d046cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libiconv-1.18-hc1393d2_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/liblzma-5.8.2-hfd05255_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libmamba-2.5.0-h06825f5_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libmamba-spdlog-2.5.0-h9ae1bf1_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libmambapy-2.5.0-py314h532c739_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libmpdec-4.0.0-hfd05255_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libsolv-0.7.35-h8883371_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.52.0-hf5d6505_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libssh2-1.11.1-h9aa295b_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-16-2.15.2-h692994f_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-2.15.2-h5d26750_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.3.1-h2466b09_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/lz4-c-1.10.0-h2466b09_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/lzo-2.10-h6a83c73_1002.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/menuinst-2.4.2-py314h13fbf68_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/msgpack-python-1.1.2-py314h909e829_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nlohmann_json-abi-3.12.0-h0f90c79_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.6.1-hf411b9b_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pixi-pycharm-0.0.10-win_hba80fca_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pybind11-abi-11-hc364b38_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pycosat-0.6.6-py314h5a2d7ad_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyh09c184e_7.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.14.3-h4b44e0e_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/reproc-14.2.5.post0-h2466b09_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/reproc-cpp-14.2.5.post0-he0c23c2_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.32.5-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ruamel.yaml-0.18.17-py314hc5dbbe4_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ruamel.yaml.clib-0.2.15-py314hc5dbbe4_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/simdjson-4.2.4-h49e36cd_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/spdlog-1.17.0-h9f585f1_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/taplo-0.10.0-h63977a8_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h6ed50ae_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyha7b4d00_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/truststore-0.10.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.3-h41ae7f8_34.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.44.35208-h818238b_34.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vcomp14-14.44.35208-h818238b_34.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/win_inet_pton-1.1.0-pyh7428d3b_8.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/yaml-cpp-0.8.0-he0c23c2_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/zstandard-0.25.0-py314hc5dbbe4_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.7-h534d264_6.conda + linux-py310: + channels: + - url: https://conda.anaconda.org/conda-forge/ + indexes: + - https://pypi.org/simple + options: + pypi-prerelease-mode: if-necessary-or-explicit + packages: + linux-64: + - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/archspec-0.2.5-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/auditwheel-6.6.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/backports.zstd-1.3.0-py310h69bd2ac_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/binutils-2.45.1-default_h4852527_101.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/binutils_impl_linux-64-2.45.1-default_hfdba357_101.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/binutils_linux-64-2.45.1-default_h4852527_101.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/boltons-25.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.2.0-py310hba01987_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_9.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.34.6-hb03c661_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/c-compiler-1.11.0-h4d9bdce_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.2.25-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-2.0.0-py310he7384ee_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.5-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cmake-3.31.8-hc85cc9f_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/conda-26.1.1-py310hff52083_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/conda-gcc-specs-14.3.0-he8ccf15_18.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-libmamba-solver-25.11.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-handling-2.4.0-pyh7900ff3_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-streaming-0.12.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cpp-expected-1.3.1-h171cf75_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cxx-compiler-1.11.0-hfcd1e18_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/distro-1.9.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/doxygen-1.13.2-h8e693c7_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/fmt-12.1.0-hff5e90c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/frozendict-2.4.7-py310h7c4b9e2_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc-14.3.0-h0dff253_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_impl_linux-64-14.3.0-hbdf3cc3_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_linux-64-14.3.0-h298d278_21.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gxx-14.3.0-h76987e4_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gxx_impl_linux-64-14.3.0-h2185e75_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gxx_linux-64-14.3.0-he467f4b_21.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.2-h33c6efd_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-resources-6.5.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib_resources-6.5.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpatch-1.33-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpointer-3.0.0-pyhcf101f3_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-64-4.18.0-he073ed8_9.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.22.2-ha1258a1_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_101.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libarchive-3.8.6-gpl_hc2c16d8_100.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-5_h4a7cf45_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-5_h0358290_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcurl-8.19.0-hcf29cc6_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libev-4.33-hd590300_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.4-hecca717_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_18.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/libgcc-devel_linux-64-14.3.0-hf649bbc_118.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-15.2.0-h69a702a_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-15.2.0-h68bc16d_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libhwloc-2.13.0-default_he001693_1000.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.18-h3b78370_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.11.0-5_h47877c9_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.2-hb03c661_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libmamba-2.5.0-hd28c85e_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libmamba-spdlog-2.5.0-h12fcf84_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libmambapy-2.5.0-py310h74f1d5f_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.67.0-had1ee68_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hb9d3cd8_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.30-pthreads_h94d23a6_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsanitizer-14.3.0-h8f1669f_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsolv-0.7.35-h9463b59_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.52.0-hf4e2dac_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libssh2-1.11.1-hcf80075_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_18.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/libstdcxx-devel_linux-64-14.3.0-h9f08a49_118.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-15.2.0-hdf11a46_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.41.3-h5347b49_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuv-1.51.0-hb03c661_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-16-2.15.2-hca6bf5a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.15.2-he237659_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/lz4-c-1.10.0-h5888daf_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/lzo-2.10-h280c20c_1002.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/menuinst-2.4.2-py310hff52083_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/msgpack-python-1.1.2-py310h03d9f68_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ninja-1.13.2-h171cf75_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nlohmann_json-abi-3.12.0-h0f90c79_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.2.6-py310hefbff90_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.1-h35e630c_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-25.0-pyh29332c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/patchelf-0.17.2-h58526e2_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-1.0.4-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-26.0.1-pyh8b19718_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pixi-pycharm-0.0.10-unix_hf108a03_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pkginfo-1.12.1.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pybind11-abi-11-hc364b38_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pycosat-0.6.6-py310h7c4b9e2_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pyelftools-0.32-pyh707e725_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pyproject-metadata-0.11.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.10.20-h3c07f61_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.10-8_cp310.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/reproc-14.2.5.post0-hb9d3cd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/reproc-cpp-14.2.5.post0-h5888daf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.32.5-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/rhash-1.4.6-hb9d3cd8_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ruamel.yaml-0.18.17-py310h139afa4_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ruamel.yaml.clib-0.2.15-py310h139afa4_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/scikit-build-core-0.11.6-pyh7e86bf3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-scm-9.2.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools_scm-9.2.2-hd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/simdjson-4.2.4-hb700be7_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/spdlog-1.17.0-hab81395_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-64-2.28-h4ee821c_9.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/taplo-0.10.0-h2d22210_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/truststore-0.10.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.46.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-cpp-0.8.0-h3f2d84a_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstandard-0.25.0-py310h139afa4_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda + - pypi: https://files.pythonhosted.org/packages/c5/0d/84a4380f930db0010168e0aa7b7a8fed9ba1835a8fbb1472bc6d0201d529/build-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl + linux-aarch64: + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-20_gnu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/archspec-0.2.5-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/auditwheel-6.6.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/backports.zstd-1.3.0-py310hfa1aa29_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/binutils-2.45.1-default_hf1166c9_101.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/binutils_impl_linux-aarch64-2.45.1-default_h5f4c503_101.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/binutils_linux-aarch64-2.45.1-default_hf1166c9_101.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/boltons-25.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/brotli-python-1.2.0-py310hbe54bbb_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/bzip2-1.0.8-h4777abc_9.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/c-ares-1.34.6-he30d5cf_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/c-compiler-1.11.0-hdceaead_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.2.25-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cffi-2.0.0-py310h0826a50_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.6-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cmake-3.31.8-hc9d863e_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/conda-26.1.1-py310h4c7bcd0_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/conda-gcc-specs-14.3.0-hadff5d6_18.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-libmamba-solver-25.11.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-handling-2.4.0-pyh7900ff3_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-streaming-0.12.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cpp-expected-1.3.1-hdc560ac_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cxx-compiler-1.11.0-h7b35c40_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/distro-1.9.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/doxygen-1.13.2-h5e0f5ae_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/fmt-12.1.0-h20c602a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/frozendict-2.4.7-py310h5b55623_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gcc-14.3.0-h2e72a27_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gcc_impl_linux-aarch64-14.3.0-h533bfc8_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gcc_linux-aarch64-14.3.0-h118592a_21.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gxx-14.3.0-ha384071_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gxx_impl_linux-aarch64-14.3.0-h0d4f5d4_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gxx_linux-aarch64-14.3.0-h32e4f2e_21.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/icu-78.3-hcab7f73_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-resources-6.5.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib_resources-6.5.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpatch-1.33-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpointer-3.0.0-pyhcf101f3_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-aarch64-4.18.0-h05a177a_9.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/keyutils-1.6.3-h86ecc28_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/krb5-1.22.2-hfd895c2_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.45.1-default_h1979696_101.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libarchive-3.8.6-gpl_hbe7d12b_100.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libblas-3.11.0-5_haddc8a3_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcblas-3.11.0-5_hd72aa62_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcurl-8.19.0-hc57f145_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libedit-3.1.20250104-pl5321h976ea20_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libev-4.33-h31becfc_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.7.4-hfae3067_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libffi-3.5.2-h376a255_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-15.2.0-h8acb6b2_18.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/libgcc-devel_linux-aarch64-14.3.0-h25ba3ff_118.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-ng-15.2.0-he9431aa_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran-15.2.0-he9431aa_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran5-15.2.0-h1b7bec0_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-15.2.0-h8acb6b2_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libhwloc-2.13.0-default_ha95e27d_1000.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libiconv-1.18-h90929bb_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblapack-3.11.0-5_h88aeb00_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblzma-5.8.2-he30d5cf_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libmamba-2.5.0-hc712cdd_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libmamba-spdlog-2.5.0-h3ad78e7_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libmambapy-2.5.0-py310hdf79504_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libnghttp2-1.68.1-hd3077d7_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libnsl-2.0.1-h86ecc28_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libopenblas-0.3.30-pthreads_h9d3fd7e_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsanitizer-14.3.0-hedb4206_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsolv-0.7.36-hdda61c4_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.52.0-h10b116e_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libssh2-1.11.1-h18c354c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-15.2.0-hef695bb_18.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/libstdcxx-devel_linux-aarch64-14.3.0-h57c8d61_118.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-ng-15.2.0-hdbbeba8_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.41.3-h1022ec0_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuv-1.51.0-he30d5cf_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxcrypt-4.4.36-h31becfc_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxml2-16-2.15.2-h79dcc73_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxml2-2.15.2-h825857f_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.3.1-h86ecc28_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lz4-c-1.10.0-h5ad3122_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lzo-2.10-h80f16a2_1002.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/menuinst-2.4.2-py310h4c7bcd0_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/msgpack-python-1.1.2-py310h0992a49_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.5-ha32ae93_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ninja-1.13.2-hdc560ac_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nlohmann_json-abi-3.12.0-h0f90c79_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/numpy-2.2.6-py310h6e5608f_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.6.1-h546c87b_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-25.0-pyh29332c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/patchelf-0.17.2-h884eca8_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-1.0.4-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-26.0.1-pyh8b19718_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pixi-pycharm-0.0.10-unix_hf108a03_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pkginfo-1.12.1.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pybind11-abi-11-hc364b38_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pycosat-0.6.6-py310h5b55623_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pyelftools-0.32-pyh707e725_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pyproject-metadata-0.11.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.10.20-h28be5d3_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.10-8_cp310.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/readline-8.3-hb682ff5_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/reproc-14.2.5.post0-h86ecc28_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/reproc-cpp-14.2.5.post0-h5ad3122_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.32.5-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rhash-1.4.6-h86ecc28_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ruamel.yaml-0.18.17-py310hef25091_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ruamel.yaml.clib-0.2.15-py310hef25091_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/scikit-build-core-0.11.6-pyh7e86bf3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-scm-9.2.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools_scm-9.2.2-hd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/simdjson-4.2.4-hfefdfc9_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/spdlog-1.17.0-h9f97df7_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-aarch64-2.28-h585391f_9.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/taplo-0.10.0-h3618846_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tk-8.6.13-noxft_h0dc03b3_103.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/truststore-0.10.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.46.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/yaml-cpp-0.8.0-h5ad3122_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstandard-0.25.0-py310hef25091_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.7-h85ac4a6_6.conda + - pypi: https://files.pythonhosted.org/packages/c5/0d/84a4380f930db0010168e0aa7b7a8fed9ba1835a8fbb1472bc6d0201d529/build-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl + linux-py311: + channels: + - url: https://conda.anaconda.org/conda-forge/ + indexes: + - https://pypi.org/simple + options: + pypi-prerelease-mode: if-necessary-or-explicit + packages: + linux-64: + - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/archspec-0.2.5-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/auditwheel-6.6.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/backports.zstd-1.3.0-py311h6b1f9c4_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/binutils-2.45.1-default_h4852527_101.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/binutils_impl_linux-64-2.45.1-default_hfdba357_101.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/binutils_linux-64-2.45.1-default_h4852527_101.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/boltons-25.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.2.0-py311h66f275b_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_9.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.34.6-hb03c661_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/c-compiler-1.11.0-h4d9bdce_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.2.25-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-2.0.0-py311h03d9500_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.5-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cmake-3.31.8-hc85cc9f_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/conda-26.1.1-py311h38be061_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/conda-gcc-specs-14.3.0-he8ccf15_18.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-libmamba-solver-25.11.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-handling-2.4.0-pyh7900ff3_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-streaming-0.12.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cpp-expected-1.3.1-h171cf75_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cxx-compiler-1.11.0-hfcd1e18_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/distro-1.9.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/doxygen-1.13.2-h8e693c7_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/fmt-12.1.0-hff5e90c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/frozendict-2.4.7-py311h49ec1c0_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc-14.3.0-h0dff253_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_impl_linux-64-14.3.0-hbdf3cc3_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_linux-64-14.3.0-h298d278_21.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gxx-14.3.0-h76987e4_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gxx_impl_linux-64-14.3.0-h2185e75_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gxx_linux-64-14.3.0-he467f4b_21.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.2-h33c6efd_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-resources-6.5.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib_resources-6.5.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpatch-1.33-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpointer-3.0.0-pyhcf101f3_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-64-4.18.0-he073ed8_9.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.22.2-ha1258a1_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_101.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libarchive-3.8.6-gpl_hc2c16d8_100.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-5_h4a7cf45_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-5_h0358290_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcurl-8.19.0-hcf29cc6_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libev-4.33-hd590300_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.4-hecca717_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_18.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/libgcc-devel_linux-64-14.3.0-hf649bbc_118.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-15.2.0-h69a702a_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-15.2.0-h68bc16d_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libhwloc-2.13.0-default_he001693_1000.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.18-h3b78370_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.11.0-5_h47877c9_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.2-hb03c661_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libmamba-2.5.0-hd28c85e_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libmamba-spdlog-2.5.0-h12fcf84_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libmambapy-2.5.0-py311hc5d5c7c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.67.0-had1ee68_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hb9d3cd8_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.30-pthreads_h94d23a6_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsanitizer-14.3.0-h8f1669f_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsolv-0.7.35-h9463b59_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.52.0-hf4e2dac_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libssh2-1.11.1-hcf80075_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_18.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/libstdcxx-devel_linux-64-14.3.0-h9f08a49_118.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-15.2.0-hdf11a46_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.41.3-h5347b49_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuv-1.51.0-hb03c661_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-16-2.15.2-hca6bf5a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.15.2-he237659_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/lz4-c-1.10.0-h5888daf_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/lzo-2.10-h280c20c_1002.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/menuinst-2.4.2-py311h38be061_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/msgpack-python-1.1.2-py311hdf67eae_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ninja-1.13.2-h171cf75_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nlohmann_json-abi-3.12.0-h0f90c79_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.4.2-py311h2e04523_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.1-h35e630c_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-25.0-pyh29332c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/patchelf-0.17.2-h58526e2_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-1.0.4-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-26.0.1-pyh8b19718_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pixi-pycharm-0.0.10-unix_hf108a03_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pkginfo-1.12.1.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pybind11-abi-11-hc364b38_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pycosat-0.6.6-py311h49ec1c0_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pyelftools-0.32-pyh707e725_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pyproject-metadata-0.11.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.11.15-hd63d673_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.11-8_cp311.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/reproc-14.2.5.post0-hb9d3cd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/reproc-cpp-14.2.5.post0-h5888daf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.32.5-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/rhash-1.4.6-hb9d3cd8_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ruamel.yaml-0.18.17-py311haee01d2_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ruamel.yaml.clib-0.2.15-py311haee01d2_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/scikit-build-core-0.11.6-pyh7e86bf3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-scm-9.2.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools_scm-9.2.2-hd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/simdjson-4.2.4-hb700be7_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/spdlog-1.17.0-hab81395_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-64-2.28-h4ee821c_9.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/taplo-0.10.0-h2d22210_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/truststore-0.10.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.46.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-cpp-0.8.0-h3f2d84a_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstandard-0.25.0-py311haee01d2_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda + - pypi: https://files.pythonhosted.org/packages/c5/0d/84a4380f930db0010168e0aa7b7a8fed9ba1835a8fbb1472bc6d0201d529/build-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl + linux-aarch64: + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-20_gnu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/archspec-0.2.5-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/auditwheel-6.6.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/backports.zstd-1.3.0-py311h6ce31b0_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/binutils-2.45.1-default_hf1166c9_101.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/binutils_impl_linux-aarch64-2.45.1-default_h5f4c503_101.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/binutils_linux-aarch64-2.45.1-default_hf1166c9_101.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/boltons-25.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/brotli-python-1.2.0-py311h14a79a7_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/bzip2-1.0.8-h4777abc_9.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/c-ares-1.34.6-he30d5cf_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/c-compiler-1.11.0-hdceaead_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.2.25-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cffi-2.0.0-py311h460c349_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.6-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cmake-3.31.8-hc9d863e_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/conda-26.1.1-py311hec3470c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/conda-gcc-specs-14.3.0-hadff5d6_18.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-libmamba-solver-25.11.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-handling-2.4.0-pyh7900ff3_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-streaming-0.12.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cpp-expected-1.3.1-hdc560ac_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cxx-compiler-1.11.0-h7b35c40_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/distro-1.9.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/doxygen-1.13.2-h5e0f5ae_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/fmt-12.1.0-h20c602a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/frozendict-2.4.7-py311h19352d5_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gcc-14.3.0-h2e72a27_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gcc_impl_linux-aarch64-14.3.0-h533bfc8_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gcc_linux-aarch64-14.3.0-h118592a_21.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gxx-14.3.0-ha384071_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gxx_impl_linux-aarch64-14.3.0-h0d4f5d4_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gxx_linux-aarch64-14.3.0-h32e4f2e_21.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/icu-78.3-hcab7f73_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-resources-6.5.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib_resources-6.5.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpatch-1.33-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpointer-3.0.0-pyhcf101f3_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-aarch64-4.18.0-h05a177a_9.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/keyutils-1.6.3-h86ecc28_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/krb5-1.22.2-hfd895c2_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.45.1-default_h1979696_101.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libarchive-3.8.6-gpl_hbe7d12b_100.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libblas-3.11.0-5_haddc8a3_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcblas-3.11.0-5_hd72aa62_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcurl-8.19.0-hc57f145_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libedit-3.1.20250104-pl5321h976ea20_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libev-4.33-h31becfc_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.7.4-hfae3067_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libffi-3.5.2-h376a255_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-15.2.0-h8acb6b2_18.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/libgcc-devel_linux-aarch64-14.3.0-h25ba3ff_118.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-ng-15.2.0-he9431aa_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran-15.2.0-he9431aa_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran5-15.2.0-h1b7bec0_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-15.2.0-h8acb6b2_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libhwloc-2.13.0-default_ha95e27d_1000.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libiconv-1.18-h90929bb_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblapack-3.11.0-5_h88aeb00_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblzma-5.8.2-he30d5cf_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libmamba-2.5.0-hc712cdd_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libmamba-spdlog-2.5.0-h3ad78e7_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libmambapy-2.5.0-py311h6a8bf82_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libnghttp2-1.68.1-hd3077d7_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libnsl-2.0.1-h86ecc28_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libopenblas-0.3.30-pthreads_h9d3fd7e_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsanitizer-14.3.0-hedb4206_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsolv-0.7.36-hdda61c4_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.52.0-h10b116e_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libssh2-1.11.1-h18c354c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-15.2.0-hef695bb_18.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/libstdcxx-devel_linux-aarch64-14.3.0-h57c8d61_118.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-ng-15.2.0-hdbbeba8_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.41.3-h1022ec0_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuv-1.51.0-he30d5cf_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxcrypt-4.4.36-h31becfc_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxml2-16-2.15.2-h79dcc73_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxml2-2.15.2-h825857f_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.3.1-h86ecc28_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lz4-c-1.10.0-h5ad3122_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lzo-2.10-h80f16a2_1002.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/menuinst-2.4.2-py311hec3470c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/msgpack-python-1.1.2-py311hfca10b7_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.5-ha32ae93_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ninja-1.13.2-hdc560ac_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nlohmann_json-abi-3.12.0-h0f90c79_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/numpy-2.4.3-py311h669026d_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.6.1-h546c87b_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-25.0-pyh29332c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/patchelf-0.17.2-h884eca8_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-1.0.4-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-26.0.1-pyh8b19718_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pixi-pycharm-0.0.10-unix_hf108a03_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pkginfo-1.12.1.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pybind11-abi-11-hc364b38_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pycosat-0.6.6-py311h19352d5_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pyelftools-0.32-pyh707e725_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pyproject-metadata-0.11.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.11.15-h91f4b29_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.11-8_cp311.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/readline-8.3-hb682ff5_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/reproc-14.2.5.post0-h86ecc28_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/reproc-cpp-14.2.5.post0-h5ad3122_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.32.5-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rhash-1.4.6-h86ecc28_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ruamel.yaml-0.18.17-py311h51cfe5d_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ruamel.yaml.clib-0.2.15-py311h51cfe5d_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/scikit-build-core-0.11.6-pyh7e86bf3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-scm-9.2.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools_scm-9.2.2-hd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/simdjson-4.2.4-hfefdfc9_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/spdlog-1.17.0-h9f97df7_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-aarch64-2.28-h585391f_9.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/taplo-0.10.0-h3618846_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tk-8.6.13-noxft_h0dc03b3_103.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/truststore-0.10.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.46.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/yaml-cpp-0.8.0-h5ad3122_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstandard-0.25.0-py311h51cfe5d_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.7-h85ac4a6_6.conda + - pypi: https://files.pythonhosted.org/packages/c5/0d/84a4380f930db0010168e0aa7b7a8fed9ba1835a8fbb1472bc6d0201d529/build-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl + macosx-py310: + channels: + - url: https://conda.anaconda.org/conda-forge/ + indexes: + - https://pypi.org/simple + options: + pypi-prerelease-mode: if-necessary-or-explicit + packages: + osx-64: + - conda: https://conda.anaconda.org/conda-forge/osx-64/_openmp_mutex-4.5-7_kmp_llvm.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/archspec-0.2.5-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/boltons-25.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/brotli-python-1.1.0-py310h9e9d8ca_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/bzip2-1.0.8-h10d778d_5.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/c-ares-1.28.1-h10d778d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/c-compiler-1.10.0-h09a7c41_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/cctools-986-hd3558d4_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/cctools_osx-64-986-h58a35ae_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.2.25-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/cffi-1.16.0-py310hdca579f_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.5-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-18-18.1.3-default_h7151d67_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-18.1.3-default_h7151d67_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clang_impl_osx-64-18.1.3-hdbcc6ac_11.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clang_osx-64-18.1.3-hb91bd55_11.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clangxx-18.1.3-default_h7151d67_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clangxx_impl_osx-64-18.1.3-h5bc21ce_11.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clangxx_osx-64-18.1.3-hb91bd55_11.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/cmake-3.27.6-hf40c264_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/compiler-rt-18.1.3-ha38d28d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt_osx-64-18.1.3-ha38d28d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/conda-23.9.0-py310h2ec42d9_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-handling-2.4.0-pyh7900ff3_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-streaming-0.12.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/cryptography-41.0.7-py310h527a09d_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/cxx-compiler-1.10.0-h20888b2_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/doxygen-1.10.0-h5ff76d1_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/icu-73.2-hf5e326d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-resources-6.5.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib_resources-6.5.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpatch-1.33-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpointer-3.0.0-pyhcf101f3_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/krb5-1.21.2-hb884880_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ld64-711-h4e51db5_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ld64_osx-64-711-had5d0d3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libblas-3.9.0-22_osx64_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcblas-3.9.0-22_osx64_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libclang-cpp18.1-18.1.3-default_h7151d67_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcurl-8.4.0-h726d00d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcxx-16.0.6-hd57cbcb_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libedit-3.1.20191231-h0678c8f_2.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/libev-4.33-h10d778d_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libexpat-2.6.2-h73e2aa4_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libffi-3.4.2-h0d85af4_5.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgcc-15.2.0-h08519bb_18.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgfortran-15.2.0-h7e5c614_18.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgfortran5-15.2.0-hd16e46c_18.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libiconv-1.17-hd75f5a5_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/liblapack-3.9.0-22_osx64_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libllvm18-18.1.3-hbcf5fad_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libnghttp2-1.52.0-he2ab024_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libopenblas-0.3.27-openmp_hfef2a42_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.45.3-h92b6c6a_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libssh2-1.11.0-hd019ec5_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libuv-1.48.0-h67532ce_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libxml2-2.12.6-hc0ae0f7_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.3.1-hd75f5a5_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-openmp-18.1.3-hb6ac08f_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-tools-18.1.3-hbcf5fad_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.5-h5846eda_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ninja-1.12.0-h7728843_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/numpy-1.26.4-py310h4bfa8fc_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/openssl-3.3.0-hd75f5a5_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-25.0-pyh29332c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-1.0.4-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-26.0.1-pyh8b19718_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pixi-pycharm-0.0.10-unix_hf108a03_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pkginfo-1.12.1.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/pycosat-0.6.6-py310h6729b98_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pyopenssl-25.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pyproject-metadata-0.11.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.10.14-h00d2728_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.10-8_cp310.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/readline-8.2-h7cca4af_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.32.5-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/rhash-1.4.4-h0dc2134_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ruamel.yaml-0.17.40-py310hb372a2b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ruamel.yaml.clib-0.2.8-py310hb372a2b_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/scikit-build-core-0.11.6-pyh7e86bf3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-scm-9.2.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools_scm-9.2.2-hd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/sigtool-0.1.3-h88f4db0_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/tapi-1100.0.11-h9ce4665_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/taplo-0.8.1-h7205ca4_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-h1abcd95_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/truststore-0.10.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.5.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.46.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/xz-5.2.6-h775f41a_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/zstandard-0.22.0-py310hd88f66e_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.5-h829000d_0.conda + - pypi: https://files.pythonhosted.org/packages/a9/ba/000a1996d4308bc65120167c21241a3b205464a2e0b58deda26ae8ac21d1/altgraph-0.17.5-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c5/0d/84a4380f930db0010168e0aa7b7a8fed9ba1835a8fbb1472bc6d0201d529/build-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2b/dd/437e601fa9d2b6bf8507256daf52196a226c3b340261f4cde8fac8e853ea/delocate-0.13.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c7/d1/a9f36f8ecdf0fb7c9b1e78c8d7af12b8c8754e74851ac7b94a8305540fc7/macholib-1.16.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl + osx-arm64: + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/_openmp_mutex-4.5-7_kmp_llvm.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/archspec-0.2.5-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/boltons-25.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-python-1.1.0-py310h1253130_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-h93a5062_5.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-ares-1.28.1-h93a5062_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-compiler-1.10.0-hdf49b6b_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cctools-986-h4c9edd9_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cctools_osx-arm64-986-hd11630f_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.2.25-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cffi-1.16.0-py310hdcd7c05_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.5-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-18-18.1.3-default_he012953_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-18.1.3-default_h4cf2255_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang_impl_osx-arm64-18.1.3-hda94301_11.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang_osx-arm64-18.1.3-h54d7cd3_11.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clangxx-18.1.3-default_h4cf2255_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clangxx_impl_osx-arm64-18.1.3-h1ba0cb9_11.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clangxx_osx-arm64-18.1.3-h54d7cd3_11.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cmake-3.27.6-h1c59155_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/compiler-rt-18.1.3-h3808999_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt_osx-arm64-18.1.3-h3808999_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/conda-23.9.0-py310hbe9552e_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-handling-2.4.0-pyh7900ff3_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-streaming-0.12.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cryptography-41.0.7-py310h4c55245_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cxx-compiler-1.10.0-hba80287_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/doxygen-1.10.0-h8fbad5d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-73.2-hc8870d7_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-resources-6.5.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib_resources-6.5.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpatch-1.33-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpointer-3.0.0-pyhcf101f3_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.21.2-h92f50d5_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ld64-711-h4c6efb1_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ld64_osx-arm64-711-h5e7191b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libblas-3.9.0-24_osxarm64_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcblas-3.9.0-24_osxarm64_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libclang-cpp18.1-18.1.3-default_he012953_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcurl-8.4.0-h2d989ff_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-16.0.6-h4653b0c_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libedit-3.1.20191231-hc8eb9b7_2.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libev-4.33-h93a5062_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.6.2-hebf3989_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.4.2-h3422bc3_5.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgcc-15.2.0-hcbb3090_18.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran-15.2.0-h07b0088_18.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran5-15.2.0-hdae7583_18.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libiconv-1.17-h0d3ecfb_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblapack-3.9.0-24_osxarm64_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libllvm18-18.1.3-h30cc82d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libnghttp2-1.52.0-hae82a92_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libopenblas-0.3.27-openmp_h6c19121_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.45.3-h091b4b1_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libssh2-1.11.0-h7a5bd25_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libuv-1.48.0-h93a5062_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-2.12.6-h35eab27_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.1-h0d3ecfb_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-18.1.3-hcd81f8e_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-tools-18.1.3-h30cc82d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.5-hb89a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ninja-1.12.0-h2ffa867_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-1.26.4-py310hd45542a_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.3.0-h0d3ecfb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-25.0-pyh29332c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-1.0.4-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-26.0.1-pyh8b19718_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pixi-pycharm-0.0.10-unix_hf108a03_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pkginfo-1.12.1.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pycosat-0.6.6-py310h2aa6e3c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pyopenssl-25.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pyproject-metadata-0.11.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.10.14-h2469fbe_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.10-8_cp310.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.2-h1d1bf99_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.32.5-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rhash-1.4.4-hb547adb_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ruamel.yaml-0.17.40-py310hd125d64_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ruamel.yaml.clib-0.2.8-py310hd125d64_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/scikit-build-core-0.11.6-pyh7e86bf3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-scm-9.2.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools_scm-9.2.2-hd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/sigtool-0.1.3-h44b9a77_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tapi-1100.0.11-he4954df_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/taplo-0.8.1-h69fbcac_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h5083fa2_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/truststore-0.10.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.5.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.46.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/xz-5.2.6-h57fd34a_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstandard-0.22.0-py310h6289e41_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.5-h4f39d0f_0.conda + - pypi: https://files.pythonhosted.org/packages/a9/ba/000a1996d4308bc65120167c21241a3b205464a2e0b58deda26ae8ac21d1/altgraph-0.17.5-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c5/0d/84a4380f930db0010168e0aa7b7a8fed9ba1835a8fbb1472bc6d0201d529/build-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2b/dd/437e601fa9d2b6bf8507256daf52196a226c3b340261f4cde8fac8e853ea/delocate-0.13.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c7/d1/a9f36f8ecdf0fb7c9b1e78c8d7af12b8c8754e74851ac7b94a8305540fc7/macholib-1.16.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl + macosx-py311: + channels: + - url: https://conda.anaconda.org/conda-forge/ + indexes: + - https://pypi.org/simple + options: + pypi-prerelease-mode: if-necessary-or-explicit + packages: + osx-64: + - conda: https://conda.anaconda.org/conda-forge/osx-64/_openmp_mutex-4.5-7_kmp_llvm.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/archspec-0.2.5-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/boltons-25.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/brotli-python-1.1.0-py311hdf8f085_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/bzip2-1.0.8-h10d778d_5.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/c-ares-1.28.1-h10d778d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/c-compiler-1.10.0-h09a7c41_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/cctools-986-hd3558d4_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/cctools_osx-64-986-h58a35ae_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.2.25-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/cffi-1.16.0-py311hc0b63fd_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.5-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-18-18.1.3-default_h7151d67_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-18.1.3-default_h7151d67_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clang_impl_osx-64-18.1.3-hdbcc6ac_11.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clang_osx-64-18.1.3-hb91bd55_11.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clangxx-18.1.3-default_h7151d67_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clangxx_impl_osx-64-18.1.3-h5bc21ce_11.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clangxx_osx-64-18.1.3-hb91bd55_11.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/cmake-3.27.6-hf40c264_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/compiler-rt-18.1.3-ha38d28d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt_osx-64-18.1.3-ha38d28d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/conda-23.9.0-py311h6eed73b_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-handling-2.4.0-pyh7900ff3_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-streaming-0.12.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/cryptography-41.0.7-py311h48c7838_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/cxx-compiler-1.10.0-h20888b2_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/doxygen-1.10.0-h5ff76d1_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/icu-73.2-hf5e326d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-resources-6.5.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib_resources-6.5.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpatch-1.33-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpointer-3.0.0-pyhcf101f3_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/krb5-1.21.2-hb884880_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ld64-711-h4e51db5_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ld64_osx-64-711-had5d0d3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libblas-3.9.0-22_osx64_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcblas-3.9.0-22_osx64_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libclang-cpp18.1-18.1.3-default_h7151d67_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcurl-8.4.0-h726d00d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcxx-16.0.6-hd57cbcb_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libedit-3.1.20191231-h0678c8f_2.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/libev-4.33-h10d778d_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libexpat-2.6.2-h73e2aa4_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libffi-3.4.2-h0d85af4_5.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgcc-15.2.0-h08519bb_18.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgfortran-15.2.0-h7e5c614_18.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgfortran5-15.2.0-hd16e46c_18.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libiconv-1.17-hd75f5a5_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/liblapack-3.9.0-22_osx64_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libllvm18-18.1.3-hbcf5fad_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libnghttp2-1.52.0-he2ab024_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libopenblas-0.3.27-openmp_hfef2a42_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.45.3-h92b6c6a_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libssh2-1.11.0-hd019ec5_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libuv-1.48.0-h67532ce_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libxml2-2.12.6-hc0ae0f7_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.3.1-hd75f5a5_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-openmp-18.1.3-hb6ac08f_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-tools-18.1.3-hbcf5fad_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.5-h5846eda_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ninja-1.12.0-h7728843_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/numpy-1.26.4-py311hc43a94b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/openssl-3.3.0-hd75f5a5_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-25.0-pyh29332c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-1.0.4-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-26.0.1-pyh8b19718_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pixi-pycharm-0.0.10-unix_hf108a03_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pkginfo-1.12.1.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/pycosat-0.6.6-py311h2725bcf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pyopenssl-25.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pyproject-metadata-0.11.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.11.8-h9f0c242_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.11-8_cp311.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/readline-8.2-h7cca4af_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.32.5-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/rhash-1.4.4-h0dc2134_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ruamel.yaml-0.17.40-py311he705e18_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ruamel.yaml.clib-0.2.8-py311he705e18_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/scikit-build-core-0.11.6-pyh7e86bf3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-scm-9.2.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools_scm-9.2.2-hd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/sigtool-0.1.3-h88f4db0_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/tapi-1100.0.11-h9ce4665_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/taplo-0.8.1-h7205ca4_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-h1abcd95_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/truststore-0.10.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.5.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.46.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/xz-5.2.6-h775f41a_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/zstandard-0.22.0-py311hed14148_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.5-h829000d_0.conda + - pypi: https://files.pythonhosted.org/packages/a9/ba/000a1996d4308bc65120167c21241a3b205464a2e0b58deda26ae8ac21d1/altgraph-0.17.5-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c5/0d/84a4380f930db0010168e0aa7b7a8fed9ba1835a8fbb1472bc6d0201d529/build-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2b/dd/437e601fa9d2b6bf8507256daf52196a226c3b340261f4cde8fac8e853ea/delocate-0.13.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c7/d1/a9f36f8ecdf0fb7c9b1e78c8d7af12b8c8754e74851ac7b94a8305540fc7/macholib-1.16.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl + osx-arm64: + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/_openmp_mutex-4.5-7_kmp_llvm.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/archspec-0.2.5-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/boltons-25.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-python-1.1.0-py311ha891d26_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-h93a5062_5.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-ares-1.28.1-h93a5062_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-compiler-1.10.0-hdf49b6b_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cctools-986-h4c9edd9_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cctools_osx-arm64-986-hd11630f_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.2.25-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cffi-1.16.0-py311h4a08483_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.5-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-18-18.1.3-default_he012953_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-18.1.3-default_h4cf2255_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang_impl_osx-arm64-18.1.3-hda94301_11.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang_osx-arm64-18.1.3-h54d7cd3_11.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clangxx-18.1.3-default_h4cf2255_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clangxx_impl_osx-arm64-18.1.3-h1ba0cb9_11.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clangxx_osx-arm64-18.1.3-h54d7cd3_11.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cmake-3.27.6-h1c59155_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/compiler-rt-18.1.3-h3808999_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt_osx-arm64-18.1.3-h3808999_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/conda-23.9.0-py311h267d04e_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-handling-2.4.0-pyh7900ff3_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-streaming-0.12.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cryptography-41.0.7-py311h08c85a6_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cxx-compiler-1.10.0-hba80287_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/doxygen-1.10.0-h8fbad5d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-73.2-hc8870d7_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-resources-6.5.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib_resources-6.5.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpatch-1.33-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpointer-3.0.0-pyhcf101f3_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.21.2-h92f50d5_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ld64-711-h4c6efb1_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ld64_osx-arm64-711-h5e7191b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libblas-3.9.0-24_osxarm64_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcblas-3.9.0-24_osxarm64_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libclang-cpp18.1-18.1.3-default_he012953_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcurl-8.4.0-h2d989ff_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-16.0.6-h4653b0c_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libedit-3.1.20191231-hc8eb9b7_2.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libev-4.33-h93a5062_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.6.2-hebf3989_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.4.2-h3422bc3_5.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgcc-15.2.0-hcbb3090_18.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran-15.2.0-h07b0088_18.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran5-15.2.0-hdae7583_18.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libiconv-1.17-h0d3ecfb_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblapack-3.9.0-24_osxarm64_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libllvm18-18.1.3-h30cc82d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libnghttp2-1.52.0-hae82a92_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libopenblas-0.3.27-openmp_h6c19121_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.45.3-h091b4b1_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libssh2-1.11.0-h7a5bd25_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libuv-1.48.0-h93a5062_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-2.12.6-h35eab27_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.1-h0d3ecfb_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-18.1.3-hcd81f8e_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-tools-18.1.3-h30cc82d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.5-hb89a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ninja-1.12.0-h2ffa867_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-1.26.4-py311h7125741_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.3.0-h0d3ecfb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-25.0-pyh29332c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-1.0.4-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-26.0.1-pyh8b19718_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pixi-pycharm-0.0.10-unix_hf108a03_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pkginfo-1.12.1.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pycosat-0.6.6-py311heffc1b2_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pyopenssl-25.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pyproject-metadata-0.11.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.11.8-hdf0ec26_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.11-8_cp311.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.2-h1d1bf99_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.32.5-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rhash-1.4.4-hb547adb_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ruamel.yaml-0.17.40-py311h05b510d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ruamel.yaml.clib-0.2.8-py311h05b510d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/scikit-build-core-0.11.6-pyh7e86bf3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-scm-9.2.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools_scm-9.2.2-hd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/sigtool-0.1.3-h44b9a77_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tapi-1100.0.11-he4954df_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/taplo-0.8.1-h69fbcac_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h5083fa2_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/truststore-0.10.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.5.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.46.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/xz-5.2.6-h57fd34a_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstandard-0.22.0-py311h67b91a1_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.5-h4f39d0f_0.conda + - pypi: https://files.pythonhosted.org/packages/a9/ba/000a1996d4308bc65120167c21241a3b205464a2e0b58deda26ae8ac21d1/altgraph-0.17.5-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c5/0d/84a4380f930db0010168e0aa7b7a8fed9ba1835a8fbb1472bc6d0201d529/build-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2b/dd/437e601fa9d2b6bf8507256daf52196a226c3b340261f4cde8fac8e853ea/delocate-0.13.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c7/d1/a9f36f8ecdf0fb7c9b1e78c8d7af12b8c8754e74851ac7b94a8305540fc7/macholib-1.16.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl + manylinux228-py310: + channels: + - url: https://conda.anaconda.org/conda-forge/ + indexes: + - https://pypi.org/simple + options: + pypi-prerelease-mode: if-necessary-or-explicit + packages: + linux-64: + - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/archspec-0.2.5-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/auditwheel-6.6.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/backports.zstd-1.3.0-py310h69bd2ac_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/boltons-25.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.2.0-py310hba01987_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_9.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.34.6-hb03c661_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.2.25-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-2.0.0-py310he7384ee_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.5-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cmake-3.31.8-hc85cc9f_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/conda-26.1.1-py310hff52083_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-libmamba-solver-25.11.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-handling-2.4.0-pyh7900ff3_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-streaming-0.12.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cpp-expected-1.3.1-h171cf75_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/distro-1.9.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/doxygen-1.13.2-h8e693c7_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/fmt-12.1.0-hff5e90c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/frozendict-2.4.7-py310h7c4b9e2_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.2-h33c6efd_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-resources-6.5.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib_resources-6.5.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpatch-1.33-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpointer-3.0.0-pyhcf101f3_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.22.2-ha1258a1_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_101.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libarchive-3.8.6-gpl_hc2c16d8_100.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-5_h4a7cf45_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-5_h0358290_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcurl-8.19.0-hcf29cc6_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libev-4.33-hd590300_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.4-hecca717_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-15.2.0-h69a702a_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-15.2.0-h68bc16d_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.18-h3b78370_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.11.0-5_h47877c9_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.2-hb03c661_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libmamba-2.5.0-hd28c85e_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libmamba-spdlog-2.5.0-h12fcf84_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libmambapy-2.5.0-py310h74f1d5f_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.67.0-had1ee68_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hb9d3cd8_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.30-pthreads_h94d23a6_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsolv-0.7.35-h9463b59_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.52.0-hf4e2dac_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libssh2-1.11.1-hcf80075_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-15.2.0-hdf11a46_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.41.3-h5347b49_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuv-1.51.0-hb03c661_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-16-2.15.2-hca6bf5a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.15.2-he237659_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/lz4-c-1.10.0-h5888daf_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/lzo-2.10-h280c20c_1002.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/menuinst-2.4.2-py310hff52083_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/msgpack-python-1.1.2-py310h03d9f68_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ninja-1.13.2-h171cf75_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nlohmann_json-abi-3.12.0-h0f90c79_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.2.6-py310hefbff90_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.1-h35e630c_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-25.0-pyh29332c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/patchelf-0.17.2-h58526e2_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-1.0.4-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-26.0.1-pyh8b19718_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pixi-pycharm-0.0.10-unix_hf108a03_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pkginfo-1.12.1.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pybind11-abi-11-hc364b38_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pycosat-0.6.6-py310h7c4b9e2_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pyelftools-0.32-pyh707e725_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pyproject-metadata-0.11.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.10.20-h3c07f61_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.10-8_cp310.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/reproc-14.2.5.post0-hb9d3cd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/reproc-cpp-14.2.5.post0-h5888daf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.32.5-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/rhash-1.4.6-hb9d3cd8_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ruamel.yaml-0.18.17-py310h139afa4_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ruamel.yaml.clib-0.2.15-py310h139afa4_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/scikit-build-core-0.11.6-pyh7e86bf3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-scm-9.2.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools_scm-9.2.2-hd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/simdjson-4.2.4-hb700be7_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/spdlog-1.17.0-hab81395_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/taplo-0.10.0-h2d22210_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/truststore-0.10.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.46.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-cpp-0.8.0-h3f2d84a_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstandard-0.25.0-py310h139afa4_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda + - pypi: https://files.pythonhosted.org/packages/c5/0d/84a4380f930db0010168e0aa7b7a8fed9ba1835a8fbb1472bc6d0201d529/build-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl + linux-aarch64: + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-20_gnu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/archspec-0.2.5-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/auditwheel-6.6.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/backports.zstd-1.3.0-py310hfa1aa29_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/boltons-25.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/brotli-python-1.2.0-py310hbe54bbb_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/bzip2-1.0.8-h4777abc_9.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/c-ares-1.34.6-he30d5cf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.2.25-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cffi-2.0.0-py310h0826a50_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.5-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cmake-3.31.8-hc9d863e_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/conda-26.1.1-py310h4c7bcd0_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-libmamba-solver-25.11.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-handling-2.4.0-pyh7900ff3_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-streaming-0.12.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cpp-expected-1.3.1-hdc560ac_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/distro-1.9.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/doxygen-1.13.2-h5e0f5ae_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/fmt-12.1.0-h20c602a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/frozendict-2.4.7-py310h5b55623_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/icu-78.2-hcab7f73_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-resources-6.5.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib_resources-6.5.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpatch-1.33-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpointer-3.0.0-pyhcf101f3_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/keyutils-1.6.3-h86ecc28_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/krb5-1.22.2-hfd895c2_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.45.1-default_h1979696_101.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libarchive-3.8.6-gpl_hbe7d12b_100.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libblas-3.11.0-5_haddc8a3_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcblas-3.11.0-5_hd72aa62_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcurl-8.19.0-hc57f145_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libedit-3.1.20250104-pl5321h976ea20_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libev-4.33-h31becfc_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.7.4-hfae3067_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libffi-3.5.2-h376a255_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-15.2.0-h8acb6b2_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-ng-15.2.0-he9431aa_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran-15.2.0-he9431aa_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran5-15.2.0-h1b7bec0_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-15.2.0-h8acb6b2_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libiconv-1.18-h90929bb_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblapack-3.11.0-5_h88aeb00_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblzma-5.8.2-he30d5cf_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libmamba-2.5.0-hc712cdd_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libmamba-spdlog-2.5.0-h3ad78e7_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libmambapy-2.5.0-py310hdf79504_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libnghttp2-1.67.0-ha888d0e_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libnsl-2.0.1-h86ecc28_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libopenblas-0.3.30-pthreads_h9d3fd7e_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsolv-0.7.36-hdda61c4_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.52.0-h10b116e_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libssh2-1.11.1-h18c354c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-15.2.0-hef695bb_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-ng-15.2.0-hdbbeba8_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.41.3-h1022ec0_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuv-1.51.0-he30d5cf_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxcrypt-4.4.36-h31becfc_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxml2-16-2.15.2-h79dcc73_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxml2-2.15.2-h825857f_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.3.1-h86ecc28_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lz4-c-1.10.0-h5ad3122_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lzo-2.10-h80f16a2_1002.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/menuinst-2.4.2-py310h4c7bcd0_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/msgpack-python-1.1.2-py310h0992a49_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.5-ha32ae93_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ninja-1.13.2-hdc560ac_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nlohmann_json-abi-3.12.0-h0f90c79_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/numpy-2.2.6-py310h6e5608f_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.6.1-h546c87b_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-25.0-pyh29332c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/patchelf-0.17.2-h884eca8_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-1.0.4-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-26.0.1-pyh8b19718_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pixi-pycharm-0.0.10-unix_hf108a03_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pkginfo-1.12.1.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pybind11-abi-11-hc364b38_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pycosat-0.6.6-py310h5b55623_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pyelftools-0.32-pyh707e725_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pyproject-metadata-0.11.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.10.20-h28be5d3_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.10-8_cp310.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/readline-8.3-hb682ff5_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/reproc-14.2.5.post0-h86ecc28_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/reproc-cpp-14.2.5.post0-h5ad3122_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.32.5-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rhash-1.4.6-h86ecc28_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ruamel.yaml-0.18.17-py310hef25091_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ruamel.yaml.clib-0.2.15-py310hef25091_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/scikit-build-core-0.11.6-pyh7e86bf3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-scm-9.2.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools_scm-9.2.2-hd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/simdjson-4.2.4-hfefdfc9_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/spdlog-1.17.0-h9f97df7_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/taplo-0.10.0-h3618846_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tk-8.6.13-noxft_h0dc03b3_103.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/truststore-0.10.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.46.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/yaml-cpp-0.8.0-h5ad3122_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstandard-0.25.0-py310hef25091_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.7-h85ac4a6_6.conda + - pypi: https://files.pythonhosted.org/packages/c5/0d/84a4380f930db0010168e0aa7b7a8fed9ba1835a8fbb1472bc6d0201d529/build-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl + manylinux228-py311: + channels: + - url: https://conda.anaconda.org/conda-forge/ + indexes: + - https://pypi.org/simple + options: + pypi-prerelease-mode: if-necessary-or-explicit + packages: + linux-64: + - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/archspec-0.2.5-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/auditwheel-6.6.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/backports.zstd-1.3.0-py311h6b1f9c4_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/boltons-25.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.2.0-py311h66f275b_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_9.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.34.6-hb03c661_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.2.25-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-2.0.0-py311h03d9500_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.5-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cmake-3.31.8-hc85cc9f_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/conda-26.1.1-py311h38be061_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-libmamba-solver-25.11.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-handling-2.4.0-pyh7900ff3_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-streaming-0.12.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cpp-expected-1.3.1-h171cf75_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/distro-1.9.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/doxygen-1.13.2-h8e693c7_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/fmt-12.1.0-hff5e90c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/frozendict-2.4.7-py311h49ec1c0_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.2-h33c6efd_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-resources-6.5.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib_resources-6.5.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpatch-1.33-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpointer-3.0.0-pyhcf101f3_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.22.2-ha1258a1_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_101.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libarchive-3.8.6-gpl_hc2c16d8_100.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-5_h4a7cf45_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-5_h0358290_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcurl-8.19.0-hcf29cc6_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libev-4.33-hd590300_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.4-hecca717_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-15.2.0-h69a702a_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-15.2.0-h68bc16d_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.18-h3b78370_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.11.0-5_h47877c9_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.2-hb03c661_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libmamba-2.5.0-hd28c85e_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libmamba-spdlog-2.5.0-h12fcf84_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libmambapy-2.5.0-py311hc5d5c7c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.67.0-had1ee68_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hb9d3cd8_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.30-pthreads_h94d23a6_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsolv-0.7.35-h9463b59_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.52.0-hf4e2dac_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libssh2-1.11.1-hcf80075_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-15.2.0-hdf11a46_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.41.3-h5347b49_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuv-1.51.0-hb03c661_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-16-2.15.2-hca6bf5a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.15.2-he237659_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/lz4-c-1.10.0-h5888daf_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/lzo-2.10-h280c20c_1002.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/menuinst-2.4.2-py311h38be061_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/msgpack-python-1.1.2-py311hdf67eae_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ninja-1.13.2-h171cf75_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nlohmann_json-abi-3.12.0-h0f90c79_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.4.2-py311h2e04523_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.1-h35e630c_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-25.0-pyh29332c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/patchelf-0.17.2-h58526e2_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-1.0.4-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-26.0.1-pyh8b19718_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pixi-pycharm-0.0.10-unix_hf108a03_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pkginfo-1.12.1.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pybind11-abi-11-hc364b38_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pycosat-0.6.6-py311h49ec1c0_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pyelftools-0.32-pyh707e725_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pyproject-metadata-0.11.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.11.15-hd63d673_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.11-8_cp311.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/reproc-14.2.5.post0-hb9d3cd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/reproc-cpp-14.2.5.post0-h5888daf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.32.5-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/rhash-1.4.6-hb9d3cd8_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ruamel.yaml-0.18.17-py311haee01d2_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ruamel.yaml.clib-0.2.15-py311haee01d2_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/scikit-build-core-0.11.6-pyh7e86bf3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-scm-9.2.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools_scm-9.2.2-hd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/simdjson-4.2.4-hb700be7_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/spdlog-1.17.0-hab81395_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/taplo-0.10.0-h2d22210_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/truststore-0.10.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.46.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-cpp-0.8.0-h3f2d84a_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstandard-0.25.0-py311haee01d2_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda + - pypi: https://files.pythonhosted.org/packages/c5/0d/84a4380f930db0010168e0aa7b7a8fed9ba1835a8fbb1472bc6d0201d529/build-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl + linux-aarch64: + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-20_gnu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/archspec-0.2.5-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/auditwheel-6.6.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/backports.zstd-1.3.0-py311h6ce31b0_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/boltons-25.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/brotli-python-1.2.0-py311h14a79a7_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/bzip2-1.0.8-h4777abc_9.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/c-ares-1.34.6-he30d5cf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.2.25-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cffi-2.0.0-py311h460c349_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.5-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cmake-3.31.8-hc9d863e_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/conda-26.1.1-py311hec3470c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-libmamba-solver-25.11.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-handling-2.4.0-pyh7900ff3_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-streaming-0.12.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cpp-expected-1.3.1-hdc560ac_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/distro-1.9.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/doxygen-1.13.2-h5e0f5ae_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/fmt-12.1.0-h20c602a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/frozendict-2.4.7-py311h19352d5_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/icu-78.2-hcab7f73_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-resources-6.5.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib_resources-6.5.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpatch-1.33-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpointer-3.0.0-pyhcf101f3_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/keyutils-1.6.3-h86ecc28_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/krb5-1.22.2-hfd895c2_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.45.1-default_h1979696_101.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libarchive-3.8.6-gpl_hbe7d12b_100.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libblas-3.11.0-5_haddc8a3_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcblas-3.11.0-5_hd72aa62_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcurl-8.19.0-hc57f145_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libedit-3.1.20250104-pl5321h976ea20_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libev-4.33-h31becfc_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.7.4-hfae3067_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libffi-3.5.2-h376a255_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-15.2.0-h8acb6b2_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-ng-15.2.0-he9431aa_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran-15.2.0-he9431aa_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran5-15.2.0-h1b7bec0_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-15.2.0-h8acb6b2_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libiconv-1.18-h90929bb_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblapack-3.11.0-5_h88aeb00_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblzma-5.8.2-he30d5cf_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libmamba-2.5.0-hc712cdd_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libmamba-spdlog-2.5.0-h3ad78e7_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libmambapy-2.5.0-py311h6a8bf82_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libnghttp2-1.67.0-ha888d0e_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libnsl-2.0.1-h86ecc28_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libopenblas-0.3.30-pthreads_h9d3fd7e_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsolv-0.7.36-hdda61c4_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.52.0-h10b116e_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libssh2-1.11.1-h18c354c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-15.2.0-hef695bb_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-ng-15.2.0-hdbbeba8_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.41.3-h1022ec0_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuv-1.51.0-he30d5cf_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxcrypt-4.4.36-h31becfc_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxml2-16-2.15.2-h79dcc73_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxml2-2.15.2-h825857f_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.3.1-h86ecc28_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lz4-c-1.10.0-h5ad3122_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lzo-2.10-h80f16a2_1002.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/menuinst-2.4.2-py311hec3470c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/msgpack-python-1.1.2-py311hfca10b7_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.5-ha32ae93_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ninja-1.13.2-hdc560ac_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nlohmann_json-abi-3.12.0-h0f90c79_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/numpy-2.4.2-py311h669026d_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.6.1-h546c87b_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-25.0-pyh29332c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/patchelf-0.17.2-h884eca8_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-1.0.4-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-26.0.1-pyh8b19718_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pixi-pycharm-0.0.10-unix_hf108a03_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pkginfo-1.12.1.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pybind11-abi-11-hc364b38_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pycosat-0.6.6-py311h19352d5_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pyelftools-0.32-pyh707e725_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pyproject-metadata-0.11.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.11.15-h91f4b29_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.11-8_cp311.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/readline-8.3-hb682ff5_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/reproc-14.2.5.post0-h86ecc28_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/reproc-cpp-14.2.5.post0-h5ad3122_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.32.5-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rhash-1.4.6-h86ecc28_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ruamel.yaml-0.18.17-py311h51cfe5d_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ruamel.yaml.clib-0.2.15-py311h51cfe5d_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/scikit-build-core-0.11.6-pyh7e86bf3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-scm-9.2.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools_scm-9.2.2-hd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/simdjson-4.2.4-hfefdfc9_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/spdlog-1.17.0-h9f97df7_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/taplo-0.10.0-h3618846_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tk-8.6.13-noxft_h0dc03b3_103.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/truststore-0.10.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.46.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/yaml-cpp-0.8.0-h5ad3122_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstandard-0.25.0-py311h51cfe5d_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.7-h85ac4a6_6.conda + - pypi: https://files.pythonhosted.org/packages/c5/0d/84a4380f930db0010168e0aa7b7a8fed9ba1835a8fbb1472bc6d0201d529/build-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl + windows-py310: + channels: + - url: https://conda.anaconda.org/conda-forge/ + indexes: + - https://pypi.org/simple + options: + pypi-prerelease-mode: if-necessary-or-explicit + packages: + win-64: + - conda: https://conda.anaconda.org/conda-forge/noarch/archspec-0.2.5-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/backports.zstd-1.3.0-py310h458dff3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/boltons-25.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/brotli-python-1.2.0-py310hfff998d_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-h0ad9c76_9.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/c-compiler-1.11.0-h528c1b4_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-h4c7d964_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.2.25-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cffi-2.0.0-py310h29418f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.5-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cmake-3.31.8-hdcbee5b_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/conda-26.1.1-py310h5588dad_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-libmamba-solver-25.11.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-handling-2.4.0-pyh7900ff3_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-streaming-0.12.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cpp-expected-1.3.1-h477610d_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cxx-compiler-1.11.0-h1c1089f_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/distro-1.9.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/doxygen-1.13.2-hbf3f430_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/fmt-12.1.0-h7f4e812_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/frozendict-2.4.7-py310h29418f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/git-2.53.0-h57928b3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-resources-6.5.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib_resources-6.5.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpatch-1.33-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpointer-3.0.0-pyhcf101f3_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/krb5-1.22.2-h0ea6238_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libarchive-3.8.6-gpl_he24518a_100.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libblas-3.11.0-5_hf2e6a31_mkl.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libcblas-3.11.0-5_h2a3cdd5_mkl.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libcurl-8.19.0-h8206538_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.7.4-hac47afa_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libffi-3.5.2-h3d046cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libhwloc-2.12.2-default_h4379cf1_1000.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libiconv-1.18-hc1393d2_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/liblapack-3.11.0-5_hf9ab0e9_mkl.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/liblzma-5.8.2-hfd05255_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libmamba-2.5.0-h06825f5_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libmamba-spdlog-2.5.0-h9ae1bf1_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libmambapy-2.5.0-py310h1916185_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libsolv-0.7.35-h8883371_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.52.0-hf5d6505_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libssh2-1.11.1-h9aa295b_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libuv-1.51.0-hfd05255_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libwinpthread-12.0.0.r4.gg4f2fc60ca-h57928b3_10.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-16-2.15.2-h692994f_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-2.15.2-h5d26750_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.3.1-h2466b09_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/llvm-openmp-22.1.0-h4fa8253_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/lz4-c-1.10.0-h2466b09_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/lzo-2.10-h6a83c73_1002.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/menuinst-2.4.2-py310h73ae2b4_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/mkl-2025.3.0-hac47afa_455.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/msgpack-python-1.1.2-py310he9f1925_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ninja-1.13.2-h477610d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nlohmann_json-abi-3.12.0-h0f90c79_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/numpy-2.2.6-py310h4987827_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.6.1-hf411b9b_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-25.0-pyh29332c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-1.0.4-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-26.0.1-pyh8b19718_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pixi-pycharm-0.0.10-win_hba80fca_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pkginfo-1.12.1.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pybind11-abi-11-hc364b38_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pycosat-0.6.6-py310h29418f3_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pyproject-metadata-0.11.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyh09c184e_7.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.10.20-hc20f281_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.10-8_cp310.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/reproc-14.2.5.post0-h2466b09_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/reproc-cpp-14.2.5.post0-he0c23c2_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.32.5-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ruamel.yaml-0.18.17-py310h1637853_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ruamel.yaml.clib-0.2.15-py310h1637853_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/scikit-build-core-0.11.6-pyh7e86bf3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-scm-9.2.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools_scm-9.2.2-hd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/simdjson-4.2.4-h49e36cd_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/spdlog-1.17.0-h9f585f1_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/taplo-0.10.0-h63977a8_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/tbb-2022.3.0-h3155e25_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h6ed50ae_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyha7b4d00_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/truststore-0.10.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.3-h41ae7f8_34.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.44.35208-h818238b_34.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vcomp14-14.44.35208-h818238b_34.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vs2022_win-64-19.44.35207-ha74f236_34.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/vswhere-3.1.7-h40126e0_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.46.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/win_inet_pton-1.1.0-pyh7428d3b_8.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/yaml-cpp-0.8.0-he0c23c2_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/zstandard-0.25.0-py310h1637853_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.7-h534d264_6.conda + - pypi: https://files.pythonhosted.org/packages/c5/0d/84a4380f930db0010168e0aa7b7a8fed9ba1835a8fbb1472bc6d0201d529/build-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/89/74/bf0ea7b89e114af19a38c2341746fd1f17f1de23fa8d8019cbcd39719c5f/delvewheel-1.12.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/54/16/12b82f791c7f50ddec566873d5bdd245baa1491bac11d15ffb98aecc8f8b/pefile-2024.8.26-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl + windows-py311: + channels: + - url: https://conda.anaconda.org/conda-forge/ + indexes: + - https://pypi.org/simple + options: + pypi-prerelease-mode: if-necessary-or-explicit + packages: + win-64: + - conda: https://conda.anaconda.org/conda-forge/noarch/archspec-0.2.5-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/backports.zstd-1.3.0-py311h71c1bcc_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/boltons-25.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/brotli-python-1.2.0-py311hc5da9e4_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-h0ad9c76_9.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/c-compiler-1.11.0-h528c1b4_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-h4c7d964_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.2.25-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cffi-2.0.0-py311h3485c13_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.5-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cmake-3.31.8-hdcbee5b_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/conda-26.1.1-py311h1ea47a8_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-libmamba-solver-25.11.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-handling-2.4.0-pyh7900ff3_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-streaming-0.12.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cpp-expected-1.3.1-h477610d_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cxx-compiler-1.11.0-h1c1089f_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/distro-1.9.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/doxygen-1.13.2-hbf3f430_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/fmt-12.1.0-h7f4e812_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/frozendict-2.4.7-py311h3485c13_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/git-2.53.0-h57928b3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-resources-6.5.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib_resources-6.5.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpatch-1.33-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpointer-3.0.0-pyhcf101f3_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/krb5-1.22.2-h0ea6238_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libarchive-3.8.6-gpl_he24518a_100.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libblas-3.11.0-5_hf2e6a31_mkl.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libcblas-3.11.0-5_h2a3cdd5_mkl.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libcurl-8.19.0-h8206538_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.7.4-hac47afa_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libffi-3.5.2-h3d046cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libhwloc-2.12.2-default_h4379cf1_1000.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libiconv-1.18-hc1393d2_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/liblapack-3.11.0-5_hf9ab0e9_mkl.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/liblzma-5.8.2-hfd05255_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libmamba-2.5.0-h06825f5_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libmamba-spdlog-2.5.0-h9ae1bf1_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libmambapy-2.5.0-py311hb0041a4_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libsolv-0.7.35-h8883371_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.52.0-hf5d6505_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libssh2-1.11.1-h9aa295b_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libuv-1.51.0-hfd05255_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libwinpthread-12.0.0.r4.gg4f2fc60ca-h57928b3_10.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-16-2.15.2-h692994f_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-2.15.2-h5d26750_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.3.1-h2466b09_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/llvm-openmp-22.1.0-h4fa8253_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/lz4-c-1.10.0-h2466b09_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/lzo-2.10-h6a83c73_1002.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/menuinst-2.4.2-py311h3e6a449_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/mkl-2025.3.0-hac47afa_455.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/msgpack-python-1.1.2-py311h3fd045d_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ninja-1.13.2-h477610d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nlohmann_json-abi-3.12.0-h0f90c79_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/numpy-2.4.2-py311h80b3fa1_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.6.1-hf411b9b_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-25.0-pyh29332c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-1.0.4-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-26.0.1-pyh8b19718_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pixi-pycharm-0.0.10-win_hba80fca_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pkginfo-1.12.1.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pybind11-abi-11-hc364b38_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pycosat-0.6.6-py311h3485c13_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pyproject-metadata-0.11.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyh09c184e_7.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.11.15-h0159041_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.11-8_cp311.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/reproc-14.2.5.post0-h2466b09_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/reproc-cpp-14.2.5.post0-he0c23c2_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.32.5-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ruamel.yaml-0.18.17-py311hf893f09_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ruamel.yaml.clib-0.2.15-py311hf893f09_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/scikit-build-core-0.11.6-pyh7e86bf3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-scm-9.2.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools_scm-9.2.2-hd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/simdjson-4.2.4-h49e36cd_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/spdlog-1.17.0-h9f585f1_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/taplo-0.10.0-h63977a8_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/tbb-2022.3.0-h3155e25_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h6ed50ae_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyha7b4d00_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/truststore-0.10.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.3-h41ae7f8_34.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.44.35208-h818238b_34.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vcomp14-14.44.35208-h818238b_34.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vs2022_win-64-19.44.35207-ha74f236_34.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/vswhere-3.1.7-h40126e0_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.46.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/win_inet_pton-1.1.0-pyh7428d3b_8.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/yaml-cpp-0.8.0-he0c23c2_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/zstandard-0.25.0-py311hf893f09_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.7-h534d264_6.conda + - pypi: https://files.pythonhosted.org/packages/c5/0d/84a4380f930db0010168e0aa7b7a8fed9ba1835a8fbb1472bc6d0201d529/build-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/89/74/bf0ea7b89e114af19a38c2341746fd1f17f1de23fa8d8019cbcd39719c5f/delvewheel-1.12.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/54/16/12b82f791c7f50ddec566873d5bdd245baa1491bac11d15ffb98aecc8f8b/pefile-2024.8.26-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl +packages: +- conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda + build_number: 20 + sha256: 1dd3fffd892081df9726d7eb7e0dea6198962ba775bd88842135a4ddb4deb3c9 + md5: a9f577daf3de00bca7c3c76c0ecbd1de + depends: + - __glibc >=2.17,<3.0.a0 + - libgomp >=7.5.0 + constrains: + - openmp_impl <0.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 28948 + timestamp: 1770939786096 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-20_gnu.conda + build_number: 20 + sha256: a2527b1d81792a0ccd2c05850960df119c2b6d8f5fdec97f2db7d25dc23b1068 + md5: 468fd3bb9e1f671d36c2cbc677e56f1d + depends: + - libgomp >=7.5.0 + constrains: + - openmp_impl <0.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 28926 + timestamp: 1770939656741 +- conda: https://conda.anaconda.org/conda-forge/osx-64/_openmp_mutex-4.5-7_kmp_llvm.conda + build_number: 7 + sha256: 30006902a9274de8abdad5a9f02ef7c8bb3d69a503486af0c1faee30b023e5b7 + md5: eaac87c21aff3ed21ad9656697bb8326 + depends: + - llvm-openmp >=9.0.1 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 8328 + timestamp: 1764092562779 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/_openmp_mutex-4.5-7_kmp_llvm.conda + build_number: 7 + sha256: 7acaa2e0782cad032bdaf756b536874346ac1375745fb250e9bdd6a48a7ab3cd + md5: a44032f282e7d2acdeb1c240308052dd + depends: + - llvm-openmp >=9.0.1 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 8325 + timestamp: 1764092507920 +- pypi: https://files.pythonhosted.org/packages/a9/ba/000a1996d4308bc65120167c21241a3b205464a2e0b58deda26ae8ac21d1/altgraph-0.17.5-py2.py3-none-any.whl + name: altgraph + version: 0.17.5 + sha256: f3a22400bce1b0c701683820ac4f3b159cd301acab067c51c653e06961600597 +- conda: https://conda.anaconda.org/conda-forge/noarch/archspec-0.2.5-pyhd8ed1ab_0.conda + sha256: eb68e1ce9e9a148168a4b1e257a8feebffdb0664b557bb526a1e4853f2d2fc00 + md5: 845b38297fca2f2d18a29748e2ece7fa + depends: + - python >=3.9 + license: MIT OR Apache-2.0 + purls: + - pkg:pypi/archspec?source=hash-mapping + size: 50894 + timestamp: 1737352715041 +- conda: https://conda.anaconda.org/conda-forge/noarch/auditwheel-6.6.0-pyhd8ed1ab_0.conda + sha256: edba8fbf77c737ee991ae56f3cf5297f23c82eeb6033d6cfb4b78c2545cc66f0 + md5: b0eb66b5e5335471c1148199a26ceb79 + depends: + - packaging >=20.9 + - pyelftools >=0.24 + - python >=3.10 + license: MIT + license_family: MIT + purls: + - pkg:pypi/auditwheel?source=hash-mapping + size: 51557 + timestamp: 1767633848607 +- conda: https://conda.anaconda.org/conda-forge/linux-64/backports.zstd-1.3.0-py310h69bd2ac_0.conda + sha256: 6660be15a45175c98f750b8bbc3fd07e0da36043624b376de49769bd14a0a16f + md5: 276a3ddf300498921601822e3b407088 + depends: + - python + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - zstd >=1.5.7,<1.6.0a0 + - python_abi 3.10.* *_cp310 + license: BSD-3-Clause AND MIT AND EPL-2.0 + purls: + - pkg:pypi/backports-zstd?source=hash-mapping + size: 191286 + timestamp: 1767044984395 +- conda: https://conda.anaconda.org/conda-forge/linux-64/backports.zstd-1.3.0-py311h6b1f9c4_0.conda + sha256: 246e50ec7fc222875c6ecfa3feab77f5661dc43e26397bc01d9e0310e3cd48a0 + md5: adda5ef2a74c9bdb338ff8a51192898a + depends: + - python + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - python_abi 3.11.* *_cp311 + - zstd >=1.5.7,<1.6.0a0 + license: BSD-3-Clause AND MIT AND EPL-2.0 + purls: + - pkg:pypi/backports-zstd?source=hash-mapping + size: 244920 + timestamp: 1767044984647 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/backports.zstd-1.3.0-py310hfa1aa29_0.conda + sha256: 92708591d7219370df1b63a96f68be0a2bc6422b8c5c35757b27751ab658ac44 + md5: e6c4c73503900c04b9e8d273fc5db976 + depends: + - python + - python 3.10.* *_cpython + - libgcc >=14 + - python_abi 3.10.* *_cp310 + - zstd >=1.5.7,<1.6.0a0 + license: BSD-3-Clause AND MIT AND EPL-2.0 + purls: + - pkg:pypi/backports-zstd?source=hash-mapping + size: 196369 + timestamp: 1767044996002 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/backports.zstd-1.3.0-py311h6ce31b0_0.conda + sha256: b11baef215becac7d657289bc4171640be7ec6ff5068d3f9fb8a2b0e06242852 + md5: 219e216268cad83c58f10435ce2001fb + depends: + - python + - python 3.11.* *_cpython + - libgcc >=14 + - zstd >=1.5.7,<1.6.0a0 + - python_abi 3.11.* *_cp311 + license: BSD-3-Clause AND MIT AND EPL-2.0 + purls: + - pkg:pypi/backports-zstd?source=hash-mapping + size: 250129 + timestamp: 1767044999147 +- conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.3.0-py314h680f03e_0.conda + noarch: generic + sha256: c31ab719d256bc6f89926131e88ecd0f0c5d003fe8481852c6424f4ec6c7eb29 + md5: a2ac7763a9ac75055b68f325d3255265 + depends: + - python >=3.14 + license: BSD-3-Clause AND MIT AND EPL-2.0 + size: 7514 + timestamp: 1767044983590 +- conda: https://conda.anaconda.org/conda-forge/win-64/backports.zstd-1.3.0-py310h458dff3_0.conda + sha256: ceb8b49b9bf0246b606089ce95e5afe0c4fd39ada3c8c381a3d03fd9beafba88 + md5: 9f9e5cd3aa06ea10681a65355f5dca09 + depends: + - python + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - python_abi 3.10.* *_cp310 + - zstd >=1.5.7,<1.6.0a0 + license: BSD-3-Clause AND MIT AND EPL-2.0 + purls: + - pkg:pypi/backports-zstd?source=hash-mapping + size: 190164 + timestamp: 1767045016166 +- conda: https://conda.anaconda.org/conda-forge/win-64/backports.zstd-1.3.0-py311h71c1bcc_0.conda + sha256: 5a30429e009b93c6dffe539cf0e3d220ef8d36ea42d36ca5c26b603cb3319c71 + md5: 49eb28c4f92e8a7440e3da6d8e8b5e58 + depends: + - python + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - zstd >=1.5.7,<1.6.0a0 + - python_abi 3.11.* *_cp311 + license: BSD-3-Clause AND MIT AND EPL-2.0 + purls: + - pkg:pypi/backports-zstd?source=hash-mapping + size: 243289 + timestamp: 1767045012846 +- conda: https://conda.anaconda.org/conda-forge/linux-64/binutils-2.45.1-default_h4852527_101.conda + sha256: 2851d34944b056d028543f0440fb631aeeff204151ea09589d8d9c13882395de + md5: 9902aeb08445c03fb31e01beeb173988 + depends: + - binutils_impl_linux-64 >=2.45.1,<2.45.2.0a0 + license: GPL-3.0-only + license_family: GPL + purls: [] + size: 35128 + timestamp: 1770267175160 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/binutils-2.45.1-default_hf1166c9_101.conda + sha256: 7113440420c6f31742c2b29d7590900362007a0bb0d31f9bc5c9a1379d9ab702 + md5: 77f58300ab7d95ce79f9c2c13ad72d5c + depends: + - binutils_impl_linux-aarch64 >=2.45.1,<2.45.2.0a0 + license: GPL-3.0-only + license_family: GPL + purls: [] + size: 35322 + timestamp: 1770267247190 +- conda: https://conda.anaconda.org/conda-forge/linux-64/binutils_impl_linux-64-2.45.1-default_hfdba357_101.conda + sha256: 74341b26a2b9475dc14ba3cf12432fcd10a23af285101883e720216d81d44676 + md5: 83aa53cb3f5fc849851a84d777a60551 + depends: + - ld_impl_linux-64 2.45.1 default_hbd61a6d_101 + - sysroot_linux-64 + - zstd >=1.5.7,<1.6.0a0 + license: GPL-3.0-only + license_family: GPL + purls: [] + size: 3744895 + timestamp: 1770267152681 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/binutils_impl_linux-aarch64-2.45.1-default_h5f4c503_101.conda + sha256: e90ab42a5225dc1eaa6e4e7201cd7b8ed52dad6ec46814be7e5a4039433ae85c + md5: df6e1dc38cbe5642350fa09d4a1d546b + depends: + - ld_impl_linux-aarch64 2.45.1 default_h1979696_101 + - sysroot_linux-aarch64 + - zstd >=1.5.7,<1.6.0a0 + license: GPL-3.0-only + license_family: GPL + purls: [] + size: 4741684 + timestamp: 1770267224406 +- conda: https://conda.anaconda.org/conda-forge/linux-64/binutils_linux-64-2.45.1-default_h4852527_101.conda + sha256: 4826f97d33cbe54459970a1e84500dbe0cccf8326aaf370e707372ae20ec5a47 + md5: dec96579f9a7035a59492bf6ee613b53 + depends: + - binutils_impl_linux-64 2.45.1 default_hfdba357_101 + license: GPL-3.0-only + license_family: GPL + purls: [] + size: 36060 + timestamp: 1770267177798 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/binutils_linux-aarch64-2.45.1-default_hf1166c9_101.conda + sha256: 4ed3cf8af327b1c8b7e71433c98eb0154027e07b726136e81235276e9025489a + md5: 99924e610d9960dc3d8b865614787cec + depends: + - binutils_impl_linux-aarch64 2.45.1 default_h5f4c503_101 + license: GPL-3.0-only + license_family: GPL + purls: [] + size: 36223 + timestamp: 1770267249899 +- conda: https://conda.anaconda.org/conda-forge/noarch/boltons-25.0.0-pyhd8ed1ab_0.conda + sha256: ea5f4c876eff2ed469551b57f1cc889a3c01128bf3e2e10b1fea11c3ef39eac2 + md5: c7eb87af73750d6fd97eff8bbee8cb9c + depends: + - python >=3.9 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/boltons?source=hash-mapping + size: 302296 + timestamp: 1749686302834 +- conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.2.0-py310hba01987_1.conda + sha256: f036fe554d902549f86689a9650a0996901d5c9242b0a1e3fbfe6dbccd2ae011 + md5: 393fca4557fbd2c4d995dcb89f569048 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libstdcxx >=14 + - python >=3.10,<3.11.0a0 + - python_abi 3.10.* *_cp310 + constrains: + - libbrotlicommon 1.2.0 hb03c661_1 + license: MIT + license_family: MIT + purls: + - pkg:pypi/brotli?source=hash-mapping + size: 367099 + timestamp: 1764017439384 +- conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.2.0-py311h66f275b_1.conda + sha256: c36eb061d9ead85f97644cfb740d485dba9b8823357f35c17851078e95e975c1 + md5: 86daecb8e4ed1042d5dc6efbe0152590 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libstdcxx >=14 + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + constrains: + - libbrotlicommon 1.2.0 hb03c661_1 + license: MIT + license_family: MIT + purls: + - pkg:pypi/brotli?source=hash-mapping + size: 367573 + timestamp: 1764017405384 +- conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.2.0-py314h3de4e8d_1.conda + sha256: 3ad3500bff54a781c29f16ce1b288b36606e2189d0b0ef2f67036554f47f12b0 + md5: 8910d2c46f7e7b519129f486e0fe927a + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libstdcxx >=14 + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + constrains: + - libbrotlicommon 1.2.0 hb03c661_1 + license: MIT + license_family: MIT + size: 367376 + timestamp: 1764017265553 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/brotli-python-1.2.0-py310hbe54bbb_1.conda + sha256: febea9d5c157f0a78dc0ffde32fe37b1f19eae812784f6e5505d471bf60d6f43 + md5: 49a57b1956565528e382d8c9af4854c7 + depends: + - libgcc >=14 + - libstdcxx >=14 + - python >=3.10,<3.11.0a0 + - python >=3.10,<3.11.0a0 *_cpython + - python_abi 3.10.* *_cp310 + constrains: + - libbrotlicommon 1.2.0 he30d5cf_1 + license: MIT + license_family: MIT + purls: + - pkg:pypi/brotli?source=hash-mapping + size: 372450 + timestamp: 1764017428950 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/brotli-python-1.2.0-py311h14a79a7_1.conda + sha256: bf73f124e8dd683c5f414b9bea077246fcdec3f6c530bd83234b5eb329b52423 + md5: 292e7c014bfab5c77a2ff9c92728bb50 + depends: + - libgcc >=14 + - libstdcxx >=14 + - python >=3.11,<3.12.0a0 + - python >=3.11,<3.12.0a0 *_cpython + - python_abi 3.11.* *_cp311 + constrains: + - libbrotlicommon 1.2.0 he30d5cf_1 + license: MIT + license_family: MIT + purls: + - pkg:pypi/brotli?source=hash-mapping + size: 373346 + timestamp: 1764017600174 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/brotli-python-1.2.0-py314h352cb57_1.conda + sha256: 5a5b0cdcd7ed89c6a8fb830924967f6314a2b71944bc1ebc2c105781ba97aa75 + md5: a1b5c571a0923a205d663d8678df4792 + depends: + - libgcc >=14 + - libstdcxx >=14 + - python >=3.14,<3.15.0a0 + - python >=3.14,<3.15.0a0 *_cp314 + - python_abi 3.14.* *_cp314 + constrains: + - libbrotlicommon 1.2.0 he30d5cf_1 + license: MIT + license_family: MIT + size: 373193 + timestamp: 1764017486851 +- conda: https://conda.anaconda.org/conda-forge/osx-64/brotli-python-1.1.0-py310h9e9d8ca_1.conda + sha256: 57d66ca3e072b889c94cfaf56eb7e1794d3b1b3179bd475a4edef50a03359354 + md5: 2362e323293e7699cf1e621d502f86d6 + depends: + - libcxx >=15.0.7 + - python >=3.10,<3.11.0a0 + - python_abi 3.10.* *_cp310 + constrains: + - libbrotlicommon 1.1.0 h0dc2134_1 + license: MIT + license_family: MIT + purls: + - pkg:pypi/brotli?source=hash-mapping + size: 367037 + timestamp: 1695990378635 +- conda: https://conda.anaconda.org/conda-forge/osx-64/brotli-python-1.1.0-py311hdf8f085_1.conda + sha256: 0f5e0a7de58006f349220365e32db521a1fe494c37ee455e5ecf05b8fe567dcc + md5: 546fdccabb90492fbaf2da4ffb78f352 + depends: + - libcxx >=15.0.7 + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + constrains: + - libbrotlicommon 1.1.0 h0dc2134_1 + license: MIT + license_family: MIT + purls: + - pkg:pypi/brotli?source=hash-mapping + size: 366864 + timestamp: 1695990449997 +- conda: https://conda.anaconda.org/conda-forge/osx-64/brotli-python-1.2.0-py314h3262eb8_1.conda + sha256: 2e34922abda4ac5726c547887161327b97c3bbd39f1204a5db162526b8b04300 + md5: 389d75a294091e0d7fa5a6fc683c4d50 + depends: + - __osx >=10.13 + - libcxx >=19 + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + constrains: + - libbrotlicommon 1.2.0 h8616949_1 + license: MIT + license_family: MIT + size: 390153 + timestamp: 1764017784596 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-python-1.1.0-py310h1253130_1.conda + sha256: dab21e18c0275bfd93a09b751096998485677ed17c2e2d08298bc5b43c10bee1 + md5: 26fab7f65a80fff9f402ec3b7860b88a + depends: + - libcxx >=15.0.7 + - python >=3.10,<3.11.0a0 + - python >=3.10,<3.11.0a0 *_cpython + - python_abi 3.10.* *_cp310 + constrains: + - libbrotlicommon 1.1.0 hb547adb_1 + license: MIT + license_family: MIT + purls: + - pkg:pypi/brotli?source=hash-mapping + size: 344275 + timestamp: 1695990848681 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-python-1.1.0-py311ha891d26_1.conda + sha256: 2d78c79ccf2c17236c52ef217a4c34b762eb7908a6903d94439f787aac1c8f4b + md5: 5e802b015e33447d1283d599d21f052b + depends: + - libcxx >=15.0.7 + - python >=3.11,<3.12.0a0 + - python >=3.11,<3.12.0a0 *_cpython + - python_abi 3.11.* *_cp311 + constrains: + - libbrotlicommon 1.1.0 hb547adb_1 + license: MIT + license_family: MIT + purls: + - pkg:pypi/brotli?source=hash-mapping + size: 343332 + timestamp: 1695991223439 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-python-1.2.0-py314h3daef5d_1.conda + sha256: 5c2e471fd262fcc3c5a9d5ea4dae5917b885e0e9b02763dbd0f0d9635ed4cb99 + md5: f9501812fe7c66b6548c7fcaa1c1f252 + depends: + - __osx >=11.0 + - libcxx >=19 + - python >=3.14,<3.15.0a0 + - python >=3.14,<3.15.0a0 *_cp314 + - python_abi 3.14.* *_cp314 + constrains: + - libbrotlicommon 1.2.0 hc919400_1 + license: MIT + license_family: MIT + size: 359854 + timestamp: 1764018178608 +- conda: https://conda.anaconda.org/conda-forge/win-64/brotli-python-1.2.0-py310hfff998d_1.conda + sha256: fd250a4f92c2176f23dd4e07de1faf76741dabcc8fa00b182748db4d9578ff7e + md5: 0caf12fa6690b7f64883b2239853dda0 + depends: + - python >=3.10,<3.11.0a0 + - python_abi 3.10.* *_cp310 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + constrains: + - libbrotlicommon 1.2.0 hfd05255_1 + license: MIT + license_family: MIT + purls: + - pkg:pypi/brotli?source=hash-mapping + size: 335476 + timestamp: 1764018212429 +- conda: https://conda.anaconda.org/conda-forge/win-64/brotli-python-1.2.0-py311hc5da9e4_1.conda + sha256: 1803c838946d79ef6485ae8c7dafc93e28722c5999b059a34118ef758387a4c9 + md5: b0c459f98ac5ea504a9d9df6242f7ee1 + depends: + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + constrains: + - libbrotlicommon 1.2.0 hfd05255_1 + license: MIT + license_family: MIT + purls: + - pkg:pypi/brotli?source=hash-mapping + size: 335333 + timestamp: 1764018370925 +- conda: https://conda.anaconda.org/conda-forge/win-64/brotli-python-1.2.0-py314he701e3d_1.conda + sha256: 6854ee7675135c57c73a04849c29cbebc2fb6a3a3bfee1f308e64bf23074719b + md5: 1302b74b93c44791403cbeee6a0f62a3 + depends: + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + constrains: + - libbrotlicommon 1.2.0 hfd05255_1 + license: MIT + license_family: MIT + size: 335782 + timestamp: 1764018443683 +- pypi: https://files.pythonhosted.org/packages/c5/0d/84a4380f930db0010168e0aa7b7a8fed9ba1835a8fbb1472bc6d0201d529/build-1.4.0-py3-none-any.whl + name: build + version: 1.4.0 + sha256: 6a07c1b8eb6f2b311b96fcbdbce5dab5fe637ffda0fd83c9cac622e927501596 + requires_dist: + - packaging>=24.0 + - pyproject-hooks + - colorama ; os_name == 'nt' + - importlib-metadata>=4.6 ; python_full_version < '3.10.2' + - tomli>=1.1.0 ; python_full_version < '3.11' + - uv>=0.1.18 ; extra == 'uv' + - virtualenv>=20.11 ; python_full_version < '3.10' and extra == 'virtualenv' + - virtualenv>=20.17 ; python_full_version >= '3.10' and python_full_version < '3.14' and extra == 'virtualenv' + - virtualenv>=20.31 ; python_full_version >= '3.14' and extra == 'virtualenv' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/4a/57/3b7d4dd193ade4641c865bc2b93aeeb71162e81fc348b8dad020215601ed/build-1.4.2-py3-none-any.whl + name: build + version: 1.4.2 + sha256: 7a4d8651ea877cb2a89458b1b198f2e69f536c95e89129dbf5d448045d60db88 + requires_dist: + - packaging>=24.0 + - pyproject-hooks + - colorama ; os_name == 'nt' + - importlib-metadata>=4.6 ; python_full_version < '3.10.2' + - tomli>=1.1.0 ; python_full_version < '3.11' + - uv>=0.1.18 ; extra == 'uv' + - virtualenv>=20.11 ; python_full_version < '3.10' and extra == 'virtualenv' + - virtualenv>=20.17 ; python_full_version >= '3.10' and python_full_version < '3.14' and extra == 'virtualenv' + - virtualenv>=20.31 ; python_full_version >= '3.14' and extra == 'virtualenv' + requires_python: '>=3.9' +- conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_9.conda + sha256: 0b75d45f0bba3e95dc693336fa51f40ea28c980131fec438afb7ce6118ed05f6 + md5: d2ffd7602c02f2b316fd921d39876885 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + license: bzip2-1.0.6 + license_family: BSD + purls: [] + size: 260182 + timestamp: 1771350215188 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/bzip2-1.0.8-h4777abc_9.conda + sha256: b3495077889dde6bb370938e7db82be545c73e8589696ad0843a32221520ad4c + md5: 840d8fc0d7b3209be93080bc20e07f2d + depends: + - libgcc >=14 + license: bzip2-1.0.6 + license_family: BSD + purls: [] + size: 192412 + timestamp: 1771350241232 +- conda: https://conda.anaconda.org/conda-forge/osx-64/bzip2-1.0.8-h10d778d_5.conda + sha256: 61fb2b488928a54d9472113e1280b468a309561caa54f33825a3593da390b242 + md5: 6097a6ca9ada32699b5fc4312dd6ef18 + license: bzip2-1.0.6 + license_family: BSD + purls: [] + size: 127885 + timestamp: 1699280178474 +- conda: https://conda.anaconda.org/conda-forge/osx-64/bzip2-1.0.8-h500dc9f_9.conda + sha256: 9f242f13537ef1ce195f93f0cc162965d6cc79da578568d6d8e50f70dd025c42 + md5: 4173ac3b19ec0a4f400b4f782910368b + depends: + - __osx >=10.13 + license: bzip2-1.0.6 + license_family: BSD + size: 133427 + timestamp: 1771350680709 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-h93a5062_5.conda + sha256: bfa84296a638bea78a8bb29abc493ee95f2a0218775642474a840411b950fe5f + md5: 1bbc659ca658bfd49a481b5ef7a0f40f + license: bzip2-1.0.6 + license_family: BSD + purls: [] + size: 122325 + timestamp: 1699280294368 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-hd037594_9.conda + sha256: 540fe54be35fac0c17feefbdc3e29725cce05d7367ffedfaaa1bdda234b019df + md5: 620b85a3f45526a8bc4d23fd78fc22f0 + depends: + - __osx >=11.0 + license: bzip2-1.0.6 + license_family: BSD + size: 124834 + timestamp: 1771350416561 +- conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-h0ad9c76_9.conda + sha256: 76dfb71df5e8d1c4eded2dbb5ba15bb8fb2e2b0fe42d94145d5eed4c75c35902 + md5: 4cb8e6b48f67de0b018719cdf1136306 + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: bzip2-1.0.6 + license_family: BSD + purls: [] + size: 56115 + timestamp: 1771350256444 +- conda: https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.34.6-hb03c661_0.conda + sha256: cc9accf72fa028d31c2a038460787751127317dcfa991f8d1f1babf216bb454e + md5: 920bb03579f15389b9e512095ad995b7 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + license: MIT + license_family: MIT + purls: [] + size: 207882 + timestamp: 1765214722852 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/c-ares-1.34.6-he30d5cf_0.conda + sha256: 7ec8a68efe479e2e298558cbc2e79d29430d5c7508254268818c0ae19b206519 + md5: 1dfbec0d08f112103405756181304c16 + depends: + - libgcc >=14 + license: MIT + license_family: MIT + purls: [] + size: 217215 + timestamp: 1765214743735 +- conda: https://conda.anaconda.org/conda-forge/osx-64/c-ares-1.28.1-h10d778d_0.conda + sha256: fccd7ad7e3dfa6b19352705b33eb738c4c55f79f398e106e6cf03bab9415595a + md5: d5eb7992227254c0e9a0ce71151f0079 + license: MIT + license_family: MIT + purls: [] + size: 152607 + timestamp: 1711819681694 +- conda: https://conda.anaconda.org/conda-forge/osx-64/c-ares-1.34.6-hb5e19a0_0.conda + sha256: 2f5bc0292d595399df0d168355b4e9820affc8036792d6984bd751fdda2bcaea + md5: fc9a153c57c9f070bebaa7eef30a8f17 + depends: + - __osx >=10.13 + license: MIT + license_family: MIT + size: 186122 + timestamp: 1765215100384 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-ares-1.28.1-h93a5062_0.conda + sha256: 2fc553d7a75e912efbdd6b82cd7916cc9cb2773e6cd873b77e02d631dd7be698 + md5: 04f776a6139f7eafc2f38668570eb7db + license: MIT + license_family: MIT + purls: [] + size: 150488 + timestamp: 1711819630164 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-ares-1.34.6-hc919400_0.conda + sha256: 2995f2aed4e53725e5efbc28199b46bf311c3cab2648fc4f10c2227d6d5fa196 + md5: bcb3cba70cf1eec964a03b4ba7775f01 + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + size: 180327 + timestamp: 1765215064054 +- conda: https://conda.anaconda.org/conda-forge/linux-64/c-compiler-1.11.0-h4d9bdce_0.conda + sha256: 8e7a40f16400d7839c82581410aa05c1f8324a693c9d50079f8c50dc9fb241f0 + md5: abd85120de1187b0d1ec305c2173c71b + depends: + - binutils + - gcc + - gcc_linux-64 14.* + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 6693 + timestamp: 1753098721814 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/c-compiler-1.11.0-hdceaead_0.conda + sha256: a16c5078619d60e54f75336ed2bbb4ee0fb6f711de02dd364983748beda31e04 + md5: 89bc32110bba0dc160bb69427e196dc4 + depends: + - binutils + - gcc + - gcc_linux-aarch64 14.* + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 6721 + timestamp: 1753098688332 +- conda: https://conda.anaconda.org/conda-forge/osx-64/c-compiler-1.10.0-h09a7c41_0.conda + sha256: 6a3f6b72bf5ad154630f79bd600f6ccf0f5c6a4be5297e4831d63016f4220e62 + md5: 7b7c12e4774b83c18612c78073d12adc + depends: + - cctools >=949.0.1 + - clang_osx-64 18.* + - ld64 >=530 + - llvm-openmp + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 6773 + timestamp: 1751115657381 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-compiler-1.10.0-hdf49b6b_0.conda + sha256: efc71f2ae5901bea633c67468b3aa774b6bcf46c9433e1ab5d640e3faf1680b9 + md5: 7ca1bdcc45db75f54ed7b3ac969ed888 + depends: + - cctools >=949.0.1 + - clang_osx-arm64 18.* + - ld64 >=530 + - llvm-openmp + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 6758 + timestamp: 1751115540465 +- conda: https://conda.anaconda.org/conda-forge/win-64/c-compiler-1.11.0-h528c1b4_0.conda + sha256: 55e04bd4af61500cb8cae064386be57d18fbfdf676655ff1c97c7e5d146c6e34 + md5: 6d994ff9ab924ba11c2c07e93afbe485 + depends: + - vs2022_win-64 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 6938 + timestamp: 1753098808371 +- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-h4c7d964_0.conda + sha256: 37950019c59b99585cee5d30dbc2cc9696ed4e11f5742606a4db1621ed8f94d6 + md5: f001e6e220355b7f87403a4d0e5bf1ca + depends: + - __win + license: ISC + purls: [] + size: 147734 + timestamp: 1772006322223 +- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda + sha256: 67cc7101b36421c5913a1687ef1b99f85b5d6868da3abbf6ec1a4181e79782fc + md5: 4492fd26db29495f0ba23f146cd5638d + depends: + - __unix + license: ISC + purls: [] + size: 147413 + timestamp: 1772006283803 +- conda: https://conda.anaconda.org/conda-forge/osx-64/cctools-986-hd3558d4_0.conda + sha256: 0879b6169986404d3e79e16676fe3de0cd962b522b7e8ef0fdad345400a28571 + md5: 64cd107846d3407b8d75899078ffb2ab + depends: + - cctools_osx-64 986 h58a35ae_0 + - ld64 711 h4e51db5_0 + - libllvm18 >=18.1.1,<18.2.0a0 + license: APSL-2.0 + license_family: Other + purls: [] + size: 21451 + timestamp: 1710484533466 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/cctools-986-h4c9edd9_0.conda + sha256: bfbfc99da17828d007286f40af86b44315769cfbcc4beba62a8ae64264bd1193 + md5: abcfabe468c14e506fceab2e85380b3b + depends: + - cctools_osx-arm64 986 hd11630f_0 + - ld64 711 h4c6efb1_0 + - libllvm18 >=18.1.1,<18.2.0a0 + license: APSL-2.0 + license_family: Other + purls: [] + size: 21460 + timestamp: 1710484691219 +- conda: https://conda.anaconda.org/conda-forge/osx-64/cctools_osx-64-986-h58a35ae_0.conda + sha256: a11f85e26b7189af87aa7e42b29a80f6bae73a92710cd5a40e278d6376a66ef5 + md5: 1139258589f2d752a578ed5b2680eb60 + depends: + - ld64_osx-64 >=711,<712.0a0 + - libcxx + - libllvm18 >=18.1.1,<18.2.0a0 + - libzlib >=1.2.13,<2.0.0a0 + - sigtool + constrains: + - ld64 711.* + - cctools 986.* + - clang 18.1.* + license: APSL-2.0 + license_family: Other + purls: [] + size: 1104790 + timestamp: 1710484461097 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/cctools_osx-arm64-986-hd11630f_0.conda + sha256: 4152323bbb78e2730fea9004333c9c51fb82a9ddd935f005280bf621849ec53d + md5: cce200c91b2d291c85e66098fe0d31c2 + depends: + - ld64_osx-arm64 >=711,<712.0a0 + - libcxx + - libllvm18 >=18.1.1,<18.2.0a0 + - libzlib >=1.2.13,<2.0.0a0 + - sigtool + constrains: + - cctools 986.* + - clang 18.1.* + - ld64 711.* + license: APSL-2.0 + license_family: Other + purls: [] + size: 1123368 + timestamp: 1710484635601 +- conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.2.25-pyhd8ed1ab_0.conda + sha256: a6b118fd1ed6099dc4fc03f9c492b88882a780fadaef4ed4f93dc70757713656 + md5: 765c4d97e877cdbbb88ff33152b86125 + depends: + - python >=3.10 + license: ISC + purls: + - pkg:pypi/certifi?source=compressed-mapping + size: 151445 + timestamp: 1772001170301 +- conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-2.0.0-py310he7384ee_1.conda + sha256: bf76ead6d59b70f3e901476a73880ac92011be63b151972d135eec55bbbe6091 + md5: 803e2d778b8dcccdc014127ec5001681 + depends: + - __glibc >=2.17,<3.0.a0 + - libffi >=3.5.2,<3.6.0a0 + - libgcc >=14 + - pycparser + - python >=3.10,<3.11.0a0 + - python_abi 3.10.* *_cp310 + license: MIT + license_family: MIT + purls: + - pkg:pypi/cffi?source=hash-mapping + size: 244766 + timestamp: 1761203011221 +- conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-2.0.0-py311h03d9500_1.conda + sha256: 3ad13377356c86d3a945ae30e9b8c8734300925ef81a3cb0a9db0d755afbe7bb + md5: 3912e4373de46adafd8f1e97e4bd166b + depends: + - __glibc >=2.17,<3.0.a0 + - libffi >=3.5.2,<3.6.0a0 + - libgcc >=14 + - pycparser + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + license: MIT + license_family: MIT + purls: + - pkg:pypi/cffi?source=hash-mapping + size: 303338 + timestamp: 1761202960110 +- conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-2.0.0-py314h4a8dc5f_1.conda + sha256: c6339858a0aaf5d939e00d345c98b99e4558f285942b27232ac098ad17ac7f8e + md5: cf45f4278afd6f4e6d03eda0f435d527 + depends: + - __glibc >=2.17,<3.0.a0 + - libffi >=3.5.2,<3.6.0a0 + - libgcc >=14 + - pycparser + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + size: 300271 + timestamp: 1761203085220 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cffi-2.0.0-py310h0826a50_1.conda + sha256: 63458040026be843a189e319190a0622486017c92ef251d4dff7ec847f9a8418 + md5: 152a5ba791642d8a81fe02d134ab3839 + depends: + - libffi >=3.5.2,<3.6.0a0 + - libgcc >=14 + - pycparser + - python >=3.10,<3.11.0a0 + - python_abi 3.10.* *_cp310 + license: MIT + license_family: MIT + purls: + - pkg:pypi/cffi?source=hash-mapping + size: 261471 + timestamp: 1761204343202 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cffi-2.0.0-py311h460c349_1.conda + sha256: a0a49dc4fc0d177ba75d797660145d9405f956944af75d0c402d7733c6c71f60 + md5: eef8f2527e60a82df85eba1cc4f9d5e1 + depends: + - libffi >=3.5.2,<3.6.0a0 + - libgcc >=14 + - pycparser + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + license: MIT + license_family: MIT + purls: + - pkg:pypi/cffi?source=hash-mapping + size: 321642 + timestamp: 1761203947874 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cffi-2.0.0-py314h0bd77cf_1.conda + sha256: 728e55b32bf538e792010308fbe55d26d02903ddc295fbe101167903a123dd6f + md5: f333c475896dbc8b15efd8f7c61154c7 + depends: + - libffi >=3.5.2,<3.6.0a0 + - libgcc >=14 + - pycparser + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + size: 318357 + timestamp: 1761203973223 +- conda: https://conda.anaconda.org/conda-forge/osx-64/cffi-1.16.0-py310hdca579f_0.conda + sha256: 37802485964f1a3137ed6ab21ebc08fe9d35e7dc4da39f2b72a814644dd1ac15 + md5: b9e6213f0eb91f40c009ce69139c1869 + depends: + - libffi >=3.4,<4.0a0 + - pycparser + - python >=3.10,<3.11.0a0 + - python_abi 3.10.* *_cp310 + license: MIT + license_family: MIT + purls: + - pkg:pypi/cffi?source=hash-mapping + size: 229407 + timestamp: 1696002017767 +- conda: https://conda.anaconda.org/conda-forge/osx-64/cffi-1.16.0-py311hc0b63fd_0.conda + sha256: 1f13a5fa7f310fdbd27f5eddceb9e62cfb10012c58a58c923dd6f51fa979748a + md5: 15d07b82223cac96af629e5e747ba27a + depends: + - libffi >=3.4,<4.0a0 + - pycparser + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + license: MIT + license_family: MIT + purls: + - pkg:pypi/cffi?source=hash-mapping + size: 289932 + timestamp: 1696002096156 +- conda: https://conda.anaconda.org/conda-forge/osx-64/cffi-2.0.0-py314h8ca4d5a_1.conda + sha256: e2c58cc2451cc96db2a3c8ec34e18889878db1e95cc3e32c85e737e02a7916fb + md5: 71c2caaa13f50fe0ebad0f961aee8073 + depends: + - __osx >=10.13 + - libffi >=3.5.2,<3.6.0a0 + - pycparser + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + size: 293633 + timestamp: 1761203106369 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/cffi-1.16.0-py310hdcd7c05_0.conda + sha256: 4edab3f1f855554e10950efe064b75138943812af829a764f9b570d1a7189d15 + md5: 8855823d908004e4d3b4fd4218795ad2 + depends: + - libffi >=3.4,<4.0a0 + - pycparser + - python >=3.10,<3.11.0a0 + - python >=3.10,<3.11.0a0 *_cpython + - python_abi 3.10.* *_cp310 + license: MIT + license_family: MIT + purls: + - pkg:pypi/cffi?source=hash-mapping + size: 232227 + timestamp: 1696002085787 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/cffi-1.16.0-py311h4a08483_0.conda + sha256: 9430416328fe2a28e206e703de771817064c8613a79a6a21fe7107f6a783104c + md5: cbdde0484a47b40e6ce2a4e5aaeb48d7 + depends: + - libffi >=3.4,<4.0a0 + - pycparser + - python >=3.11,<3.12.0a0 + - python >=3.11,<3.12.0a0 *_cpython + - python_abi 3.11.* *_cp311 + license: MIT + license_family: MIT + purls: + - pkg:pypi/cffi?source=hash-mapping + size: 292511 + timestamp: 1696002194472 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/cffi-2.0.0-py314h44086f9_1.conda + sha256: 5b5ee5de01eb4e4fd2576add5ec9edfc654fbaf9293e7b7ad2f893a67780aa98 + md5: 10dd19e4c797b8f8bdb1ec1fbb6821d7 + depends: + - __osx >=11.0 + - libffi >=3.5.2,<3.6.0a0 + - pycparser + - python >=3.14,<3.15.0a0 + - python >=3.14,<3.15.0a0 *_cp314 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + size: 292983 + timestamp: 1761203354051 +- conda: https://conda.anaconda.org/conda-forge/win-64/cffi-2.0.0-py310h29418f3_1.conda + sha256: abd04b75ee9a04a2f00dc102b4dc126f393fde58536ca4eaf1a72bb7d60dadf4 + md5: 269ba3d69bf6569296a29425a26400df + depends: + - pycparser + - python >=3.10,<3.11.0a0 + - python_abi 3.10.* *_cp310 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: MIT + license_family: MIT + purls: + - pkg:pypi/cffi?source=hash-mapping + size: 239862 + timestamp: 1761203282977 +- conda: https://conda.anaconda.org/conda-forge/win-64/cffi-2.0.0-py311h3485c13_1.conda + sha256: c9caca6098e3d92b1a269159b759d757518f2c477fbbb5949cb9fee28807c1f1 + md5: f02335db0282d5077df5bc84684f7ff9 + depends: + - pycparser + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: MIT + license_family: MIT + purls: + - pkg:pypi/cffi?source=hash-mapping + size: 297941 + timestamp: 1761203850323 +- conda: https://conda.anaconda.org/conda-forge/win-64/cffi-2.0.0-py314h5a2d7ad_1.conda + sha256: 924f2f01fa7a62401145ef35ab6fc95f323b7418b2644a87fea0ea68048880ed + md5: c360170be1c9183654a240aadbedad94 + depends: + - pycparser + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: MIT + license_family: MIT + size: 294731 + timestamp: 1761203441365 +- conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.5-pyhd8ed1ab_0.conda + sha256: 05ea76a016c77839b64f9f8ec581775f6c8a259044bd5b45a177e46ab4e7feac + md5: beb628209b2b354b98203066f90b3287 + depends: + - python >=3.10 + license: MIT + license_family: MIT + purls: + - pkg:pypi/charset-normalizer?source=compressed-mapping + size: 53210 + timestamp: 1772816516728 +- conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.6-pyhd8ed1ab_0.conda + sha256: d86dfd428b2e3c364fa90e07437c8405d635aa4ef54b25ab51d9c712be4112a5 + md5: 49ee13eb9b8f44d63879c69b8a40a74b + depends: + - python >=3.10 + license: MIT + license_family: MIT + purls: + - pkg:pypi/charset-normalizer?source=compressed-mapping + size: 58510 + timestamp: 1773660086450 +- conda: https://conda.anaconda.org/conda-forge/osx-64/clang-18.1.3-default_h7151d67_0.conda + sha256: 12fbd85852e6a55612d33e8beb4bfe19b6b9b64b44e97753f5c8a2a42decb64a + md5: 1160f27e680531f1ef4f32517238a7f5 + depends: + - clang-18 18.1.3 default_h7151d67_0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + purls: [] + size: 22898 + timestamp: 1712569254288 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-18.1.3-default_h4cf2255_0.conda + sha256: 613f4c4773f1dd274d2682a9170d52cb466f437a47ebcad2c2634c3b37aeb73f + md5: efbaa3d968b1dcacba9eb980d1ab66f4 + depends: + - clang-18 18.1.3 default_he012953_0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + purls: [] + size: 22913 + timestamp: 1712569692457 +- conda: https://conda.anaconda.org/conda-forge/osx-64/clang-18-18.1.3-default_h7151d67_0.conda + sha256: 41a929a017ef2b1b3c5066ddde16c0e68b5fc15a0de49d61cdf414fc13d09336 + md5: 76cf851fa13b7f48939befb147cc78eb + depends: + - libclang-cpp18.1 18.1.3 default_h7151d67_0 + - libcxx >=16.0.6 + - libllvm18 >=18.1.3,<18.2.0a0 + constrains: + - clangxx 18.1.3 + - llvm-tools 18.1.3 + - clang-tools 18.1.3 + - clangdev 18.1.3 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + purls: [] + size: 760437 + timestamp: 1712569132861 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-18-18.1.3-default_he012953_0.conda + sha256: edb5c1e2ffc7704b0e0bce0f5315eb1aba8fd9710e61bcbdeb40e340720123c6 + md5: 931dd6124b399ae12172f235f5ace407 + depends: + - libclang-cpp18.1 18.1.3 default_he012953_0 + - libcxx >=16.0.6 + - libllvm18 >=18.1.3,<18.2.0a0 + constrains: + - clang-tools 18.1.3 + - clangxx 18.1.3 + - llvm-tools 18.1.3 + - clangdev 18.1.3 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + purls: [] + size: 754206 + timestamp: 1712569562918 +- conda: https://conda.anaconda.org/conda-forge/osx-64/clang_impl_osx-64-18.1.3-hdbcc6ac_11.conda + sha256: cfa641fb177fc1a75c5e2d9f941ad6576f5786a254d5af265e5b548ebaea29d0 + md5: f895cb5eeb844bc8b2dd9147ec07896b + depends: + - cctools_osx-64 + - clang 18.1.3.* + - compiler-rt 18.1.3.* + - ld64_osx-64 + - llvm-tools 18.1.3.* + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 17413 + timestamp: 1712621383914 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang_impl_osx-arm64-18.1.3-hda94301_11.conda + sha256: f00e3930fa341ad5fa87a90f297b385a949bf2ee100a3a2cc2a135629fde6d7e + md5: 90e54a957e833f7cd2412b6d2e1d84fa + depends: + - cctools_osx-arm64 + - clang 18.1.3.* + - compiler-rt 18.1.3.* + - ld64_osx-arm64 + - llvm-tools 18.1.3.* + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 17571 + timestamp: 1712621386541 +- conda: https://conda.anaconda.org/conda-forge/osx-64/clang_osx-64-18.1.3-hb91bd55_11.conda + sha256: 94f9471f5b5b14a229cc44d65c01d383f79de179830b03045fc864f6489550f3 + md5: b0acbcfd68b99fe852942eea93a0f36d + depends: + - clang_impl_osx-64 18.1.3 hdbcc6ac_11 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 20494 + timestamp: 1712621391590 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang_osx-arm64-18.1.3-h54d7cd3_11.conda + sha256: 595cbec0f835ba16ad551315079193d16fc7f3a4e136aa1045ab9104cac79bf7 + md5: 7bdafeb8d61d59551df2417995bc3d46 + depends: + - clang_impl_osx-arm64 18.1.3 hda94301_11 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 20490 + timestamp: 1712621394350 +- conda: https://conda.anaconda.org/conda-forge/osx-64/clangxx-18.1.3-default_h7151d67_0.conda + sha256: 53d34a151f47971f55425154423b470273fb2c51e1c0a4ddb261aaa6502a7d50 + md5: 323c1678ff1cf1b8d05981eb2906f45e + depends: + - clang 18.1.3 default_h7151d67_0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + purls: [] + size: 22972 + timestamp: 1712569279378 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/clangxx-18.1.3-default_h4cf2255_0.conda + sha256: 1f9c1605d4f74b1d5df7d44676a5a6c53d542fc8c44d94fcc1d4d1977cede661 + md5: fd98656c5b62774633c84c41f42bdd6d + depends: + - clang 18.1.3 default_h4cf2255_0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + purls: [] + size: 22939 + timestamp: 1712569715149 +- conda: https://conda.anaconda.org/conda-forge/osx-64/clangxx_impl_osx-64-18.1.3-h5bc21ce_11.conda + sha256: 89fe02a10de21dc553ff79296ef322536b692e50382e248c8625f07dba6176c2 + md5: 1e203622262bd949727467d61e819184 + depends: + - clang_osx-64 18.1.3 hb91bd55_11 + - clangxx 18.1.3.* + - libcxx >=16 + - libllvm18 >=18.1.3,<18.2.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 17496 + timestamp: 1712621429065 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/clangxx_impl_osx-arm64-18.1.3-h1ba0cb9_11.conda + sha256: 91c6d2a6d9555110d6710d3766eb724dfdeed17b23a7965649523675d2251fce + md5: 5c29e4473f07af49ced6984531048fa4 + depends: + - clang_osx-arm64 18.1.3 h54d7cd3_11 + - clangxx 18.1.3.* + - libcxx >=16 + - libllvm18 >=18.1.3,<18.2.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 17636 + timestamp: 1712621421262 +- conda: https://conda.anaconda.org/conda-forge/osx-64/clangxx_osx-64-18.1.3-hb91bd55_11.conda + sha256: fa2acbc8c9575951a523e1f2dc16bd82d22386fbd312dbe05559bed2be94f306 + md5: 5c514320afcbaef94ab371abd3995bfb + depends: + - clang_osx-64 18.1.3 hb91bd55_11 + - clangxx_impl_osx-64 18.1.3 h5bc21ce_11 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 19255 + timestamp: 1712621436405 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/clangxx_osx-arm64-18.1.3-h54d7cd3_11.conda + sha256: c92c008817c2e25409b1328e580798855d082b504b39d8f42b21791da215c9f6 + md5: 3b5c8fe78441bc034aceadfa80dae7cc + depends: + - clang_osx-arm64 18.1.3 h54d7cd3_11 + - clangxx_impl_osx-arm64 18.1.3 h1ba0cb9_11 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 19244 + timestamp: 1712621431069 +- conda: https://conda.anaconda.org/conda-forge/linux-64/cmake-3.31.8-hc85cc9f_0.conda + sha256: 10660ed21b9d591f8306028bd36212467b94f23bc2f78faec76524f6ee592613 + md5: 057e16a12847eea846ecf99710d3591b + depends: + - __glibc >=2.17,<3.0.a0 + - bzip2 >=1.0.8,<2.0a0 + - libcurl >=8.14.1,<9.0a0 + - libexpat >=2.7.1,<3.0a0 + - libgcc >=14 + - liblzma >=5.8.1,<6.0a0 + - libstdcxx >=14 + - libuv >=1.51.0,<2.0a0 + - libzlib >=1.3.1,<2.0a0 + - ncurses >=6.5,<7.0a0 + - rhash >=1.4.6,<2.0a0 + - zstd >=1.5.7,<1.6.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 20991288 + timestamp: 1757877168657 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cmake-3.31.8-hc9d863e_0.conda + sha256: 91cbfd13132b7253a6ef001292f5cf59deac38d2cbc86d6c1ad6ebf344cd998c + md5: 855e698fd08794a573cd6104be8da4d0 + depends: + - bzip2 >=1.0.8,<2.0a0 + - libcurl >=8.14.1,<9.0a0 + - libexpat >=2.7.1,<3.0a0 + - libgcc >=14 + - liblzma >=5.8.1,<6.0a0 + - libstdcxx >=14 + - libuv >=1.51.0,<2.0a0 + - libzlib >=1.3.1,<2.0a0 + - ncurses >=6.5,<7.0a0 + - rhash >=1.4.6,<2.0a0 + - zstd >=1.5.7,<1.6.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 20216587 + timestamp: 1757877248575 +- conda: https://conda.anaconda.org/conda-forge/osx-64/cmake-3.27.6-hf40c264_0.conda + sha256: 9216698f88b82e99db950f8c372038931c54ea3e0b0b05e2a3ce03ec4b405df7 + md5: 771da6a52aaf0f9d84114d0ed0d0299f + depends: + - bzip2 >=1.0.8,<2.0a0 + - libcurl >=8.3.0,<9.0a0 + - libcxx >=15.0.7 + - libexpat >=2.5.0,<3.0a0 + - libuv >=1.46.0,<2.0a0 + - libzlib >=1.2.13,<2.0.0a0 + - ncurses >=6.4,<7.0a0 + - rhash >=1.4.4,<2.0a0 + - xz >=5.2.6,<6.0a0 + - zstd >=1.5.5,<1.6.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 16525734 + timestamp: 1695270838345 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/cmake-3.27.6-h1c59155_0.conda + sha256: 31be31e358e6f6f8818d8f9c9086da4404f8c6fc89d71d55887bed11ce6d463e + md5: 3c0dd04401438fec44cd113247ba2852 + depends: + - bzip2 >=1.0.8,<2.0a0 + - libcurl >=8.3.0,<9.0a0 + - libcxx >=15.0.7 + - libexpat >=2.5.0,<3.0a0 + - libuv >=1.46.0,<2.0a0 + - libzlib >=1.2.13,<2.0.0a0 + - ncurses >=6.4,<7.0a0 + - rhash >=1.4.4,<2.0a0 + - xz >=5.2.6,<6.0a0 + - zstd >=1.5.5,<1.6.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 16007289 + timestamp: 1695270816826 +- conda: https://conda.anaconda.org/conda-forge/win-64/cmake-3.31.8-hdcbee5b_0.conda + sha256: 074400a63931d8d571b2b2284bc5f105fd578c381847b05d5e3d0b03c3db8f69 + md5: 96afa0e05c4a683b1c3de91b0259b235 + depends: + - bzip2 >=1.0.8,<2.0a0 + - libcurl >=8.14.1,<9.0a0 + - libexpat >=2.7.1,<3.0a0 + - liblzma >=5.8.1,<6.0a0 + - libuv >=1.51.0,<2.0a0 + - libzlib >=1.3.1,<2.0a0 + - ucrt >=10.0.20348.0 + - vc14_runtime >=14.44.35208 + - zstd >=1.5.7,<1.6.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 14669008 + timestamp: 1757878123930 +- conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda + sha256: ab29d57dc70786c1269633ba3dff20288b81664d3ff8d21af995742e2bb03287 + md5: 962b9857ee8e7018c22f2776ffa0b2d7 + depends: + - python >=3.9 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/colorama?source=hash-mapping + size: 27011 + timestamp: 1733218222191 +- conda: https://conda.anaconda.org/conda-forge/osx-64/compiler-rt-18.1.3-ha38d28d_0.conda + sha256: 623f4a180fdb58c5480ea8e724162a57c5955b2f6ecc938a8314bf853dda4b60 + md5: 7a828727c9afa54e7a773e734f628a88 + depends: + - clang 18.1.3.* + - clangxx 18.1.3.* + - compiler-rt_osx-64 18.1.3.* + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + purls: [] + size: 96452 + timestamp: 1712580504480 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/compiler-rt-18.1.3-h3808999_0.conda + sha256: dfada604649fb2cfa6fb3dbd657fccf81cd01e00a7f6f29da24fc40e36cd51fa + md5: 09f614cf0dc4ea2b249c2e522b337730 + depends: + - clang 18.1.3.* + - clangxx 18.1.3.* + - compiler-rt_osx-arm64 18.1.3.* + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + purls: [] + size: 96152 + timestamp: 1712580507858 +- conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt_osx-64-18.1.3-ha38d28d_0.conda + sha256: 4084d02399a9176a7a8bdccc530142b429846c166a1a0d65d15a0b7de465e7bb + md5: 678d71ebac649fc7324026e05930bf4c + depends: + - clang 18.1.3.* + - clangxx 18.1.3.* + constrains: + - compiler-rt 18.1.3 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + purls: [] + size: 10367732 + timestamp: 1712580438913 +- conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt_osx-arm64-18.1.3-h3808999_0.conda + sha256: 4bbe97d77ae12edd5c0206d014e0473ae8c4fcacbc1e1b21e8e92fd694608301 + md5: 78c11131b59e53aedcf7854956a9347c + depends: + - clang 18.1.3.* + - clangxx 18.1.3.* + constrains: + - compiler-rt 18.1.3 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + purls: [] + size: 10165573 + timestamp: 1712580450851 +- conda: https://conda.anaconda.org/conda-forge/linux-64/conda-26.1.1-py310hff52083_0.conda + sha256: 38b5e5057fe3a69ea82125874f4653cfda2d5ca764a9a0bb8084e1ea3c53a661 + md5: fdd3d2814d732e0d878fc7d4a2289f7f + depends: + - archspec >=0.2.3 + - boltons >=23.0.0 + - charset-normalizer + - conda-libmamba-solver >=25.4.0 + - conda-package-handling >=2.2.0 + - distro >=1.5.0 + - frozendict >=2.4.2 + - jsonpatch >=1.32 + - menuinst >=2 + - packaging >=23.0 + - platformdirs >=3.10.0 + - pluggy >=1.0.0 + - pycosat >=0.6.3 + - python >=3.10,<3.11.0a0 + - python_abi 3.10.* *_cp310 + - requests >=2.28.0,<3 + - ruamel.yaml >=0.11.14,<0.19 + - setuptools >=60.0.0 + - tqdm >=4 + - truststore >=0.8.0 + - zstandard >=0.19.0 + constrains: + - conda-env >=2.6 + - conda-content-trust >=0.1.1 + - conda-build >=25.9 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/conda?source=hash-mapping + size: 999473 + timestamp: 1772191385548 +- conda: https://conda.anaconda.org/conda-forge/linux-64/conda-26.1.1-py311h38be061_0.conda + sha256: 9cd790637fcab45938ad49753d15b0cfbe847f9f0d4a1b7213d30b6fb412fede + md5: 52f7c28c287da1a28cb9cabda1f5d0cf + depends: + - archspec >=0.2.3 + - boltons >=23.0.0 + - charset-normalizer + - conda-libmamba-solver >=25.4.0 + - conda-package-handling >=2.2.0 + - distro >=1.5.0 + - frozendict >=2.4.2 + - jsonpatch >=1.32 + - menuinst >=2 + - packaging >=23.0 + - platformdirs >=3.10.0 + - pluggy >=1.0.0 + - pycosat >=0.6.3 + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + - requests >=2.28.0,<3 + - ruamel.yaml >=0.11.14,<0.19 + - setuptools >=60.0.0 + - tqdm >=4 + - truststore >=0.8.0 + - zstandard >=0.19.0 + constrains: + - conda-env >=2.6 + - conda-build >=25.9 + - conda-content-trust >=0.1.1 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/conda?source=compressed-mapping + size: 1286583 + timestamp: 1772191375962 +- conda: https://conda.anaconda.org/conda-forge/linux-64/conda-26.1.1-py314hdafbbf9_0.conda + sha256: 287ebc90f9659755cf626e1dd1d405690bef16e805942b4a3d8008e2376ff8bf + md5: c1c5e3d6e85f5fe5a47789d7a10b140f + depends: + - archspec >=0.2.3 + - boltons >=23.0.0 + - charset-normalizer + - conda-libmamba-solver >=25.4.0 + - conda-package-handling >=2.2.0 + - distro >=1.5.0 + - frozendict >=2.4.2 + - jsonpatch >=1.32 + - menuinst >=2 + - packaging >=23.0 + - platformdirs >=3.10.0 + - pluggy >=1.0.0 + - pycosat >=0.6.3 + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + - requests >=2.28.0,<3 + - ruamel.yaml >=0.11.14,<0.19 + - setuptools >=60.0.0 + - tqdm >=4 + - truststore >=0.8.0 + - zstandard >=0.19.0 + constrains: + - conda-build >=25.9 + - conda-env >=2.6 + - conda-content-trust >=0.1.1 + license: BSD-3-Clause + license_family: BSD + size: 1307275 + timestamp: 1772191378974 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/conda-26.1.1-py310h4c7bcd0_0.conda + sha256: 87aed41c4a995f4939816fce5c3555d66ad9551707fc117f3dde3884629c5b3a + md5: 42e348e1bb733f0095fa1ded7e1cfb00 + depends: + - archspec >=0.2.3 + - boltons >=23.0.0 + - charset-normalizer + - conda-libmamba-solver >=25.4.0 + - conda-package-handling >=2.2.0 + - distro >=1.5.0 + - frozendict >=2.4.2 + - jsonpatch >=1.32 + - menuinst >=2 + - packaging >=23.0 + - platformdirs >=3.10.0 + - pluggy >=1.0.0 + - pycosat >=0.6.3 + - python >=3.10,<3.11.0a0 + - python >=3.10,<3.11.0a0 *_cpython + - python_abi 3.10.* *_cp310 + - requests >=2.28.0,<3 + - ruamel.yaml >=0.11.14,<0.19 + - setuptools >=60.0.0 + - tqdm >=4 + - truststore >=0.8.0 + - zstandard >=0.19.0 + constrains: + - conda-env >=2.6 + - conda-content-trust >=0.1.1 + - conda-build >=25.9 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/conda?source=hash-mapping + size: 1001496 + timestamp: 1772191435996 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/conda-26.1.1-py311hec3470c_0.conda + sha256: 6c0920b4eaf5c13201c05c7de3080289468a1281ad9eb14719635815acf44523 + md5: 2d434ed94247068c4cc439c22d51b693 + depends: + - archspec >=0.2.3 + - boltons >=23.0.0 + - charset-normalizer + - conda-libmamba-solver >=25.4.0 + - conda-package-handling >=2.2.0 + - distro >=1.5.0 + - frozendict >=2.4.2 + - jsonpatch >=1.32 + - menuinst >=2 + - packaging >=23.0 + - platformdirs >=3.10.0 + - pluggy >=1.0.0 + - pycosat >=0.6.3 + - python >=3.11,<3.12.0a0 + - python >=3.11,<3.12.0a0 *_cpython + - python_abi 3.11.* *_cp311 + - requests >=2.28.0,<3 + - ruamel.yaml >=0.11.14,<0.19 + - setuptools >=60.0.0 + - tqdm >=4 + - truststore >=0.8.0 + - zstandard >=0.19.0 + constrains: + - conda-env >=2.6 + - conda-build >=25.9 + - conda-content-trust >=0.1.1 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/conda?source=hash-mapping + size: 1288665 + timestamp: 1772191444841 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/conda-26.1.1-py314h28a4750_0.conda + sha256: 694fdd47a58ea57163ca5bb64bbe1332d413644f3a2cfa9ea515828aa98b73ab + md5: d511b5ac95faec60409f48c00a6d8f06 + depends: + - archspec >=0.2.3 + - boltons >=23.0.0 + - charset-normalizer + - conda-libmamba-solver >=25.4.0 + - conda-package-handling >=2.2.0 + - distro >=1.5.0 + - frozendict >=2.4.2 + - jsonpatch >=1.32 + - menuinst >=2 + - packaging >=23.0 + - platformdirs >=3.10.0 + - pluggy >=1.0.0 + - pycosat >=0.6.3 + - python >=3.14,<3.15.0a0 + - python >=3.14,<3.15.0a0 *_cp314 + - python_abi 3.14.* *_cp314 + - requests >=2.28.0,<3 + - ruamel.yaml >=0.11.14,<0.19 + - setuptools >=60.0.0 + - tqdm >=4 + - truststore >=0.8.0 + - zstandard >=0.19.0 + constrains: + - conda-build >=25.9 + - conda-content-trust >=0.1.1 + - conda-env >=2.6 + license: BSD-3-Clause + license_family: BSD + size: 1311034 + timestamp: 1772191450615 +- conda: https://conda.anaconda.org/conda-forge/osx-64/conda-23.9.0-py310h2ec42d9_2.conda + sha256: 743fb814fa36fc2bfb976d258fc0854ceb6cb2552cf2bc8a6ab7407c8aed0dff + md5: 478a4d7f1b36bbf317b41027e2bc5d9d + depends: + - archspec + - boltons >=23.0.0 + - conda-package-handling >=2.2.0 + - jsonpatch >=1.32 + - packaging >=23.0 + - pluggy >=1.0.0 + - pycosat >=0.6.3 + - pyopenssl >=16.2.0 + - python >=3.10,<3.11.0a0 + - python_abi 3.10.* *_cp310 + - requests >=2.27.0,<3 + - ruamel.yaml >=0.11.14,<0.18 + - setuptools >=60.0.0 + - tqdm >=4 + - truststore >=0.8.0 + constrains: + - conda-env >=2.6 + - conda-content-trust >=0.1.1 + - conda-libmamba-solver >=23.7.0 + - conda-build >=3 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/conda?source=hash-mapping + size: 970554 + timestamp: 1698451059802 +- conda: https://conda.anaconda.org/conda-forge/osx-64/conda-23.9.0-py311h6eed73b_2.conda + sha256: 894332c6be0df4be919dadd33dc9bf365e9851db3a6c65b5331986d6277296f4 + md5: 8f27c249b5c0a2185f18250120613565 + depends: + - archspec + - boltons >=23.0.0 + - conda-package-handling >=2.2.0 + - jsonpatch >=1.32 + - packaging >=23.0 + - pluggy >=1.0.0 + - pycosat >=0.6.3 + - pyopenssl >=16.2.0 + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + - requests >=2.27.0,<3 + - ruamel.yaml >=0.11.14,<0.18 + - setuptools >=60.0.0 + - tqdm >=4 + - truststore >=0.8.0 + constrains: + - conda-libmamba-solver >=23.7.0 + - conda-build >=3 + - conda-env >=2.6 + - conda-content-trust >=0.1.1 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/conda?source=hash-mapping + size: 1264324 + timestamp: 1698451045537 +- conda: https://conda.anaconda.org/conda-forge/osx-64/conda-26.1.1-py314hee6578b_0.conda + sha256: 30f3fda3b376079a273a6a73dc510fdc663c77ba4fa696f82a48545476eb8014 + md5: fa5b5fd3010a1bfcf558901f3ee09b9e + depends: + - archspec >=0.2.3 + - boltons >=23.0.0 + - charset-normalizer + - conda-libmamba-solver >=25.4.0 + - conda-package-handling >=2.2.0 + - distro >=1.5.0 + - frozendict >=2.4.2 + - jsonpatch >=1.32 + - menuinst >=2 + - packaging >=23.0 + - platformdirs >=3.10.0 + - pluggy >=1.0.0 + - pycosat >=0.6.3 + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + - requests >=2.28.0,<3 + - ruamel.yaml >=0.11.14,<0.19 + - setuptools >=60.0.0 + - tqdm >=4 + - truststore >=0.8.0 + - zstandard >=0.19.0 + constrains: + - conda-content-trust >=0.1.1 + - conda-build >=25.9 + - conda-env >=2.6 + license: BSD-3-Clause + license_family: BSD + size: 1310551 + timestamp: 1772191748761 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/conda-23.9.0-py310hbe9552e_2.conda + sha256: 58834d003f2dfef45ccd8421adb0bdc4228542223563aa8681f3563c026fb005 + md5: 629fd52fcd8e0559573559a6b008ce0e + depends: + - archspec + - boltons >=23.0.0 + - conda-package-handling >=2.2.0 + - jsonpatch >=1.32 + - packaging >=23.0 + - pluggy >=1.0.0 + - pycosat >=0.6.3 + - pyopenssl >=16.2.0 + - python >=3.10,<3.11.0a0 + - python >=3.10,<3.11.0a0 *_cpython + - python_abi 3.10.* *_cp310 + - requests >=2.27.0,<3 + - ruamel.yaml >=0.11.14,<0.18 + - setuptools >=60.0.0 + - tqdm >=4 + - truststore >=0.8.0 + constrains: + - conda-content-trust >=0.1.1 + - conda-libmamba-solver >=23.7.0 + - conda-env >=2.6 + - conda-build >=3 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/conda?source=hash-mapping + size: 970987 + timestamp: 1698451243924 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/conda-23.9.0-py311h267d04e_2.conda + sha256: 700460cbbf01e9b37b375a62f25e195583964dd87720755d0bad43913c30d928 + md5: f03a4e5f471e82036ebc4b5db54abc9d + depends: + - archspec + - boltons >=23.0.0 + - conda-package-handling >=2.2.0 + - jsonpatch >=1.32 + - packaging >=23.0 + - pluggy >=1.0.0 + - pycosat >=0.6.3 + - pyopenssl >=16.2.0 + - python >=3.11,<3.12.0a0 + - python >=3.11,<3.12.0a0 *_cpython + - python_abi 3.11.* *_cp311 + - requests >=2.27.0,<3 + - ruamel.yaml >=0.11.14,<0.18 + - setuptools >=60.0.0 + - tqdm >=4 + - truststore >=0.8.0 + constrains: + - conda-content-trust >=0.1.1 + - conda-env >=2.6 + - conda-libmamba-solver >=23.7.0 + - conda-build >=3 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/conda?source=hash-mapping + size: 1261327 + timestamp: 1698451125796 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/conda-26.1.1-py314h4dc9dd8_0.conda + sha256: e07221f4bda014e492e9a8e99dc5ec307147afd44483346e58eaec6770f10865 + md5: 29a62536271a0869f2d0ecb04e834634 + depends: + - archspec >=0.2.3 + - boltons >=23.0.0 + - charset-normalizer + - conda-libmamba-solver >=25.4.0 + - conda-package-handling >=2.2.0 + - distro >=1.5.0 + - frozendict >=2.4.2 + - jsonpatch >=1.32 + - menuinst >=2 + - packaging >=23.0 + - platformdirs >=3.10.0 + - pluggy >=1.0.0 + - pycosat >=0.6.3 + - python >=3.14,<3.15.0a0 + - python >=3.14,<3.15.0a0 *_cp314 + - python_abi 3.14.* *_cp314 + - requests >=2.28.0,<3 + - ruamel.yaml >=0.11.14,<0.19 + - setuptools >=60.0.0 + - tqdm >=4 + - truststore >=0.8.0 + - zstandard >=0.19.0 + constrains: + - conda-content-trust >=0.1.1 + - conda-build >=25.9 + - conda-env >=2.6 + license: BSD-3-Clause + license_family: BSD + size: 1310581 + timestamp: 1772191962239 +- conda: https://conda.anaconda.org/conda-forge/win-64/conda-26.1.1-py310h5588dad_0.conda + sha256: b46279535611a3082d932c0aa5d6e13e2a56bb021a55370879692126a388b8e5 + md5: 1e3fa316ac3da6d31d703ca70c8bbf47 + depends: + - archspec >=0.2.3 + - boltons >=23.0.0 + - charset-normalizer + - conda-libmamba-solver >=25.4.0 + - conda-package-handling >=2.2.0 + - distro >=1.5.0 + - frozendict >=2.4.2 + - jsonpatch >=1.32 + - menuinst >=2 + - packaging >=23.0 + - platformdirs >=3.10.0 + - pluggy >=1.0.0 + - pycosat >=0.6.3 + - python >=3.10,<3.11.0a0 + - python_abi 3.10.* *_cp310 + - requests >=2.28.0,<3 + - ruamel.yaml >=0.11.14,<0.19 + - setuptools >=60.0.0 + - tqdm >=4 + - truststore >=0.8.0 + - zstandard >=0.19.0 + constrains: + - conda-content-trust >=0.1.1 + - conda-build >=25.9 + - conda-env >=2.6 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/conda?source=hash-mapping + size: 1002216 + timestamp: 1772191581878 +- conda: https://conda.anaconda.org/conda-forge/win-64/conda-26.1.1-py311h1ea47a8_0.conda + sha256: a2d7a3b3b48bf15bb705a6b6dce061e0ee05275159fbe105acea30be989d13cd + md5: 07554fc0615396c760ca7bebd6a3797c + depends: + - archspec >=0.2.3 + - boltons >=23.0.0 + - charset-normalizer + - conda-libmamba-solver >=25.4.0 + - conda-package-handling >=2.2.0 + - distro >=1.5.0 + - frozendict >=2.4.2 + - jsonpatch >=1.32 + - menuinst >=2 + - packaging >=23.0 + - platformdirs >=3.10.0 + - pluggy >=1.0.0 + - pycosat >=0.6.3 + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + - requests >=2.28.0,<3 + - ruamel.yaml >=0.11.14,<0.19 + - setuptools >=60.0.0 + - tqdm >=4 + - truststore >=0.8.0 + - zstandard >=0.19.0 + constrains: + - conda-env >=2.6 + - conda-build >=25.9 + - conda-content-trust >=0.1.1 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/conda?source=hash-mapping + size: 1287539 + timestamp: 1772191674230 +- conda: https://conda.anaconda.org/conda-forge/win-64/conda-26.1.1-py314h86ab7b2_0.conda + sha256: 1b6770ef97301830842c57ad0c18ad25858c0d62e2a1b1248d9b37fb1ce3eaf6 + md5: 2ce9348410797986e1c59939d6162826 + depends: + - archspec >=0.2.3 + - boltons >=23.0.0 + - charset-normalizer + - conda-libmamba-solver >=25.4.0 + - conda-package-handling >=2.2.0 + - distro >=1.5.0 + - frozendict >=2.4.2 + - jsonpatch >=1.32 + - menuinst >=2 + - packaging >=23.0 + - platformdirs >=3.10.0 + - pluggy >=1.0.0 + - pycosat >=0.6.3 + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + - requests >=2.28.0,<3 + - ruamel.yaml >=0.11.14,<0.19 + - setuptools >=60.0.0 + - tqdm >=4 + - truststore >=0.8.0 + - zstandard >=0.19.0 + constrains: + - conda-env >=2.6 + - conda-content-trust >=0.1.1 + - conda-build >=25.9 + license: BSD-3-Clause + license_family: BSD + size: 1309098 + timestamp: 1772191684896 +- conda: https://conda.anaconda.org/conda-forge/linux-64/conda-gcc-specs-14.3.0-he8ccf15_18.conda + sha256: b90ec0e6a9eb22f7240b3584fe785457cff961fec68d40e6aece5d596f9bbd9a + md5: 0e3e144115c43c9150d18fa20db5f31c + depends: + - gcc_impl_linux-64 >=14.3.0,<14.3.1.0a0 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 31705 + timestamp: 1771378159534 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/conda-gcc-specs-14.3.0-hadff5d6_18.conda + sha256: 7b018e74d2f828e887faabc9d5c5bef6d432c3356dcac3e691ee6b24bc82ef52 + md5: 184c1aba41c40e6bc59fa91b37cd7c3f + depends: + - gcc_impl_linux-aarch64 >=14.3.0,<14.3.1.0a0 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 31474 + timestamp: 1771377963347 +- conda: https://conda.anaconda.org/conda-forge/noarch/conda-libmamba-solver-25.11.0-pyhd8ed1ab_1.conda + sha256: 001812b000c9791db53a85b0f215952b7497ca1fd6e3070314e20f707556765b + md5: 1d545b8b06123889395de8a3674fc0e7 + depends: + - boltons >=23.0.0 + - libmambapy >=2.0.0 + - msgpack-python >=1.1.1 + - python >=3.10 + - requests >=2.28.0,<3 + - zstandard >=0.15 + constrains: + - conda >=25.9 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/conda-libmamba-solver?source=hash-mapping + size: 56969 + timestamp: 1770137431666 +- conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-handling-2.4.0-pyh7900ff3_2.conda + sha256: 8b2b1c235b7cbfa8488ad88ff934bdad25bac6a4c035714681fbff85b602f3f0 + md5: 32c158f481b4fd7630c565030f7bc482 + depends: + - conda-package-streaming >=0.9.0 + - python >=3.9 + - requests + - zstandard >=0.15 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/conda-package-handling?source=hash-mapping + size: 257995 + timestamp: 1736345601691 +- conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-streaming-0.12.0-pyhd8ed1ab_0.conda + sha256: 11b76b0be2f629e8035be1d723ccb6e583eb0d2af93bde56113da7fa6e2f2649 + md5: ff75d06af779966a5aeae1be1d409b96 + depends: + - python >=3.9 + - zstandard >=0.15 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/conda-package-streaming?source=hash-mapping + size: 21933 + timestamp: 1751548225624 +- conda: https://conda.anaconda.org/conda-forge/linux-64/cpp-expected-1.3.1-h171cf75_0.conda + sha256: 0d9405d9f2de5d4b15d746609d87807aac10e269072d6408b769159762ed113d + md5: d17488e343e4c5c0bd0db18b3934d517 + depends: + - libstdcxx >=14 + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + license: CC0-1.0 + purls: [] + size: 24283 + timestamp: 1756734785482 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cpp-expected-1.3.1-hdc560ac_0.conda + sha256: 4edebca2a9dadd8afabb3948a007edae2072e4869d8959b3e51aebc2367e1df4 + md5: 13f0be21fdd39114c28501ac21f0dd00 + depends: + - libstdcxx >=14 + - libgcc >=14 + license: CC0-1.0 + purls: [] + size: 25132 + timestamp: 1756734793606 +- conda: https://conda.anaconda.org/conda-forge/osx-64/cpp-expected-1.3.1-h0ba0a54_0.conda + sha256: 3192481102b7ad011933620791355148c16fb29ab8e0dac657de5388c05f44e8 + md5: d788061f51b79dfcb6c1521507ca08c7 + depends: + - __osx >=10.13 + - libcxx >=19 + license: CC0-1.0 + size: 24618 + timestamp: 1756734941438 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/cpp-expected-1.3.1-h4f10f1e_0.conda + sha256: a7380056125a29ddc4c4efc4e39670bc8002609c70f143d92df801b42e0b486f + md5: 5cb4f9b93055faf7b6ae76da6123f927 + depends: + - __osx >=11.0 + - libcxx >=19 + license: CC0-1.0 + size: 24960 + timestamp: 1756734870487 +- conda: https://conda.anaconda.org/conda-forge/win-64/cpp-expected-1.3.1-h477610d_0.conda + sha256: cd24ac6768812d53c3b14c29b468cc9a5516b71e1880d67f58d98d9787f4cc3a + md5: 444e9f7d9b3f69006c3af5db59e11364 + depends: + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + license: CC0-1.0 + purls: [] + size: 21733 + timestamp: 1756734797622 +- conda: https://conda.anaconda.org/conda-forge/osx-64/cryptography-41.0.7-py310h527a09d_1.conda + sha256: cb43f44af3ff4ec8ffb1517234075d39e64442ec75ce995f1e9bd8b032a8aef0 + md5: e5291aa101f6590559177df876cd0955 + depends: + - cffi >=1.12 + - openssl >=3.1.4,<4.0a0 + - python >=3.10,<3.11.0a0 + - python_abi 3.10.* *_cp310 + license: Apache-2.0 AND BSD-3-Clause AND PSF-2.0 AND MIT + license_family: BSD + purls: + - pkg:pypi/cryptography?source=hash-mapping + size: 1218731 + timestamp: 1701563760923 +- conda: https://conda.anaconda.org/conda-forge/osx-64/cryptography-41.0.7-py311h48c7838_1.conda + sha256: f4c5e683386acf06cfa85805d264c9cd540361ec6e86740cb03312e560aa706a + md5: 65293feff96135571de02c047ecbd5a2 + depends: + - cffi >=1.12 + - openssl >=3.1.4,<4.0a0 + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + license: Apache-2.0 AND BSD-3-Clause AND PSF-2.0 AND MIT + license_family: BSD + purls: + - pkg:pypi/cryptography?source=hash-mapping + size: 1280957 + timestamp: 1701563770508 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/cryptography-41.0.7-py310h4c55245_1.conda + sha256: 85ce5e6db3093fea6bb45c28d783db002339cc56b578789d6141b136a4266a59 + md5: 9d2f02b43aaceb00fbe294ce9e9646c6 + depends: + - cffi >=1.12 + - openssl >=3.1.4,<4.0a0 + - python >=3.10,<3.11.0a0 + - python >=3.10,<3.11.0a0 *_cpython + - python_abi 3.10.* *_cp310 + license: Apache-2.0 AND BSD-3-Clause AND PSF-2.0 AND MIT + license_family: BSD + purls: + - pkg:pypi/cryptography?source=hash-mapping + size: 1200542 + timestamp: 1701563810375 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/cryptography-41.0.7-py311h08c85a6_1.conda + sha256: 9d51ba743069d19aae08361a7b051ca1f281fb3b3ccb162e96c2503cf5a7d365 + md5: 729546a91873db64ab8e675008845fb5 + depends: + - cffi >=1.12 + - openssl >=3.1.4,<4.0a0 + - python >=3.11,<3.12.0a0 + - python >=3.11,<3.12.0a0 *_cpython + - python_abi 3.11.* *_cp311 + license: Apache-2.0 AND BSD-3-Clause AND PSF-2.0 AND MIT + license_family: BSD + purls: + - pkg:pypi/cryptography?source=hash-mapping + size: 1263886 + timestamp: 1701563842828 +- conda: https://conda.anaconda.org/conda-forge/linux-64/cxx-compiler-1.11.0-hfcd1e18_0.conda + sha256: 3fcc97ae3e89c150401a50a4de58794ffc67b1ed0e1851468fcc376980201e25 + md5: 5da8c935dca9186673987f79cef0b2a5 + depends: + - c-compiler 1.11.0 h4d9bdce_0 + - gxx + - gxx_linux-64 14.* + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 6635 + timestamp: 1753098722177 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cxx-compiler-1.11.0-h7b35c40_0.conda + sha256: b87cd33501867d999caa1a57e488e69dc9e08011ec8685586df754302247a7a4 + md5: 0234c63e6b36b1677fd6c5238ef0a4ec + depends: + - c-compiler 1.11.0 hdceaead_0 + - gxx + - gxx_linux-aarch64 14.* + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 6705 + timestamp: 1753098688728 +- conda: https://conda.anaconda.org/conda-forge/osx-64/cxx-compiler-1.10.0-h20888b2_0.conda + sha256: 15f6ea7258555b2e34d147d378f4e8e08343ca3e71a18bd98b89a3dbc43142a2 + md5: b3a935ade707c54ebbea5f8a7c6f4549 + depends: + - c-compiler 1.10.0 h09a7c41_0 + - clangxx_osx-64 18.* + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 6785 + timestamp: 1751115659099 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/cxx-compiler-1.10.0-hba80287_0.conda + sha256: 52cbfc615a9727294fccdd507f11919ca01ff29bd928bb5aa0b211697a983e9f + md5: 7fca30a1585a85ec8ab63579afcac5d3 + depends: + - c-compiler 1.10.0 hdf49b6b_0 + - clangxx_osx-arm64 18.* + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 6784 + timestamp: 1751115541888 +- conda: https://conda.anaconda.org/conda-forge/win-64/cxx-compiler-1.11.0-h1c1089f_0.conda + sha256: c888f4fe9ec117c1c01bfaa4c722ca475ebbb341c92d1718afa088bb0d710619 + md5: 4d94d3c01add44dc9d24359edf447507 + depends: + - vs2022_win-64 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 6957 + timestamp: 1753098809481 +- pypi: https://files.pythonhosted.org/packages/2b/dd/437e601fa9d2b6bf8507256daf52196a226c3b340261f4cde8fac8e853ea/delocate-0.13.0-py3-none-any.whl + name: delocate + version: 0.13.0 + sha256: 11f7596f88984c33f76b27fe2eea7637d1ce369a9e0b6737bbc706b6426e862c + requires_dist: + - packaging>=20.9 + - typing-extensions>=4.12.2 + - macholib + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/89/74/bf0ea7b89e114af19a38c2341746fd1f17f1de23fa8d8019cbcd39719c5f/delvewheel-1.12.0-py3-none-any.whl + name: delvewheel + version: 1.12.0 + sha256: 659ef85a83e4503e037e65570f7a87d2ad4e0ee55dc2d19d9afed420a031caf0 + requires_dist: + - pefile>=2024.8.26 + requires_python: '>=3.9' +- conda: https://conda.anaconda.org/conda-forge/noarch/distro-1.9.0-pyhd8ed1ab_1.conda + sha256: 5603c7d0321963bb9b4030eadabc3fd7ca6103a38475b4e0ed13ed6d97c86f4e + md5: 0a2014fd9860f8b1eaa0b1f3d3771a08 + depends: + - python >=3.9 + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/distro?source=hash-mapping + size: 41773 + timestamp: 1734729953882 +- conda: https://conda.anaconda.org/conda-forge/linux-64/doxygen-1.13.2-h8e693c7_0.conda + sha256: 349c4c872357b4a533e127b2ade8533796e8e062abc2cd685756a1a063ae1e35 + md5: 0869f41ea5c64643dd2f5b47f32709ca + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + - libiconv >=1.17,<2.0a0 + - libstdcxx >=13 + license: GPL-2.0-only + license_family: GPL + purls: [] + size: 13148627 + timestamp: 1738164137421 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/doxygen-1.13.2-h5e0f5ae_0.conda + sha256: 671fc9849fcdb9138daf2ab6b2d45b0650055ba1496cda19c415f57cabc381b8 + md5: 9091aa1c92ed01d5fe3d34d7e585b6a1 + depends: + - libgcc >=13 + - libiconv >=1.17,<2.0a0 + - libstdcxx >=13 + license: GPL-2.0-only + license_family: GPL + purls: [] + size: 13227405 + timestamp: 1738171320483 +- conda: https://conda.anaconda.org/conda-forge/osx-64/doxygen-1.10.0-h5ff76d1_0.conda + sha256: c329a379f8bc8a66bb91527efca44fb17b35ccf6f1dd1efc6b439fafe9ff67d4 + md5: 4b0fd9ed5a22b919a04bc147f9d65654 + depends: + - libcxx >=15 + - libiconv >=1.17,<2.0a0 + license: GPL-2.0-only + license_family: GPL + purls: [] + size: 11525553 + timestamp: 1703609916595 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/doxygen-1.10.0-h8fbad5d_0.conda + sha256: d609f61b22cb7fc5441a5bf1e6ac989840977cc682e94d726fdcc74c6cd89ea2 + md5: 80aaa05136ea0b7cea754bb28488cc0f + depends: + - libcxx >=15 + - libiconv >=1.17,<2.0a0 + license: GPL-2.0-only + license_family: GPL + purls: [] + size: 10593614 + timestamp: 1703609902689 +- conda: https://conda.anaconda.org/conda-forge/win-64/doxygen-1.13.2-hbf3f430_0.conda + sha256: 7a0fd40fd704e97a8f6533a081ba29579766d7a60bcb8e5de76679b066c4a72e + md5: 5cb2e11931773612d7a24b53f0c57594 + depends: + - libiconv >=1.17,<2.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: GPL-2.0-only + license_family: GPL + purls: [] + size: 9219343 + timestamp: 1738165042524 +- conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda + sha256: ee6cf346d017d954255bbcbdb424cddea4d14e4ed7e9813e429db1d795d01144 + md5: 8e662bd460bda79b1ea39194e3c4c9ab + depends: + - python >=3.10 + - typing_extensions >=4.6.0 + license: MIT and PSF-2.0 + purls: + - pkg:pypi/exceptiongroup?source=hash-mapping + size: 21333 + timestamp: 1763918099466 +- conda: https://conda.anaconda.org/conda-forge/linux-64/fmt-12.1.0-hff5e90c_0.conda + sha256: d4e92ba7a7b4965341dc0fca57ec72d01d111b53c12d11396473115585a9ead6 + md5: f7d7a4104082b39e3b3473fbd4a38229 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libstdcxx >=14 + license: MIT + license_family: MIT + purls: [] + size: 198107 + timestamp: 1767681153946 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/fmt-12.1.0-h20c602a_0.conda + sha256: 7826619c80af5a5fb0c1f2a965c93f4b92670523e12ff45c592daa3f11340746 + md5: 067209b690c2d7f42e1e4c370d1aff12 + depends: + - libgcc >=14 + - libstdcxx >=14 + license: MIT + license_family: MIT + purls: [] + size: 197671 + timestamp: 1767681179883 +- conda: https://conda.anaconda.org/conda-forge/osx-64/fmt-12.1.0-hda137b5_0.conda + sha256: 3c56fc4b3528acb29d89d139f9800b86425e643be8d9caddd4d6f4a8b09a8db4 + md5: 265ec3c628a7e2324d86a08205ada7a8 + depends: + - __osx >=10.13 + - libcxx >=19 + license: MIT + license_family: MIT + size: 188352 + timestamp: 1767681462452 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/fmt-12.1.0-h403dcb5_0.conda + sha256: dba5d4a93dc62f20e4c2de813ccf7beefed1fb54313faff9c4f2383e4744c8e5 + md5: ae2f556fbb43e5a75cc80a47ac942a8e + depends: + - __osx >=11.0 + - libcxx >=19 + license: MIT + license_family: MIT + size: 180970 + timestamp: 1767681372955 +- conda: https://conda.anaconda.org/conda-forge/win-64/fmt-12.1.0-h7f4e812_0.conda + sha256: cce96406ec353692ab46cd9d992eddb6923979c1a342cbdba33521a7c234176f + md5: 6e226b58e18411571aaa57a16ad10831 + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: MIT + license_family: MIT + purls: [] + size: 186390 + timestamp: 1767681264793 +- conda: https://conda.anaconda.org/conda-forge/linux-64/frozendict-2.4.7-py310h7c4b9e2_0.conda + sha256: 584dd9b80818771700875465b2906a4a8cc1e766d802ce269a00d8622b92e522 + md5: 901de6f1f35f811f8d194785838a5977 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - python >=3.10,<3.11.0a0 + - python_abi 3.10.* *_cp310 + license: LGPL-3.0-only + license_family: LGPL + purls: + - pkg:pypi/frozendict?source=hash-mapping + size: 49924 + timestamp: 1763082943540 +- conda: https://conda.anaconda.org/conda-forge/linux-64/frozendict-2.4.7-py311h49ec1c0_0.conda + sha256: df99ccc63c065875cc150f451aaab03e6733898219cf2f248543fe53b08deff0 + md5: cfc74ea184e02e531732abb17778e9fc + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + license: LGPL-3.0-only + license_family: LGPL + purls: + - pkg:pypi/frozendict?source=hash-mapping + size: 32010 + timestamp: 1763082979695 +- conda: https://conda.anaconda.org/conda-forge/linux-64/frozendict-2.4.7-py314h5bd0f2a_0.conda + sha256: 3e04b8293122e923f1c66599525e8b0e743f532b5c53d932c41105311b721526 + md5: 7a884102c0e9fb57012a6f49259475fc + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + license: LGPL-3.0-only + license_family: LGPL + size: 31627 + timestamp: 1763082886391 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/frozendict-2.4.7-py310h5b55623_0.conda + sha256: bc856378ebcd12d761a9992cdb37719ea1dfed9c8b77e45951723aefbe8cd7da + md5: 31ee97292b96431bdafcc3af09c21550 + depends: + - libgcc >=14 + - python >=3.10,<3.11.0a0 + - python >=3.10,<3.11.0a0 *_cpython + - python_abi 3.10.* *_cp310 + license: LGPL-3.0-only + license_family: LGPL + purls: + - pkg:pypi/frozendict?source=hash-mapping + size: 51959 + timestamp: 1763082951492 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/frozendict-2.4.7-py311h19352d5_0.conda + sha256: 0951b89bc10e54b5e20c6bd8ef990e5afc155d13d713c45a525fe87f478980a6 + md5: 9ef6a694ecd981dad43ab8f1864bcf43 + depends: + - libgcc >=14 + - python >=3.11,<3.12.0a0 + - python >=3.11,<3.12.0a0 *_cpython + - python_abi 3.11.* *_cp311 + license: LGPL-3.0-only + license_family: LGPL + purls: + - pkg:pypi/frozendict?source=hash-mapping + size: 32258 + timestamp: 1763083003765 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/frozendict-2.4.7-py314h51f160d_0.conda + sha256: 669bfad0045393c79ad96fea1900d30d9c497cde6dd79ff6500be53245874c67 + md5: 723828d9832e586bf2f9c52c38d4bf01 + depends: + - libgcc >=14 + - python >=3.14,<3.15.0a0 + - python >=3.14,<3.15.0a0 *_cp314 + - python_abi 3.14.* *_cp314 + license: LGPL-3.0-only + license_family: LGPL + size: 31504 + timestamp: 1763082941890 +- conda: https://conda.anaconda.org/conda-forge/osx-64/frozendict-2.4.7-py314h6482030_0.conda + sha256: 5d0f185b622da1bd23beafb7e66dc14d3d1335f1c3e7eca91e731f2ded12800b + md5: d7ab51dbffe250c5570d766c44db6af0 + depends: + - __osx >=10.13 + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + license: LGPL-3.0-only + license_family: LGPL + size: 31842 + timestamp: 1763083176058 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/frozendict-2.4.7-py314h0612a62_0.conda + sha256: 614c604a4ff2ee59579d6ad6489726b56027bd49f50f4674cdaf98c6a0daa6be + md5: 8e7628502497ee2940f8864a22e3bd0c + depends: + - __osx >=11.0 + - python >=3.14,<3.15.0a0 + - python >=3.14,<3.15.0a0 *_cp314 + - python_abi 3.14.* *_cp314 + license: LGPL-3.0-only + license_family: LGPL + size: 32182 + timestamp: 1763083208667 +- conda: https://conda.anaconda.org/conda-forge/win-64/frozendict-2.4.7-py310h29418f3_0.conda + sha256: 0d07dddfc0fcaf7532b2d7b70619422116f95296d68d714686c32b3eb431c218 + md5: 76c23d3bc5ebfa998703241569ee7b7e + depends: + - python >=3.10,<3.11.0a0 + - python_abi 3.10.* *_cp310 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: LGPL-3.0-only + license_family: LGPL + purls: + - pkg:pypi/frozendict?source=hash-mapping + size: 47769 + timestamp: 1763083252959 +- conda: https://conda.anaconda.org/conda-forge/win-64/frozendict-2.4.7-py311h3485c13_0.conda + sha256: 2f719c3f15a54d02b5970075d013440eb9cc16503128cd9a8e97cb6275c57c82 + md5: b17cb83dcb04b06a3377c3ce8423bca9 + depends: + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: LGPL-3.0-only + license_family: LGPL + purls: + - pkg:pypi/frozendict?source=hash-mapping + size: 32227 + timestamp: 1763083050764 +- conda: https://conda.anaconda.org/conda-forge/win-64/frozendict-2.4.7-py314h5a2d7ad_0.conda + sha256: 87f206e4ac1ee9cc7099f3bbb05c039650b9a606bebb59c3778e5f2050795930 + md5: dbac0ebdc50febbb706fcd765227c90f + depends: + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: LGPL-3.0-only + license_family: LGPL + size: 32072 + timestamp: 1763082973024 +- conda: https://conda.anaconda.org/conda-forge/linux-64/gcc-14.3.0-h0dff253_18.conda + sha256: 9b34b57b06b485e33a40d430f71ac88c8f381673592507cf7161c50ff0832772 + md5: 52d6457abc42e320787ada5f9033fa99 + depends: + - conda-gcc-specs + - gcc_impl_linux-64 14.3.0 hbdf3cc3_18 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 29506 + timestamp: 1771378321585 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gcc-14.3.0-h2e72a27_18.conda + sha256: debc5c801b3af35f1d474aead8621c4869a022d35ca3c5195a9843d81c1c9ab4 + md5: db4bf1a70c2481c06fe8174390a325c0 + depends: + - conda-gcc-specs + - gcc_impl_linux-aarch64 14.3.0 h533bfc8_18 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 29438 + timestamp: 1771378102660 +- conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_impl_linux-64-14.3.0-hbdf3cc3_18.conda + sha256: 3b31a273b806c6851e16e9cf63ef87cae28d19be0df148433f3948e7da795592 + md5: 30bb690150536f622873758b0e8d6712 + depends: + - binutils_impl_linux-64 >=2.45 + - libgcc >=14.3.0 + - libgcc-devel_linux-64 14.3.0 hf649bbc_118 + - libgomp >=14.3.0 + - libsanitizer 14.3.0 h8f1669f_18 + - libstdcxx >=14.3.0 + - libstdcxx-devel_linux-64 14.3.0 h9f08a49_118 + - sysroot_linux-64 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 76302378 + timestamp: 1771378056505 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gcc_impl_linux-aarch64-14.3.0-h533bfc8_18.conda + sha256: e2488aac8472cfdff4f8a893861acd1ce1c66eafb28e7585ec52fe4e7546df7e + md5: 2ac1b579c1560e021a4086d0d704e2be + depends: + - binutils_impl_linux-aarch64 >=2.45 + - libgcc >=14.3.0 + - libgcc-devel_linux-aarch64 14.3.0 h25ba3ff_118 + - libgomp >=14.3.0 + - libsanitizer 14.3.0 hedb4206_18 + - libstdcxx >=14.3.0 + - libstdcxx-devel_linux-aarch64 14.3.0 h57c8d61_118 + - sysroot_linux-aarch64 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 69149627 + timestamp: 1771377858762 +- conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_linux-64-14.3.0-h298d278_21.conda + sha256: 27ad0cd10dccffca74e20fb38c9f8643ff8fce56eee260bf89fa257d5ab0c90a + md5: 1403ed5fe091bd7442e4e8a229d14030 + depends: + - gcc_impl_linux-64 14.3.0.* + - binutils_linux-64 + - sysroot_linux-64 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 28946 + timestamp: 1770908213807 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gcc_linux-aarch64-14.3.0-h118592a_21.conda + sha256: 2b4c579549e63f8f7e29aa332a95b85a5a33976d6caf42d7c3dc147d2939d7a0 + md5: dfe811f86ef2d8f511263ef38b773a39 + depends: + - gcc_impl_linux-aarch64 14.3.0.* + - binutils_linux-aarch64 + - sysroot_linux-aarch64 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 28666 + timestamp: 1770908257439 +- conda: https://conda.anaconda.org/conda-forge/win-64/git-2.53.0-h57928b3_0.conda + sha256: 6bc7eb1202395c044ff24f175f9f6d594bdc4c620e0cfa9e03ed46ef34c265ba + md5: b63e3ad61f7507fc72479ab0dde1a6be + license: GPL-2.0-or-later and LGPL-2.1-or-later + purls: [] + size: 123465948 + timestamp: 1770982612399 +- conda: https://conda.anaconda.org/conda-forge/linux-64/gxx-14.3.0-h76987e4_18.conda + sha256: 1b490c9be9669f9c559db7b2a1f7d8b973c58ca0c6f21a5d2ba3f0ab2da63362 + md5: 19189121d644d4ef75fed05383bc75f5 + depends: + - gcc 14.3.0 h0dff253_18 + - gxx_impl_linux-64 14.3.0 h2185e75_18 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 28883 + timestamp: 1771378355605 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gxx-14.3.0-ha384071_18.conda + sha256: 09fb56bcb1594d667e39b1ff4fced377f1b3f6c83f5b651d500db0b4865df68a + md5: 3d5380505980f8859a796af4c1b49452 + depends: + - gcc 14.3.0 h2e72a27_18 + - gxx_impl_linux-aarch64 14.3.0 h0d4f5d4_18 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 28822 + timestamp: 1771378129202 +- conda: https://conda.anaconda.org/conda-forge/linux-64/gxx_impl_linux-64-14.3.0-h2185e75_18.conda + sha256: 38ffca57cc9c264d461ac2ce9464a9d605e0f606d92d831de9075cb0d95fc68a + md5: 6514b3a10e84b6a849e1b15d3753eb22 + depends: + - gcc_impl_linux-64 14.3.0 hbdf3cc3_18 + - libstdcxx-devel_linux-64 14.3.0 h9f08a49_118 + - sysroot_linux-64 + - tzdata + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 14566100 + timestamp: 1771378271421 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gxx_impl_linux-aarch64-14.3.0-h0d4f5d4_18.conda + sha256: 859a78ff16bef8d1d1d89d0604929c3c256ac0248b9a688e8defe9bbc027c886 + md5: a12277d1ec675dbb993ad72dce735530 + depends: + - gcc_impl_linux-aarch64 14.3.0 h533bfc8_18 + - libstdcxx-devel_linux-aarch64 14.3.0 h57c8d61_118 + - sysroot_linux-aarch64 + - tzdata + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 13513218 + timestamp: 1771378064341 +- conda: https://conda.anaconda.org/conda-forge/linux-64/gxx_linux-64-14.3.0-he467f4b_21.conda + sha256: 1e07c197e0779fa9105e59cd55a835ded96bfde59eb169439736a89b27b48e5d + md5: 7b51f4ff82eeb1f386bfee20a7bed3ed + depends: + - gxx_impl_linux-64 14.3.0.* + - gcc_linux-64 ==14.3.0 h298d278_21 + - binutils_linux-64 + - sysroot_linux-64 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 27503 + timestamp: 1770908213813 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gxx_linux-aarch64-14.3.0-h32e4f2e_21.conda + sha256: 10059135f9960de93f991ce7fb6ef9d833dc2ac675459a1a08def052e5a29667 + md5: 3114b029596eff0aeb9fc0c81f598211 + depends: + - gxx_impl_linux-aarch64 14.3.0.* + - gcc_linux-aarch64 ==14.3.0 h118592a_21 + - binutils_linux-aarch64 + - sysroot_linux-aarch64 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 27275 + timestamp: 1770908257444 +- conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda + sha256: 84c64443368f84b600bfecc529a1194a3b14c3656ee2e832d15a20e0329b6da3 + md5: 164fc43f0b53b6e3a7bc7dce5e4f1dc9 + depends: + - python >=3.10 + - hyperframe >=6.1,<7 + - hpack >=4.1,<5 + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/h2?source=hash-mapping + size: 95967 + timestamp: 1756364871835 +- conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda + sha256: 6ad78a180576c706aabeb5b4c8ceb97c0cb25f1e112d76495bff23e3779948ba + md5: 0a802cb9888dd14eeefc611f05c40b6e + depends: + - python >=3.9 + license: MIT + license_family: MIT + purls: + - pkg:pypi/hpack?source=hash-mapping + size: 30731 + timestamp: 1737618390337 +- conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda + sha256: 77af6f5fe8b62ca07d09ac60127a30d9069fdc3c68d6b256754d0ffb1f7779f8 + md5: 8e6923fc12f1fe8f8c4e5c9f343256ac + depends: + - python >=3.9 + license: MIT + license_family: MIT + purls: + - pkg:pypi/hyperframe?source=hash-mapping + size: 17397 + timestamp: 1737618427549 +- conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.2-h33c6efd_0.conda + sha256: 142a722072fa96cf16ff98eaaf641f54ab84744af81754c292cb81e0881c0329 + md5: 186a18e3ba246eccfc7cff00cd19a870 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libstdcxx >=14 + license: MIT + license_family: MIT + purls: [] + size: 12728445 + timestamp: 1767969922681 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/icu-78.2-hcab7f73_0.conda + sha256: dcbaa3042084ac58685e3ef4547e4c4be9d37dc52b92ea18581288af95e48b52 + md5: 998ee7d53e32f7ab57fc35707285527e + depends: + - libgcc >=14 + - libstdcxx >=14 + license: MIT + license_family: MIT + purls: [] + size: 12851689 + timestamp: 1772208964788 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/icu-78.3-hcab7f73_0.conda + sha256: 49ba6aed2c6b482bb0ba41078057555d29764299bc947b990708617712ef6406 + md5: 546da38c2fa9efacf203e2ad3f987c59 + depends: + - libgcc >=14 + - libstdcxx >=14 + license: MIT + purls: [] + size: 12837286 + timestamp: 1773822650615 +- conda: https://conda.anaconda.org/conda-forge/osx-64/icu-73.2-hf5e326d_0.conda + sha256: f66362dc36178ac9b7c7a9b012948a9d2d050b3debec24bbd94aadbc44854185 + md5: 5cc301d759ec03f28328428e28f65591 + license: MIT + license_family: MIT + purls: [] + size: 11787527 + timestamp: 1692901622519 +- conda: https://conda.anaconda.org/conda-forge/osx-64/icu-78.2-h14c5de8_0.conda + sha256: f3066beae7fe3002f09c8a412cdf1819f49a2c9a485f720ec11664330cf9f1fe + md5: 30334add4de016489b731c6662511684 + depends: + - __osx >=10.13 + license: MIT + license_family: MIT + size: 12263724 + timestamp: 1767970604977 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-73.2-hc8870d7_0.conda + sha256: ff9cd0c6cd1349954c801fb443c94192b637e1b414514539f3c49c56a39f51b1 + md5: 8521bd47c0e11c5902535bb1a17c565f + license: MIT + license_family: MIT + purls: [] + size: 11997841 + timestamp: 1692902104771 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.2-hef89b57_0.conda + sha256: 24bc62335106c30fecbcc1dba62c5eba06d18b90ea1061abd111af7b9c89c2d7 + md5: 114e6bfe7c5ad2525eb3597acdbf2300 + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + size: 12389400 + timestamp: 1772209104304 +- conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda + sha256: ae89d0299ada2a3162c2614a9d26557a92aa6a77120ce142f8e0109bbf0342b0 + md5: 53abe63df7e10a6ba605dc5f9f961d36 + depends: + - python >=3.10 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/idna?source=hash-mapping + size: 50721 + timestamp: 1760286526795 +- conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda + sha256: c18ab120a0613ada4391b15981d86ff777b5690ca461ea7e9e49531e8f374745 + md5: 63ccfdc3a3ce25b027b8767eb722fca8 + depends: + - python >=3.9 + - zipp >=3.20 + - python + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/importlib-metadata?source=hash-mapping + size: 34641 + timestamp: 1747934053147 +- conda: https://conda.anaconda.org/conda-forge/noarch/importlib-resources-6.5.2-pyhd8ed1ab_0.conda + sha256: a99a3dafdfff2bb648d2b10637c704400295cb2ba6dc929e2d814870cf9f6ae5 + md5: e376ea42e9ae40f3278b0f79c9bf9826 + depends: + - importlib_resources >=6.5.2,<6.5.3.0a0 + - python >=3.9 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 9724 + timestamp: 1736252443859 +- conda: https://conda.anaconda.org/conda-forge/noarch/importlib_resources-6.5.2-pyhd8ed1ab_0.conda + sha256: acc1d991837c0afb67c75b77fdc72b4bf022aac71fedd8b9ea45918ac9b08a80 + md5: c85c76dc67d75619a92f51dfbce06992 + depends: + - python >=3.9 + - zipp >=3.1.0 + constrains: + - importlib-resources >=6.5.2,<6.5.3.0a0 + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/importlib-resources?source=hash-mapping + size: 33781 + timestamp: 1736252433366 +- conda: https://conda.anaconda.org/conda-forge/noarch/jsonpatch-1.33-pyhd8ed1ab_1.conda + sha256: 304955757d1fedbe344af43b12b5467cca072f83cce6109361ba942e186b3993 + md5: cb60ae9cf02b9fcb8004dec4089e5691 + depends: + - jsonpointer >=1.9 + - python >=3.9 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/jsonpatch?source=hash-mapping + size: 17311 + timestamp: 1733814664790 +- conda: https://conda.anaconda.org/conda-forge/noarch/jsonpointer-3.0.0-pyhcf101f3_3.conda + sha256: 1a1328476d14dfa8b84dbacb7f7cd7051c175498406dc513ca6c679dc44f3981 + md5: cd2214824e36b0180141d422aba01938 + depends: + - python >=3.10 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/jsonpointer?source=hash-mapping + size: 13967 + timestamp: 1765026384757 +- conda: https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-64-4.18.0-he073ed8_9.conda + sha256: 41557eeadf641de6aeae49486cef30d02a6912d8da98585d687894afd65b356a + md5: 86d9cba083cd041bfbf242a01a7a1999 + constrains: + - sysroot_linux-64 ==2.28 + license: LGPL-2.0-or-later AND LGPL-2.0-or-later WITH exceptions AND GPL-2.0-or-later + license_family: GPL + purls: [] + size: 1278712 + timestamp: 1765578681495 +- conda: https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-aarch64-4.18.0-h05a177a_9.conda + sha256: 5d224bf4df9bac24e69de41897c53756108c5271a0e5d2d2f66fd4e2fbc1d84b + md5: bb3b7cad9005f2cbf9d169fb30263f3e + constrains: + - sysroot_linux-aarch64 ==2.28 + license: LGPL-2.0-or-later AND LGPL-2.0-or-later WITH exceptions AND GPL-2.0-or-later + license_family: GPL + purls: [] + size: 1248134 + timestamp: 1765578613607 +- conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda + sha256: 0960d06048a7185d3542d850986d807c6e37ca2e644342dd0c72feefcf26c2a4 + md5: b38117a3c920364aff79f870c984b4a3 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + license: LGPL-2.1-or-later + purls: [] + size: 134088 + timestamp: 1754905959823 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/keyutils-1.6.3-h86ecc28_0.conda + sha256: 5ce830ca274b67de11a7075430a72020c1fb7d486161a82839be15c2b84e9988 + md5: e7df0aab10b9cbb73ab2a467ebfaf8c7 + depends: + - libgcc >=13 + license: LGPL-2.1-or-later + purls: [] + size: 129048 + timestamp: 1754906002667 +- conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.22.2-ha1258a1_0.conda + sha256: 3e307628ca3527448dd1cb14ad7bb9d04d1d28c7d4c5f97ba196ae984571dd25 + md5: fb53fb07ce46a575c5d004bbc96032c2 + depends: + - __glibc >=2.17,<3.0.a0 + - keyutils >=1.6.3,<2.0a0 + - libedit >=3.1.20250104,<3.2.0a0 + - libedit >=3.1.20250104,<4.0a0 + - libgcc >=14 + - libstdcxx >=14 + - openssl >=3.5.5,<4.0a0 + license: MIT + license_family: MIT + purls: [] + size: 1386730 + timestamp: 1769769569681 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/krb5-1.22.2-hfd895c2_0.conda + sha256: b53999d888dda53c506b264e8c02b5f5c8e022c781eda0718f007339e6bc90ba + md5: d9ca108bd680ea86a963104b6b3e95ca + depends: + - keyutils >=1.6.3,<2.0a0 + - libedit >=3.1.20250104,<3.2.0a0 + - libedit >=3.1.20250104,<4.0a0 + - libgcc >=14 + - libstdcxx >=14 + - openssl >=3.5.5,<4.0a0 + license: MIT + license_family: MIT + purls: [] + size: 1517436 + timestamp: 1769773395215 +- conda: https://conda.anaconda.org/conda-forge/osx-64/krb5-1.21.2-hb884880_0.conda + sha256: 081ae2008a21edf57c048f331a17c65d1ccb52d6ca2f87ee031a73eff4dc0fc6 + md5: 80505a68783f01dc8d7308c075261b2f + depends: + - libcxx >=15.0.7 + - libedit >=3.1.20191231,<3.2.0a0 + - libedit >=3.1.20191231,<4.0a0 + - openssl >=3.1.2,<4.0a0 + license: MIT + license_family: MIT + purls: [] + size: 1183568 + timestamp: 1692098004387 +- conda: https://conda.anaconda.org/conda-forge/osx-64/krb5-1.22.2-h207b36a_0.conda + sha256: df009385e8262c234c0dae9016540b86dad3d299f0d9366d08e327e8e7731634 + md5: e66e2c52d2fdddcf314ad750fb4ebb4a + depends: + - __osx >=10.13 + - libcxx >=19 + - libedit >=3.1.20250104,<3.2.0a0 + - libedit >=3.1.20250104,<4.0a0 + - openssl >=3.5.5,<4.0a0 + license: MIT + license_family: MIT + size: 1193620 + timestamp: 1769770267475 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.21.2-h92f50d5_0.conda + sha256: 70bdb9b4589ec7c7d440e485ae22b5a352335ffeb91a771d4c162996c3070875 + md5: 92f1cff174a538e0722bf2efb16fc0b2 + depends: + - libcxx >=15.0.7 + - libedit >=3.1.20191231,<3.2.0a0 + - libedit >=3.1.20191231,<4.0a0 + - openssl >=3.1.2,<4.0a0 + license: MIT + license_family: MIT + purls: [] + size: 1195575 + timestamp: 1692098070699 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.22.2-h385eeb1_0.conda + sha256: c0a0bf028fe7f3defcdcaa464e536cf1b202d07451e18ad83fdd169d15bef6ed + md5: e446e1822f4da8e5080a9de93474184d + depends: + - __osx >=11.0 + - libcxx >=19 + - libedit >=3.1.20250104,<3.2.0a0 + - libedit >=3.1.20250104,<4.0a0 + - openssl >=3.5.5,<4.0a0 + license: MIT + license_family: MIT + size: 1160828 + timestamp: 1769770119811 +- conda: https://conda.anaconda.org/conda-forge/win-64/krb5-1.22.2-h0ea6238_0.conda + sha256: eb60f1ad8b597bcf95dee11bc11fe71a8325bc1204cf51d2bb1f2120ffd77761 + md5: 4432f52dc0c8eb6a7a6abc00a037d93c + depends: + - openssl >=3.5.5,<4.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: MIT + license_family: MIT + purls: [] + size: 751055 + timestamp: 1769769688841 +- conda: https://conda.anaconda.org/conda-forge/osx-64/ld64-711-h4e51db5_0.conda + sha256: 230be4e751f17fa1ccc15066086d1726d1d223e98f8337f435b4472bfe00436b + md5: cc84dae1a60ee59f6098f93b76d74b60 + depends: + - ld64_osx-64 711 had5d0d3_0 + - libllvm18 >=18.1.1,<18.2.0a0 + constrains: + - cctools_osx-64 986.* + - cctools 986.* + license: APSL-2.0 + license_family: Other + purls: [] + size: 18568 + timestamp: 1710484499499 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/ld64-711-h4c6efb1_0.conda + sha256: 467371e8dbd4fc99f507024c3d10c0ac4a8528286e9507a1f365e26cb90f4df0 + md5: 289df626863e8c720c3aa220964378cc + depends: + - ld64_osx-arm64 711 h5e7191b_0 + - libllvm18 >=18.1.1,<18.2.0a0 + constrains: + - cctools 986.* + - cctools_osx-arm64 986.* + license: APSL-2.0 + license_family: Other + purls: [] + size: 18678 + timestamp: 1710484665887 +- conda: https://conda.anaconda.org/conda-forge/osx-64/ld64_osx-64-711-had5d0d3_0.conda + sha256: 14d3fd593a7fd1cc472167dc00fd1d3176b8ce9dfc9b9d003359ecde4ded7459 + md5: cb63e1d1e11a1fffad54333330486ddd + depends: + - libcxx + - libllvm18 >=18.1.1,<18.2.0a0 + - sigtool + - tapi >=1100.0.11,<1101.0a0 + constrains: + - cctools_osx-64 986.* + - ld 711.* + - cctools 986.* + - clang >=18.1.1,<19.0a0 + license: APSL-2.0 + license_family: Other + purls: [] + size: 1071472 + timestamp: 1710484364960 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/ld64_osx-arm64-711-h5e7191b_0.conda + sha256: 82f964dcff2052b327762ca44651407451ad396a1540c664928841c72b7cf3c0 + md5: c751b76ae8112e3d516831063da179cc + depends: + - libcxx + - libllvm18 >=18.1.1,<18.2.0a0 + - sigtool + - tapi >=1100.0.11,<1101.0a0 + constrains: + - ld 711.* + - cctools 986.* + - cctools_osx-arm64 986.* + - clang >=18.1.1,<19.0a0 + license: APSL-2.0 + license_family: Other + purls: [] + size: 1064448 + timestamp: 1710484550965 +- conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_101.conda + sha256: 565941ac1f8b0d2f2e8f02827cbca648f4d18cd461afc31f15604cd291b5c5f3 + md5: 12bd9a3f089ee6c9266a37dab82afabd + depends: + - __glibc >=2.17,<3.0.a0 + - zstd >=1.5.7,<1.6.0a0 + constrains: + - binutils_impl_linux-64 2.45.1 + license: GPL-3.0-only + license_family: GPL + purls: [] + size: 725507 + timestamp: 1770267139900 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.45.1-default_h1979696_101.conda + sha256: 44527364aa333be631913451c32eb0cae1e09343827e9ce3ccabd8d962584226 + md5: 35b2ae7fadf364b8e5fb8185aaeb80e5 + depends: + - zstd >=1.5.7,<1.6.0a0 + constrains: + - binutils_impl_linux-aarch64 2.45.1 + license: GPL-3.0-only + license_family: GPL + purls: [] + size: 875924 + timestamp: 1770267209884 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libarchive-3.8.6-gpl_hc2c16d8_100.conda + sha256: 69ea8da58658ad26cb64fb0bfccd8a3250339811f0b57c6b8a742e5e51bacf70 + md5: 981d372c31a23e1aa9965d4e74d085d5 + depends: + - __glibc >=2.17,<3.0.a0 + - bzip2 >=1.0.8,<2.0a0 + - libgcc >=14 + - liblzma >=5.8.2,<6.0a0 + - libxml2 + - libxml2-16 >=2.14.6 + - libzlib >=1.3.1,<2.0a0 + - lz4-c >=1.10.0,<1.11.0a0 + - lzo >=2.10,<3.0a0 + - openssl >=3.5.5,<4.0a0 + - zstd >=1.5.7,<1.6.0a0 + license: BSD-2-Clause + license_family: BSD + purls: [] + size: 887139 + timestamp: 1773243188979 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libarchive-3.8.6-gpl_hbe7d12b_100.conda + sha256: 635a78a04461e82150263ee9a1fbf6c965de0b811a10e87392a1e44be1115a39 + md5: f2c45cbb67fd0f668a1a0c152b70dc5f + depends: + - bzip2 >=1.0.8,<2.0a0 + - libgcc >=14 + - liblzma >=5.8.2,<6.0a0 + - libxml2 + - libxml2-16 >=2.14.6 + - libzlib >=1.3.1,<2.0a0 + - lz4-c >=1.10.0,<1.11.0a0 + - lzo >=2.10,<3.0a0 + - openssl >=3.5.5,<4.0a0 + - zstd >=1.5.7,<1.6.0a0 + license: BSD-2-Clause + license_family: BSD + purls: [] + size: 1000663 + timestamp: 1773243230880 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libarchive-3.8.6-gpl_h2bf6321_100.conda + sha256: 54a4e32132d45557e5f79ec88e4ab951c36fbd8acf256949121656c9f6979998 + md5: b69c2c71c786c9fd1524e69072e96bc7 + depends: + - __osx >=11.0 + - bzip2 >=1.0.8,<2.0a0 + - libiconv >=1.18,<2.0a0 + - liblzma >=5.8.2,<6.0a0 + - libxml2 + - libxml2-16 >=2.14.6 + - libzlib >=1.3.1,<2.0a0 + - lz4-c >=1.10.0,<1.11.0a0 + - lzo >=2.10,<3.0a0 + - openssl >=3.5.5,<4.0a0 + - zstd >=1.5.7,<1.6.0a0 + license: BSD-2-Clause + license_family: BSD + size: 761501 + timestamp: 1773243700449 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarchive-3.8.6-gpl_h6fbacd7_100.conda + sha256: 57fcc5cb6203cb0e119f46be708c8b2cf2bae47dc7580e5b4e76bd4b4c6d164a + md5: 4133c0cef1c6a25426b35f790e006648 + depends: + - __osx >=11.0 + - bzip2 >=1.0.8,<2.0a0 + - libiconv >=1.18,<2.0a0 + - liblzma >=5.8.2,<6.0a0 + - libxml2 + - libxml2-16 >=2.14.6 + - libzlib >=1.3.1,<2.0a0 + - lz4-c >=1.10.0,<1.11.0a0 + - lzo >=2.10,<3.0a0 + - openssl >=3.5.5,<4.0a0 + - zstd >=1.5.7,<1.6.0a0 + license: BSD-2-Clause + license_family: BSD + size: 791560 + timestamp: 1773243648871 +- conda: https://conda.anaconda.org/conda-forge/win-64/libarchive-3.8.6-gpl_he24518a_100.conda + sha256: 0cc7f963d689fcadc0f7e83eb1f538ea73543af92e2b988d552a3d12cceb56e6 + md5: c76cc84cfafa74e43d8951db29983ebb + depends: + - bzip2 >=1.0.8,<2.0a0 + - liblzma >=5.8.2,<6.0a0 + - libxml2 + - libxml2-16 >=2.14.6 + - libzlib >=1.3.1,<2.0a0 + - lz4-c >=1.10.0,<1.11.0a0 + - lzo >=2.10,<3.0a0 + - openssl >=3.5.5,<4.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - zstd >=1.5.7,<1.6.0a0 + license: BSD-2-Clause + license_family: BSD + purls: [] + size: 1106665 + timestamp: 1773243755298 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-5_h4a7cf45_openblas.conda + build_number: 5 + sha256: 18c72545080b86739352482ba14ba2c4815e19e26a7417ca21a95b76ec8da24c + md5: c160954f7418d7b6e87eaf05a8913fa9 + depends: + - libopenblas >=0.3.30,<0.3.31.0a0 + - libopenblas >=0.3.30,<1.0a0 + constrains: + - mkl <2026 + - liblapack 3.11.0 5*_openblas + - libcblas 3.11.0 5*_openblas + - blas 2.305 openblas + - liblapacke 3.11.0 5*_openblas + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 18213 + timestamp: 1765818813880 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-6_h4a7cf45_openblas.conda + build_number: 6 + sha256: 7bfe936dbb5db04820cf300a9cc1f5ee8d5302fc896c2d66e30f1ee2f20fbfd6 + md5: 6d6d225559bfa6e2f3c90ee9c03d4e2e + depends: + - libopenblas >=0.3.32,<0.3.33.0a0 + - libopenblas >=0.3.32,<1.0a0 + constrains: + - blas 2.306 openblas + - liblapack 3.11.0 6*_openblas + - liblapacke 3.11.0 6*_openblas + - libcblas 3.11.0 6*_openblas + - mkl <2026 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 18621 + timestamp: 1774503034895 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libblas-3.11.0-5_haddc8a3_openblas.conda + build_number: 5 + sha256: 700f3c03d0fba8e687a345404a45fbabe781c1cf92242382f62cef2948745ec4 + md5: 5afcea37a46f76ec1322943b3c4dfdc0 + depends: + - libopenblas >=0.3.30,<0.3.31.0a0 + - libopenblas >=0.3.30,<1.0a0 + constrains: + - mkl <2026 + - libcblas 3.11.0 5*_openblas + - liblapack 3.11.0 5*_openblas + - liblapacke 3.11.0 5*_openblas + - blas 2.305 openblas + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 18369 + timestamp: 1765818610617 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libblas-3.9.0-22_osx64_openblas.conda + build_number: 22 + sha256: d72060239f904b3a81d2329efcf84dc62c2dfd66dbc4efc8dcae1afdf8f02b59 + md5: b80966a8c8dd0b531f8e65f709d732e8 + depends: + - libopenblas >=0.3.27,<0.3.28.0a0 + - libopenblas >=0.3.27,<1.0a0 + constrains: + - liblapacke 3.9.0 22_osx64_openblas + - blas * openblas + - libcblas 3.9.0 22_osx64_openblas + - liblapack 3.9.0 22_osx64_openblas + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 14749 + timestamp: 1712542279018 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libblas-3.9.0-24_osxarm64_openblas.conda + build_number: 24 + sha256: 4739f7463efb12e6d71536d8b0285a8de5aaadcc442bfedb9d92d1b4cbc47847 + md5: 35cb711e7bc46ee5f3dd67af99ad1986 + depends: + - libopenblas >=0.3.27,<0.3.28.0a0 + - libopenblas >=0.3.27,<1.0a0 + constrains: + - liblapack 3.9.0 24_osxarm64_openblas + - blas * openblas + - liblapacke 3.9.0 24_osxarm64_openblas + - libcblas 3.9.0 24_osxarm64_openblas + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 15144 + timestamp: 1726668802976 +- conda: https://conda.anaconda.org/conda-forge/win-64/libblas-3.11.0-5_hf2e6a31_mkl.conda + build_number: 5 + sha256: f0cb7b2697461a306341f7ff32d5b361bb84f3e94478464c1e27ee01fc8f276b + md5: f9decf88743af85c9c9e05556a4c47c0 + depends: + - mkl >=2025.3.0,<2026.0a0 + constrains: + - liblapack 3.11.0 5*_mkl + - libcblas 3.11.0 5*_mkl + - blas 2.305 mkl + - liblapacke 3.11.0 5*_mkl + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 67438 + timestamp: 1765819100043 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-5_h0358290_openblas.conda + build_number: 5 + sha256: 0cbdcc67901e02dc17f1d19e1f9170610bd828100dc207de4d5b6b8ad1ae7ad8 + md5: 6636a2b6f1a87572df2970d3ebc87cc0 + depends: + - libblas 3.11.0 5_h4a7cf45_openblas + constrains: + - liblapacke 3.11.0 5*_openblas + - blas 2.305 openblas + - liblapack 3.11.0 5*_openblas + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 18194 + timestamp: 1765818837135 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-6_h0358290_openblas.conda + build_number: 6 + sha256: 57edafa7796f6fa3ebbd5367692dd4c7f552be42109c2dd1a7c89b55089bf374 + md5: 36ae340a916635b97ac8a0655ace2a35 + depends: + - libblas 3.11.0 6_h4a7cf45_openblas + constrains: + - blas 2.306 openblas + - liblapack 3.11.0 6*_openblas + - liblapacke 3.11.0 6*_openblas + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 18622 + timestamp: 1774503050205 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcblas-3.11.0-5_hd72aa62_openblas.conda + build_number: 5 + sha256: 3fad5c9de161dccb4e42c8b1ae8eccb33f4ed56bccbcced9cbb0956ae7869e61 + md5: 0b2f1143ae2d0aa4c991959d0daaf256 + depends: + - libblas 3.11.0 5_haddc8a3_openblas + constrains: + - liblapack 3.11.0 5*_openblas + - liblapacke 3.11.0 5*_openblas + - blas 2.305 openblas + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 18371 + timestamp: 1765818618899 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libcblas-3.9.0-22_osx64_openblas.conda + build_number: 22 + sha256: 6a2ba9198e2320c3e22fe3d121310cf8a8ac663e94100c5693b34523fcb3cc04 + md5: b9fef82772330f61b2b0201c72d2c29b + depends: + - libblas 3.9.0 22_osx64_openblas + constrains: + - liblapacke 3.9.0 22_osx64_openblas + - blas * openblas + - liblapack 3.9.0 22_osx64_openblas + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 14636 + timestamp: 1712542311437 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcblas-3.9.0-24_osxarm64_openblas.conda + build_number: 24 + sha256: 40dc3f7c44af5cd5a2020386cb30f92943a9d8f7f54321b4d6ae32b2e54af9a4 + md5: c8977086a19233153e454bb2b332a920 + depends: + - libblas 3.9.0 24_osxarm64_openblas + constrains: + - liblapack 3.9.0 24_osxarm64_openblas + - blas * openblas + - liblapacke 3.9.0 24_osxarm64_openblas + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 15062 + timestamp: 1726668809379 +- conda: https://conda.anaconda.org/conda-forge/win-64/libcblas-3.11.0-5_h2a3cdd5_mkl.conda + build_number: 5 + sha256: 49dc59d8e58360920314b8d276dd80da7866a1484a9abae4ee2760bc68f3e68d + md5: b3fa8e8b55310ba8ef0060103afb02b5 + depends: + - libblas 3.11.0 5_hf2e6a31_mkl + constrains: + - liblapack 3.11.0 5*_mkl + - liblapacke 3.11.0 5*_mkl + - blas 2.305 mkl + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 68079 + timestamp: 1765819124349 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libclang-cpp18.1-18.1.3-default_h7151d67_0.conda + sha256: e3b693234b50f553441795f7f7f89e4f1b1258433634f3c9988e75f30ea9e3ee + md5: 02eea994247b28cbf46b8ca52530bb39 + depends: + - libcxx >=16.0.6 + - libllvm18 >=18.1.3,<18.2.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + purls: [] + size: 13694951 + timestamp: 1712568723512 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libclang-cpp18.1-18.1.3-default_he012953_0.conda + sha256: a528f933aa430c86591ed94e7eb5e4c16947232f149920250ba78e104d91e0b3 + md5: d8e0decc03dadc234e0885bb2a857c68 + depends: + - libcxx >=16.0.6 + - libllvm18 >=18.1.3,<18.2.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + purls: [] + size: 12809223 + timestamp: 1712569190982 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libcurl-8.19.0-hcf29cc6_0.conda + sha256: a0390fd0536ebcd2244e243f5f00ab8e76ab62ed9aa214cd54470fe7496620f4 + md5: d50608c443a30c341c24277d28290f76 + depends: + - __glibc >=2.17,<3.0.a0 + - krb5 >=1.22.2,<1.23.0a0 + - libgcc >=14 + - libnghttp2 >=1.67.0,<2.0a0 + - libssh2 >=1.11.1,<2.0a0 + - libzlib >=1.3.1,<2.0a0 + - openssl >=3.5.5,<4.0a0 + - zstd >=1.5.7,<1.6.0a0 + license: curl + license_family: MIT + purls: [] + size: 466704 + timestamp: 1773218522665 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcurl-8.19.0-hc57f145_0.conda + sha256: 75c1b2f9cff7598c593dda96c55963298bebb5bcb5a77af0b4c41cb03d26100b + md5: d5306c7ec07faf48cfb0e552c67339e0 + depends: + - krb5 >=1.22.2,<1.23.0a0 + - libgcc >=14 + - libnghttp2 >=1.67.0,<2.0a0 + - libssh2 >=1.11.1,<2.0a0 + - libzlib >=1.3.1,<2.0a0 + - openssl >=3.5.5,<4.0a0 + - zstd >=1.5.7,<1.6.0a0 + license: curl + license_family: MIT + purls: [] + size: 485694 + timestamp: 1773218484057 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libcurl-8.19.0-h8f0b9e4_0.conda + sha256: 55c6b34ae18a7f8f57d9ffe3f4ec2a82ddcc8a87248d2447f9bbba3ba66d8aec + md5: 8bc2742696d50c358f4565b25ba33b08 + depends: + - __osx >=11.0 + - krb5 >=1.22.2,<1.23.0a0 + - libnghttp2 >=1.67.0,<2.0a0 + - libssh2 >=1.11.1,<2.0a0 + - libzlib >=1.3.1,<2.0a0 + - openssl >=3.5.5,<4.0a0 + - zstd >=1.5.7,<1.6.0a0 + license: curl + license_family: MIT + size: 419039 + timestamp: 1773219507657 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libcurl-8.4.0-h726d00d_0.conda + sha256: cd3400ecb42fc420acb18e2d836535c44ebd501ebeb4e0bf3830776e9b4ca650 + md5: 2c17b4dedf0039736951471f493353bd + depends: + - krb5 >=1.21.2,<1.22.0a0 + - libnghttp2 >=1.52.0,<2.0a0 + - libssh2 >=1.11.0,<2.0a0 + - libzlib >=1.2.13,<2.0.0a0 + - openssl >=3.1.3,<4.0a0 + - zstd >=1.5.5,<1.6.0a0 + license: curl + license_family: MIT + purls: [] + size: 366039 + timestamp: 1697009485409 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcurl-8.19.0-hd5a2499_0.conda + sha256: c4d581b067fa60f9dc0e1c5f18b756760ff094a03139e6b206eb98d185ae2bb1 + md5: 9fc7771fc8104abed9119113160be15a + depends: + - __osx >=11.0 + - krb5 >=1.22.2,<1.23.0a0 + - libnghttp2 >=1.67.0,<2.0a0 + - libssh2 >=1.11.1,<2.0a0 + - libzlib >=1.3.1,<2.0a0 + - openssl >=3.5.5,<4.0a0 + - zstd >=1.5.7,<1.6.0a0 + license: curl + license_family: MIT + size: 399616 + timestamp: 1773219210246 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcurl-8.4.0-h2d989ff_0.conda + sha256: 5ca24ab030b1c56ce07921bf901ea99076e8b7e45586b4a04e5187cc67c87273 + md5: afabb3372209028627ec03e206f4d967 + depends: + - krb5 >=1.21.2,<1.22.0a0 + - libnghttp2 >=1.52.0,<2.0a0 + - libssh2 >=1.11.0,<2.0a0 + - libzlib >=1.2.13,<2.0.0a0 + - openssl >=3.1.3,<4.0a0 + - zstd >=1.5.5,<1.6.0a0 + license: curl + license_family: MIT + purls: [] + size: 348974 + timestamp: 1697009607821 +- conda: https://conda.anaconda.org/conda-forge/win-64/libcurl-8.19.0-h8206538_0.conda + sha256: 6b2143ba5454b399dab4471e9e1d07352a2f33b569975e6b8aedc2d9bf51cbb0 + md5: ed181e29a7ebf0f60b84b98d6140a340 + depends: + - krb5 >=1.22.2,<1.23.0a0 + - libssh2 >=1.11.1,<2.0a0 + - libzlib >=1.3.1,<2.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: curl + license_family: MIT + purls: [] + size: 392543 + timestamp: 1773218585056 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libcxx-16.0.6-hd57cbcb_0.conda + sha256: 9063271847cf05f3a6cc6cae3e7f0ced032ab5f3a3c9d3f943f876f39c5c2549 + md5: 7d6972792161077908b62971802f289a + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + purls: [] + size: 1142172 + timestamp: 1686896907750 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libcxx-22.1.1-h19cb2f5_0.conda + sha256: db3adcb33eaca02311d3ba17e06c60ceaedda20240414f7b1df6e7f9ec902bfa + md5: 799141ac68a99265f04bcee196b2df51 + depends: + - __osx >=11.0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 564942 + timestamp: 1773203656390 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-16.0.6-h4653b0c_0.conda + sha256: 11d3fb51c14832d9e4f6d84080a375dec21ea8a3a381a1910e67ff9cedc20355 + md5: 9d7d724faf0413bf1dbc5a85935700c8 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + purls: [] + size: 1160232 + timestamp: 1686896993785 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-22.1.1-h55c6f16_0.conda + sha256: 3c8142cdd3109c250a926c492ec45bc954697b288e5d1154ada95272ffa21be8 + md5: 7a290d944bc0c481a55baf33fa289deb + depends: + - __osx >=11.0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 570281 + timestamp: 1773203613980 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.conda + sha256: d789471216e7aba3c184cd054ed61ce3f6dac6f87a50ec69291b9297f8c18724 + md5: c277e0a4d549b03ac1e9d6cbbe3d017b + depends: + - ncurses + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + - ncurses >=6.5,<7.0a0 + license: BSD-2-Clause + license_family: BSD + purls: [] + size: 134676 + timestamp: 1738479519902 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libedit-3.1.20250104-pl5321h976ea20_0.conda + sha256: c0b27546aa3a23d47919226b3a1635fccdb4f24b94e72e206a751b33f46fd8d6 + md5: fb640d776fc92b682a14e001980825b1 + depends: + - ncurses + - libgcc >=13 + - ncurses >=6.5,<7.0a0 + license: BSD-2-Clause + license_family: BSD + purls: [] + size: 148125 + timestamp: 1738479808948 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libedit-3.1.20191231-h0678c8f_2.tar.bz2 + sha256: dbd3c3f2eca1d21c52e4c03b21930bbce414c4592f8ce805801575b9e9256095 + md5: 6016a8a1d0e63cac3de2c352cd40208b + depends: + - ncurses >=6.2,<7.0.0a0 + license: BSD-2-Clause + license_family: BSD + purls: [] + size: 105382 + timestamp: 1597616576726 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libedit-3.1.20250104-pl5321ha958ccf_0.conda + sha256: 6cc49785940a99e6a6b8c6edbb15f44c2dd6c789d9c283e5ee7bdfedd50b4cd6 + md5: 1f4ed31220402fcddc083b4bff406868 + depends: + - ncurses + - __osx >=10.13 + - ncurses >=6.5,<7.0a0 + license: BSD-2-Clause + license_family: BSD + size: 115563 + timestamp: 1738479554273 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libedit-3.1.20191231-hc8eb9b7_2.tar.bz2 + sha256: 3912636197933ecfe4692634119e8644904b41a58f30cad9d1fc02f6ba4d9fca + md5: 30e4362988a2623e9eb34337b83e01f9 + depends: + - ncurses >=6.2,<7.0.0a0 + license: BSD-2-Clause + license_family: BSD + purls: [] + size: 96607 + timestamp: 1597616630749 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libedit-3.1.20250104-pl5321hafb1f1b_0.conda + sha256: 66aa216a403de0bb0c1340a88d1a06adaff66bae2cfd196731aa24db9859d631 + md5: 44083d2d2c2025afca315c7a172eab2b + depends: + - ncurses + - __osx >=11.0 + - ncurses >=6.5,<7.0a0 + license: BSD-2-Clause + license_family: BSD + size: 107691 + timestamp: 1738479560845 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libev-4.33-hd590300_2.conda + sha256: 1cd6048169fa0395af74ed5d8f1716e22c19a81a8a36f934c110ca3ad4dd27b4 + md5: 172bf1cd1ff8629f2b1179945ed45055 + depends: + - libgcc-ng >=12 + license: BSD-2-Clause + license_family: BSD + purls: [] + size: 112766 + timestamp: 1702146165126 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libev-4.33-h31becfc_2.conda + sha256: 973af77e297f1955dd1f69c2cbdc5ab9dfc88388a5576cd152cda178af0fd006 + md5: a9a13cb143bbaa477b1ebaefbe47a302 + depends: + - libgcc-ng >=12 + license: BSD-2-Clause + license_family: BSD + purls: [] + size: 115123 + timestamp: 1702146237623 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libev-4.33-h10d778d_2.conda + sha256: 0d238488564a7992942aa165ff994eca540f687753b4f0998b29b4e4d030ff43 + md5: 899db79329439820b7e8f8de41bca902 + license: BSD-2-Clause + license_family: BSD + purls: [] + size: 106663 + timestamp: 1702146352558 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libev-4.33-h93a5062_2.conda + sha256: 95cecb3902fbe0399c3a7e67a5bed1db813e5ab0e22f4023a5e0f722f2cc214f + md5: 36d33e440c31857372a72137f78bacf5 + license: BSD-2-Clause + license_family: BSD + purls: [] + size: 107458 + timestamp: 1702146414478 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.4-hecca717_0.conda + sha256: d78f1d3bea8c031d2f032b760f36676d87929b18146351c4464c66b0869df3f5 + md5: e7f7ce06ec24cfcfb9e36d28cf82ba57 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + constrains: + - expat 2.7.4.* + license: MIT + license_family: MIT + purls: [] + size: 76798 + timestamp: 1771259418166 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.7.4-hfae3067_0.conda + sha256: 995ce3ad96d0f4b5ed6296b051a0d7b6377718f325bc0e792fbb96b0e369dad7 + md5: 57f3b3da02a50a1be2a6fe847515417d + depends: + - libgcc >=14 + constrains: + - expat 2.7.4.* + license: MIT + license_family: MIT + purls: [] + size: 76564 + timestamp: 1771259530958 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libexpat-2.6.2-h73e2aa4_0.conda + sha256: a188a77b275d61159a32ab547f7d17892226e7dac4518d2c6ac3ac8fc8dfde92 + md5: 3d1d51c8f716d97c864d12f7af329526 + constrains: + - expat 2.6.2.* + license: MIT + license_family: MIT + purls: [] + size: 69246 + timestamp: 1710362566073 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libexpat-2.7.4-h991f03e_0.conda + sha256: 8d9d79b2de7d6f335692391f5281607221bf5d040e6724dad4c4d77cd603ce43 + md5: a684eb8a19b2aa68fde0267df172a1e3 + depends: + - __osx >=10.13 + constrains: + - expat 2.7.4.* + license: MIT + license_family: MIT + size: 74578 + timestamp: 1771260142624 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.6.2-hebf3989_0.conda + sha256: ba7173ac30064ea901a4c9fb5a51846dcc25512ceb565759be7d18cbf3e5415e + md5: e3cde7cfa87f82f7cb13d482d5e0ad09 + constrains: + - expat 2.6.2.* + license: MIT + license_family: MIT + purls: [] + size: 63655 + timestamp: 1710362424980 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.7.4-hf6b4638_0.conda + sha256: 03887d8080d6a8fe02d75b80929271b39697ecca7628f0657d7afaea87761edf + md5: a92e310ae8dfc206ff449f362fc4217f + depends: + - __osx >=11.0 + constrains: + - expat 2.7.4.* + license: MIT + license_family: MIT + size: 68199 + timestamp: 1771260020767 +- conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.7.4-hac47afa_0.conda + sha256: b31f6fb629c4e17885aaf2082fb30384156d16b48b264e454de4a06a313b533d + md5: 1c1ced969021592407f16ada4573586d + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + constrains: + - expat 2.7.4.* + license: MIT + license_family: MIT + purls: [] + size: 70323 + timestamp: 1771259521393 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda + sha256: 31f19b6a88ce40ebc0d5a992c131f57d919f73c0b92cd1617a5bec83f6e961e6 + md5: a360c33a5abe61c07959e449fa1453eb + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + license: MIT + license_family: MIT + purls: [] + size: 58592 + timestamp: 1769456073053 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libffi-3.5.2-h376a255_0.conda + sha256: 3df4c539449aabc3443bbe8c492c01d401eea894603087fca2917aa4e1c2dea9 + md5: 2f364feefb6a7c00423e80dcb12db62a + depends: + - libgcc >=14 + license: MIT + license_family: MIT + purls: [] + size: 55952 + timestamp: 1769456078358 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libffi-3.4.2-h0d85af4_5.tar.bz2 + sha256: 7a2d27a936ceee6942ea4d397f9c7d136f12549d86f7617e8b6bad51e01a941f + md5: ccb34fb14960ad8b125962d3d79b31a9 + license: MIT + license_family: MIT + purls: [] + size: 51348 + timestamp: 1636488394370 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libffi-3.5.2-hd1f9c09_0.conda + sha256: 951958d1792238006fdc6fce7f71f1b559534743b26cc1333497d46e5903a2d6 + md5: 66a0dc7464927d0853b590b6f53ba3ea + depends: + - __osx >=10.13 + license: MIT + license_family: MIT + size: 53583 + timestamp: 1769456300951 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.4.2-h3422bc3_5.tar.bz2 + sha256: 41b3d13efb775e340e4dba549ab5c029611ea6918703096b2eaa9c015c0750ca + md5: 086914b672be056eb70fd4285b6783b6 + license: MIT + license_family: MIT + purls: [] + size: 39020 + timestamp: 1636488587153 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-hcf2aa1b_0.conda + sha256: 6686a26466a527585e6a75cc2a242bf4a3d97d6d6c86424a441677917f28bec7 + md5: 43c04d9cb46ef176bb2a4c77e324d599 + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + size: 40979 + timestamp: 1769456747661 +- conda: https://conda.anaconda.org/conda-forge/win-64/libffi-3.5.2-h3d046cb_0.conda + sha256: 59d01f2dfa8b77491b5888a5ab88ff4e1574c9359f7e229da254cdfe27ddc190 + md5: 720b39f5ec0610457b725eb3f396219a + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: MIT + license_family: MIT + purls: [] + size: 45831 + timestamp: 1769456418774 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_18.conda + sha256: faf7d2017b4d718951e3a59d081eb09759152f93038479b768e3d612688f83f5 + md5: 0aa00f03f9e39fb9876085dee11a85d4 + depends: + - __glibc >=2.17,<3.0.a0 + - _openmp_mutex >=4.5 + constrains: + - libgcc-ng ==15.2.0=*_18 + - libgomp 15.2.0 he0feb66_18 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 1041788 + timestamp: 1771378212382 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-15.2.0-h8acb6b2_18.conda + sha256: 43df385bedc1cab11993c4369e1f3b04b4ca5d0ea16cba6a0e7f18dbc129fcc9 + md5: 552567ea2b61e3a3035759b2fdb3f9a6 + depends: + - _openmp_mutex >=4.5 + constrains: + - libgcc-ng ==15.2.0=*_18 + - libgomp 15.2.0 h8acb6b2_18 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 622900 + timestamp: 1771378128706 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libgcc-15.2.0-h08519bb_18.conda + sha256: 83366f11615ab234aa1e0797393f9e07b78124b5a24c4a9f8af0113d02df818e + md5: 9a5cb96e43f5c2296690186e15b3296f + depends: + - _openmp_mutex + constrains: + - libgcc-ng ==15.2.0=*_18 + - libgomp 15.2.0 18 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 423025 + timestamp: 1771378225170 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgcc-15.2.0-hcbb3090_18.conda + sha256: 1d9c4f35586adb71bcd23e31b68b7f3e4c4ab89914c26bed5f2859290be5560e + md5: 92df6107310b1fff92c4cc84f0de247b + depends: + - _openmp_mutex + constrains: + - libgcc-ng ==15.2.0=*_18 + - libgomp 15.2.0 18 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 401974 + timestamp: 1771378877463 +- conda: https://conda.anaconda.org/conda-forge/noarch/libgcc-devel_linux-64-14.3.0-hf649bbc_118.conda + sha256: 1abc6a81ee66e8ac9ac09a26e2d6ad7bba23f0a0cc3a6118654f036f9c0e1854 + md5: 06901733131833f5edd68cf3d9679798 + depends: + - __unix + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 3084533 + timestamp: 1771377786730 +- conda: https://conda.anaconda.org/conda-forge/noarch/libgcc-devel_linux-aarch64-14.3.0-h25ba3ff_118.conda + sha256: 058fab0156cb13897f7e4a2fc9d63c922d3de09b6429390365f91b62f1dddb0e + md5: 3733752e5a7a0737c8c4f1897f2074f9 + depends: + - __unix + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 2335839 + timestamp: 1771377646960 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_18.conda + sha256: e318a711400f536c81123e753d4c797a821021fb38970cebfb3f454126016893 + md5: d5e96b1ed75ca01906b3d2469b4ce493 + depends: + - libgcc 15.2.0 he0feb66_18 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 27526 + timestamp: 1771378224552 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-ng-15.2.0-he9431aa_18.conda + sha256: 83bb0415f59634dccfa8335d4163d1f6db00a27b36666736f9842b650b92cf2f + md5: 4feebd0fbf61075a1a9c2e9b3936c257 + depends: + - libgcc 15.2.0 h8acb6b2_18 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 27568 + timestamp: 1771378136019 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-15.2.0-h69a702a_18.conda + sha256: d2c9fad338fd85e4487424865da8e74006ab2e2475bd788f624d7a39b2a72aee + md5: 9063115da5bc35fdc3e1002e69b9ef6e + depends: + - libgfortran5 15.2.0 h68bc16d_18 + constrains: + - libgfortran-ng ==15.2.0=*_18 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 27523 + timestamp: 1771378269450 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran-15.2.0-he9431aa_18.conda + sha256: 7dcd7dff2505d56fd5272a6e712ec912f50a46bf07dc6873a7e853694304e6e4 + md5: 41f261f5e4e2e8cbd236c2f1f15dae1b + depends: + - libgfortran5 15.2.0 h1b7bec0_18 + constrains: + - libgfortran-ng ==15.2.0=*_18 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 27587 + timestamp: 1771378169244 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libgfortran-15.2.0-h7e5c614_18.conda + sha256: fb06c2a2ef06716a0f2a6550f5d13cdd1d89365993068512b7ae3c34e6e665d9 + md5: 34a9f67498721abcfef00178bcf4b190 + depends: + - libgfortran5 15.2.0 hd16e46c_18 + constrains: + - libgfortran-ng ==15.2.0=*_18 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 139761 + timestamp: 1771378423828 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran-15.2.0-h07b0088_18.conda + sha256: 63f89087c3f0c8621c5c89ecceec1e56e5e1c84f65fc9c5feca33a07c570a836 + md5: 26981599908ed2205366e8fc91b37fc6 + depends: + - libgfortran5 15.2.0 hdae7583_18 + constrains: + - libgfortran-ng ==15.2.0=*_18 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 138973 + timestamp: 1771379054939 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-15.2.0-h68bc16d_18.conda + sha256: 539b57cf50ec85509a94ba9949b7e30717839e4d694bc94f30d41c9d34de2d12 + md5: 646855f357199a12f02a87382d429b75 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=15.2.0 + constrains: + - libgfortran 15.2.0 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 2482475 + timestamp: 1771378241063 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran5-15.2.0-h1b7bec0_18.conda + sha256: 85347670dfb4a8d4c13cd7cae54138dcf2b1606b6bede42eef5507bf5f9660c6 + md5: 574d88ce3348331e962cfa5ed451b247 + depends: + - libgcc >=15.2.0 + constrains: + - libgfortran 15.2.0 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 1486341 + timestamp: 1771378148102 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libgfortran5-15.2.0-hd16e46c_18.conda + sha256: ddaf9dcf008c031b10987991aa78643e03c24a534ad420925cbd5851b31faa11 + md5: ca52daf58cea766656266c8771d8be81 + depends: + - libgcc >=15.2.0 + constrains: + - libgfortran 15.2.0 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 1062274 + timestamp: 1771378232014 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran5-15.2.0-hdae7583_18.conda + sha256: 91033978ba25e6a60fb86843cf7e1f7dc8ad513f9689f991c9ddabfaf0361e7e + md5: c4a6f7989cffb0544bfd9207b6789971 + depends: + - libgcc >=15.2.0 + constrains: + - libgfortran 15.2.0 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 598634 + timestamp: 1771378886363 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_18.conda + sha256: 21337ab58e5e0649d869ab168d4e609b033509de22521de1bfed0c031bfc5110 + md5: 239c5e9546c38a1e884d69effcf4c882 + depends: + - __glibc >=2.17,<3.0.a0 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 603262 + timestamp: 1771378117851 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-15.2.0-h8acb6b2_18.conda + sha256: fc716f11a6a8525e27a5d332ef6a689210b0d2a4dd1133edc0f530659aa9faa6 + md5: 4faa39bf919939602e594253bd673958 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 588060 + timestamp: 1771378040807 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libhwloc-2.13.0-default_he001693_1000.conda + sha256: 5041d295813dfb84652557839825880aae296222ab725972285c5abe3b6e4288 + md5: c197985b58bc813d26b42881f0021c82 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libstdcxx >=14 + - libxml2 + - libxml2-16 >=2.14.6 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 2436378 + timestamp: 1770953868164 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libhwloc-2.13.0-default_ha95e27d_1000.conda + sha256: 88888d99e81c93e7331f2eb0fec08b3c4a47a1bfa1c88b3e641f6568569b6261 + md5: 974183f6420938051e2f3208922d057f + depends: + - libgcc >=14 + - libstdcxx >=14 + - libxml2 + - libxml2-16 >=2.14.6 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 2453519 + timestamp: 1770953713701 +- conda: https://conda.anaconda.org/conda-forge/win-64/libhwloc-2.12.2-default_h4379cf1_1000.conda + sha256: 8cdf11333a81085468d9aa536ebb155abd74adc293576f6013fc0c85a7a90da3 + md5: 3b576f6860f838f950c570f4433b086e + depends: + - libwinpthread >=12.0.0.r4.gg4f2fc60ca + - libxml2 + - libxml2-16 >=2.14.6 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 2411241 + timestamp: 1765104337762 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.18-h3b78370_2.conda + sha256: c467851a7312765447155e071752d7bf9bf44d610a5687e32706f480aad2833f + md5: 915f5995e94f60e9a4826e0b0920ee88 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + license: LGPL-2.1-only + purls: [] + size: 790176 + timestamp: 1754908768807 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libiconv-1.18-h90929bb_2.conda + sha256: 1473451cd282b48d24515795a595801c9b65b567fe399d7e12d50b2d6cdb04d9 + md5: 5a86bf847b9b926f3a4f203339748d78 + depends: + - libgcc >=14 + license: LGPL-2.1-only + purls: [] + size: 791226 + timestamp: 1754910975665 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libiconv-1.17-hd75f5a5_2.conda + sha256: 23d4923baeca359423a7347c2ed7aaf48c68603df0cf8b87cc94a10b0d4e9a23 + md5: 6c3628d047e151efba7cf08c5e54d1ca + license: LGPL-2.1-only + purls: [] + size: 666538 + timestamp: 1702682713201 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libiconv-1.18-h57a12c2_2.conda + sha256: a1c8cecdf9966921e13f0ae921309a1f415dfbd2b791f2117cf7e8f5e61a48b6 + md5: 210a85a1119f97ea7887188d176db135 + depends: + - __osx >=10.13 + license: LGPL-2.1-only + size: 737846 + timestamp: 1754908900138 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libiconv-1.17-h0d3ecfb_2.conda + sha256: bc7de5097b97bcafcf7deaaed505f7ce02f648aac8eccc0d5a47cc599a1d0304 + md5: 69bda57310071cf6d2b86caf11573d2d + license: LGPL-2.1-only + purls: [] + size: 676469 + timestamp: 1702682458114 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libiconv-1.18-h23cfdf5_2.conda + sha256: de0336e800b2af9a40bdd694b03870ac4a848161b35c8a2325704f123f185f03 + md5: 4d5a7445f0b25b6a3ddbb56e790f5251 + depends: + - __osx >=11.0 + license: LGPL-2.1-only + size: 750379 + timestamp: 1754909073836 +- conda: https://conda.anaconda.org/conda-forge/win-64/libiconv-1.18-hc1393d2_2.conda + sha256: 0dcdb1a5f01863ac4e8ba006a8b0dc1a02d2221ec3319b5915a1863254d7efa7 + md5: 64571d1dd6cdcfa25d0664a5950fdaa2 + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: LGPL-2.1-only + purls: [] + size: 696926 + timestamp: 1754909290005 +- conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.11.0-5_h47877c9_openblas.conda + build_number: 5 + sha256: c723b6599fcd4c6c75dee728359ef418307280fa3e2ee376e14e85e5bbdda053 + md5: b38076eb5c8e40d0106beda6f95d7609 + depends: + - libblas 3.11.0 5_h4a7cf45_openblas + constrains: + - blas 2.305 openblas + - liblapacke 3.11.0 5*_openblas + - libcblas 3.11.0 5*_openblas + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 18200 + timestamp: 1765818857876 +- conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.11.0-6_h47877c9_openblas.conda + build_number: 6 + sha256: 371f517eb7010b21c6cc882c7606daccebb943307cb9a3bf2c70456a5c024f7d + md5: 881d801569b201c2e753f03c84b85e15 + depends: + - libblas 3.11.0 6_h4a7cf45_openblas + constrains: + - blas 2.306 openblas + - liblapacke 3.11.0 6*_openblas + - libcblas 3.11.0 6*_openblas + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 18624 + timestamp: 1774503065378 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblapack-3.11.0-5_h88aeb00_openblas.conda + build_number: 5 + sha256: 692222d186d3ffbc99eaf04b5b20181fd26aee1edec1106435a0a755c57cce86 + md5: 88d1e4133d1182522b403e9ba7435f04 + depends: + - libblas 3.11.0 5_haddc8a3_openblas + constrains: + - liblapacke 3.11.0 5*_openblas + - blas 2.305 openblas + - libcblas 3.11.0 5*_openblas + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 18392 + timestamp: 1765818627104 +- conda: https://conda.anaconda.org/conda-forge/osx-64/liblapack-3.9.0-22_osx64_openblas.conda + build_number: 22 + sha256: e36744f3e780564d6748b5dd05e15ad6a1af9184cf32ab9d1304c13a6bc3e16b + md5: f21b282ff7ba14df6134a0fe6ab42b1b + depends: + - libblas 3.9.0 22_osx64_openblas + constrains: + - liblapacke 3.9.0 22_osx64_openblas + - blas * openblas + - libcblas 3.9.0 22_osx64_openblas + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 14657 + timestamp: 1712542322711 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblapack-3.9.0-24_osxarm64_openblas.conda + build_number: 24 + sha256: 67fbfd0466eee443cda9596ed22daabedc96b7b4d1b31f49b1c1b0983dd1dd2c + md5: 49a3241f76cdbe705e346204a328f66c + depends: + - libblas 3.9.0 24_osxarm64_openblas + constrains: + - blas * openblas + - liblapacke 3.9.0 24_osxarm64_openblas + - libcblas 3.9.0 24_osxarm64_openblas + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 15063 + timestamp: 1726668815824 +- conda: https://conda.anaconda.org/conda-forge/win-64/liblapack-3.11.0-5_hf9ab0e9_mkl.conda + build_number: 5 + sha256: a2d33f5cc2b8a9042f2af6981c6733ab1a661463823eaa56595a9c58c0ab77e1 + md5: e62c42a4196dee97d20400612afcb2b1 + depends: + - libblas 3.11.0 5_hf2e6a31_mkl + constrains: + - libcblas 3.11.0 5*_mkl + - blas 2.305 mkl + - liblapacke 3.11.0 5*_mkl + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 80225 + timestamp: 1765819148014 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libllvm18-18.1.3-hbcf5fad_0.conda + sha256: bc42a9999c8846f50f5b3bb9a2338caeab34f2d7de8202e3fad7f929f38e3287 + md5: f286e87d892273a1ef3059744c833f91 + depends: + - libcxx >=16 + - libxml2 >=2.12.6,<2.14.0a0 + - libzlib >=1.2.13,<2.0.0a0 + - zstd >=1.5.5,<1.6.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + purls: [] + size: 27580830 + timestamp: 1712517566570 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libllvm18-18.1.3-h30cc82d_0.conda + sha256: 5a8781ab13b163fd028916d050bb209718b14de85493bb7a4b93ea798998b9fe + md5: fad73e8421bcd0de381d172c2224d3a5 + depends: + - libcxx >=16 + - libxml2 >=2.12.6,<2.14.0a0 + - libzlib >=1.2.13,<2.0.0a0 + - zstd >=1.5.5,<1.6.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + purls: [] + size: 25782519 + timestamp: 1712517407600 +- conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.2-hb03c661_0.conda + sha256: 755c55ebab181d678c12e49cced893598f2bab22d582fbbf4d8b83c18be207eb + md5: c7c83eecbb72d88b940c249af56c8b17 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + constrains: + - xz 5.8.2.* + license: 0BSD + purls: [] + size: 113207 + timestamp: 1768752626120 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblzma-5.8.2-he30d5cf_0.conda + sha256: 843c46e20519651a3e357a8928352b16c5b94f4cd3d5481acc48be2e93e8f6a3 + md5: 96944e3c92386a12755b94619bae0b35 + depends: + - libgcc >=14 + constrains: + - xz 5.8.2.* + license: 0BSD + purls: [] + size: 125916 + timestamp: 1768754941722 +- conda: https://conda.anaconda.org/conda-forge/osx-64/liblzma-5.8.2-h11316ed_0.conda + sha256: 7ab3c98abd3b5d5ec72faa8d9f5d4b50dcee4970ed05339bc381861199dabb41 + md5: 688a0c3d57fa118b9c97bf7e471ab46c + depends: + - __osx >=10.13 + constrains: + - xz 5.8.2.* + license: 0BSD + size: 105482 + timestamp: 1768753411348 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.2-h8088a28_0.conda + sha256: 7bfc7ffb2d6a9629357a70d4eadeadb6f88fa26ebc28f606b1c1e5e5ed99dc7e + md5: 009f0d956d7bfb00de86901d16e486c7 + depends: + - __osx >=11.0 + constrains: + - xz 5.8.2.* + license: 0BSD + size: 92242 + timestamp: 1768752982486 +- conda: https://conda.anaconda.org/conda-forge/win-64/liblzma-5.8.2-hfd05255_0.conda + sha256: f25bf293f550c8ed2e0c7145eb404324611cfccff37660869d97abf526eb957c + md5: ba0bfd4c3cf73f299ffe46ff0eaeb8e3 + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + constrains: + - xz 5.8.2.* + license: 0BSD + purls: [] + size: 106169 + timestamp: 1768752763559 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libmamba-2.5.0-hd28c85e_0.conda + sha256: ca2d384f30e1582b7c6ae9f1406fb51f993e44c92799e3cabf2130f69c7261d5 + md5: a24532d0660b8a58ca2955301281f71e + depends: + - cpp-expected >=1.3.1,<1.3.2.0a0 + - __glibc >=2.17,<3.0.a0 + - libstdcxx >=14 + - libgcc >=14 + - zstd >=1.5.7,<1.6.0a0 + - reproc >=14.2,<15.0a0 + - spdlog >=1.17.0,<1.18.0a0 + - libarchive >=3.8.5,<3.9.0a0 + - openssl >=3.5.4,<4.0a0 + - nlohmann_json-abi ==3.12.0 + - fmt >=12.1.0,<12.2.0a0 + - simdjson >=4.2.4,<4.3.0a0 + - libsolv >=0.7.35,<0.8.0a0 + - reproc-cpp >=14.2,<15.0a0 + - libcurl >=8.18.0,<9.0a0 + - yaml-cpp >=0.8.0,<0.9.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 2567543 + timestamp: 1767884157869 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libmamba-2.5.0-hc712cdd_0.conda + sha256: 480913318158db625ca7862a2447eda8aa84c8a315d4f86cc1764a5f1050e61c + md5: 45c3a33d8c6db2382678b3c90af03dd4 + depends: + - cpp-expected >=1.3.1,<1.3.2.0a0 + - libstdcxx >=14 + - libgcc >=14 + - nlohmann_json-abi ==3.12.0 + - zstd >=1.5.7,<1.6.0a0 + - libsolv >=0.7.35,<0.8.0a0 + - yaml-cpp >=0.8.0,<0.9.0a0 + - reproc-cpp >=14.2,<15.0a0 + - fmt >=12.1.0,<12.2.0a0 + - spdlog >=1.17.0,<1.18.0a0 + - reproc >=14.2,<15.0a0 + - openssl >=3.5.4,<4.0a0 + - simdjson >=4.2.4,<4.3.0a0 + - libarchive >=3.8.5,<3.9.0a0 + - libcurl >=8.18.0,<9.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 2414027 + timestamp: 1767884182395 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libmamba-2.5.0-h7fe6c55_0.conda + sha256: 614dc840d50442e8732e7373821ca5802626bd9b0654491a135e6cf3dbbbb428 + md5: bcc1e88e0437b6a0a5fb5bab84b7b995 + depends: + - cpp-expected >=1.3.1,<1.3.2.0a0 + - __osx >=10.13 + - libcxx >=19 + - simdjson >=4.2.4,<4.3.0a0 + - reproc >=14.2,<15.0a0 + - libarchive >=3.8.5,<3.9.0a0 + - yaml-cpp >=0.8.0,<0.9.0a0 + - spdlog >=1.17.0,<1.18.0a0 + - nlohmann_json-abi ==3.12.0 + - zstd >=1.5.7,<1.6.0a0 + - reproc-cpp >=14.2,<15.0a0 + - openssl >=3.5.4,<4.0a0 + - libcurl >=8.18.0,<9.0a0 + - fmt >=12.1.0,<12.2.0a0 + - libsolv >=0.7.35,<0.8.0a0 + license: BSD-3-Clause + license_family: BSD + size: 1785898 + timestamp: 1767884200743 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmamba-2.5.0-h7950639_0.conda + sha256: 78fccef61fe4d6763c60e19dd5bc8aad7db553188609e3bd91159d158aecabaa + md5: 29e8e662089a1226a90a5dc5d499b7b7 + depends: + - cpp-expected >=1.3.1,<1.3.2.0a0 + - libcxx >=19 + - __osx >=11.0 + - zstd >=1.5.7,<1.6.0a0 + - reproc >=14.2,<15.0a0 + - libsolv >=0.7.35,<0.8.0a0 + - fmt >=12.1.0,<12.2.0a0 + - yaml-cpp >=0.8.0,<0.9.0a0 + - libarchive >=3.8.5,<3.9.0a0 + - nlohmann_json-abi ==3.12.0 + - spdlog >=1.17.0,<1.18.0a0 + - simdjson >=4.2.4,<4.3.0a0 + - libcurl >=8.18.0,<9.0a0 + - openssl >=3.5.4,<4.0a0 + - reproc-cpp >=14.2,<15.0a0 + license: BSD-3-Clause + license_family: BSD + size: 1653523 + timestamp: 1767884201469 +- conda: https://conda.anaconda.org/conda-forge/win-64/libmamba-2.5.0-h06825f5_0.conda + sha256: 632acf45a127242ca0dddc942c635bd43de718c51477ac000ed579410b7363a3 + md5: df96c0c3390a753e0c2df57fdbf98d97 + depends: + - cpp-expected >=1.3.1,<1.3.2.0a0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - libarchive >=3.8.5,<3.9.0a0 + - libcurl >=8.18.0,<9.0a0 + - spdlog >=1.17.0,<1.18.0a0 + - zstd >=1.5.7,<1.6.0a0 + - yaml-cpp >=0.8.0,<0.9.0a0 + - reproc >=14.2,<15.0a0 + - fmt >=12.1.0,<12.2.0a0 + - nlohmann_json-abi ==3.12.0 + - libsolv >=0.7.35,<0.8.0a0 + - simdjson >=4.2.4,<4.3.0a0 + - openssl >=3.5.4,<4.0a0 + - reproc-cpp >=14.2,<15.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 4995231 + timestamp: 1767884194847 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libmamba-spdlog-2.5.0-h12fcf84_0.conda + sha256: 75deca8004690aed0985845f734927e48aa49a683ee09b3d9ff4e22ace9e4a8e + md5: c866cdca3b16b5c7a0fd9916d5d64577 + depends: + - libstdcxx >=14 + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + - libmamba >=2.5.0,<2.6.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 20396 + timestamp: 1767884157870 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libmamba-spdlog-2.5.0-h3ad78e7_0.conda + sha256: d100a04349427cfb8cc76b4c0736bd27fd77ccb9c07e8a25e9988cbf718c610b + md5: 4abcea9b345dd46ecc86ca7c20f3db62 + depends: + - libstdcxx >=14 + - libgcc >=14 + - libmamba >=2.5.0,<2.6.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 23017 + timestamp: 1767884182397 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libmamba-spdlog-2.5.0-hb923e0c_0.conda + sha256: 3bc7cdc7d617a62b86df95cb198614794a533edc360d47b5116a9295215e6955 + md5: 7e25602d391cbdba87191a231594058d + depends: + - libcxx >=19 + - __osx >=10.13 + - libmamba >=2.5.0,<2.6.0a0 + license: BSD-3-Clause + license_family: BSD + size: 20784 + timestamp: 1767884200753 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmamba-spdlog-2.5.0-h85b9800_0.conda + sha256: c0efbd9cf938a44fe98cfeb77d9bbb119f58bf0202ec5009b7d6621c6b96721c + md5: 6a3a2f6d6e90363288a96bc355b417c2 + depends: + - libcxx >=19 + - __osx >=11.0 + - libmamba >=2.5.0,<2.6.0a0 + license: BSD-3-Clause + license_family: BSD + size: 23068 + timestamp: 1767884201476 +- conda: https://conda.anaconda.org/conda-forge/win-64/libmamba-spdlog-2.5.0-h9ae1bf1_0.conda + sha256: 172991ecd8ffe8aadff9f083b8c1de282d91e670c939cdfff5970ccacbe98548 + md5: 463b59502db7115998f7d537ccd932df + depends: + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - libmamba >=2.5.0,<2.6.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 18007 + timestamp: 1767884194852 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libmambapy-2.5.0-py310h74f1d5f_0.conda + sha256: a949389f9c3196fed8377a47ee266546f3e35d6d237f8209d3bb77ffc104c748 + md5: edd4cf55ce1926c90c5702ba24b3fc08 + depends: + - python + - libmamba ==2.5.0 hd28c85e_0 + - libmamba-spdlog ==2.5.0 h12fcf84_0 + - libstdcxx >=14 + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + - libmamba >=2.5.0,<2.6.0a0 + - openssl >=3.5.4,<4.0a0 + - nlohmann_json-abi ==3.12.0 + - zstd >=1.5.7,<1.6.0a0 + - spdlog >=1.17.0,<1.18.0a0 + - pybind11-abi ==11 + - python_abi 3.10.* *_cp310 + - fmt >=12.1.0,<12.2.0a0 + - yaml-cpp >=0.8.0,<0.9.0a0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/libmambapy?source=hash-mapping + size: 943029 + timestamp: 1767884157872 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libmambapy-2.5.0-py311hc5d5c7c_0.conda + sha256: ebd16f6685bdc2f0cf595f0f441b638b378a43e76e2124763c35d548df09084b + md5: f72a2daebdd84c968828602bfa081ae5 + depends: + - python + - libmamba ==2.5.0 hd28c85e_0 + - libmamba-spdlog ==2.5.0 h12fcf84_0 + - __glibc >=2.17,<3.0.a0 + - libstdcxx >=14 + - libgcc >=14 + - zstd >=1.5.7,<1.6.0a0 + - fmt >=12.1.0,<12.2.0a0 + - python_abi 3.11.* *_cp311 + - openssl >=3.5.4,<4.0a0 + - yaml-cpp >=0.8.0,<0.9.0a0 + - spdlog >=1.17.0,<1.18.0a0 + - nlohmann_json-abi ==3.12.0 + - pybind11-abi ==11 + - libmamba >=2.5.0,<2.6.0a0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/libmambapy?source=hash-mapping + size: 944797 + timestamp: 1767884157872 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libmambapy-2.5.0-py314hcbd71af_0.conda + sha256: 578a2ec09095c81674af0fa88ee44083c3a4ab10c31b498ddfa519fc9ff855b1 + md5: 54125b30d5031808bca8018561843f40 + depends: + - python + - libmamba ==2.5.0 hd28c85e_0 + - libmamba-spdlog ==2.5.0 h12fcf84_0 + - libstdcxx >=14 + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + - zstd >=1.5.7,<1.6.0a0 + - python_abi 3.14.* *_cp314 + - pybind11-abi ==11 + - fmt >=12.1.0,<12.2.0a0 + - nlohmann_json-abi ==3.12.0 + - spdlog >=1.17.0,<1.18.0a0 + - openssl >=3.5.4,<4.0a0 + - yaml-cpp >=0.8.0,<0.9.0a0 + - libmamba >=2.5.0,<2.6.0a0 + license: BSD-3-Clause + license_family: BSD + size: 948138 + timestamp: 1767884157875 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libmambapy-2.5.0-py310hdf79504_0.conda + sha256: 48fe0ec831974af7f660bfe8e8bfbf5a1a4a2fed125496b1ee53fd83c40a5027 + md5: 59097ccbbc66568039aa714f48f77700 + depends: + - python + - libmamba ==2.5.0 hc712cdd_0 + - libmamba-spdlog ==2.5.0 h3ad78e7_0 + - libstdcxx >=14 + - libgcc >=14 + - python 3.10.* *_cpython + - zstd >=1.5.7,<1.6.0a0 + - pybind11-abi ==11 + - spdlog >=1.17.0,<1.18.0a0 + - yaml-cpp >=0.8.0,<0.9.0a0 + - fmt >=12.1.0,<12.2.0a0 + - nlohmann_json-abi ==3.12.0 + - openssl >=3.5.4,<4.0a0 + - python_abi 3.10.* *_cp310 + - libmamba >=2.5.0,<2.6.0a0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/libmambapy?source=hash-mapping + size: 832789 + timestamp: 1767884182399 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libmambapy-2.5.0-py311h6a8bf82_0.conda + sha256: caef2c6e32e15afc8bb1cf66151223738a29d45cf639acad0267bce948518cc7 + md5: e022e9542b664361fcbc1f9c5528a0a8 + depends: + - python + - libmamba ==2.5.0 hc712cdd_0 + - libmamba-spdlog ==2.5.0 h3ad78e7_0 + - python 3.11.* *_cpython + - libstdcxx >=14 + - libgcc >=14 + - nlohmann_json-abi ==3.12.0 + - fmt >=12.1.0,<12.2.0a0 + - libmamba >=2.5.0,<2.6.0a0 + - python_abi 3.11.* *_cp311 + - zstd >=1.5.7,<1.6.0a0 + - pybind11-abi ==11 + - openssl >=3.5.4,<4.0a0 + - yaml-cpp >=0.8.0,<0.9.0a0 + - spdlog >=1.17.0,<1.18.0a0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/libmambapy?source=hash-mapping + size: 832040 + timestamp: 1767884182400 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libmambapy-2.5.0-py314h709e558_0.conda + sha256: c226d92922115e9e4a0097b15521b0238a69a028ed0d525f5a5ed6696314ed69 + md5: b9108a7151ea087a321b7ebe3aaba999 + depends: + - python + - libmamba ==2.5.0 hc712cdd_0 + - libmamba-spdlog ==2.5.0 h3ad78e7_0 + - python 3.14.* *_cp314 + - libstdcxx >=14 + - libgcc >=14 + - fmt >=12.1.0,<12.2.0a0 + - spdlog >=1.17.0,<1.18.0a0 + - python_abi 3.14.* *_cp314 + - zstd >=1.5.7,<1.6.0a0 + - yaml-cpp >=0.8.0,<0.9.0a0 + - libmamba >=2.5.0,<2.6.0a0 + - pybind11-abi ==11 + - openssl >=3.5.4,<4.0a0 + - nlohmann_json-abi ==3.12.0 + license: BSD-3-Clause + license_family: BSD + size: 834849 + timestamp: 1767884182402 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libmambapy-2.5.0-py314haca2e77_0.conda + sha256: a3dad1d241d2fd1831dd4e8893ecdd4e4daa1cba4f1c3d8b630d5f4cd5a1279d + md5: a015fcf12fbe739adfae4cb32f627da6 + depends: + - python + - libmamba ==2.5.0 h7fe6c55_0 + - libmamba-spdlog ==2.5.0 hb923e0c_0 + - __osx >=10.13 + - libcxx >=19 + - fmt >=12.1.0,<12.2.0a0 + - pybind11-abi ==11 + - libmamba >=2.5.0,<2.6.0a0 + - yaml-cpp >=0.8.0,<0.9.0a0 + - python_abi 3.14.* *_cp314 + - zstd >=1.5.7,<1.6.0a0 + - spdlog >=1.17.0,<1.18.0a0 + - nlohmann_json-abi ==3.12.0 + - openssl >=3.5.4,<4.0a0 + license: BSD-3-Clause + license_family: BSD + size: 815795 + timestamp: 1767884200763 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmambapy-2.5.0-py314hf8f60b7_0.conda + sha256: 11824fa9b721afe43cfd83ba899c893c1dba0b42c85ec618aa9284fd2ad66d6c + md5: c215957a49ac69b30d94a39eb1182009 + depends: + - python + - libmamba ==2.5.0 h7950639_0 + - libmamba-spdlog ==2.5.0 h85b9800_0 + - __osx >=11.0 + - python 3.14.* *_cp314 + - libcxx >=19 + - yaml-cpp >=0.8.0,<0.9.0a0 + - libmamba >=2.5.0,<2.6.0a0 + - zstd >=1.5.7,<1.6.0a0 + - spdlog >=1.17.0,<1.18.0a0 + - nlohmann_json-abi ==3.12.0 + - python_abi 3.14.* *_cp314 + - openssl >=3.5.4,<4.0a0 + - fmt >=12.1.0,<12.2.0a0 + - pybind11-abi ==11 + license: BSD-3-Clause + license_family: BSD + size: 769644 + timestamp: 1767884201481 +- conda: https://conda.anaconda.org/conda-forge/win-64/libmambapy-2.5.0-py310h1916185_0.conda + sha256: c62cb131596e5aaba82591a5c76081d06b6b4dde5af25c25cbd796efc0458fab + md5: 4c67f7b1103f72faa72a50f79587990b + depends: + - python + - libmamba ==2.5.0 h06825f5_0 + - libmamba-spdlog ==2.5.0 h9ae1bf1_0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - spdlog >=1.17.0,<1.18.0a0 + - python_abi 3.10.* *_cp310 + - fmt >=12.1.0,<12.2.0a0 + - nlohmann_json-abi ==3.12.0 + - openssl >=3.5.4,<4.0a0 + - yaml-cpp >=0.8.0,<0.9.0a0 + - libmamba >=2.5.0,<2.6.0a0 + - zstd >=1.5.7,<1.6.0a0 + - pybind11-abi ==11 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/libmambapy?source=hash-mapping + size: 583910 + timestamp: 1767884194854 +- conda: https://conda.anaconda.org/conda-forge/win-64/libmambapy-2.5.0-py311hb0041a4_0.conda + sha256: d3ec31a3cfb43b07d04899cfd84376a31049be9611ab249b4889f0672e6d81b9 + md5: 2b522dd15f2449d921759864fd0648aa + depends: + - python + - libmamba ==2.5.0 h06825f5_0 + - libmamba-spdlog ==2.5.0 h9ae1bf1_0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - nlohmann_json-abi ==3.12.0 + - openssl >=3.5.4,<4.0a0 + - python_abi 3.11.* *_cp311 + - zstd >=1.5.7,<1.6.0a0 + - libmamba >=2.5.0,<2.6.0a0 + - fmt >=12.1.0,<12.2.0a0 + - pybind11-abi ==11 + - yaml-cpp >=0.8.0,<0.9.0a0 + - spdlog >=1.17.0,<1.18.0a0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/libmambapy?source=hash-mapping + size: 583683 + timestamp: 1767884194856 +- conda: https://conda.anaconda.org/conda-forge/win-64/libmambapy-2.5.0-py314h532c739_0.conda + sha256: 3b5bec6472c07448e8485def16a11157c32295e9016130809fc4b3b1e6dda174 + md5: c9cd67775b772d64b54239fefb4d8504 + depends: + - python + - libmamba ==2.5.0 h06825f5_0 + - libmamba-spdlog ==2.5.0 h9ae1bf1_0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - fmt >=12.1.0,<12.2.0a0 + - zstd >=1.5.7,<1.6.0a0 + - yaml-cpp >=0.8.0,<0.9.0a0 + - nlohmann_json-abi ==3.12.0 + - spdlog >=1.17.0,<1.18.0a0 + - pybind11-abi ==11 + - libmamba >=2.5.0,<2.6.0a0 + - python_abi 3.14.* *_cp314 + - openssl >=3.5.4,<4.0a0 + license: BSD-3-Clause + license_family: BSD + size: 587744 + timestamp: 1767884194858 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb03c661_1.conda + sha256: fe171ed5cf5959993d43ff72de7596e8ac2853e9021dec0344e583734f1e0843 + md5: 2c21e66f50753a083cbe6b80f38268fa + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + license: BSD-2-Clause + license_family: BSD + size: 92400 + timestamp: 1769482286018 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libmpdec-4.0.0-he30d5cf_1.conda + sha256: 57c0dd12d506e84541c4e877898bd2a59cca141df493d34036f18b2751e0a453 + md5: 7b9813e885482e3ccb1fa212b86d7fd0 + depends: + - libgcc >=14 + license: BSD-2-Clause + license_family: BSD + size: 114056 + timestamp: 1769482343003 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libmpdec-4.0.0-hf3981d6_1.conda + sha256: 1096c740109386607938ab9f09a7e9bca06d86770a284777586d6c378b8fb3fd + md5: ec88ba8a245855935b871a7324373105 + depends: + - __osx >=10.13 + license: BSD-2-Clause + license_family: BSD + size: 79899 + timestamp: 1769482558610 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmpdec-4.0.0-h84a0fba_1.conda + sha256: 1089c7f15d5b62c622625ec6700732ece83be8b705da8c6607f4dabb0c4bd6d2 + md5: 57c4be259f5e0b99a5983799a228ae55 + depends: + - __osx >=11.0 + license: BSD-2-Clause + license_family: BSD + size: 73690 + timestamp: 1769482560514 +- conda: https://conda.anaconda.org/conda-forge/win-64/libmpdec-4.0.0-hfd05255_1.conda + sha256: 40dcd0b9522a6e0af72a9db0ced619176e7cfdb114855c7a64f278e73f8a7514 + md5: e4a9fc2bba3b022dad998c78856afe47 + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: BSD-2-Clause + license_family: BSD + size: 89411 + timestamp: 1769482314283 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.67.0-had1ee68_0.conda + sha256: a4a7dab8db4dc81c736e9a9b42bdfd97b087816e029e221380511960ac46c690 + md5: b499ce4b026493a13774bcf0f4c33849 + depends: + - __glibc >=2.17,<3.0.a0 + - c-ares >=1.34.5,<2.0a0 + - libev >=4.33,<4.34.0a0 + - libev >=4.33,<5.0a0 + - libgcc >=14 + - libstdcxx >=14 + - libzlib >=1.3.1,<2.0a0 + - openssl >=3.5.2,<4.0a0 + license: MIT + license_family: MIT + purls: [] + size: 666600 + timestamp: 1756834976695 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libnghttp2-1.67.0-ha888d0e_0.conda + sha256: b03f406fd5c3f865a5e08c89b625245a9c4e026438fd1a445e45e6a0d69c2749 + md5: 981082c1cc262f514a5a2cf37cab9b81 + depends: + - c-ares >=1.34.5,<2.0a0 + - libev >=4.33,<4.34.0a0 + - libev >=4.33,<5.0a0 + - libgcc >=14 + - libstdcxx >=14 + - libzlib >=1.3.1,<2.0a0 + - openssl >=3.5.2,<4.0a0 + license: MIT + license_family: MIT + purls: [] + size: 728661 + timestamp: 1756835019535 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libnghttp2-1.68.1-hd3077d7_0.conda + sha256: 13782715b9eeebc4ad16d36e84ca569d1495e3516aea3fe546a32caa0a597d82 + md5: be5f0f007a4500a226ef001115535a3d + depends: + - c-ares >=1.34.6,<2.0a0 + - libev >=4.33,<4.34.0a0 + - libev >=4.33,<5.0a0 + - libgcc >=14 + - libstdcxx >=14 + - libzlib >=1.3.1,<2.0a0 + - openssl >=3.5.5,<4.0a0 + license: MIT + license_family: MIT + purls: [] + size: 726928 + timestamp: 1773854039807 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libnghttp2-1.52.0-he2ab024_0.conda + sha256: 093e4f3f62b3b07befa403e84a1f550cffe3b3961e435d42a75284f44be5f68a + md5: 12ac7d100bf260263e30a019517f42a2 + depends: + - c-ares >=1.18.1,<2.0a0 + - libcxx >=14.0.6 + - libev >=4.33,<4.34.0a0 + - libzlib >=1.2.13,<2.0.0a0 + - openssl >=3.0.8,<4.0a0 + license: MIT + license_family: MIT + purls: [] + size: 613074 + timestamp: 1677678399575 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libnghttp2-1.67.0-h3338091_0.conda + sha256: c48d7e1cc927aef83ff9c48ae34dd1d7495c6ccc1edc4a3a6ba6aff1624be9ac + md5: e7630cef881b1174d40f3e69a883e55f + depends: + - __osx >=10.13 + - c-ares >=1.34.5,<2.0a0 + - libcxx >=19 + - libev >=4.33,<4.34.0a0 + - libev >=4.33,<5.0a0 + - libzlib >=1.3.1,<2.0a0 + - openssl >=3.5.2,<4.0a0 + license: MIT + license_family: MIT + size: 605680 + timestamp: 1756835898134 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libnghttp2-1.52.0-hae82a92_0.conda + sha256: 1a3944d6295dcbecdf6489ce8a05fe416ad401727c901ec390e9200a351bdb10 + md5: 1d319e95a0216f801293626a00337712 + depends: + - c-ares >=1.18.1,<2.0a0 + - libcxx >=14.0.6 + - libev >=4.33,<4.34.0a0 + - libzlib >=1.2.13,<2.0.0a0 + - openssl >=3.0.8,<4.0a0 + license: MIT + license_family: MIT + purls: [] + size: 564295 + timestamp: 1677678452375 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libnghttp2-1.67.0-hc438710_0.conda + sha256: a07cb53b5ffa2d5a18afc6fd5a526a5a53dd9523fbc022148bd2f9395697c46d + md5: a4b4dd73c67df470d091312ab87bf6ae + depends: + - __osx >=11.0 + - c-ares >=1.34.5,<2.0a0 + - libcxx >=19 + - libev >=4.33,<4.34.0a0 + - libev >=4.33,<5.0a0 + - libzlib >=1.3.1,<2.0a0 + - openssl >=3.5.2,<4.0a0 + license: MIT + license_family: MIT + size: 575454 + timestamp: 1756835746393 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hb9d3cd8_1.conda + sha256: 927fe72b054277cde6cb82597d0fcf6baf127dcbce2e0a9d8925a68f1265eef5 + md5: d864d34357c3b65a4b731f78c0801dc4 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + license: LGPL-2.1-only + license_family: GPL + purls: [] + size: 33731 + timestamp: 1750274110928 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libnsl-2.0.1-h86ecc28_1.conda + sha256: c0dc4d84198e3eef1f37321299e48e2754ca83fd12e6284754e3cb231357c3a5 + md5: d5d58b2dc3e57073fe22303f5fed4db7 + depends: + - libgcc >=13 + license: LGPL-2.1-only + license_family: GPL + purls: [] + size: 34831 + timestamp: 1750274211 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.30-pthreads_h94d23a6_4.conda + sha256: 199d79c237afb0d4780ccd2fbf829cea80743df60df4705202558675e07dd2c5 + md5: be43915efc66345cccb3c310b6ed0374 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libgfortran + - libgfortran5 >=14.3.0 + constrains: + - openblas >=0.3.30,<0.3.31.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 5927939 + timestamp: 1763114673331 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.32-pthreads_h94d23a6_0.conda + sha256: 6dc30b28f32737a1c52dada10c8f3a41bc9e021854215efca04a7f00487d09d9 + md5: 89d61bc91d3f39fda0ca10fcd3c68594 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libgfortran + - libgfortran5 >=14.3.0 + constrains: + - openblas >=0.3.32,<0.3.33.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 5928890 + timestamp: 1774471724897 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libopenblas-0.3.30-pthreads_h9d3fd7e_4.conda + sha256: 794a7270ea049ec931537874cd8d2de0ef4b3cef71c055cfd8b4be6d2f4228b0 + md5: 11d7d57b7bdd01da745bbf2b67020b2e + depends: + - libgcc >=14 + - libgfortran + - libgfortran5 >=14.3.0 + constrains: + - openblas >=0.3.30,<0.3.31.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 4959359 + timestamp: 1763114173544 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libopenblas-0.3.27-openmp_hfef2a42_0.conda + sha256: 45519189c0295296268cb7eabeeaa03ef54d780416c9a24be1d2a21db63a7848 + md5: 00237c9c7f2cb6725fe2960680a6e225 + depends: + - libgfortran >=5 + - libgfortran5 >=12.3.0 + - llvm-openmp >=16.0.6 + constrains: + - openblas >=0.3.27,<0.3.28.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 6047531 + timestamp: 1712366254156 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libopenblas-0.3.27-openmp_h6c19121_0.conda + sha256: feb2662444fc98a4842fe54cc70b1f109b2146108e7bac2b3bbad1f219cede90 + md5: 82eba59f4eca26a9fc904d584f8761c0 + depends: + - libgfortran >=5 + - libgfortran5 >=12.3.0 + - llvm-openmp >=16.0.6 + constrains: + - openblas >=0.3.27,<0.3.28.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 2925015 + timestamp: 1712364212874 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libsanitizer-14.3.0-h8f1669f_18.conda + sha256: e03ed186eefb46d7800224ad34bad1268c9d19ecb8f621380a50601c6221a4a7 + md5: ad3a0e2dc4cce549b2860e2ef0e6d75b + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14.3.0 + - libstdcxx >=14.3.0 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 7949259 + timestamp: 1771377982207 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsanitizer-14.3.0-hedb4206_18.conda + sha256: 48641a458e3da681038af7ebdab143f9b6861ad9d1dcc2b4997ff2b744709423 + md5: 03feac8b6e64b72ae536fdb264e2618d + depends: + - libgcc >=14.3.0 + - libstdcxx >=14.3.0 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 7526147 + timestamp: 1771377792671 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libsolv-0.7.35-h9463b59_0.conda + sha256: 2fc2cdc8ea4dfd9277ae910fa3cfbf342d7890837a2002cf427fd306a869150b + md5: 21769ce326958ec230cdcbd0f2ad97eb + depends: + - libstdcxx >=14 + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + - libzlib >=1.3.1,<2.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 518374 + timestamp: 1754325691186 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsolv-0.7.35-hdda61c4_0.conda + sha256: f68dde30e903721825214310a98ff2444857d168b12ef657c064aad22a620f06 + md5: 3e817cbcc10f018c547a1b4885094b15 + depends: + - libstdcxx >=14 + - libgcc >=14 + - libzlib >=1.3.1,<2.0a0 + license: BSD-3-Clause + license_family: BSD + size: 535157 + timestamp: 1754325829284 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsolv-0.7.36-hdda61c4_0.conda + sha256: 25019059bcbe38bdf66899d3d7b5dd48d17e01b2ff9f9e8e4d494ce51e156d75 + md5: 9b21c050436d116716f113cecd3bbcb8 + depends: + - libstdcxx >=14 + - libgcc >=14 + - libzlib >=1.3.1,<2.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 535353 + timestamp: 1773328550407 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libsolv-0.7.35-h6fd32b5_0.conda + sha256: 9a510035a9b72e3e059f2cd5f031f300ed8f2971014fcdea06a84c104ce3b44b + md5: 9aca75cdbe9f71e9b2e717fb3e02cba0 + depends: + - __osx >=10.13 + - libcxx >=19 + - libzlib >=1.3.1,<2.0a0 + license: BSD-3-Clause + license_family: BSD + size: 457297 + timestamp: 1754325699071 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsolv-0.7.35-h5f525b2_0.conda + sha256: 6da97a1c572659c2be3c3f2f39d9238dac5af2b1fd546adf2b735b0fda2ed8ec + md5: b7ffc6dc926929b9b35af5084a761f26 + depends: + - libcxx >=19 + - __osx >=11.0 + - libzlib >=1.3.1,<2.0a0 + license: BSD-3-Clause + license_family: BSD + size: 428408 + timestamp: 1754325703193 +- conda: https://conda.anaconda.org/conda-forge/win-64/libsolv-0.7.35-h8883371_0.conda + sha256: 80ccb7857fa2b60679a5209ca04334c86c46a441e8f4f2859308b69f8e1e928a + md5: 987be7025314bcfe936de3f0e91082b5 + depends: + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - libzlib >=1.3.1,<2.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 466924 + timestamp: 1754325716718 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.52.0-hf4e2dac_0.conda + sha256: d716847b7deca293d2e49ed1c8ab9e4b9e04b9d780aea49a97c26925b28a7993 + md5: fd893f6a3002a635b5e50ceb9dd2c0f4 + depends: + - __glibc >=2.17,<3.0.a0 + - icu >=78.2,<79.0a0 + - libgcc >=14 + - libzlib >=1.3.1,<2.0a0 + license: blessing + purls: [] + size: 951405 + timestamp: 1772818874251 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.52.0-h10b116e_0.conda + sha256: 1ddaf91b44fae83856276f4cb7ce544ffe41d4b55c1e346b504c6b45f19098d6 + md5: 77891484f18eca74b8ad83694da9815e + depends: + - icu >=78.2,<79.0a0 + - libgcc >=14 + - libzlib >=1.3.1,<2.0a0 + license: blessing + purls: [] + size: 952296 + timestamp: 1772818881550 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.45.3-h92b6c6a_0.conda + sha256: 4d44b68fb29dcbc2216a8cae0b274b02ef9b4ae05d1d0f785362ed30b91c9b52 + md5: 68e462226209f35182ef66eda0f794ff + depends: + - libzlib >=1.2.13,<2.0.0a0 + license: Unlicense + purls: [] + size: 902546 + timestamp: 1713367776445 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.52.0-h77d7759_0.conda + sha256: f500d1cd50cfcd288d02b8fc3c3b7ecf8de6fec7b86e57ea058def02908e4231 + md5: d553eb96758e038b04027b30fe314b2d + depends: + - __osx >=11.0 + - libzlib >=1.3.1,<2.0a0 + license: blessing + size: 996526 + timestamp: 1772819669038 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.45.3-h091b4b1_0.conda + sha256: 4337f466eb55bbdc74e168b52ec8c38f598e3664244ec7a2536009036e2066cc + md5: c8c1186c7f3351f6ffddb97b1f54fc58 + depends: + - libzlib >=1.2.13,<2.0.0a0 + license: Unlicense + purls: [] + size: 824794 + timestamp: 1713367748819 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.52.0-h1ae2325_0.conda + sha256: beb0fd5594d6d7c7cd42c992b6bb4d66cbb39d6c94a8234f15956da99a04306c + md5: f6233a3fddc35a2ec9f617f79d6f3d71 + depends: + - __osx >=11.0 + - icu >=78.2,<79.0a0 + - libzlib >=1.3.1,<2.0a0 + license: blessing + size: 918420 + timestamp: 1772819478684 +- conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.52.0-hf5d6505_0.conda + sha256: 5fccf1e4e4062f8b9a554abf4f9735a98e70f82e2865d0bfdb47b9de94887583 + md5: 8830689d537fda55f990620680934bb1 + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: blessing + purls: [] + size: 1297302 + timestamp: 1772818899033 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libssh2-1.11.1-hcf80075_0.conda + sha256: fa39bfd69228a13e553bd24601332b7cfeb30ca11a3ca50bb028108fe90a7661 + md5: eecce068c7e4eddeb169591baac20ac4 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + - libzlib >=1.3.1,<2.0a0 + - openssl >=3.5.0,<4.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 304790 + timestamp: 1745608545575 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libssh2-1.11.1-h18c354c_0.conda + sha256: 1e289bcce4ee6a5817a19c66e296f3c644dcfa6e562e5c1cba807270798814e7 + md5: eecc495bcfdd9da8058969656f916cc2 + depends: + - libgcc >=13 + - libzlib >=1.3.1,<2.0a0 + - openssl >=3.5.0,<4.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 311396 + timestamp: 1745609845915 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libssh2-1.11.0-hd019ec5_0.conda + sha256: f3886763b88f4b24265db6036535ef77b7b77ce91b1cbe588c0fbdd861eec515 + md5: ca3a72efba692c59a90d4b9fc0dfe774 + depends: + - libzlib >=1.2.13,<2.0.0a0 + - openssl >=3.1.1,<4.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 259556 + timestamp: 1685837820566 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libssh2-1.11.1-hed3591d_0.conda + sha256: 00654ba9e5f73aa1f75c1f69db34a19029e970a4aeb0fa8615934d8e9c369c3c + md5: a6cb15db1c2dc4d3a5f6cf3772e09e81 + depends: + - __osx >=10.13 + - libzlib >=1.3.1,<2.0a0 + - openssl >=3.5.0,<4.0a0 + license: BSD-3-Clause + license_family: BSD + size: 284216 + timestamp: 1745608575796 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libssh2-1.11.0-h7a5bd25_0.conda + sha256: bb57d0c53289721fff1eeb3103a1c6a988178e88d8a8f4345b0b91a35f0e0015 + md5: 029f7dc931a3b626b94823bc77830b01 + depends: + - libzlib >=1.2.13,<2.0.0a0 + - openssl >=3.1.1,<4.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 255610 + timestamp: 1685837894256 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libssh2-1.11.1-h1590b86_0.conda + sha256: 8bfe837221390ffc6f111ecca24fa12d4a6325da0c8d131333d63d6c37f27e0a + md5: b68e8f66b94b44aaa8de4583d3d4cc40 + depends: + - libzlib >=1.3.1,<2.0a0 + - openssl >=3.5.0,<4.0a0 + license: BSD-3-Clause + license_family: BSD + size: 279193 + timestamp: 1745608793272 +- conda: https://conda.anaconda.org/conda-forge/win-64/libssh2-1.11.1-h9aa295b_0.conda + sha256: cbdf93898f2e27cefca5f3fe46519335d1fab25c4ea2a11b11502ff63e602c09 + md5: 9dce2f112bfd3400f4f432b3d0ac07b2 + depends: + - libzlib >=1.3.1,<2.0a0 + - openssl >=3.5.0,<4.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 292785 + timestamp: 1745608759342 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_18.conda + sha256: 78668020064fdaa27e9ab65cd2997e2c837b564ab26ce3bf0e58a2ce1a525c6e + md5: 1b08cd684f34175e4514474793d44bcb + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc 15.2.0 he0feb66_18 + constrains: + - libstdcxx-ng ==15.2.0=*_18 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 5852330 + timestamp: 1771378262446 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-15.2.0-hef695bb_18.conda + sha256: 31fdb9ffafad106a213192d8319b9f810e05abca9c5436b60e507afb35a6bc40 + md5: f56573d05e3b735cb03efeb64a15f388 + depends: + - libgcc 15.2.0 h8acb6b2_18 + constrains: + - libstdcxx-ng ==15.2.0=*_18 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 5541411 + timestamp: 1771378162499 +- conda: https://conda.anaconda.org/conda-forge/noarch/libstdcxx-devel_linux-64-14.3.0-h9f08a49_118.conda + sha256: b1c3824769b92a1486bf3e2cc5f13304d83ae613ea061b7bc47bb6080d6dfdba + md5: 865a399bce236119301ebd1532fced8d + depends: + - __unix + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 20171098 + timestamp: 1771377827750 +- conda: https://conda.anaconda.org/conda-forge/noarch/libstdcxx-devel_linux-aarch64-14.3.0-h57c8d61_118.conda + sha256: 609585a02b05a2b0f2cabb18849328455cbce576f2e3eb8108f3ef7f4cb165a6 + md5: bcf29f2ed914259a258204b05346abb1 + depends: + - __unix + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 17565700 + timestamp: 1771377672552 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-15.2.0-hdf11a46_18.conda + sha256: 3c902ffd673cb3c6ddde624cdb80f870b6c835f8bf28384b0016e7d444dd0145 + md5: 6235adb93d064ecdf3d44faee6f468de + depends: + - libstdcxx 15.2.0 h934c35e_18 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 27575 + timestamp: 1771378314494 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-ng-15.2.0-hdbbeba8_18.conda + sha256: 035a31cde134e706e30029a837a31f729ad32b7c5bca023271dfe91a8ba6c896 + md5: 699d294376fe18d80b7ce7876c3a875d + depends: + - libstdcxx 15.2.0 hef695bb_18 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 27645 + timestamp: 1771378204663 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.41.3-h5347b49_0.conda + sha256: 1a7539cfa7df00714e8943e18de0b06cceef6778e420a5ee3a2a145773758aee + md5: db409b7c1720428638e7c0d509d3e1b5 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 40311 + timestamp: 1766271528534 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.41.3-h1022ec0_0.conda + sha256: c37a8e89b700646f3252608f8368e7eb8e2a44886b92776e57ad7601fc402a11 + md5: cf2861212053d05f27ec49c3784ff8bb + depends: + - libgcc >=14 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 43453 + timestamp: 1766271546875 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libuv-1.51.0-hb03c661_1.conda + sha256: c180f4124a889ac343fc59d15558e93667d894a966ec6fdb61da1604481be26b + md5: 0f03292cc56bf91a077a134ea8747118 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + license: MIT + license_family: MIT + purls: [] + size: 895108 + timestamp: 1753948278280 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuv-1.51.0-he30d5cf_1.conda + sha256: 7a0fb5638582efc887a18b7d270b0c4a6f6e681bf401cab25ebafa2482569e90 + md5: 8e62bf5af966325ee416f19c6f14ffa3 + depends: + - libgcc >=14 + license: MIT + license_family: MIT + purls: [] + size: 629238 + timestamp: 1753948296190 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libuv-1.48.0-h67532ce_0.conda + sha256: fb87f7bfd464a3a841d23f418c86a206818da0c4346984392071d9342c9ea367 + md5: c8e7344c74f0d86584f7ecdc9f25c198 + license: MIT + license_family: MIT + purls: [] + size: 407040 + timestamp: 1709913680478 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libuv-1.48.0-h93a5062_0.conda + sha256: 60bed2a7a85096387ab0381cbc32ea2da7f8dd99bd90e440983019c0cdd96ad1 + md5: abfd49e80f13453b62a56be226120ea8 + license: MIT + license_family: MIT + purls: [] + size: 405988 + timestamp: 1709913494015 +- conda: https://conda.anaconda.org/conda-forge/win-64/libuv-1.51.0-hfd05255_1.conda + sha256: f03dc82e6fb1725788e73ae97f0cd3d820d5af0d351a274104a0767035444c59 + md5: 31e1545994c48efc3e6ea32ca02a8724 + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: MIT + license_family: MIT + purls: [] + size: 297087 + timestamp: 1753948490874 +- conda: https://conda.anaconda.org/conda-forge/win-64/libwinpthread-12.0.0.r4.gg4f2fc60ca-h57928b3_10.conda + sha256: 0fccf2d17026255b6e10ace1f191d0a2a18f2d65088fd02430be17c701f8ffe0 + md5: 8a86073cf3b343b87d03f41790d8b4e5 + depends: + - ucrt + constrains: + - pthreads-win32 <0.0a0 + - msys2-conda-epoch <0.0a0 + license: MIT AND BSD-3-Clause-Clear + purls: [] + size: 36621 + timestamp: 1759768399557 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda + sha256: 6ae68e0b86423ef188196fff6207ed0c8195dd84273cb5623b85aa08033a410c + md5: 5aa797f8787fe7a17d1b0821485b5adc + depends: + - libgcc-ng >=12 + license: LGPL-2.1-or-later + purls: [] + size: 100393 + timestamp: 1702724383534 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxcrypt-4.4.36-h31becfc_1.conda + sha256: 6b46c397644091b8a26a3048636d10b989b1bf266d4be5e9474bf763f828f41f + md5: b4df5d7d4b63579d081fd3a4cf99740e + depends: + - libgcc-ng >=12 + license: LGPL-2.1-or-later + purls: [] + size: 114269 + timestamp: 1702724369203 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.15.2-he237659_0.conda + sha256: 275c324f87bda1a3b67d2f4fcc3555eeff9e228a37655aa001284a7ceb6b0392 + md5: e49238a1609f9a4a844b09d9926f2c3d + depends: + - __glibc >=2.17,<3.0.a0 + - icu >=78.2,<79.0a0 + - libgcc >=14 + - libiconv >=1.18,<2.0a0 + - liblzma >=5.8.2,<6.0a0 + - libxml2-16 2.15.2 hca6bf5a_0 + - libzlib >=1.3.1,<2.0a0 + license: MIT + license_family: MIT + purls: [] + size: 45968 + timestamp: 1772704614539 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxml2-2.15.2-h825857f_0.conda + sha256: 3e51e1952cb60c8107094b6b78473d91ff49d428ad4bef6806124b383e8fe29c + md5: 19de96909ee1198e2853acd8aba89f6c + depends: + - icu >=78.2,<79.0a0 + - libgcc >=14 + - libiconv >=1.18,<2.0a0 + - liblzma >=5.8.2,<6.0a0 + - libxml2-16 2.15.2 h79dcc73_0 + - libzlib >=1.3.1,<2.0a0 + license: MIT + license_family: MIT + purls: [] + size: 47837 + timestamp: 1772704681112 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libxml2-2.12.6-hc0ae0f7_2.conda + sha256: 2598a525b1769338f96c3d4badad7d8b95c9ddcea86db3f9479a274803190e5c + md5: 50b997370584f2c83ca0c38e9028eab9 + depends: + - icu >=73.2,<74.0a0 + - libiconv >=1.17,<2.0a0 + - libzlib >=1.2.13,<2.0.0a0 + - xz >=5.2.6,<6.0a0 + license: MIT + license_family: MIT + purls: [] + size: 619622 + timestamp: 1713314870641 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libxml2-2.15.2-hd552753_0.conda + sha256: 5b9e8a5146275ac0539231f646ee51a9e4629e730026ff69dadff35bfb745911 + md5: eea3155f3b4a3b75af504c871ec23858 + depends: + - __osx >=11.0 + - icu >=78.2,<79.0a0 + - libiconv >=1.18,<2.0a0 + - liblzma >=5.8.2,<6.0a0 + - libxml2-16 2.15.2 h7a90416_0 + - libzlib >=1.3.1,<2.0a0 + license: MIT + license_family: MIT + size: 41106 + timestamp: 1772705465931 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-2.12.6-h35eab27_2.conda + sha256: 14870a455d478682a60655e3026c51d01ebc1747ccce726ae495a693b304c9b1 + md5: d3a4a3d691494491a08e05f66a0aa35a + depends: + - icu >=73.2,<74.0a0 + - libiconv >=1.17,<2.0a0 + - libzlib >=1.3.1,<1.4.0a0 + - xz >=5.2.6,<6.0a0 + license: MIT + license_family: MIT + purls: [] + size: 587544 + timestamp: 1713314830067 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-2.15.2-h8d039ee_0.conda + sha256: 99cb32dd06a2e58c12981b71a84b052293f27b5ab042e3f21d895f5d7ee13eff + md5: e476ba84e57f2bd2004a27381812ad4e + depends: + - __osx >=11.0 + - icu >=78.2,<79.0a0 + - libiconv >=1.18,<2.0a0 + - liblzma >=5.8.2,<6.0a0 + - libxml2-16 2.15.2 h5ef1a60_0 + - libzlib >=1.3.1,<2.0a0 + license: MIT + license_family: MIT + size: 41206 + timestamp: 1772704982288 +- conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-2.15.2-h5d26750_0.conda + sha256: f905eb7046987c336122121759e7f09144729f6898f48cd06df2a945b86998d8 + md5: 1007e1bfe181a2aee214779ee7f13d30 + depends: + - libiconv >=1.18,<2.0a0 + - liblzma >=5.8.2,<6.0a0 + - libxml2-16 2.15.2 h692994f_0 + - libzlib >=1.3.1,<2.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + constrains: + - icu <0.0a0 + license: MIT + license_family: MIT + purls: [] + size: 43681 + timestamp: 1772704748950 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-16-2.15.2-hca6bf5a_0.conda + sha256: 08d2b34b49bec9613784f868209bb7c3bb8840d6cf835ff692e036b09745188c + md5: f3bc152cb4f86babe30f3a4bf0dbef69 + depends: + - __glibc >=2.17,<3.0.a0 + - icu >=78.2,<79.0a0 + - libgcc >=14 + - libiconv >=1.18,<2.0a0 + - liblzma >=5.8.2,<6.0a0 + - libzlib >=1.3.1,<2.0a0 + constrains: + - libxml2 2.15.2 + license: MIT + license_family: MIT + purls: [] + size: 557492 + timestamp: 1772704601644 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxml2-16-2.15.2-h79dcc73_0.conda + sha256: da6b2ebbcecc158200d90be39514e4e902971628029b35b7f6ad57270659c5d9 + md5: e3ec9079759d35b875097d6a9a69e744 + depends: + - icu >=78.2,<79.0a0 + - libgcc >=14 + - libiconv >=1.18,<2.0a0 + - liblzma >=5.8.2,<6.0a0 + - libzlib >=1.3.1,<2.0a0 + constrains: + - libxml2 2.15.2 + license: MIT + license_family: MIT + purls: [] + size: 598438 + timestamp: 1772704671710 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libxml2-16-2.15.2-h7a90416_0.conda + sha256: f67e4b7d7f97e57ecd611a42e42d5f6c047fd3d1eb8270813b888924440c8a59 + md5: 0c8bdbfd118f5963ab343846094932a3 + depends: + - __osx >=11.0 + - icu >=78.2,<79.0a0 + - libiconv >=1.18,<2.0a0 + - liblzma >=5.8.2,<6.0a0 + - libzlib >=1.3.1,<2.0a0 + constrains: + - libxml2 2.15.2 + license: MIT + license_family: MIT + size: 495922 + timestamp: 1772705426323 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-16-2.15.2-h5ef1a60_0.conda + sha256: 6432259204e78c8a8a815afae987fbf60bd722605fe2c4b022e65196b17d4537 + md5: b284e2b02d53ef7981613839fb86beee + depends: + - __osx >=11.0 + - icu >=78.2,<79.0a0 + - libiconv >=1.18,<2.0a0 + - liblzma >=5.8.2,<6.0a0 + - libzlib >=1.3.1,<2.0a0 + constrains: + - libxml2 2.15.2 + license: MIT + license_family: MIT + size: 466220 + timestamp: 1772704950232 +- conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-16-2.15.2-h692994f_0.conda + sha256: b8c71b3b609c7cfe17f3f2a47c75394d7b30acfb8b34ad7a049ea8757b4d33df + md5: e365238134188e42ed36ee996159d482 + depends: + - libiconv >=1.18,<2.0a0 + - liblzma >=5.8.2,<6.0a0 + - libzlib >=1.3.1,<2.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + constrains: + - libxml2 2.15.2 + - icu <0.0a0 + license: MIT + license_family: MIT + purls: [] + size: 520078 + timestamp: 1772704728534 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda + sha256: d4bfe88d7cb447768e31650f06257995601f89076080e76df55e3112d4e47dc4 + md5: edb0dca6bc32e4f4789199455a1dbeb8 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + constrains: + - zlib 1.3.1 *_2 + license: Zlib + license_family: Other + purls: [] + size: 60963 + timestamp: 1727963148474 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.3.1-h86ecc28_2.conda + sha256: 5a2c1eeef69342e88a98d1d95bff1603727ab1ff4ee0e421522acd8813439b84 + md5: 08aad7cbe9f5a6b460d0976076b6ae64 + depends: + - libgcc >=13 + constrains: + - zlib 1.3.1 *_2 + license: Zlib + license_family: Other + purls: [] + size: 66657 + timestamp: 1727963199518 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.3.1-hd23fc13_2.conda + sha256: 8412f96504fc5993a63edf1e211d042a1fd5b1d51dedec755d2058948fcced09 + md5: 003a54a4e32b02f7355b50a837e699da + depends: + - __osx >=10.13 + constrains: + - zlib 1.3.1 *_2 + license: Zlib + license_family: Other + size: 57133 + timestamp: 1727963183990 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.3.1-hd75f5a5_0.conda + sha256: 49fd2bde256952ab6a8265f3b2978ae624db1f096e3340253699e2534426244a + md5: fad941436715cc1b6f6e55a14372f70c + constrains: + - zlib 1.3.1 *_0 + license: Zlib + license_family: Other + purls: [] + size: 57480 + timestamp: 1709241092733 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.1-h0d3ecfb_0.conda + sha256: 9c59bd3f3e3e1900620e3a85c04d3a3699cb93c714333d06cb8afdd7addaae9d + md5: 2a2463424cc5e961a6d04bbbfb5838cf + constrains: + - zlib 1.3.1 *_0 + license: Zlib + license_family: Other + purls: [] + size: 47040 + timestamp: 1709241137619 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.1-h8359307_2.conda + sha256: ce34669eadaba351cd54910743e6a2261b67009624dbc7daeeafdef93616711b + md5: 369964e85dc26bfe78f41399b366c435 + depends: + - __osx >=11.0 + constrains: + - zlib 1.3.1 *_2 + license: Zlib + license_family: Other + size: 46438 + timestamp: 1727963202283 +- conda: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.3.1-h2466b09_2.conda + sha256: ba945c6493449bed0e6e29883c4943817f7c79cbff52b83360f7b341277c6402 + md5: 41fbfac52c601159df6c01f875de31b9 + depends: + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + constrains: + - zlib 1.3.1 *_2 + license: Zlib + license_family: Other + purls: [] + size: 55476 + timestamp: 1727963768015 +- conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-openmp-18.1.3-hb6ac08f_0.conda + sha256: 997e4169ea474a7bc137fed3b5f4d94b1175162b3318e8cb3943003e460fe458 + md5: 506f270f4f00980d27cc1fc127e0ed37 + constrains: + - openmp 18.1.3|18.1.3.* + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + purls: [] + size: 300597 + timestamp: 1712603382363 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-18.1.3-hcd81f8e_0.conda + sha256: 4cb4eadd633669496ed70c580c965f5f2ed29336890636c61a53e9c1c1541073 + md5: 24cbf1fb1b83056f8ba1beaac0619bf8 + constrains: + - openmp 18.1.3|18.1.3.* + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + purls: [] + size: 276320 + timestamp: 1712603367897 +- conda: https://conda.anaconda.org/conda-forge/win-64/llvm-openmp-22.1.0-h4fa8253_0.conda + sha256: bb55a3736380759d338f87aac68df4fd7d845ae090b94400525f5d21a55eea31 + md5: e5505e0b7d6ef5c19d5c0c1884a2f494 + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + constrains: + - openmp 22.1.0|22.1.0.* + - intel-openmp <0.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + purls: [] + size: 347404 + timestamp: 1772025050288 +- conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-tools-18.1.3-hbcf5fad_0.conda + sha256: be89293b54032198a28d3a4b91e50eb4d79e252d9e3ab609501ea0324fbf478a + md5: f91db97d91a080e0024307fa3808cc7b + depends: + - libllvm18 18.1.3 hbcf5fad_0 + - libxml2 >=2.12.6,<2.14.0a0 + - libzlib >=1.2.13,<2.0.0a0 + - zstd >=1.5.5,<1.6.0a0 + constrains: + - clang-tools 18.1.3 + - llvmdev 18.1.3 + - llvm 18.1.3 + - clang 18.1.3 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + purls: [] + size: 24449337 + timestamp: 1712518244229 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-tools-18.1.3-h30cc82d_0.conda + sha256: 48eb7b17ca6de1b43dfddc3b4a629a8a9764c9da3f3012980e1b917c71f06a4f + md5: 505aef673d805f9efe0c61954a6a99d0 + depends: + - libllvm18 18.1.3 h30cc82d_0 + - libxml2 >=2.12.6,<2.14.0a0 + - libzlib >=1.2.13,<2.0.0a0 + - zstd >=1.5.5,<1.6.0a0 + constrains: + - llvm 18.1.3 + - clang-tools 18.1.3 + - clang 18.1.3 + - llvmdev 18.1.3 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + purls: [] + size: 23023681 + timestamp: 1712517958538 +- conda: https://conda.anaconda.org/conda-forge/linux-64/lz4-c-1.10.0-h5888daf_1.conda + sha256: 47326f811392a5fd3055f0f773036c392d26fdb32e4d8e7a8197eed951489346 + md5: 9de5350a85c4a20c685259b889aa6393 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + - libstdcxx >=13 + license: BSD-2-Clause + license_family: BSD + purls: [] + size: 167055 + timestamp: 1733741040117 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lz4-c-1.10.0-h5ad3122_1.conda + sha256: 67e55058d275beea76c1882399640c37b5be8be4eb39354c94b610928e9a0573 + md5: 6654e411da94011e8fbe004eacb8fe11 + depends: + - libgcc >=13 + - libstdcxx >=13 + license: BSD-2-Clause + license_family: BSD + purls: [] + size: 184953 + timestamp: 1733740984533 +- conda: https://conda.anaconda.org/conda-forge/osx-64/lz4-c-1.10.0-h240833e_1.conda + sha256: 8da3c9d4b596e481750440c0250a7e18521e7f69a47e1c8415d568c847c08a1c + md5: d6b9bd7e356abd7e3a633d59b753495a + depends: + - __osx >=10.13 + - libcxx >=18 + license: BSD-2-Clause + license_family: BSD + size: 159500 + timestamp: 1733741074747 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/lz4-c-1.10.0-h286801f_1.conda + sha256: 94d3e2a485dab8bdfdd4837880bde3dd0d701e2b97d6134b8806b7c8e69c8652 + md5: 01511afc6cc1909c5303cf31be17b44f + depends: + - __osx >=11.0 + - libcxx >=18 + license: BSD-2-Clause + license_family: BSD + size: 148824 + timestamp: 1733741047892 +- conda: https://conda.anaconda.org/conda-forge/win-64/lz4-c-1.10.0-h2466b09_1.conda + sha256: 632cf3bdaf7a7aeb846de310b6044d90917728c73c77f138f08aa9438fc4d6b5 + md5: 0b69331897a92fac3d8923549d48d092 + depends: + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: BSD-2-Clause + license_family: BSD + purls: [] + size: 139891 + timestamp: 1733741168264 +- conda: https://conda.anaconda.org/conda-forge/linux-64/lzo-2.10-h280c20c_1002.conda + sha256: 5c6bbeec116e29f08e3dad3d0524e9bc5527098e12fc432c0e5ca53ea16337d4 + md5: 45161d96307e3a447cc3eb5896cf6f8c + depends: + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + license: GPL-2.0-or-later + license_family: GPL + purls: [] + size: 191060 + timestamp: 1753889274283 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lzo-2.10-h80f16a2_1002.conda + sha256: 036428c7b9fd22889108d04c91cecc431f95dc3dba2ede3057330c8125080fd5 + md5: 97af2e332449dd9e92ad7db93b02e918 + depends: + - libgcc >=14 + license: GPL-2.0-or-later + license_family: GPL + purls: [] + size: 190187 + timestamp: 1753889356434 +- conda: https://conda.anaconda.org/conda-forge/osx-64/lzo-2.10-h4132b18_1002.conda + sha256: bb5fe07123a7d573af281d04b75e1e77e87e62c5c4eb66d9781aa919450510d1 + md5: 5a047b9aa4be1dcdb62bd561d9eb6ceb + depends: + - __osx >=10.13 + license: GPL-2.0-or-later + license_family: GPL + size: 174634 + timestamp: 1753889269889 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/lzo-2.10-h925e9cb_1002.conda + sha256: db40fd25c6306bfda469f84cddd8b5ebb9aa08d509cecb49dfd0bb8228466d0c + md5: e56eaa1beab0e7fed559ae9c0264dd88 + depends: + - __osx >=11.0 + license: GPL-2.0-or-later + license_family: GPL + size: 152755 + timestamp: 1753889267953 +- conda: https://conda.anaconda.org/conda-forge/win-64/lzo-2.10-h6a83c73_1002.conda + sha256: 344f4f225c6dfb523fb477995545542224c37a5c86161f053a1a18fe547aa979 + md5: c5cb4159f0eea65663b31dd1e49bbb71 + depends: + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + license: GPL-2.0-or-later + license_family: GPL + purls: [] + size: 165589 + timestamp: 1753889311940 +- pypi: https://files.pythonhosted.org/packages/c7/d1/a9f36f8ecdf0fb7c9b1e78c8d7af12b8c8754e74851ac7b94a8305540fc7/macholib-1.16.4-py2.py3-none-any.whl + name: macholib + version: 1.16.4 + sha256: da1a3fa8266e30f0ce7e97c6a54eefaae8edd1e5f86f3eb8b95457cae90265ea + requires_dist: + - altgraph>=0.17 +- conda: https://conda.anaconda.org/conda-forge/linux-64/menuinst-2.4.2-py310hff52083_0.conda + sha256: ec100872ca86c8dc6a08b16d0046661dd85ebb6b6910c57dfcafecbdc622a1ba + md5: 937b4f62485b63f71ee8d50ae021cc33 + depends: + - python >=3.10,<3.11.0a0 + - python_abi 3.10.* *_cp310 + license: BSD-3-Clause AND MIT + purls: + - pkg:pypi/menuinst?source=hash-mapping + size: 155578 + timestamp: 1765733217218 +- conda: https://conda.anaconda.org/conda-forge/linux-64/menuinst-2.4.2-py311h38be061_0.conda + sha256: 096f1db22fd47ddcf5df82aed016ef8cef4c1b810925bf63b67cfc3f9ba67cdb + md5: ba48e568ec4fdbcb8f3fef87bca9fddb + depends: + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + license: BSD-3-Clause AND MIT + purls: + - pkg:pypi/menuinst?source=hash-mapping + size: 186910 + timestamp: 1765733175922 +- conda: https://conda.anaconda.org/conda-forge/linux-64/menuinst-2.4.2-py314hdafbbf9_0.conda + sha256: 223306ba7f78599abc65f8ca14116650c228cbdca273ca15804544ac343a9e69 + md5: 608ee3d8065e9b1e9e1f3115d8aab9ab + depends: + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + license: BSD-3-Clause AND MIT + size: 188752 + timestamp: 1765733220513 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/menuinst-2.4.2-py310h4c7bcd0_0.conda + sha256: 331b93ad811c1033b5d22a23541b23c75c0d1b31ad0ed2d6f4117a79f3676f0e + md5: 928764c3c75aaabcc1bac5ebf4a8a7c2 + depends: + - python >=3.10,<3.11.0a0 + - python >=3.10,<3.11.0a0 *_cpython + - python_abi 3.10.* *_cp310 + license: BSD-3-Clause AND MIT + purls: + - pkg:pypi/menuinst?source=hash-mapping + size: 156117 + timestamp: 1765733228621 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/menuinst-2.4.2-py311hec3470c_0.conda + sha256: 803b3fc3b4c0c4abc8d2c720793c1cbe784506762a0dcdcb736805c0aebc797d + md5: b2b440c867b680594a750a00c3425417 + depends: + - python >=3.11,<3.12.0a0 + - python >=3.11,<3.12.0a0 *_cpython + - python_abi 3.11.* *_cp311 + license: BSD-3-Clause AND MIT + purls: + - pkg:pypi/menuinst?source=hash-mapping + size: 187037 + timestamp: 1765733232285 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/menuinst-2.4.2-py314h28a4750_0.conda + sha256: ed5d3d0b646207b15aea1022ed10ccccfebfa271b152eeb6169b767a02b632a5 + md5: 41fc65edb06fbcc2c2e68c02d06f6bf7 + depends: + - python >=3.14,<3.15.0a0 + - python >=3.14,<3.15.0a0 *_cp314 + - python_abi 3.14.* *_cp314 + license: BSD-3-Clause AND MIT + size: 188584 + timestamp: 1765733234092 +- conda: https://conda.anaconda.org/conda-forge/osx-64/menuinst-2.4.2-py314hee6578b_0.conda + sha256: f9967b4794840bbc1e1a02b0f8e2d9c2a97216e1d5eb88024ca3e34d6f0c7838 + md5: 70759a82982d21ee091d7004b945048a + depends: + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + license: BSD-3-Clause AND MIT + size: 187629 + timestamp: 1765733352246 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/menuinst-2.4.2-py314h4dc9dd8_0.conda + sha256: cfe6079a2193f9ecf0279bff01eb57499a5a081607ea3c83b2c5522c00a538ca + md5: 312610ff2ccaa1e4995f4fb3d8c04f96 + depends: + - python >=3.14,<3.15.0a0 + - python >=3.14,<3.15.0a0 *_cp314 + - python_abi 3.14.* *_cp314 + license: BSD-3-Clause AND MIT + size: 188284 + timestamp: 1765733422732 +- conda: https://conda.anaconda.org/conda-forge/win-64/menuinst-2.4.2-py310h73ae2b4_0.conda + sha256: 3b5ab966d63a2e217f15a437be470bee04d69b63f5205a5d1a8d012008ba6b04 + md5: fd40b3f1395d1b1e9071961d90a3f0f0 + depends: + - python >=3.10,<3.11.0a0 + - python_abi 3.10.* *_cp310 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: BSD-3-Clause AND MIT + purls: + - pkg:pypi/menuinst?source=hash-mapping + size: 146344 + timestamp: 1765733517640 +- conda: https://conda.anaconda.org/conda-forge/win-64/menuinst-2.4.2-py311h3e6a449_0.conda + sha256: 0482c0c5962ba3da648071affec41b416a51c6afbf52264ea40434e43993b0cf + md5: 25b1fdcd2436106cab080dc1932dba63 + depends: + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: BSD-3-Clause AND MIT + purls: + - pkg:pypi/menuinst?source=hash-mapping + size: 179383 + timestamp: 1765733304312 +- conda: https://conda.anaconda.org/conda-forge/win-64/menuinst-2.4.2-py314h13fbf68_0.conda + sha256: 1f4535acbc5a2d75e2b6d83fca659c468bc2597af798fdf2e45091265a094a32 + md5: ced101aaa08315eb8a058b1190500d12 + depends: + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: BSD-3-Clause AND MIT + size: 179510 + timestamp: 1765733497067 +- conda: https://conda.anaconda.org/conda-forge/win-64/mkl-2025.3.0-hac47afa_455.conda + sha256: b2b4c84b95210760e4d12319416c60ab66e03674ccdcbd14aeb59f82ebb1318d + md5: fd05d1e894497b012d05a804232254ed + depends: + - llvm-openmp >=21.1.8 + - tbb >=2022.3.0 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: LicenseRef-IntelSimplifiedSoftwareOct2022 + license_family: Proprietary + purls: [] + size: 100224829 + timestamp: 1767634557029 +- conda: https://conda.anaconda.org/conda-forge/linux-64/msgpack-python-1.1.2-py310h03d9f68_1.conda + sha256: 61cf3572d6afa3fa711c5f970a832783d2c281facb7b3b946a6b71a0bac2c592 + md5: 5eea9d8f8fcf49751dab7927cb0dfc3f + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libstdcxx >=14 + - python >=3.10,<3.11.0a0 + - python_abi 3.10.* *_cp310 + license: Apache-2.0 + license_family: Apache + purls: + - pkg:pypi/msgpack?source=hash-mapping + size: 95105 + timestamp: 1762504073388 +- conda: https://conda.anaconda.org/conda-forge/linux-64/msgpack-python-1.1.2-py311hdf67eae_1.conda + sha256: 8c81a6208def64afc3e208326d78d7af60bcbc32d44afe1269b332df84084f29 + md5: c1153b2cb3318889ce624a3b4f0db7f7 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libstdcxx >=14 + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + license: Apache-2.0 + license_family: Apache + purls: + - pkg:pypi/msgpack?source=hash-mapping + size: 102979 + timestamp: 1762504186626 +- conda: https://conda.anaconda.org/conda-forge/linux-64/msgpack-python-1.1.2-py314h9891dd4_1.conda + sha256: d41c2734d314303e329680aeef282766fe399a0ce63297a68a2f8f9b43b1b68a + md5: c6752022dcdbf4b9ef94163de1ab7f03 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libstdcxx >=14 + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + license: Apache-2.0 + license_family: Apache + size: 103380 + timestamp: 1762504077009 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/msgpack-python-1.1.2-py310h0992a49_1.conda + sha256: 663967ac8fbe9a5e32246784d0c6c08be8394dab5c045297121550beb967b127 + md5: 0d9ac8c2994a3681e44edcf9bb1a3e8e + depends: + - libgcc >=14 + - libstdcxx >=14 + - python >=3.10,<3.11.0a0 + - python >=3.10,<3.11.0a0 *_cpython + - python_abi 3.10.* *_cp310 + license: Apache-2.0 + license_family: Apache + purls: + - pkg:pypi/msgpack?source=hash-mapping + size: 93092 + timestamp: 1762504199089 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/msgpack-python-1.1.2-py311hfca10b7_1.conda + sha256: 35a36e3062bf84a70c0105b1553a1aa7b16a1dad19a97945efeea2b92ca95f23 + md5: 560e361fc9aff96fdd179e7e5d41471e + depends: + - libgcc >=14 + - libstdcxx >=14 + - python >=3.11,<3.12.0a0 + - python >=3.11,<3.12.0a0 *_cpython + - python_abi 3.11.* *_cp311 + license: Apache-2.0 + license_family: Apache + purls: + - pkg:pypi/msgpack?source=hash-mapping + size: 100340 + timestamp: 1762504276815 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/msgpack-python-1.1.2-py314hd7d8586_1.conda + sha256: 124a778a7065d75d9d36d80563e75d3a13455b160a761cd38a5ce8f50f87705c + md5: e93c66201de71acb9e99d94f84f897b1 + depends: + - libgcc >=14 + - libstdcxx >=14 + - python >=3.14,<3.15.0a0 + - python >=3.14,<3.15.0a0 *_cp314 + - python_abi 3.14.* *_cp314 + license: Apache-2.0 + license_family: Apache + size: 100176 + timestamp: 1762504193305 +- conda: https://conda.anaconda.org/conda-forge/osx-64/msgpack-python-1.1.2-py314h00ed6fe_1.conda + sha256: 1e82a903c5b5fb1555851ff1ef9068a538f4d8652eee2c31935d2d6d326a99f7 + md5: 977962f6bb6f922ee0caabcb5a1b1d8c + depends: + - __osx >=10.13 + - libcxx >=19 + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + license: Apache-2.0 + license_family: Apache + size: 92312 + timestamp: 1762504434513 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/msgpack-python-1.1.2-py314h784bc60_1.conda + sha256: 9dc4ebe88064cf96bb97a4de83be10fbc52a24d2ff48a4561fb0fed337b526f0 + md5: 305227e4de261896033ad8081e8b52ae + depends: + - __osx >=11.0 + - libcxx >=19 + - python >=3.14,<3.15.0a0 + - python >=3.14,<3.15.0a0 *_cp314 + - python_abi 3.14.* *_cp314 + license: Apache-2.0 + license_family: Apache + size: 92381 + timestamp: 1762504601981 +- conda: https://conda.anaconda.org/conda-forge/win-64/msgpack-python-1.1.2-py310he9f1925_1.conda + sha256: 6b7bfd07c5be57df2922e2f5238751ee6bb09d81540a44c6554d059eac2a3bd5 + md5: 65fb9838e245ef4bea6cab32a7056dfc + depends: + - python >=3.10,<3.11.0a0 + - python_abi 3.10.* *_cp310 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: Apache-2.0 + license_family: Apache + purls: + - pkg:pypi/msgpack?source=hash-mapping + size: 80807 + timestamp: 1762504309629 +- conda: https://conda.anaconda.org/conda-forge/win-64/msgpack-python-1.1.2-py311h3fd045d_1.conda + sha256: 9883b64dea87c50e98fabc05719ff0fdc347f57d7bacda19bcd69b80d8c436d4 + md5: b0f2fb2eadce667ad09ca7d3ff868c71 + depends: + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: Apache-2.0 + license_family: Apache + purls: + - pkg:pypi/msgpack?source=hash-mapping + size: 87848 + timestamp: 1762504210288 +- conda: https://conda.anaconda.org/conda-forge/win-64/msgpack-python-1.1.2-py314h909e829_1.conda + sha256: 2ce1f564d5aa2e0637c03692baeea4ecf234c7fb2a43e7810c369e1b054d7a30 + md5: ad4584f884d029b02fc9eaf89afc5d9f + depends: + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: Apache-2.0 + license_family: Apache + size: 88657 + timestamp: 1762504357246 +- conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda + sha256: 3fde293232fa3fca98635e1167de6b7c7fda83caf24b9d6c91ec9eefb4f4d586 + md5: 47e340acb35de30501a76c7c799c41d7 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + license: X11 AND BSD-3-Clause + purls: [] + size: 891641 + timestamp: 1738195959188 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.5-ha32ae93_3.conda + sha256: 91cfb655a68b0353b2833521dc919188db3d8a7f4c64bea2c6a7557b24747468 + md5: 182afabe009dc78d8b73100255ee6868 + depends: + - libgcc >=13 + license: X11 AND BSD-3-Clause + purls: [] + size: 926034 + timestamp: 1738196018799 +- conda: https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.5-h0622a9a_3.conda + sha256: ea4a5d27ded18443749aefa49dc79f6356da8506d508b5296f60b8d51e0c4bd9 + md5: ced34dd9929f491ca6dab6a2927aff25 + depends: + - __osx >=10.13 + license: X11 AND BSD-3-Clause + size: 822259 + timestamp: 1738196181298 +- conda: https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.5-h5846eda_0.conda + sha256: 6ecc73db0e49143092c0934355ac41583a5d5a48c6914c5f6ca48e562d3a4b79 + md5: 02a888433d165c99bf09784a7b14d900 + license: X11 AND BSD-3-Clause + purls: [] + size: 823601 + timestamp: 1715195267791 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.5-h5e97a16_3.conda + sha256: 2827ada40e8d9ca69a153a45f7fd14f32b2ead7045d3bbb5d10964898fe65733 + md5: 068d497125e4bf8a66bf707254fff5ae + depends: + - __osx >=11.0 + license: X11 AND BSD-3-Clause + size: 797030 + timestamp: 1738196177597 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.5-hb89a1cb_0.conda + sha256: 87d7cf716d9d930dab682cb57b3b8d3a61940b47d6703f3529a155c938a6990a + md5: b13ad5724ac9ae98b6b4fd87e4500ba4 + license: X11 AND BSD-3-Clause + purls: [] + size: 795131 + timestamp: 1715194898402 +- conda: https://conda.anaconda.org/conda-forge/linux-64/ninja-1.13.2-h171cf75_0.conda + sha256: 6f7d59dbec0a7b00bf5d103a4306e8886678b796ff2151b62452d4582b2a53fb + md5: b518e9e92493721281a60fa975bddc65 + depends: + - libstdcxx >=14 + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 186323 + timestamp: 1763688260928 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ninja-1.13.2-hdc560ac_0.conda + sha256: 45fbc7c8c44681f5cefba1e5b26ca504a4485b000c5dfaa31cec0b7bc78d0de4 + md5: 8b5222a41b5d51fb1a5a2c514e770218 + depends: + - libstdcxx >=14 + - libgcc >=14 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 182666 + timestamp: 1763688214250 +- conda: https://conda.anaconda.org/conda-forge/osx-64/ninja-1.12.0-h7728843_0.conda + sha256: dcc10cbea89b1846c76d7df06023f23866e794beb6412fffafb2fce6da19db05 + md5: 1ac079f6ecddd2c336f3acb7b371851f + depends: + - libcxx >=16 + license: Apache-2.0 + license_family: Apache + purls: [] + size: 124810 + timestamp: 1713204841161 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/ninja-1.12.0-h2ffa867_0.conda + sha256: 634ff2cda6a77b9cd8935e748a1d5698f51f87f1a226638ddc95eb22f6a172ea + md5: 24e1b17a513393ee4e81e51fdab1fa93 + depends: + - libcxx >=16 + license: Apache-2.0 + license_family: Apache + purls: [] + size: 111688 + timestamp: 1713205253264 +- conda: https://conda.anaconda.org/conda-forge/win-64/ninja-1.13.2-h477610d_0.conda + sha256: e41a945c34a5f0bd2109b73a65486cd93023fa0a9bcba3ef98f9a3da40ba1180 + md5: 7ecb9f2f112c66f959d2bb7dbdb89b67 + depends: + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 309417 + timestamp: 1763688227932 +- conda: https://conda.anaconda.org/conda-forge/noarch/nlohmann_json-abi-3.12.0-h0f90c79_1.conda + sha256: 2a909594ca78843258e4bda36e43d165cda844743329838a29402823c8f20dec + md5: 59659d0213082bc13be8500bab80c002 + license: MIT + license_family: MIT + purls: [] + size: 4335 + timestamp: 1758194464430 +- conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.2.6-py310hefbff90_0.conda + sha256: 0ba94a61f91d67413e60fa8daa85627a8f299b5054b0eff8f93d26da83ec755e + md5: b0cea2c364bf65cd19e023040eeab05d + depends: + - __glibc >=2.17,<3.0.a0 + - libblas >=3.9.0,<4.0a0 + - libcblas >=3.9.0,<4.0a0 + - libgcc >=13 + - liblapack >=3.9.0,<4.0a0 + - libstdcxx >=13 + - python >=3.10,<3.11.0a0 + - python_abi 3.10.* *_cp310 + constrains: + - numpy-base <0a0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/numpy?source=hash-mapping + size: 7893263 + timestamp: 1747545075833 +- conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.4.2-py311h2e04523_1.conda + sha256: 2f9971a62316b9acb6ade749cebb59ffe750d1c2d99fe7061c6440589f6d3299 + md5: a8105076864776eceae69d64d30e24d7 + depends: + - python + - __glibc >=2.17,<3.0.a0 + - libstdcxx >=14 + - libgcc >=14 + - libblas >=3.9.0,<4.0a0 + - python_abi 3.11.* *_cp311 + - libcblas >=3.9.0,<4.0a0 + - liblapack >=3.9.0,<4.0a0 + constrains: + - numpy-base <0a0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/numpy?source=compressed-mapping + size: 9385101 + timestamp: 1770098496391 +- conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.4.3-py311h2e04523_0.conda + sha256: ea4e92bb68b58ce92c0d4152c308eecfee94f131d5ef247395fbe70b7697074d + md5: cfc8f864dea571677095ebae8e6f0c07 + depends: + - python + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + - libstdcxx >=14 + - libcblas >=3.9.0,<4.0a0 + - liblapack >=3.9.0,<4.0a0 + - python_abi 3.11.* *_cp311 + - libblas >=3.9.0,<4.0a0 + constrains: + - numpy-base <0a0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/numpy?source=compressed-mapping + size: 9384747 + timestamp: 1773839224422 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/numpy-2.2.6-py310h6e5608f_0.conda + sha256: d7234b9c45e4863c7d4c5221c1e91d69b0e0009464bf361c3fea47e64dc4adc2 + md5: 9e9f1f279eb02c41bda162a42861adc0 + depends: + - libblas >=3.9.0,<4.0a0 + - libcblas >=3.9.0,<4.0a0 + - libgcc >=13 + - liblapack >=3.9.0,<4.0a0 + - libstdcxx >=13 + - python >=3.10,<3.11.0a0 + - python >=3.10,<3.11.0a0 *_cpython + - python_abi 3.10.* *_cp310 + constrains: + - numpy-base <0a0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/numpy?source=hash-mapping + size: 6556655 + timestamp: 1747545077963 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/numpy-2.4.2-py311h669026d_1.conda + sha256: b40796e2b47878a38ffa5e76703a1d4d9f5fc09787cdf54fed9f4af8b66d1eb8 + md5: 6b411688a868a37d95abfb99ebc8b88e + depends: + - python + - libstdcxx >=14 + - libgcc >=14 + - python 3.11.* *_cpython + - liblapack >=3.9.0,<4.0a0 + - libcblas >=3.9.0,<4.0a0 + - python_abi 3.11.* *_cp311 + - libblas >=3.9.0,<4.0a0 + constrains: + - numpy-base <0a0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/numpy?source=hash-mapping + size: 8462316 + timestamp: 1770098524745 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/numpy-2.4.3-py311h669026d_0.conda + sha256: 33e4d3e097a9d05e9e09d2895f4bd20f7fc93c8cb0df35da4716d0ba836a0d86 + md5: 23c6d37dec83159283cfeee4fceebf84 + depends: + - python + - python 3.11.* *_cpython + - libgcc >=14 + - libstdcxx >=14 + - libblas >=3.9.0,<4.0a0 + - liblapack >=3.9.0,<4.0a0 + - python_abi 3.11.* *_cp311 + - libcblas >=3.9.0,<4.0a0 + constrains: + - numpy-base <0a0 + license: BSD-3-Clause + purls: + - pkg:pypi/numpy?source=hash-mapping + size: 8464385 + timestamp: 1773839300790 +- conda: https://conda.anaconda.org/conda-forge/osx-64/numpy-1.26.4-py310h4bfa8fc_0.conda + sha256: 914476e2d3273fdf9c0419a7bdcb7b31a5ec25949e4afbc847297ff3a50c62c8 + md5: cd6a2298387f558c9ea70ee73a189791 + depends: + - libblas >=3.9.0,<4.0a0 + - libcblas >=3.9.0,<4.0a0 + - libcxx >=16 + - liblapack >=3.9.0,<4.0a0 + - python >=3.10,<3.11.0a0 + - python_abi 3.10.* *_cp310 + constrains: + - numpy-base <0a0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/numpy?source=hash-mapping + size: 6491938 + timestamp: 1707226191321 +- conda: https://conda.anaconda.org/conda-forge/osx-64/numpy-1.26.4-py311hc43a94b_0.conda + sha256: dc9628197125ee1d02b2e7a859a769d26291d747ed79337309b8a9e67a8b8e00 + md5: bb02b8801d17265160e466cf8bbf28da + depends: + - libblas >=3.9.0,<4.0a0 + - libcblas >=3.9.0,<4.0a0 + - libcxx >=16 + - liblapack >=3.9.0,<4.0a0 + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + constrains: + - numpy-base <0a0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/numpy?source=hash-mapping + size: 7504319 + timestamp: 1707226235372 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-1.26.4-py310hd45542a_0.conda + sha256: e3078108a4973e73c813b89228f4bd8095ec58f96ca29f55d2e45a6223a9a1db + md5: 267ee89a3a0b8c8fa838a2353f9ea0c0 + depends: + - libblas >=3.9.0,<4.0a0 + - libcblas >=3.9.0,<4.0a0 + - libcxx >=16 + - liblapack >=3.9.0,<4.0a0 + - python >=3.10,<3.11.0a0 + - python >=3.10,<3.11.0a0 *_cpython + - python_abi 3.10.* *_cp310 + constrains: + - numpy-base <0a0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/numpy?source=hash-mapping + size: 5475744 + timestamp: 1707226187124 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-1.26.4-py311h7125741_0.conda + sha256: 160a52a01fea44fe9753a2ed22cf13d7b55c8a89ea0b8738546fdbf4795d6514 + md5: 3160b93669a0def35a7a8158ebb33816 + depends: + - libblas >=3.9.0,<4.0a0 + - libcblas >=3.9.0,<4.0a0 + - libcxx >=16 + - liblapack >=3.9.0,<4.0a0 + - python >=3.11,<3.12.0a0 + - python >=3.11,<3.12.0a0 *_cpython + - python_abi 3.11.* *_cp311 + constrains: + - numpy-base <0a0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/numpy?source=hash-mapping + size: 6652352 + timestamp: 1707226297967 +- conda: https://conda.anaconda.org/conda-forge/win-64/numpy-2.2.6-py310h4987827_0.conda + sha256: 6f628e51763b86a535a723664e3aa1e38cb7147a2697f80b75c1980c1ed52f3e + md5: d2596785ac2cf5bab04e2ee9e5d04041 + depends: + - libblas >=3.9.0,<4.0a0 + - libcblas >=3.9.0,<4.0a0 + - liblapack >=3.9.0,<4.0a0 + - python >=3.10,<3.11.0a0 + - python_abi 3.10.* *_cp310 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + constrains: + - numpy-base <0a0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/numpy?source=hash-mapping + size: 6596153 + timestamp: 1747545352390 +- conda: https://conda.anaconda.org/conda-forge/win-64/numpy-2.4.2-py311h80b3fa1_1.conda + sha256: c5cd26fb28d92d6c3843b96489f433ef87d1866d03a746f7228230b74bef431a + md5: a824c6667179120c458beb9e9394932f + depends: + - python + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - python_abi 3.11.* *_cp311 + - libcblas >=3.9.0,<4.0a0 + - liblapack >=3.9.0,<4.0a0 + - libblas >=3.9.0,<4.0a0 + constrains: + - numpy-base <0a0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/numpy?source=hash-mapping + size: 7803678 + timestamp: 1770098404597 +- conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.1-h35e630c_1.conda + sha256: 44c877f8af015332a5d12f5ff0fb20ca32f896526a7d0cdb30c769df1144fb5c + md5: f61eb8cd60ff9057122a3d338b99c00f + depends: + - __glibc >=2.17,<3.0.a0 + - ca-certificates + - libgcc >=14 + license: Apache-2.0 + license_family: Apache + purls: [] + size: 3164551 + timestamp: 1769555830639 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.6.1-h546c87b_1.conda + sha256: 7f8048c0e75b2620254218d72b4ae7f14136f1981c5eb555ef61645a9344505f + md5: 25f5885f11e8b1f075bccf4a2da91c60 + depends: + - ca-certificates + - libgcc >=14 + license: Apache-2.0 + license_family: Apache + purls: [] + size: 3692030 + timestamp: 1769557678657 +- conda: https://conda.anaconda.org/conda-forge/osx-64/openssl-3.3.0-hd75f5a5_0.conda + sha256: d3889b0c89c2742e92e20f01e8f298b64c221df5d577c639b823a0bfe314e2e3 + md5: eb8c33aa7929a7714eab8b90c1d88afe + depends: + - ca-certificates + constrains: + - pyopenssl >=22.1 + license: Apache-2.0 + license_family: Apache + purls: [] + size: 2541802 + timestamp: 1714467068742 +- conda: https://conda.anaconda.org/conda-forge/osx-64/openssl-3.6.1-hb6871ef_1.conda + sha256: e02e5639b0e4d6d4fcf0f3b082642844fb5a37316f5b0a1126c6271347462e90 + md5: 30bb8d08b99b9a7600d39efb3559fff0 + depends: + - __osx >=10.13 + - ca-certificates + license: Apache-2.0 + license_family: Apache + size: 2777136 + timestamp: 1769557662405 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.3.0-h0d3ecfb_0.conda + sha256: 51f9be8fe929c2bb3243cd0707b6dfcec27541f8284b4bd9b063c288fc46f482 + md5: 25b0e522c3131886a637e347b2ca0c0f + depends: + - ca-certificates + constrains: + - pyopenssl >=22.1 + license: Apache-2.0 + license_family: Apache + purls: [] + size: 2888226 + timestamp: 1714466346030 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.1-hd24854e_1.conda + sha256: 361f5c5e60052abc12bdd1b50d7a1a43e6a6653aab99a2263bf2288d709dcf67 + md5: f4f6ad63f98f64191c3e77c5f5f29d76 + depends: + - __osx >=11.0 + - ca-certificates + license: Apache-2.0 + license_family: Apache + size: 3104268 + timestamp: 1769556384749 +- conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.6.1-hf411b9b_1.conda + sha256: 53a5ad2e5553b8157a91bb8aa375f78c5958f77cb80e9d2ce59471ea8e5c0bd6 + md5: eb585509b815415bc964b2c7e11c7eb3 + depends: + - ca-certificates + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: Apache-2.0 + license_family: Apache + purls: [] + size: 9343023 + timestamp: 1769557547888 +- conda: https://conda.anaconda.org/conda-forge/noarch/packaging-25.0-pyh29332c3_1.conda + sha256: 289861ed0c13a15d7bbb408796af4de72c2fe67e2bcb0de98f4c3fce259d7991 + md5: 58335b26c38bf4a20f399384c33cbcf9 + depends: + - python >=3.8 + - python + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/packaging?source=hash-mapping + size: 62477 + timestamp: 1745345660407 +- conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda + sha256: c1fc0f953048f743385d31c468b4a678b3ad20caffdeaa94bed85ba63049fd58 + md5: b76541e68fea4d511b1ac46a28dcd2c6 + depends: + - python >=3.8 + - python + license: Apache-2.0 + license_family: APACHE + size: 72010 + timestamp: 1769093650580 +- conda: https://conda.anaconda.org/conda-forge/linux-64/patchelf-0.17.2-h58526e2_0.conda + sha256: eb355ac225be2f698e19dba4dcab7cb0748225677a9799e9cc8e4cadc3cb738f + md5: ba76a6a448819560b5f8b08a9c74f415 + depends: + - libgcc-ng >=7.5.0 + - libstdcxx-ng >=7.5.0 + license: GPL-3.0-or-later + license_family: GPL + purls: [] + size: 94048 + timestamp: 1673473024463 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/patchelf-0.17.2-h884eca8_0.conda + sha256: 8b98158f36a7a92013a1982ab7a60947151350ac5c513c1d1575825d0fa52518 + md5: bbd8dee69c4ac2e2d07bca100b8fcc31 + depends: + - libgcc-ng >=7.5.0 + - libstdcxx-ng >=7.5.0 + license: GPL-3.0-or-later + license_family: GPL + purls: [] + size: 101306 + timestamp: 1673473812166 +- conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-1.0.4-pyhd8ed1ab_0.conda + sha256: 29ea20d0faf20374fcd61c25f6d32fb8e9a2c786a7f1473a0c3ead359470fbe1 + md5: 2908273ac396d2cd210a8127f5f1c0d6 + depends: + - python >=3.10 + license: MPL-2.0 + license_family: MOZILLA + purls: + - pkg:pypi/pathspec?source=hash-mapping + size: 53739 + timestamp: 1769677743677 +- pypi: https://files.pythonhosted.org/packages/54/16/12b82f791c7f50ddec566873d5bdd245baa1491bac11d15ffb98aecc8f8b/pefile-2024.8.26-py3-none-any.whl + name: pefile + version: 2024.8.26 + sha256: 76f8b485dcd3b1bb8166f1128d395fa3d87af26360c2358fb75b80019b957c6f + requires_python: '>=3.6.0' +- conda: https://conda.anaconda.org/conda-forge/noarch/pip-26.0.1-pyh8b19718_0.conda + sha256: 8e1497814a9997654ed7990a79c054ea5a42545679407acbc6f7e809c73c9120 + md5: 67bdec43082fd8a9cffb9484420b39a2 + depends: + - python >=3.10,<3.13.0a0 + - setuptools + - wheel + license: MIT + license_family: MIT + purls: + - pkg:pypi/pip?source=compressed-mapping + size: 1181790 + timestamp: 1770270305795 +- conda: https://conda.anaconda.org/conda-forge/noarch/pixi-pycharm-0.0.10-unix_hf108a03_0.conda + sha256: c84a62f421f3ba388df06df7f414d7b568ad4bc3c33a7799b3405f213a3b1ff5 + md5: 07b709969aa53039501c5960e45794b8 + depends: + - __unix + - python >=3.8 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 7034 + timestamp: 1763572165675 +- conda: https://conda.anaconda.org/conda-forge/noarch/pixi-pycharm-0.0.10-win_hba80fca_0.conda + sha256: c0399f79f0656df7e265ae53630e08cad2d2203a2f39181ff1a68b3b39466d0d + md5: 6dea6b7cca5948b0cfd6eeb5ddecce67 + depends: + - __win + - python >=3.8 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 7042 + timestamp: 1763572121812 +- conda: https://conda.anaconda.org/conda-forge/noarch/pkginfo-1.12.1.2-pyhd8ed1ab_0.conda + sha256: 353fd5a2c3ce31811a6272cd328874eb0d327b1eafd32a1e19001c4ad137ad3a + md5: dc702b2fae7ebe770aff3c83adb16b63 + depends: + - python >=3.9 + license: MIT + license_family: MIT + purls: + - pkg:pypi/pkginfo?source=hash-mapping + size: 30536 + timestamp: 1739984682585 +- conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.4-pyhcf101f3_0.conda + sha256: 0289f0a38337ee201d984f8f31f11f6ef076cfbbfd0ab9181d12d9d1d099bf46 + md5: 82c1787f2a65c0155ef9652466ee98d6 + depends: + - python >=3.10 + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/platformdirs?source=compressed-mapping + size: 25646 + timestamp: 1773199142345 +- conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda + sha256: e14aafa63efa0528ca99ba568eaf506eb55a0371d12e6250aaaa61718d2eb62e + md5: d7585b6550ad04c8c5e21097ada2888e + depends: + - python >=3.9 + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/pluggy?source=compressed-mapping + size: 25877 + timestamp: 1764896838868 +- conda: https://conda.anaconda.org/conda-forge/noarch/pybind11-abi-11-hc364b38_1.conda + sha256: 9e7fe12f727acd2787fb5816b2049cef4604b7a00ad3e408c5e709c298ce8bf1 + md5: f0599959a2447c1e544e216bddf393fa + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 14671 + timestamp: 1752769938071 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pycosat-0.6.6-py310h7c4b9e2_3.conda + sha256: 86d343a2122b55394fda137eaf5461b6e91ac459ffc6f5b4c78f69f00ffd1a12 + md5: 14ab9efb46276ca0d751c942381e90dd + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - python >=3.10,<3.11.0a0 + - python_abi 3.10.* *_cp310 + license: MIT + license_family: MIT + purls: + - pkg:pypi/pycosat?source=hash-mapping + size: 84754 + timestamp: 1757744718942 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pycosat-0.6.6-py311h49ec1c0_3.conda + sha256: 61c07e45a0a0c7a2b0dc986a65067fc2b00aba51663b7b05d4449c7862d7a390 + md5: 77c1b47af5775a813193f7870be8644a + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + license: MIT + license_family: MIT + purls: + - pkg:pypi/pycosat?source=hash-mapping + size: 88491 + timestamp: 1757744790912 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pycosat-0.6.6-py314h5bd0f2a_3.conda + sha256: ccef6174b89815de1ede61b3b20ebccfe301865f2954d789e0b5c1e52dd45f91 + md5: be49bb746ad2cd2ba6737b4afd6cf32a + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - python >=3.14.0rc2,<3.15.0a0 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + size: 88644 + timestamp: 1757744868118 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pycosat-0.6.6-py310h5b55623_3.conda + sha256: 8d9511499803b3899273964a9a571760de5bd7ad4d90cbdf9a16946fc1c60605 + md5: 49ad177a7adc4c714b2725c36f8b1f45 + depends: + - libgcc >=14 + - python >=3.10,<3.11.0a0 + - python >=3.10,<3.11.0a0 *_cpython + - python_abi 3.10.* *_cp310 + license: MIT + license_family: MIT + purls: + - pkg:pypi/pycosat?source=hash-mapping + size: 86257 + timestamp: 1757744805289 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pycosat-0.6.6-py311h19352d5_3.conda + sha256: 792ef42d5691757c087c2214e03e6e5cd1470075bc99c53a62067690345f80be + md5: 8b3741984919ba072ef6d1243e543336 + depends: + - libgcc >=14 + - python >=3.11,<3.12.0a0 + - python >=3.11,<3.12.0a0 *_cpython + - python_abi 3.11.* *_cp311 + license: MIT + license_family: MIT + purls: + - pkg:pypi/pycosat?source=hash-mapping + size: 88731 + timestamp: 1757744856802 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pycosat-0.6.6-py314h51f160d_3.conda + sha256: 20c29d8283581ed5fece2ea5ebac9c1f78756ff523d9c866b50110d8fadc3b7f + md5: 180a289ef4d6ce81588a13f55a4b7238 + depends: + - libgcc >=14 + - python >=3.14.0rc2,<3.15.0a0 + - python >=3.14.0rc2,<3.15.0a0 *_cp314 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + size: 89501 + timestamp: 1757744787708 +- conda: https://conda.anaconda.org/conda-forge/osx-64/pycosat-0.6.6-py310h6729b98_0.conda + sha256: c8ce26a91bd19ab83f8fb7e2f8ada1de799453b519ee156f59aa901146f353d8 + md5: 89b601f80d076bf8053eea906293353c + depends: + - python >=3.10,<3.11.0a0 + - python_abi 3.10.* *_cp310 + license: MIT + license_family: MIT + purls: + - pkg:pypi/pycosat?source=hash-mapping + size: 84654 + timestamp: 1696356173413 +- conda: https://conda.anaconda.org/conda-forge/osx-64/pycosat-0.6.6-py311h2725bcf_0.conda + sha256: 1899b863919c949d38634dbdaec7af2ddb52326a496dd68751ab4f4fe0e8f36a + md5: 47b4652f8a7e6222786663c757815dd5 + depends: + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + license: MIT + license_family: MIT + purls: + - pkg:pypi/pycosat?source=hash-mapping + size: 88031 + timestamp: 1696356171531 +- conda: https://conda.anaconda.org/conda-forge/osx-64/pycosat-0.6.6-py314h03d016b_3.conda + sha256: 6e361e86d25f9ca4b923c85cb0fb34c581b68199d9787df433260722e8101ab7 + md5: a4e0b3801e6673059cea365dc47e4a6e + depends: + - __osx >=10.13 + - python >=3.14.0rc2,<3.15.0a0 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + size: 96705 + timestamp: 1757744863538 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/pycosat-0.6.6-py310h2aa6e3c_0.conda + sha256: 43fc36a584cc9db9cbcd0bee62875ca7702e68fd1df1f35db87f3a14098bb8bc + md5: 3a048bfd19ef0f4e1d6efd3f821c3988 + depends: + - python >=3.10,<3.11.0a0 + - python >=3.10,<3.11.0a0 *_cpython + - python_abi 3.10.* *_cp310 + license: MIT + license_family: MIT + purls: + - pkg:pypi/pycosat?source=hash-mapping + size: 82535 + timestamp: 1696356406059 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/pycosat-0.6.6-py311heffc1b2_0.conda + sha256: 4451971678bbc4fb314201f786c5c3640d429985d195e7d940bfd7d33a384560 + md5: d60b2f87d7b8dd1623fb1baf91a0e311 + depends: + - python >=3.11,<3.12.0a0 + - python >=3.11,<3.12.0a0 *_cpython + - python_abi 3.11.* *_cp311 + license: MIT + license_family: MIT + purls: + - pkg:pypi/pycosat?source=hash-mapping + size: 85652 + timestamp: 1696356197481 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/pycosat-0.6.6-py314hb84d1df_3.conda + sha256: ec919254bca5ba7ef89ac1284582aa91297b89c3b640feda05a3cab0a0402db2 + md5: b23019984b3399dada68581c20e6ef85 + depends: + - __osx >=11.0 + - python >=3.14.0rc2,<3.15.0a0 + - python >=3.14.0rc2,<3.15.0a0 *_cp314 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + size: 92986 + timestamp: 1757744788529 +- conda: https://conda.anaconda.org/conda-forge/win-64/pycosat-0.6.6-py310h29418f3_3.conda + sha256: e81fa9c4554907d3051f4fe6166d66949075bd6fac01f284902f73f4ac9da73e + md5: c51140b7978bf63c441af87be1f6fedf + depends: + - python >=3.10,<3.11.0a0 + - python_abi 3.10.* *_cp310 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: MIT + license_family: MIT + purls: + - pkg:pypi/pycosat?source=hash-mapping + size: 76648 + timestamp: 1757744973237 +- conda: https://conda.anaconda.org/conda-forge/win-64/pycosat-0.6.6-py311h3485c13_3.conda + sha256: f2968e9d6516d7df4c678ce99e922285f244bfaf65069fb2cb3d307b4661f889 + md5: b0cdbb8f4ecd5e1750400ef8bbcb390b + depends: + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: MIT + license_family: MIT + purls: + - pkg:pypi/pycosat?source=hash-mapping + size: 79248 + timestamp: 1757744865552 +- conda: https://conda.anaconda.org/conda-forge/win-64/pycosat-0.6.6-py314h5a2d7ad_3.conda + sha256: e14a8c506e699c968596f1a07e925d63dcc49ee9f3623c4c8a5541ad186e9071 + md5: 4e6be0e1a7a9cd7dde994137b8ebd5cf + depends: + - python >=3.14.0rc2,<3.15.0a0 + - python_abi 3.14.* *_cp314 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: MIT + license_family: MIT + size: 79551 + timestamp: 1757744726713 +- conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda + sha256: 79db7928d13fab2d892592223d7570f5061c192f27b9febd1a418427b719acc6 + md5: 12c566707c80111f9799308d9e265aef + depends: + - python >=3.9 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/pycparser?source=hash-mapping + size: 110100 + timestamp: 1733195786147 +- conda: https://conda.anaconda.org/conda-forge/noarch/pyelftools-0.32-pyh707e725_1.conda + sha256: de3a334388959397ba7b69ee92d5dfaa0c1bd6a7ffcf49c3c4de2ac045c69d28 + md5: eae78c632c980c396cf6f711cf515c3a + depends: + - __unix + - python >=3.9 + license: Unlicense + purls: + - pkg:pypi/pyelftools?source=hash-mapping + size: 149336 + timestamp: 1744148364068 +- conda: https://conda.anaconda.org/conda-forge/noarch/pyopenssl-25.1.0-pyhd8ed1ab_0.conda + sha256: 0d7a8ebdfff0f579a64a95a94cf280ec2889d6c52829a9dbbd3ea9eef02c2f6f + md5: 63d6393b45f33dc0782d73f6d8ae36a0 + depends: + - cryptography >=41.0.5,<46 + - python >=3.9 + - typing-extensions >=4.9 + - typing_extensions >=4.9 + license: Apache-2.0 + license_family: Apache + purls: + - pkg:pypi/pyopenssl?source=hash-mapping + size: 123256 + timestamp: 1747560884456 +- pypi: https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl + name: pyproject-hooks + version: 1.2.0 + sha256: 9e5c6bfa8dcc30091c74b0cf803c81fdd29d94f01992a7707bc97babb1141913 + requires_python: '>=3.7' +- conda: https://conda.anaconda.org/conda-forge/noarch/pyproject-metadata-0.11.0-pyhd8ed1ab_0.conda + sha256: 7e709bde682104c241674f8005fd560d7ea8599458c94d03ed51ef8a4ae7d737 + md5: cd6dae6c673c8f12fe7267eac3503961 + depends: + - packaging >=23.2 + - python >=3.10 + license: MIT + license_family: MIT + purls: + - pkg:pypi/pyproject-metadata?source=hash-mapping + size: 25200 + timestamp: 1770672303277 +- conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyh09c184e_7.conda + sha256: d016e04b0e12063fbee4a2d5fbb9b39a8d191b5a0042f0b8459188aedeabb0ca + md5: e2fd202833c4a981ce8a65974fe4abd1 + depends: + - __win + - python >=3.9 + - win_inet_pton + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/pysocks?source=hash-mapping + size: 21784 + timestamp: 1733217448189 +- conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda + sha256: ba3b032fa52709ce0d9fd388f63d330a026754587a2f461117cac9ab73d8d0d8 + md5: 461219d1a5bd61342293efa2c0c90eac + depends: + - __unix + - python >=3.9 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/pysocks?source=hash-mapping + size: 21085 + timestamp: 1733217331982 +- conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.10.20-h3c07f61_0_cpython.conda + sha256: 8ff2ce308faf2588b69c65b120293f59a8f2577b772b34df4e817d220b09e081 + md5: 5d4e2b00d99feacd026859b7fa239dc0 + depends: + - __glibc >=2.17,<3.0.a0 + - bzip2 >=1.0.8,<2.0a0 + - ld_impl_linux-64 >=2.36.1 + - libexpat >=2.7.4,<3.0a0 + - libffi >=3.4,<4.0a0 + - libgcc >=14 + - liblzma >=5.8.2,<6.0a0 + - libnsl >=2.0.1,<2.1.0a0 + - libsqlite >=3.51.2,<4.0a0 + - libuuid >=2.41.3,<3.0a0 + - libxcrypt >=4.4.36 + - libzlib >=1.3.1,<2.0a0 + - ncurses >=6.5,<7.0a0 + - openssl >=3.5.5,<4.0a0 + - readline >=8.3,<9.0a0 + - tk >=8.6.13,<8.7.0a0 + - tzdata + constrains: + - python_abi 3.10.* *_cp310 + license: Python-2.0 + purls: [] + size: 25455342 + timestamp: 1772729810280 +- conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.11.15-hd63d673_0_cpython.conda + sha256: bf6a32c69889d38482436a786bea32276756cedf0e9805cc856ffd088e8d00f0 + md5: a5ebcefec0c12a333bcd6d7bf3bddc1f + depends: + - __glibc >=2.17,<3.0.a0 + - bzip2 >=1.0.8,<2.0a0 + - ld_impl_linux-64 >=2.36.1 + - libexpat >=2.7.4,<3.0a0 + - libffi >=3.5.2,<3.6.0a0 + - libgcc >=14 + - liblzma >=5.8.2,<6.0a0 + - libnsl >=2.0.1,<2.1.0a0 + - libsqlite >=3.51.2,<4.0a0 + - libuuid >=2.41.3,<3.0a0 + - libxcrypt >=4.4.36 + - libzlib >=1.3.1,<2.0a0 + - ncurses >=6.5,<7.0a0 + - openssl >=3.5.5,<4.0a0 + - readline >=8.3,<9.0a0 + - tk >=8.6.13,<8.7.0a0 + - tzdata + constrains: + - python_abi 3.11.* *_cp311 + license: Python-2.0 + purls: [] + size: 30949404 + timestamp: 1772730362552 +- conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.14.3-h32b2ec7_101_cp314.conda + build_number: 101 + sha256: cb0628c5f1732f889f53a877484da98f5a0e0f47326622671396fb4f2b0cd6bd + md5: c014ad06e60441661737121d3eae8a60 + depends: + - __glibc >=2.17,<3.0.a0 + - bzip2 >=1.0.8,<2.0a0 + - ld_impl_linux-64 >=2.36.1 + - libexpat >=2.7.3,<3.0a0 + - libffi >=3.5.2,<3.6.0a0 + - libgcc >=14 + - liblzma >=5.8.2,<6.0a0 + - libmpdec >=4.0.0,<5.0a0 + - libsqlite >=3.51.2,<4.0a0 + - libuuid >=2.41.3,<3.0a0 + - libzlib >=1.3.1,<2.0a0 + - ncurses >=6.5,<7.0a0 + - openssl >=3.5.5,<4.0a0 + - python_abi 3.14.* *_cp314 + - readline >=8.3,<9.0a0 + - tk >=8.6.13,<8.7.0a0 + - tzdata + - zstd >=1.5.7,<1.6.0a0 + license: Python-2.0 + size: 36702440 + timestamp: 1770675584356 + python_site_packages_path: lib/python3.14/site-packages +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.10.20-h28be5d3_0_cpython.conda + sha256: 2f16794d69e058404cca633021b284e70253dfb76e4b314d9dbd448aa0354e84 + md5: 5d61c9a2acf7c675f7ae5f6cf51ffb0b + depends: + - bzip2 >=1.0.8,<2.0a0 + - ld_impl_linux-aarch64 >=2.36.1 + - libexpat >=2.7.4,<3.0a0 + - libffi >=3.4,<4.0a0 + - libgcc >=14 + - liblzma >=5.8.2,<6.0a0 + - libnsl >=2.0.1,<2.1.0a0 + - libsqlite >=3.51.2,<4.0a0 + - libuuid >=2.41.3,<3.0a0 + - libxcrypt >=4.4.36 + - libzlib >=1.3.1,<2.0a0 + - ncurses >=6.5,<7.0a0 + - openssl >=3.5.5,<4.0a0 + - readline >=8.3,<9.0a0 + - tk >=8.6.13,<8.7.0a0 + - tzdata + constrains: + - python_abi 3.10.* *_cp310 + license: Python-2.0 + purls: [] + size: 13234644 + timestamp: 1772728813900 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.11.15-h91f4b29_0_cpython.conda + sha256: da3aa4c63af904d38c2e0b6ceecfa539d60c2653ac3cff7cae79d87298dc4fb0 + md5: bb09184ea3313703da05516cd730e8f8 + depends: + - bzip2 >=1.0.8,<2.0a0 + - ld_impl_linux-aarch64 >=2.36.1 + - libexpat >=2.7.4,<3.0a0 + - libffi >=3.5.2,<3.6.0a0 + - libgcc >=14 + - liblzma >=5.8.2,<6.0a0 + - libnsl >=2.0.1,<2.1.0a0 + - libsqlite >=3.51.2,<4.0a0 + - libuuid >=2.41.3,<3.0a0 + - libxcrypt >=4.4.36 + - libzlib >=1.3.1,<2.0a0 + - ncurses >=6.5,<7.0a0 + - openssl >=3.5.5,<4.0a0 + - readline >=8.3,<9.0a0 + - tk >=8.6.13,<8.7.0a0 + - tzdata + constrains: + - python_abi 3.11.* *_cp311 + license: Python-2.0 + purls: [] + size: 14306513 + timestamp: 1772728906052 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.14.3-hb06a95a_101_cp314.conda + build_number: 101 + sha256: 87e9dff5646aba87cecfbc08789634c855871a7325169299d749040b0923a356 + md5: 205011b36899ff0edf41b3db0eda5a44 + depends: + - bzip2 >=1.0.8,<2.0a0 + - ld_impl_linux-aarch64 >=2.36.1 + - libexpat >=2.7.3,<3.0a0 + - libffi >=3.5.2,<3.6.0a0 + - libgcc >=14 + - liblzma >=5.8.2,<6.0a0 + - libmpdec >=4.0.0,<5.0a0 + - libsqlite >=3.51.2,<4.0a0 + - libuuid >=2.41.3,<3.0a0 + - libzlib >=1.3.1,<2.0a0 + - ncurses >=6.5,<7.0a0 + - openssl >=3.5.5,<4.0a0 + - python_abi 3.14.* *_cp314 + - readline >=8.3,<9.0a0 + - tk >=8.6.13,<8.7.0a0 + - tzdata + - zstd >=1.5.7,<1.6.0a0 + license: Python-2.0 + size: 37305578 + timestamp: 1770674395875 + python_site_packages_path: lib/python3.14/site-packages +- conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.10.14-h00d2728_0_cpython.conda + sha256: 00c1de2d46ede26609ef4e84a44b83be7876ba6a0215b7c83bff41a0656bf694 + md5: 0a1cddc4382c5c171e791c70740546dd + depends: + - bzip2 >=1.0.8,<2.0a0 + - libffi >=3.4,<4.0a0 + - libsqlite >=3.45.2,<4.0a0 + - libzlib >=1.2.13,<2.0.0a0 + - ncurses >=6.4.20240210,<7.0a0 + - openssl >=3.2.1,<4.0a0 + - readline >=8.2,<9.0a0 + - tk >=8.6.13,<8.7.0a0 + - tzdata + - xz >=5.2.6,<6.0a0 + constrains: + - python_abi 3.10.* *_cp310 + license: Python-2.0 + purls: [] + size: 11890228 + timestamp: 1710940046031 +- conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.11.8-h9f0c242_0_cpython.conda + sha256: 645dad20b46041ecd6a85eccbb3291fa1ad7921eea065c0081efff78c3d7e27a + md5: 22bda10a0f425564a538aed9a0e8a9df + depends: + - bzip2 >=1.0.8,<2.0a0 + - libexpat >=2.5.0,<3.0a0 + - libffi >=3.4,<4.0a0 + - libsqlite >=3.45.1,<4.0a0 + - libzlib >=1.2.13,<2.0.0a0 + - ncurses >=6.4,<7.0a0 + - openssl >=3.2.1,<4.0a0 + - readline >=8.2,<9.0a0 + - tk >=8.6.13,<8.7.0a0 + - tzdata + - xz >=5.2.6,<6.0a0 + constrains: + - python_abi 3.11.* *_cp311 + license: Python-2.0 + purls: [] + size: 14067894 + timestamp: 1708117836907 +- conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.14.3-h4f44bb5_101_cp314.conda + build_number: 101 + sha256: f64e357aa0168a201c9b3eedf500d89a8550d6631d26a95590b12de61f8fd660 + md5: 030ec23658b941438ac42303aff0db2b + depends: + - __osx >=10.13 + - bzip2 >=1.0.8,<2.0a0 + - libexpat >=2.7.3,<3.0a0 + - libffi >=3.5.2,<3.6.0a0 + - liblzma >=5.8.2,<6.0a0 + - libmpdec >=4.0.0,<5.0a0 + - libsqlite >=3.51.2,<4.0a0 + - libzlib >=1.3.1,<2.0a0 + - ncurses >=6.5,<7.0a0 + - openssl >=3.5.5,<4.0a0 + - python_abi 3.14.* *_cp314 + - readline >=8.3,<9.0a0 + - tk >=8.6.13,<8.7.0a0 + - tzdata + - zstd >=1.5.7,<1.6.0a0 + license: Python-2.0 + size: 14387288 + timestamp: 1770676578632 + python_site_packages_path: lib/python3.14/site-packages +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.10.14-h2469fbe_0_cpython.conda + sha256: 454d609fe25daedce9e886efcbfcadad103ed0362e7cb6d2bcddec90b1ecd3ee + md5: 4ae999c8227c6d8c7623d32d51d25ea9 + depends: + - bzip2 >=1.0.8,<2.0a0 + - libffi >=3.4,<4.0a0 + - libsqlite >=3.45.2,<4.0a0 + - libzlib >=1.2.13,<2.0.0a0 + - ncurses >=6.4.20240210,<7.0a0 + - openssl >=3.2.1,<4.0a0 + - readline >=8.2,<9.0a0 + - tk >=8.6.13,<8.7.0a0 + - tzdata + - xz >=5.2.6,<6.0a0 + constrains: + - python_abi 3.10.* *_cp310 + license: Python-2.0 + purls: [] + size: 12336005 + timestamp: 1710939659384 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.11.8-hdf0ec26_0_cpython.conda + sha256: 6c9bbac137759e013e6a50593c7cf10a06032fcb1ef3a994c598c7a95e73a8e1 + md5: 8f4076d960f17f19ae8b2f66727ea1c6 + depends: + - bzip2 >=1.0.8,<2.0a0 + - libexpat >=2.5.0,<3.0a0 + - libffi >=3.4,<4.0a0 + - libsqlite >=3.45.1,<4.0a0 + - libzlib >=1.2.13,<2.0.0a0 + - ncurses >=6.4,<7.0a0 + - openssl >=3.2.1,<4.0a0 + - readline >=8.2,<9.0a0 + - tk >=8.6.13,<8.7.0a0 + - tzdata + - xz >=5.2.6,<6.0a0 + constrains: + - python_abi 3.11.* *_cp311 + license: Python-2.0 + purls: [] + size: 14623079 + timestamp: 1708116925163 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.14.3-h4c637c5_101_cp314.conda + build_number: 101 + sha256: fccce2af62d11328d232df9f6bbf63464fd45f81f718c661757f9c628c4378ce + md5: 753c8d0447677acb7ddbcc6e03e82661 + depends: + - __osx >=11.0 + - bzip2 >=1.0.8,<2.0a0 + - libexpat >=2.7.3,<3.0a0 + - libffi >=3.5.2,<3.6.0a0 + - liblzma >=5.8.2,<6.0a0 + - libmpdec >=4.0.0,<5.0a0 + - libsqlite >=3.51.2,<4.0a0 + - libzlib >=1.3.1,<2.0a0 + - ncurses >=6.5,<7.0a0 + - openssl >=3.5.5,<4.0a0 + - python_abi 3.14.* *_cp314 + - readline >=8.3,<9.0a0 + - tk >=8.6.13,<8.7.0a0 + - tzdata + - zstd >=1.5.7,<1.6.0a0 + license: Python-2.0 + size: 13522698 + timestamp: 1770675365241 + python_site_packages_path: lib/python3.14/site-packages +- conda: https://conda.anaconda.org/conda-forge/win-64/python-3.10.20-hc20f281_0_cpython.conda + sha256: e71595dd281a9902d7b84f545f16d7d4c0fb62cc6816431301f8f4870c94dc8c + md5: 6c18c24d33a7ac8a4f81c68b8eb8581b + depends: + - bzip2 >=1.0.8,<2.0a0 + - libexpat >=2.7.4,<3.0a0 + - libffi >=3.4,<4.0a0 + - liblzma >=5.8.2,<6.0a0 + - libsqlite >=3.51.2,<4.0a0 + - libzlib >=1.3.1,<2.0a0 + - openssl >=3.5.5,<4.0a0 + - tk >=8.6.13,<8.7.0a0 + - tzdata + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + constrains: + - python_abi 3.10.* *_cp310 + license: Python-2.0 + purls: [] + size: 16028082 + timestamp: 1772728853200 +- conda: https://conda.anaconda.org/conda-forge/win-64/python-3.11.15-h0159041_0_cpython.conda + sha256: a1f1031088ce69bc99c82b95980c1f54e16cbd5c21f042e9c1ea25745a8fc813 + md5: d09dbf470b41bca48cbe6a78ba1e009b + depends: + - bzip2 >=1.0.8,<2.0a0 + - libexpat >=2.7.4,<3.0a0 + - libffi >=3.5.2,<3.6.0a0 + - liblzma >=5.8.2,<6.0a0 + - libsqlite >=3.51.2,<4.0a0 + - libzlib >=1.3.1,<2.0a0 + - openssl >=3.5.5,<4.0a0 + - tk >=8.6.13,<8.7.0a0 + - tzdata + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + constrains: + - python_abi 3.11.* *_cp311 + license: Python-2.0 + purls: [] + size: 18416208 + timestamp: 1772728847666 +- conda: https://conda.anaconda.org/conda-forge/win-64/python-3.14.3-h4b44e0e_101_cp314.conda + build_number: 101 + sha256: 3f99d83bfd95b9bdae64a42a1e4bf5131dc20b724be5ac8a9a7e1ac2c0f006d7 + md5: 7ec2be7eaf59f83f3e5617665f3fbb2e + depends: + - bzip2 >=1.0.8,<2.0a0 + - libexpat >=2.7.3,<3.0a0 + - libffi >=3.5.2,<3.6.0a0 + - liblzma >=5.8.2,<6.0a0 + - libmpdec >=4.0.0,<5.0a0 + - libsqlite >=3.51.2,<4.0a0 + - libzlib >=1.3.1,<2.0a0 + - openssl >=3.5.5,<4.0a0 + - python_abi 3.14.* *_cp314 + - tk >=8.6.13,<8.7.0a0 + - tzdata + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - zstd >=1.5.7,<1.6.0a0 + license: Python-2.0 + size: 18273230 + timestamp: 1770675442998 + python_site_packages_path: Lib/site-packages +- conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.10-8_cp310.conda + build_number: 8 + sha256: 7ad76fa396e4bde336872350124c0819032a9e8a0a40590744ff9527b54351c1 + md5: 05e00f3b21e88bb3d658ac700b2ce58c + constrains: + - python 3.10.* *_cpython + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 6999 + timestamp: 1752805924192 +- conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.11-8_cp311.conda + build_number: 8 + sha256: fddf123692aa4b1fc48f0471e346400d9852d96eeed77dbfdd746fa50a8ff894 + md5: 8fcb6b0e2161850556231336dae58358 + constrains: + - python 3.11.* *_cpython + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 7003 + timestamp: 1752805919375 +- conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda + build_number: 8 + sha256: ad6d2e9ac39751cc0529dd1566a26751a0bf2542adb0c232533d32e176e21db5 + md5: 0539938c55b6b1a59b560e843ad864a4 + constrains: + - python 3.14.* *_cp314 + license: BSD-3-Clause + license_family: BSD + size: 6989 + timestamp: 1752805904792 +- conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda + sha256: 12ffde5a6f958e285aa22c191ca01bbd3d6e710aa852e00618fa6ddc59149002 + md5: d7d95fc8287ea7bf33e0e7116d2b95ec + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - ncurses >=6.5,<7.0a0 + license: GPL-3.0-only + license_family: GPL + purls: [] + size: 345073 + timestamp: 1765813471974 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/readline-8.3-hb682ff5_0.conda + sha256: fe695f9d215e9a2e3dd0ca7f56435ab4df24f5504b83865e3d295df36e88d216 + md5: 3d49cad61f829f4f0e0611547a9cda12 + depends: + - libgcc >=14 + - ncurses >=6.5,<7.0a0 + license: GPL-3.0-only + license_family: GPL + purls: [] + size: 357597 + timestamp: 1765815673644 +- conda: https://conda.anaconda.org/conda-forge/osx-64/readline-8.2-h7cca4af_2.conda + sha256: 53017e80453c4c1d97aaf78369040418dea14cf8f46a2fa999f31bd70b36c877 + md5: 342570f8e02f2f022147a7f841475784 + depends: + - ncurses >=6.5,<7.0a0 + license: GPL-3.0-only + license_family: GPL + purls: [] + size: 256712 + timestamp: 1740379577668 +- conda: https://conda.anaconda.org/conda-forge/osx-64/readline-8.3-h68b038d_0.conda + sha256: 4614af680aa0920e82b953fece85a03007e0719c3399f13d7de64176874b80d5 + md5: eefd65452dfe7cce476a519bece46704 + depends: + - __osx >=10.13 + - ncurses >=6.5,<7.0a0 + license: GPL-3.0-only + license_family: GPL + size: 317819 + timestamp: 1765813692798 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.2-h1d1bf99_2.conda + sha256: 7db04684d3904f6151eff8673270922d31da1eea7fa73254d01c437f49702e34 + md5: 63ef3f6e6d6d5c589e64f11263dc5676 + depends: + - ncurses >=6.5,<7.0a0 + license: GPL-3.0-only + license_family: GPL + purls: [] + size: 252359 + timestamp: 1740379663071 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda + sha256: a77010528efb4b548ac2a4484eaf7e1c3907f2aec86123ed9c5212ae44502477 + md5: f8381319127120ce51e081dce4865cf4 + depends: + - __osx >=11.0 + - ncurses >=6.5,<7.0a0 + license: GPL-3.0-only + license_family: GPL + size: 313930 + timestamp: 1765813902568 +- conda: https://conda.anaconda.org/conda-forge/linux-64/reproc-14.2.5.post0-hb9d3cd8_0.conda + sha256: a1973f41a6b956f1305f9aaefdf14b2f35a8c9615cfe5f143f1784ed9aa6bf47 + md5: 69fbc0a9e42eb5fe6733d2d60d818822 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + license: MIT + license_family: MIT + purls: [] + size: 34194 + timestamp: 1731925834928 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/reproc-14.2.5.post0-h86ecc28_0.conda + sha256: 3bbcfd61da8ab71c0b7b5bbff471669f64e6a3fb759411a46a2d4fd31a9642cc + md5: 70b14ba118c2c19b240a39577b3e607a + depends: + - libgcc >=13 + license: MIT + license_family: MIT + purls: [] + size: 36102 + timestamp: 1745309589538 +- conda: https://conda.anaconda.org/conda-forge/osx-64/reproc-14.2.5.post0-h6e16a3a_0.conda + sha256: dda2a8bc1bf16b563b74c2a01dccea657bda573b0c45e708bfeee01c208bcbaf + md5: eda18d4a7dce3831016086a482965345 + depends: + - __osx >=10.13 + license: MIT + license_family: MIT + size: 31749 + timestamp: 1731926270954 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/reproc-14.2.5.post0-h5505292_0.conda + sha256: a5f0dbfa8099a3d3c281ea21932b6359775fd8ce89acc53877a6ee06f50642bc + md5: f1d129089830365d9dac932c4dd8c675 + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + size: 32023 + timestamp: 1731926255834 +- conda: https://conda.anaconda.org/conda-forge/win-64/reproc-14.2.5.post0-h2466b09_0.conda + sha256: 112dee79da4f55de91f029dd9808f4284bc5e0cf0c4d308d4cec3381bf5bc836 + md5: c3ca4c18c99a3b9832e11b11af227713 + depends: + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: MIT + license_family: MIT + purls: [] + size: 37058 + timestamp: 1731926140985 +- conda: https://conda.anaconda.org/conda-forge/linux-64/reproc-cpp-14.2.5.post0-h5888daf_0.conda + sha256: 568485837b905b1ea7bdb6e6496d914b83db57feda57f6050d5a694977478691 + md5: 828302fca535f9cfeb598d5f7c204323 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + - libstdcxx >=13 + - reproc 14.2.5.post0 hb9d3cd8_0 + license: MIT + license_family: MIT + purls: [] + size: 25665 + timestamp: 1731925852714 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/reproc-cpp-14.2.5.post0-h5ad3122_0.conda + sha256: 57831399b5c2ccc4a2ec4fad4ec70609ddc0e7098a1d8cca62e063860fd1674b + md5: fde98968589573ad478b504642319105 + depends: + - libgcc >=13 + - libstdcxx >=13 + - reproc 14.2.5.post0 h86ecc28_0 + license: MIT + license_family: MIT + purls: [] + size: 26291 + timestamp: 1745309832653 +- conda: https://conda.anaconda.org/conda-forge/osx-64/reproc-cpp-14.2.5.post0-h240833e_0.conda + sha256: 4d8638b7f44082302c7687c99079789f42068d34cddc0959c11ad5d28aab3d47 + md5: 420229341978751bd96faeced92c200e + depends: + - __osx >=10.13 + - libcxx >=18 + - reproc 14.2.5.post0 h6e16a3a_0 + license: MIT + license_family: MIT + size: 24394 + timestamp: 1731926392643 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/reproc-cpp-14.2.5.post0-h286801f_0.conda + sha256: f1b6aa9d9131ea159a5883bc5990b91b4b8f56eb52e0dc2b01aa9622e14edc81 + md5: 11a3d09937d250fc4423bf28837d9363 + depends: + - __osx >=11.0 + - libcxx >=18 + - reproc 14.2.5.post0 h5505292_0 + license: MIT + license_family: MIT + size: 24834 + timestamp: 1731926355120 +- conda: https://conda.anaconda.org/conda-forge/win-64/reproc-cpp-14.2.5.post0-he0c23c2_0.conda + sha256: ccf49fb5149298015ab410aae88e43600954206608089f0dfb7aea8b771bbe8e + md5: d2ce31fa746dddeb37f24f32da0969e9 + depends: + - reproc 14.2.5.post0 h2466b09_0 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: MIT + license_family: MIT + purls: [] + size: 30096 + timestamp: 1731926177599 +- conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.32.5-pyhcf101f3_1.conda + sha256: 7813c38b79ae549504b2c57b3f33394cea4f2ad083f0994d2045c2e24cb538c5 + md5: c65df89a0b2e321045a9e01d1337b182 + depends: + - python >=3.10 + - certifi >=2017.4.17 + - charset-normalizer >=2,<4 + - idna >=2.5,<4 + - urllib3 >=1.21.1,<3 + - python + constrains: + - chardet >=3.0.2,<6 + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/requests?source=compressed-mapping + size: 63602 + timestamp: 1766926974520 +- conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.33.0-pyhcf101f3_0.conda + sha256: fbc7183778e1f9976ae7d812986c227f9d43f841326ac03b5f43f1ac93fa8f3b + md5: bee5ed456361bfe8af502beaf5db82e2 + depends: + - python >=3.10 + - certifi >=2023.5.7 + - charset-normalizer >=2,<4 + - idna >=2.5,<4 + - urllib3 >=1.26,<3 + - python + constrains: + - chardet >=3.0.2,<6 + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/requests?source=compressed-mapping + size: 63788 + timestamp: 1774462091279 +- conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.33.1-pyhcf101f3_0.conda + sha256: c0249bc4bf4c0e8e06d0e7b4d117a5d593cc4ab2144d5006d6d47c83cb0af18e + md5: 10afbb4dbf06ff959ad25a92ccee6e59 + depends: + - python >=3.10 + - certifi >=2023.5.7 + - charset-normalizer >=2,<4 + - idna >=2.5,<4 + - urllib3 >=1.26,<3 + - python + constrains: + - chardet >=3.0.2,<6 + license: Apache-2.0 + purls: + - pkg:pypi/requests?source=compressed-mapping + size: 63712 + timestamp: 1774894783063 +- pypi: https://files.pythonhosted.org/packages/3f/51/d4db610ef29373b879047326cbf6fa98b6c1969d6f6dc423279de2b1be2c/requests_toolbelt-1.0.0-py2.py3-none-any.whl + name: requests-toolbelt + version: 1.0.0 + sha256: cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06 + requires_dist: + - requests>=2.0.1,<3.0.0 + requires_python: '>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*' +- pypi: https://files.pythonhosted.org/packages/ff/9a/9afaade874b2fa6c752c36f1548f718b5b83af81ed9b76628329dab81c1b/rfc3986-2.0.0-py2.py3-none-any.whl + name: rfc3986 + version: 2.0.0 + sha256: 50b1502b60e289cb37883f3dfd34532b8873c7de9f49bb546641ce9cbd256ebd + requires_dist: + - idna ; extra == 'idna2008' + requires_python: '>=3.7' +- conda: https://conda.anaconda.org/conda-forge/linux-64/rhash-1.4.6-hb9d3cd8_1.conda + sha256: d5c73079c1dd2c2a313c3bfd81c73dbd066b7eb08d213778c8bff520091ae894 + md5: c1c9b02933fdb2cfb791d936c20e887e + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + license: MIT + license_family: MIT + purls: [] + size: 193775 + timestamp: 1748644872902 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rhash-1.4.6-h86ecc28_1.conda + sha256: 0fe6f40213f2d8af4fcb7388eeb782a4e496c8bab32c189c3a34b37e8004e5a4 + md5: 745d02c0c22ea2f28fbda2cb5dbec189 + depends: + - libgcc >=13 + license: MIT + license_family: MIT + purls: [] + size: 207475 + timestamp: 1748644952027 +- conda: https://conda.anaconda.org/conda-forge/osx-64/rhash-1.4.4-h0dc2134_0.conda + sha256: f1ae47e8c4e46f856faf5d8ee1e5291f55627aa93401b61a877f18ade5780c87 + md5: 55a2ada70c8a208c01f77978f2783121 + license: MIT + license_family: MIT + purls: [] + size: 177229 + timestamp: 1693456080514 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/rhash-1.4.4-hb547adb_0.conda + sha256: 3ab595e2280ed2118b6b1e8ce7e5949da2047846c81b6af1bbf5ac859d062edd + md5: 710c4b1abf65b697c1d9716eba16dbb0 + license: MIT + license_family: MIT + purls: [] + size: 177491 + timestamp: 1693456037505 +- conda: https://conda.anaconda.org/conda-forge/linux-64/ruamel.yaml-0.18.17-py310h139afa4_2.conda + sha256: 0741675606a288ca70a68282d9b8b67b61cc6e991dcec38bae9ec1e38237524c + md5: 26ad912afb7835e474284d61f482905d + depends: + - python + - ruamel.yaml.clib >=0.2.15 + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - python_abi 3.10.* *_cp310 + license: MIT + license_family: MIT + purls: + - pkg:pypi/ruamel-yaml?source=hash-mapping + size: 219162 + timestamp: 1766175793325 +- conda: https://conda.anaconda.org/conda-forge/linux-64/ruamel.yaml-0.18.17-py311haee01d2_2.conda + sha256: 5324d0353c9cca813501ea9b20186f8e6835cd4ff6e4dfa897c5faeecce8cdaa + md5: 672395a7f912a9eda492959b7632ae6c + depends: + - python + - ruamel.yaml.clib >=0.2.15 + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + - python_abi 3.11.* *_cp311 + license: MIT + license_family: MIT + purls: + - pkg:pypi/ruamel-yaml?source=hash-mapping + size: 294535 + timestamp: 1766175791754 +- conda: https://conda.anaconda.org/conda-forge/linux-64/ruamel.yaml-0.18.17-py314h0f05182_2.conda + sha256: 59f7773ed8c6f2bcab3e953e2b4816c86cf71e5508dc571f8073b8c2294b5787 + md5: 8ea76c64b49b16c37769ea7c4dca993b + depends: + - python + - ruamel.yaml.clib >=0.2.15 + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + size: 308487 + timestamp: 1766175778417 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ruamel.yaml-0.18.17-py310hef25091_2.conda + sha256: 4ba656144b8e56490f4dcec674310a4a7c411e43dfad8945c43c239c1faec898 + md5: e867ca69a8d4866b05a363bfddad2250 + depends: + - python + - ruamel.yaml.clib >=0.2.15 + - libgcc >=14 + - python 3.10.* *_cpython + - python_abi 3.10.* *_cp310 + license: MIT + license_family: MIT + purls: + - pkg:pypi/ruamel-yaml?source=hash-mapping + size: 222819 + timestamp: 1766175822103 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ruamel.yaml-0.18.17-py311h51cfe5d_2.conda + sha256: b965d2023a41acbf76bd965e106835d19e6a26cd69c4e1d439df17471336226e + md5: ecf191a9fa6a518ca91aaa49e3c87584 + depends: + - python + - ruamel.yaml.clib >=0.2.15 + - libgcc >=14 + - python 3.11.* *_cpython + - python_abi 3.11.* *_cp311 + license: MIT + license_family: MIT + purls: + - pkg:pypi/ruamel-yaml?source=hash-mapping + size: 298156 + timestamp: 1766175797018 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ruamel.yaml-0.18.17-py314h2e8dab5_2.conda + sha256: baedba4fb0d0929ffcbebd001876c115d23c5620457eb9347cdac5978963c262 + md5: 1f86e018331edc941dedc796c4373fe3 + depends: + - python + - ruamel.yaml.clib >=0.2.15 + - libgcc >=14 + - python 3.14.* *_cp314 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + size: 311783 + timestamp: 1766175823921 +- conda: https://conda.anaconda.org/conda-forge/osx-64/ruamel.yaml-0.17.40-py310hb372a2b_0.conda + sha256: a6f883e95ff6c0b48ecdc16113deae57961c24a3d9458ebabd489f61a9aae4d5 + md5: 150037c34bc1cd6bbe69876c4e7347f4 + depends: + - python >=3.10,<3.11.0a0 + - python_abi 3.10.* *_cp310 + - ruamel.yaml.clib >=0.1.2 + - setuptools + license: MIT + license_family: MIT + purls: + - pkg:pypi/ruamel-yaml?source=hash-mapping + size: 200022 + timestamp: 1698138926099 +- conda: https://conda.anaconda.org/conda-forge/osx-64/ruamel.yaml-0.17.40-py311he705e18_0.conda + sha256: 0260c295cdfae417f107fe2fae66bae4eb260195885d81d8b1cd4fc6d81c849b + md5: 4796cc1d45c88ace8f5bb7950167a568 + depends: + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + - ruamel.yaml.clib >=0.1.2 + - setuptools + license: MIT + license_family: MIT + purls: + - pkg:pypi/ruamel-yaml?source=hash-mapping + size: 277064 + timestamp: 1698138918002 +- conda: https://conda.anaconda.org/conda-forge/osx-64/ruamel.yaml-0.18.17-py314hd330473_2.conda + sha256: 59edac475c2e53dda7802554aa8310b4214ef0a536841be4ab318e0b5b7563fc + md5: c64fb655de0ccaafb1d875f4fa1f0fc3 + depends: + - python + - ruamel.yaml.clib >=0.2.15 + - __osx >=10.13 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + size: 308947 + timestamp: 1766175829662 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/ruamel.yaml-0.17.40-py310hd125d64_0.conda + sha256: efc0814c8d5b9e20d75a425f0a9c782e5642a4a349849fa95c8b5b2f1108f6c9 + md5: 77e106fbe41acee97140e992dc52ad77 + depends: + - python >=3.10,<3.11.0a0 + - python >=3.10,<3.11.0a0 *_cpython + - python_abi 3.10.* *_cp310 + - ruamel.yaml.clib >=0.1.2 + - setuptools + license: MIT + license_family: MIT + purls: + - pkg:pypi/ruamel-yaml?source=hash-mapping + size: 200368 + timestamp: 1698139000522 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/ruamel.yaml-0.17.40-py311h05b510d_0.conda + sha256: bf44774cbd03eb8d396a078b4af1b194f8600f8ca7ea7ca0e3d61dc16b400cb4 + md5: 640b6933c680860877b32a4c11076ab9 + depends: + - python >=3.11,<3.12.0a0 + - python >=3.11,<3.12.0a0 *_cpython + - python_abi 3.11.* *_cp311 + - ruamel.yaml.clib >=0.1.2 + - setuptools + license: MIT + license_family: MIT + purls: + - pkg:pypi/ruamel-yaml?source=hash-mapping + size: 276178 + timestamp: 1698139045095 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/ruamel.yaml-0.18.17-py314ha14b1ff_2.conda + sha256: 0f498e343be464219a99424260ff442144d0461a3a5eb30c9de6081af358b281 + md5: 87fc3a204f105e7e61c60a72509cccbd + depends: + - python + - ruamel.yaml.clib >=0.2.15 + - __osx >=11.0 + - python 3.14.* *_cp314 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + size: 311922 + timestamp: 1766175797575 +- conda: https://conda.anaconda.org/conda-forge/win-64/ruamel.yaml-0.18.17-py310h1637853_2.conda + sha256: cb42613022b37517a10064e399a9f5b929a02d6c8a135e84b248a69d39fc7a8a + md5: 20dfd23643ca21f251dfa6c6853c06c4 + depends: + - python + - ruamel.yaml.clib >=0.2.15 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - python_abi 3.10.* *_cp310 + license: MIT + license_family: MIT + purls: + - pkg:pypi/ruamel-yaml?source=hash-mapping + size: 217306 + timestamp: 1766175806668 +- conda: https://conda.anaconda.org/conda-forge/win-64/ruamel.yaml-0.18.17-py311hf893f09_2.conda + sha256: 90f4058642a6badfe710b2d1b0dd8cd802485303a209e6591c3c77ed74f0c363 + md5: a4d4fcbe5a1b6e5bae7cb5a1bac4919d + depends: + - python + - ruamel.yaml.clib >=0.2.15 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - python_abi 3.11.* *_cp311 + license: MIT + license_family: MIT + purls: + - pkg:pypi/ruamel-yaml?source=hash-mapping + size: 292781 + timestamp: 1766175809044 +- conda: https://conda.anaconda.org/conda-forge/win-64/ruamel.yaml-0.18.17-py314hc5dbbe4_2.conda + sha256: 62b73874b6c264a73e7904b33322128c4881c78dfe2fb9131becfbf84343ee2d + md5: 027ff6055e5c82ba4e085857f09302cb + depends: + - python + - ruamel.yaml.clib >=0.2.15 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + size: 306951 + timestamp: 1766175833786 +- conda: https://conda.anaconda.org/conda-forge/linux-64/ruamel.yaml.clib-0.2.15-py310h139afa4_1.conda + sha256: 242ff560883541acc447b4fb11f1c6c0a4e91479b70c8ce895aee5d9a8ce346a + md5: a7e3055859e9162d5f7adb9b3c229d56 + depends: + - python + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - python_abi 3.10.* *_cp310 + license: MIT + license_family: MIT + purls: + - pkg:pypi/ruamel-yaml-clib?source=hash-mapping + size: 152839 + timestamp: 1766159514181 +- conda: https://conda.anaconda.org/conda-forge/linux-64/ruamel.yaml.clib-0.2.15-py311haee01d2_1.conda + sha256: 2d7e8976b0542b7aae1a9e4383b7b1135e64e9e190ce394aed44983adc6eb3f2 + md5: e3dfd8043a0fac038fe0d7c2d08ac28c + depends: + - python + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - python_abi 3.11.* *_cp311 + license: MIT + license_family: MIT + purls: + - pkg:pypi/ruamel-yaml-clib?source=hash-mapping + size: 153044 + timestamp: 1766159530795 +- conda: https://conda.anaconda.org/conda-forge/linux-64/ruamel.yaml.clib-0.2.15-py314h0f05182_1.conda + sha256: 3bd8db7556e87c98933a47ff9f962af7b8e0dc3757a72180b27cbfcb1f98d2d9 + md5: 4f35ae1228a6c5d9df593367ffe8dda1 + depends: + - python + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + size: 150041 + timestamp: 1766159514023 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ruamel.yaml.clib-0.2.15-py310hef25091_1.conda + sha256: fc5cf2db69fab279d0be46a8a077d9354991be5f4d317a73c453fc8df7c69f0a + md5: e91e48a36a6c9f761e259b967878831a + depends: + - python + - python 3.10.* *_cpython + - libgcc >=14 + - python_abi 3.10.* *_cp310 + license: MIT + license_family: MIT + purls: + - pkg:pypi/ruamel-yaml-clib?source=hash-mapping + size: 153169 + timestamp: 1766159548278 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ruamel.yaml.clib-0.2.15-py311h51cfe5d_1.conda + sha256: 77be521169904f2687cb09b6ab8d6bcee0d73d06284bfed84617668ad81c22f3 + md5: 471b202396dfeb16adde1930cd7a8001 + depends: + - python + - libgcc >=14 + - python 3.11.* *_cpython + - python_abi 3.11.* *_cp311 + license: MIT + license_family: MIT + purls: + - pkg:pypi/ruamel-yaml-clib?source=hash-mapping + size: 152961 + timestamp: 1766159559428 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ruamel.yaml.clib-0.2.15-py314h2e8dab5_1.conda + sha256: 18a34470b351fccfe6694215b01a9a68a0a9979336b0ea85709bbdeef0658e1c + md5: ca756356e2920f248a74cb42e0b4578d + depends: + - python + - python 3.14.* *_cp314 + - libgcc >=14 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + size: 148495 + timestamp: 1766159541094 +- conda: https://conda.anaconda.org/conda-forge/osx-64/ruamel.yaml.clib-0.2.15-py314hd330473_1.conda + sha256: dbcc0ff6e902468314d10d9f59d289ad078e5eac02d72b9092fa96e88b91d5dd + md5: e41e8948899a09937c068f71fe65ebb6 + depends: + - python + - __osx >=10.13 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + size: 136902 + timestamp: 1766159517466 +- conda: https://conda.anaconda.org/conda-forge/osx-64/ruamel.yaml.clib-0.2.8-py310hb372a2b_0.conda + sha256: 76535acf0bbefbbfeeca68bc732e4b8eea7526f0ef2090f2bdcf0283ec4b3738 + md5: a6254db88b5bf45d4870c3a63dc39e8d + depends: + - python >=3.10,<3.11.0a0 + - python_abi 3.10.* *_cp310 + license: MIT + license_family: MIT + purls: + - pkg:pypi/ruamel-yaml-clib?source=hash-mapping + size: 118488 + timestamp: 1707314814452 +- conda: https://conda.anaconda.org/conda-forge/osx-64/ruamel.yaml.clib-0.2.8-py311he705e18_0.conda + sha256: e6d5b2c9a75191305c8d367d13218c0bd0cc7a640ae776b541124c0fe8341bc9 + md5: 3fdbde273667047893775e077cef290d + depends: + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + license: MIT + license_family: MIT + purls: + - pkg:pypi/ruamel-yaml-clib?source=hash-mapping + size: 117859 + timestamp: 1707314957390 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/ruamel.yaml.clib-0.2.15-py314ha14b1ff_1.conda + sha256: ad575cae7f662b2dafca88c4ce05120e322f825c0610e54b0a116550c817bbbe + md5: 5836fbf79e5f279ffbe4ba06066c51a3 + depends: + - python + - python 3.14.* *_cp314 + - __osx >=11.0 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + size: 133016 + timestamp: 1766159585543 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/ruamel.yaml.clib-0.2.8-py310hd125d64_0.conda + sha256: 83b27f5dafd201a9408886ff18af6ccdde45e748c934fce588a4b531cdd249d5 + md5: e0b9a24f19622386be17bf9f29674e81 + depends: + - python >=3.10,<3.11.0a0 + - python >=3.10,<3.11.0a0 *_cpython + - python_abi 3.10.* *_cp310 + license: MIT + license_family: MIT + purls: + - pkg:pypi/ruamel-yaml-clib?source=hash-mapping + size: 111512 + timestamp: 1707315215965 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/ruamel.yaml.clib-0.2.8-py311h05b510d_0.conda + sha256: 8b64d7ac6d544cdb1c5e3677c3a6ea10f1d87f818888b25df5f3b97f271ef14f + md5: 0fbb200e26cec1931d0337ee70422965 + depends: + - python >=3.11,<3.12.0a0 + - python >=3.11,<3.12.0a0 *_cpython + - python_abi 3.11.* *_cp311 + license: MIT + license_family: MIT + purls: + - pkg:pypi/ruamel-yaml-clib?source=hash-mapping + size: 111700 + timestamp: 1707315151942 +- conda: https://conda.anaconda.org/conda-forge/win-64/ruamel.yaml.clib-0.2.15-py310h1637853_1.conda + sha256: 3c2ba1f6757863affd1a2996cffcf63b2e13594300862cd38c9235b652a17ad7 + md5: 07f6b7231ccb637d76e1550ababded60 + depends: + - python + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - python_abi 3.10.* *_cp310 + license: MIT + license_family: MIT + purls: + - pkg:pypi/ruamel-yaml-clib?source=hash-mapping + size: 107521 + timestamp: 1766159541493 +- conda: https://conda.anaconda.org/conda-forge/win-64/ruamel.yaml.clib-0.2.15-py311hf893f09_1.conda + sha256: 5810ddd1efe4ac259ad0ff55778da71205a68edfbbb4d45488b270e7f2f23438 + md5: 4bf8909dc04f6ab8c6d7f2a2a4a51d19 + depends: + - python + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - python_abi 3.11.* *_cp311 + license: MIT + license_family: MIT + purls: + - pkg:pypi/ruamel-yaml-clib?source=hash-mapping + size: 107529 + timestamp: 1766159555820 +- conda: https://conda.anaconda.org/conda-forge/win-64/ruamel.yaml.clib-0.2.15-py314hc5dbbe4_1.conda + sha256: b719637ce71e533193cd2bcacbf6ba5c10deaafa1be90d96040ee2314c6b17d1 + md5: 496de351b0f9afe9e245229528304f25 + depends: + - python + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + size: 105668 + timestamp: 1766159584330 +- conda: https://conda.anaconda.org/conda-forge/noarch/scikit-build-core-0.11.6-pyh7e86bf3_1.conda + sha256: bf802baa1a770c0ca631624a3627f84cae7978b56da02826b37ff1c5852a720a + md5: 4965b07e5cae94005cbe759e39f3def1 + depends: + - typing_extensions >=3.10.0 + - python >=3.8 + - exceptiongroup >=1.0 + - importlib-metadata >=4.13 + - importlib-resources >=1.3 + - packaging >=21.3 + - pathspec >=0.10.1 + - tomli >=1.2.2 + - typing-extensions >=3.10 + - python + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/scikit-build-core?source=hash-mapping + size: 213181 + timestamp: 1755919500167 +- conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda + sha256: 82088a6e4daa33329a30bc26dc19a98c7c1d3f05c0f73ce9845d4eab4924e9e1 + md5: 8e194e7b992f99a5015edbd4ebd38efd + depends: + - python >=3.10 + license: MIT + license_family: MIT + purls: + - pkg:pypi/setuptools?source=compressed-mapping + size: 639697 + timestamp: 1773074868565 +- conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-scm-9.2.2-pyhd8ed1ab_0.conda + sha256: 2161ac35fc22770b248bab0be2cc3b5bd765f528a9e60e7f3be784fd8d0d605a + md5: e2e4d7094d0580ccd62e2a41947444f3 + depends: + - importlib-metadata + - packaging >=20.0 + - python >=3.10 + - setuptools >=45 + - tomli >=1.0.0 + - typing-extensions + license: MIT + license_family: MIT + purls: + - pkg:pypi/setuptools-scm?source=hash-mapping + size: 52539 + timestamp: 1760965125925 +- conda: https://conda.anaconda.org/conda-forge/noarch/setuptools_scm-9.2.2-hd8ed1ab_0.conda + sha256: 60eec92bd931bbcba700b9a70b1446dccbf62d3298e408d3a28e09b8ecd96d98 + md5: 7537abc2590073ffde5545c648ad6974 + depends: + - setuptools-scm >=9.2.2,<9.2.3.0a0 + license: MIT + license_family: MIT + purls: [] + size: 6653 + timestamp: 1760965126461 +- conda: https://conda.anaconda.org/conda-forge/osx-64/sigtool-0.1.3-h88f4db0_0.tar.bz2 + sha256: 46fdeadf8f8d725819c4306838cdfd1099cd8fe3e17bd78862a5dfdcd6de61cf + md5: fbfb84b9de9a6939cb165c02c69b1865 + depends: + - openssl >=3.0.0,<4.0a0 + license: MIT + license_family: MIT + purls: [] + size: 213817 + timestamp: 1643442169866 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/sigtool-0.1.3-h44b9a77_0.tar.bz2 + sha256: 70791ae00a3756830cb50451db55f63e2a42a2fa2a8f1bab1ebd36bbb7d55bff + md5: 4a2cac04f86a4540b8c9b8d8f597848f + depends: + - openssl >=3.0.0,<4.0a0 + license: MIT + license_family: MIT + purls: [] + size: 210264 + timestamp: 1643442231687 +- conda: https://conda.anaconda.org/conda-forge/linux-64/simdjson-4.2.4-hb700be7_0.conda + sha256: ffe0c49e65486b485e66c7e116b1782189c970c16cb2fe9710a568e44bb9ede3 + md5: da6caa4c932708d447fb80eed702cb4e + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libstdcxx >=14 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 294996 + timestamp: 1766034103379 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/simdjson-4.2.4-hfefdfc9_0.conda + sha256: 8731e7cb9438deb3275c4d33d402b99da12f250c4b0bd635a58784c5a01e38f5 + md5: 829b13867c30e5d44ab7d851bfdb5d63 + depends: + - libgcc >=14 + - libstdcxx >=14 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 260530 + timestamp: 1766034125791 +- conda: https://conda.anaconda.org/conda-forge/osx-64/simdjson-4.2.4-hcb651aa_0.conda + sha256: 33767091b867a05e47cdb8e756e84d82237be25a82f896ece073f06801ebfee7 + md5: 4670f8951ec3f5f3a09e7c580d964088 + depends: + - __osx >=10.13 + - libcxx >=19 + license: Apache-2.0 + license_family: APACHE + size: 286025 + timestamp: 1766034310103 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/simdjson-4.2.4-ha7d2532_0.conda + sha256: 142758c665c2a896c1f275213068b324e92f378b03ba8d0019f57d72ea319515 + md5: b6ac50035bdc00e3f01322c43062b855 + depends: + - __osx >=11.0 + - libcxx >=19 + license: Apache-2.0 + license_family: APACHE + size: 252462 + timestamp: 1766034371359 +- conda: https://conda.anaconda.org/conda-forge/win-64/simdjson-4.2.4-h49e36cd_0.conda + sha256: 4bb3d41240e455bffc919042d8bbe64ae6cfd560dc9eeda0e84fd8f33b53da26 + md5: c625e0530b27e3bad5f59fa00744bbb8 + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 298171 + timestamp: 1766034112737 +- conda: https://conda.anaconda.org/conda-forge/linux-64/spdlog-1.17.0-hab81395_1.conda + sha256: c650f3df027afde77a5fbf58600ec4ed81a9edddf81f323cfb3e260f6dc19f56 + md5: a3b0e874fa56f72bc54e5c595712a333 + depends: + - __glibc >=2.17,<3.0.a0 + - fmt >=12.1.0,<12.2.0a0 + - libgcc >=14 + - libstdcxx >=14 + license: MIT + license_family: MIT + purls: [] + size: 196681 + timestamp: 1767781665629 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/spdlog-1.17.0-h9f97df7_1.conda + sha256: 36f5c0d73d88760438388bc940a65af4d9de3ecaf6fa5656a22a060d262d56f5 + md5: 910d3cbb4ccf371b6355a98b1233eb8f + depends: + - fmt >=12.1.0,<12.2.0a0 + - libgcc >=14 + - libstdcxx >=14 + license: MIT + license_family: MIT + purls: [] + size: 195699 + timestamp: 1767781668042 +- conda: https://conda.anaconda.org/conda-forge/osx-64/spdlog-1.17.0-h30f01e4_1.conda + sha256: a44fbcfdccf08211d39af11c08707b7f5748ad5e619adea7957decd21949018c + md5: 9ffcaf6ea8a92baea102b24c556140ae + depends: + - __osx >=10.13 + - fmt >=12.1.0,<12.2.0a0 + - libcxx >=19 + license: MIT + license_family: MIT + size: 173402 + timestamp: 1767782141460 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/spdlog-1.17.0-ha0f8610_1.conda + sha256: 465e81abc0e662937046a2c6318d1a9e74baee0addd51234d36e08bae6811296 + md5: 1885f7cface8cd627774407eeacb2caf + depends: + - __osx >=11.0 + - fmt >=12.1.0,<12.2.0a0 + - libcxx >=19 + license: MIT + license_family: MIT + size: 166603 + timestamp: 1767781942683 +- conda: https://conda.anaconda.org/conda-forge/win-64/spdlog-1.17.0-h9f585f1_1.conda + sha256: 90c9befa5f154463647c8e101bc7a4e05cb84b731e2dea5406bedfea02f8b012 + md5: 5c17c0a063b4d36b15d5f9c0ca5377a0 + depends: + - fmt >=12.1.0,<12.2.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: MIT + license_family: MIT + purls: [] + size: 174787 + timestamp: 1767781882230 +- conda: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-64-2.28-h4ee821c_9.conda + sha256: c47299fe37aebb0fcf674b3be588e67e4afb86225be4b0d452c7eb75c086b851 + md5: 13dc3adbc692664cd3beabd216434749 + depends: + - __glibc >=2.28 + - kernel-headers_linux-64 4.18.0 he073ed8_9 + - tzdata + license: LGPL-2.0-or-later AND LGPL-2.0-or-later WITH exceptions AND GPL-2.0-or-later + license_family: GPL + purls: [] + size: 24008591 + timestamp: 1765578833462 +- conda: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-aarch64-2.28-h585391f_9.conda + sha256: 1bd2db6b2e451247bab103e4a0128cf6c7595dd72cb26d70f7fadd9edd1d1bc3 + md5: fdf07ab944a222ff28c754914fdb0740 + depends: + - __glibc >=2.28 + - kernel-headers_linux-aarch64 4.18.0 h05a177a_9 + - tzdata + license: LGPL-2.0-or-later AND LGPL-2.0-or-later WITH exceptions AND GPL-2.0-or-later + license_family: GPL + purls: [] + size: 23644746 + timestamp: 1765578629426 +- conda: https://conda.anaconda.org/conda-forge/osx-64/tapi-1100.0.11-h9ce4665_0.tar.bz2 + sha256: 34b18ce8d1518b67e333ca1d3af733c3976ecbdf3a36b727f9b4dedddcc588fa + md5: f9ff42ccf809a21ba6f8607f8de36108 + depends: + - libcxx >=10.0.0.a0 + license: NCSA + license_family: MIT + purls: [] + size: 201044 + timestamp: 1602664232074 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/tapi-1100.0.11-he4954df_0.tar.bz2 + sha256: 1709265fbee693a9e8b4126b0a3e68a6c4718b05821c659279c1af051f2d40f3 + md5: d83362e7d0513f35f454bc50b0ca591d + depends: + - libcxx >=11.0.0.a0 + license: NCSA + license_family: MIT + purls: [] + size: 191416 + timestamp: 1602687595316 +- conda: https://conda.anaconda.org/conda-forge/linux-64/taplo-0.10.0-h2d22210_1.conda + sha256: 7d313578d79ece2b328084d906958888b5a474326a24833317d95a71e264b219 + md5: a4935b2eea119342f6a9d666e821984d + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + - openssl >=3.5.0,<4.0a0 + constrains: + - __glibc >=2.17 + license: MIT + license_family: MIT + purls: [] + size: 4319647 + timestamp: 1748302828104 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/taplo-0.10.0-h3618846_1.conda + sha256: 50944952f49509d1125bfafe2a958e55f5dc585dd6f7608c6707dd892e8356a8 + md5: 9bdb00138021e1f22b8d14a2f7fe52dc + depends: + - libgcc >=13 + - openssl >=3.5.0,<4.0a0 + constrains: + - __glibc >=2.17 + license: MIT + license_family: MIT + purls: [] + size: 4155701 + timestamp: 1748302870538 +- conda: https://conda.anaconda.org/conda-forge/osx-64/taplo-0.10.0-hffa81eb_1.conda + sha256: 47b343fd4779605c431f10e1bfe07e84df63884d4e081aafca027262b317bb7a + md5: c8ed0c445e126bc7519c32509b67fa2a + depends: + - __osx >=10.13 + - openssl >=3.5.0,<4.0a0 + constrains: + - __osx >=10.13 + license: MIT + license_family: MIT + size: 4286090 + timestamp: 1748302835791 +- conda: https://conda.anaconda.org/conda-forge/osx-64/taplo-0.8.1-h7205ca4_0.conda + sha256: 493b5f8db450f37e8bb50fdfd02c06499c18391c806d2220e65ac801f6b7c2f0 + md5: 8e99d4b2850401094fe7c83273d3c4e8 + license: MIT + license_family: MIT + purls: [] + size: 3446470 + timestamp: 1689048461323 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/taplo-0.10.0-h2b2570c_1.conda + sha256: c05b9d0bb740f48671d643d0e258639a3e727785b1eb62582385943ddabc5b6b + md5: 7b818d29210b93c231bc5bb0cd133d3b + depends: + - __osx >=11.0 + - openssl >=3.5.0,<4.0a0 + constrains: + - __osx >=11.0 + license: MIT + license_family: MIT + size: 4005794 + timestamp: 1748302845549 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/taplo-0.8.1-h69fbcac_0.conda + sha256: 5a46bbdac42c2aa1d59f3f7f61aa92eaed5f6936b01de4f3519f5ad40374973f + md5: 268425eeb6db286378bb05f69331feea + license: MIT + license_family: MIT + purls: [] + size: 3339855 + timestamp: 1689048706766 +- conda: https://conda.anaconda.org/conda-forge/win-64/taplo-0.10.0-h63977a8_1.conda + sha256: b38dd1dd1fe52d26f739d144a85fd277103320bd8e037b66a299457d5a827a04 + md5: 5fc2fa2f444b00e0f5b1f60a23f2c2f8 + depends: + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + - ucrt >=10.0.20348.0 + license: MIT + license_family: MIT + purls: [] + size: 4441127 + timestamp: 1748302918824 +- conda: https://conda.anaconda.org/conda-forge/win-64/tbb-2022.3.0-h3155e25_2.conda + sha256: abd9a489f059fba85c8ffa1abdaa4d515d6de6a3325238b8e81203b913cf65a9 + md5: 0f9817ffbe25f9e69ceba5ea70c52606 + depends: + - libhwloc >=2.12.2,<2.12.3.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 155869 + timestamp: 1767886839029 +- conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda + sha256: cafeec44494f842ffeca27e9c8b0c27ed714f93ac77ddadc6aaf726b5554ebac + md5: cffd3bdd58090148f4cfcd831f4b26ab + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libzlib >=1.3.1,<2.0a0 + constrains: + - xorg-libx11 >=1.8.12,<2.0a0 + license: TCL + license_family: BSD + purls: [] + size: 3301196 + timestamp: 1769460227866 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tk-8.6.13-noxft_h0dc03b3_103.conda + sha256: e25c314b52764219f842b41aea2c98a059f06437392268f09b03561e4f6e5309 + md5: 7fc6affb9b01e567d2ef1d05b84aa6ed + depends: + - libgcc >=14 + - libzlib >=1.3.1,<2.0a0 + constrains: + - xorg-libx11 >=1.8.12,<2.0a0 + license: TCL + license_family: BSD + purls: [] + size: 3368666 + timestamp: 1769464148928 +- conda: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-h1abcd95_1.conda + sha256: 30412b2e9de4ff82d8c2a7e5d06a15f4f4fef1809a72138b6ccb53a33b26faf5 + md5: bf830ba5afc507c6232d4ef0fb1a882d + depends: + - libzlib >=1.2.13,<2.0.0a0 + license: TCL + license_family: BSD + purls: [] + size: 3270220 + timestamp: 1699202389792 +- conda: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-h7142dee_3.conda + sha256: 7f0d9c320288532873e2d8486c331ec6d87919c9028208d3f6ac91dc8f99a67b + md5: 6e6efb7463f8cef69dbcb4c2205bf60e + depends: + - __osx >=10.13 + - libzlib >=1.3.1,<2.0a0 + license: TCL + license_family: BSD + size: 3282953 + timestamp: 1769460532442 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h010d191_3.conda + sha256: 799cab4b6cde62f91f750149995d149bc9db525ec12595e8a1d91b9317f038b3 + md5: a9d86bc62f39b94c4661716624eb21b0 + depends: + - __osx >=11.0 + - libzlib >=1.3.1,<2.0a0 + license: TCL + license_family: BSD + size: 3127137 + timestamp: 1769460817696 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h5083fa2_1.conda + sha256: 72457ad031b4c048e5891f3f6cb27a53cb479db68a52d965f796910e71a403a8 + md5: b50a57ba89c32b62428b71a875291c9b + depends: + - libzlib >=1.2.13,<2.0.0a0 + license: TCL + license_family: BSD + purls: [] + size: 3145523 + timestamp: 1699202432999 +- conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h6ed50ae_3.conda + sha256: 0e79810fae28f3b69fe7391b0d43f5474d6bd91d451d5f2bde02f55ae481d5e3 + md5: 0481bfd9814bf525bd4b3ee4b51494c4 + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: TCL + license_family: BSD + purls: [] + size: 3526350 + timestamp: 1769460339384 +- conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.0-pyhcf101f3_0.conda + sha256: 62940c563de45790ba0f076b9f2085a842a65662268b02dd136a8e9b1eaf47a8 + md5: 72e780e9aa2d0a3295f59b1874e3768b + depends: + - python >=3.10 + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/tomli?source=compressed-mapping + size: 21453 + timestamp: 1768146676791 +- conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda + sha256: 91cafdb64268e43e0e10d30bd1bef5af392e69f00edd34dfaf909f69ab2da6bd + md5: b5325cf06a000c5b14970462ff5e4d58 + depends: + - python >=3.10 + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/tomli?source=compressed-mapping + size: 21561 + timestamp: 1774492402955 +- conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda + sha256: 9ef8e47cf00e4d6dcc114eb32a1504cc18206300572ef14d76634ba29dfe1eb6 + md5: e5ce43272193b38c2e9037446c1d9206 + depends: + - python >=3.10 + - __unix + - python + license: MPL-2.0 and MIT + purls: + - pkg:pypi/tqdm?source=compressed-mapping + size: 94132 + timestamp: 1770153424136 +- conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyha7b4d00_0.conda + sha256: 63cc2def6e168622728c7800ed6b3c1761ceecb18b354c81cee1a0a94c09900a + md5: af77160f8428924c17db94e04aa69409 + depends: + - python >=3.10 + - colorama + - __win + - python + license: MPL-2.0 and MIT + purls: + - pkg:pypi/tqdm?source=hash-mapping + size: 93399 + timestamp: 1770153445242 +- conda: https://conda.anaconda.org/conda-forge/noarch/truststore-0.10.4-pyhcf101f3_0.conda + sha256: eece5be81588c39a855a0b70da84e0febb878a6d91dd27d6d21370ce9e5c5a46 + md5: c2db35b004913ec69bcac64fb0783de0 + depends: + - python >=3.10,<4 + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/truststore?source=hash-mapping + size: 24279 + timestamp: 1766494826559 +- conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda + sha256: 7c2df5721c742c2a47b2c8f960e718c930031663ac1174da67c1ed5999f7938c + md5: edd329d7d3a4ab45dcf905899a7a6115 + depends: + - typing_extensions ==4.15.0 pyhcf101f3_0 + license: PSF-2.0 + license_family: PSF + purls: [] + size: 91383 + timestamp: 1756220668932 +- conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda + sha256: 032271135bca55aeb156cee361c81350c6f3fb203f57d024d7e5a1fc9ef18731 + md5: 0caa1af407ecff61170c9437a808404d + depends: + - python >=3.10 + - python + license: PSF-2.0 + license_family: PSF + purls: + - pkg:pypi/typing-extensions?source=hash-mapping + size: 51692 + timestamp: 1756220668932 +- conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + sha256: 1d30098909076af33a35017eed6f2953af1c769e273a0626a04722ac4acaba3c + md5: ad659d0a2b3e47e38d829aa8cad2d610 + license: LicenseRef-Public-Domain + purls: [] + size: 119135 + timestamp: 1767016325805 +- conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda + sha256: 3005729dce6f3d3f5ec91dfc49fc75a0095f9cd23bab49efb899657297ac91a5 + md5: 71b24316859acd00bdb8b38f5e2ce328 + constrains: + - vc14_runtime >=14.29.30037 + - vs2015_runtime >=14.29.30037 + license: LicenseRef-MicrosoftWindowsSDK10 + purls: [] + size: 694692 + timestamp: 1756385147981 +- conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.5.0-pyhd8ed1ab_0.conda + sha256: 4fb9789154bd666ca74e428d973df81087a697dbb987775bc3198d2215f240f8 + md5: 436c165519e140cb08d246a4472a9d6a + depends: + - brotli-python >=1.0.9 + - h2 >=4,<5 + - pysocks >=1.5.6,<2.0,!=1.5.7 + - python >=3.9 + - zstandard >=0.18.0 + license: MIT + license_family: MIT + purls: + - pkg:pypi/urllib3?source=hash-mapping + size: 101735 + timestamp: 1750271478254 +- conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda + sha256: af641ca7ab0c64525a96fd9ad3081b0f5bcf5d1cbb091afb3f6ed5a9eee6111a + md5: 9272daa869e03efe68833e3dc7a02130 + depends: + - backports.zstd >=1.0.0 + - brotli-python >=1.2.0 + - h2 >=4,<5 + - pysocks >=1.5.6,<2.0,!=1.5.7 + - python >=3.10 + license: MIT + license_family: MIT + purls: + - pkg:pypi/urllib3?source=hash-mapping + size: 103172 + timestamp: 1767817860341 +- conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.3-h41ae7f8_34.conda + sha256: 9dc40c2610a6e6727d635c62cced5ef30b7b30123f5ef67d6139e23d21744b3a + md5: 1e610f2416b6acdd231c5f573d754a0f + depends: + - vc14_runtime >=14.44.35208 + track_features: + - vc14 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 19356 + timestamp: 1767320221521 +- conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.44.35208-h818238b_34.conda + sha256: 02732f953292cce179de9b633e74928037fa3741eb5ef91c3f8bae4f761d32a5 + md5: 37eb311485d2d8b2c419449582046a42 + depends: + - ucrt >=10.0.20348.0 + - vcomp14 14.44.35208 h818238b_34 + constrains: + - vs2015_runtime 14.44.35208.* *_34 + license: LicenseRef-MicrosoftVisualCpp2015-2022Runtime + license_family: Proprietary + purls: [] + size: 683233 + timestamp: 1767320219644 +- conda: https://conda.anaconda.org/conda-forge/win-64/vcomp14-14.44.35208-h818238b_34.conda + sha256: 878d5d10318b119bd98ed3ed874bd467acbe21996e1d81597a1dbf8030ea0ce6 + md5: 242d9f25d2ae60c76b38a5e42858e51d + depends: + - ucrt >=10.0.20348.0 + constrains: + - vs2015_runtime 14.44.35208.* *_34 + license: LicenseRef-MicrosoftVisualCpp2015-2022Runtime + license_family: Proprietary + purls: [] + size: 115235 + timestamp: 1767320173250 +- conda: https://conda.anaconda.org/conda-forge/win-64/vs2022_win-64-19.44.35207-ha74f236_34.conda + sha256: 05bc657625b58159bcea039a35cc89d1f8baf54bf4060019c2b559a03ba4a45e + md5: 1d699ffd41c140b98e199ddd9787e1e1 + depends: + - vswhere + constrains: + - vs_win-64 2022.14 + track_features: + - vc14 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 23060 + timestamp: 1767320175868 +- conda: https://conda.anaconda.org/conda-forge/noarch/vswhere-3.1.7-h40126e0_1.conda + sha256: b72270395326dc56de9bd6ca82f63791b3c8c9e2b98e25242a9869a4ca821895 + md5: f622897afff347b715d046178ad745a5 + depends: + - __win + license: MIT + license_family: MIT + purls: [] + size: 238764 + timestamp: 1745560912727 +- conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.46.3-pyhd8ed1ab_0.conda + sha256: d6cf2f0ebd5e09120c28ecba450556ce553752652d91795442f0e70f837126ae + md5: bdbd7385b4a67025ac2dba4ef8cb6a8f + depends: + - packaging >=24.0 + - python >=3.10 + license: MIT + license_family: MIT + purls: + - pkg:pypi/wheel?source=hash-mapping + size: 31858 + timestamp: 1769139207397 +- conda: https://conda.anaconda.org/conda-forge/noarch/win_inet_pton-1.1.0-pyh7428d3b_8.conda + sha256: 93807369ab91f230cf9e6e2a237eaa812492fe00face5b38068735858fba954f + md5: 46e441ba871f524e2b067929da3051c2 + depends: + - __win + - python >=3.9 + license: LicenseRef-Public-Domain + purls: + - pkg:pypi/win-inet-pton?source=hash-mapping + size: 9555 + timestamp: 1733130678956 +- conda: https://conda.anaconda.org/conda-forge/osx-64/xz-5.2.6-h775f41a_0.tar.bz2 + sha256: eb09823f34cc2dd663c0ec4ab13f246f45dcd52e5b8c47b9864361de5204a1c8 + md5: a72f9d4ea13d55d745ff1ed594747f10 + license: LGPL-2.1 and GPL-2.0 + purls: [] + size: 238119 + timestamp: 1660346964847 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/xz-5.2.6-h57fd34a_0.tar.bz2 + sha256: 59d78af0c3e071021cfe82dc40134c19dab8cdf804324b62940f5c8cd71803ec + md5: 39c6b54e94014701dd157f4f576ed211 + license: LGPL-2.1 and GPL-2.0 + purls: [] + size: 235693 + timestamp: 1660346961024 +- conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-cpp-0.8.0-h3f2d84a_0.conda + sha256: 4b0b713a4308864a59d5f0b66ac61b7960151c8022511cdc914c0c0458375eca + md5: 92b90f5f7a322e74468bb4909c7354b5 + depends: + - libstdcxx >=13 + - libgcc >=13 + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + license: MIT + license_family: MIT + purls: [] + size: 223526 + timestamp: 1745307989800 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/yaml-cpp-0.8.0-h5ad3122_0.conda + sha256: e146d83cdcf92506ab709c6e10acabd18a3394a23e6334a322c57e5d1d6d9f26 + md5: b9e5a9da5729019c4f216cf0d386a70c + depends: + - libstdcxx >=13 + - libgcc >=13 + license: MIT + license_family: MIT + purls: [] + size: 213281 + timestamp: 1745308220432 +- conda: https://conda.anaconda.org/conda-forge/osx-64/yaml-cpp-0.8.0-h92383a6_0.conda + sha256: 67d25c3aa2b4ee54abc53060188542d6086b377878ebf3e2b262ae7379e05a6d + md5: e15e9855092a8bdaaaed6ad5c173fffa + depends: + - libcxx >=18 + - __osx >=10.13 + license: MIT + license_family: MIT + size: 145204 + timestamp: 1745308032698 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/yaml-cpp-0.8.0-ha1acc90_0.conda + sha256: 66ba31cfb8014fdd3456f2b3b394df123bbd05d95b75328b7c4131639e299749 + md5: 30475b3d0406587cf90386a283bb3cd0 + depends: + - libcxx >=18 + - __osx >=11.0 + license: MIT + license_family: MIT + size: 136222 + timestamp: 1745308075886 +- conda: https://conda.anaconda.org/conda-forge/win-64/yaml-cpp-0.8.0-he0c23c2_0.conda + sha256: 031642d753e0ebd666a76cea399497cc7048ff363edf7d76a630ee0a19e341da + md5: 9bb5064a9fca5ca8e7d7f1ae677354b6 + depends: + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + - ucrt >=10.0.20348.0 + license: MIT + license_family: MIT + purls: [] + size: 148572 + timestamp: 1745308037198 +- conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda + sha256: b4533f7d9efc976511a73ef7d4a2473406d7f4c750884be8e8620b0ce70f4dae + md5: 30cd29cb87d819caead4d55184c1d115 + depends: + - python >=3.10 + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/zipp?source=hash-mapping + size: 24194 + timestamp: 1764460141901 +- conda: https://conda.anaconda.org/conda-forge/linux-64/zstandard-0.25.0-py310h139afa4_1.conda + sha256: b0103e8bb639dbc6b9de8ef9a18a06b403b687a33dec83c25bd003190942259a + md5: 3741aefc198dfed2e3c9adc79d706bb7 + depends: + - python + - cffi >=1.11 + - zstd >=1.5.7,<1.5.8.0a0 + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + - zstd >=1.5.7,<1.6.0a0 + - python_abi 3.10.* *_cp310 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/zstandard?source=hash-mapping + size: 455614 + timestamp: 1762512676430 +- conda: https://conda.anaconda.org/conda-forge/linux-64/zstandard-0.25.0-py311haee01d2_1.conda + sha256: d534a6518c2d8eccfa6579d75f665261484f0f2f7377b50402446a9433d46234 + md5: ca45bfd4871af957aaa5035593d5efd2 + depends: + - python + - cffi >=1.11 + - zstd >=1.5.7,<1.5.8.0a0 + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + - zstd >=1.5.7,<1.6.0a0 + - python_abi 3.11.* *_cp311 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/zstandard?source=hash-mapping + size: 466893 + timestamp: 1762512695614 +- conda: https://conda.anaconda.org/conda-forge/linux-64/zstandard-0.25.0-py314h0f05182_1.conda + sha256: e589f694b44084f2e04928cabd5dda46f20544a512be2bdb0d067d498e4ac8d0 + md5: 2930a6e1c7b3bc5f66172e324a8f5fc3 + depends: + - python + - cffi >=1.11 + - zstd >=1.5.7,<1.5.8.0a0 + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - zstd >=1.5.7,<1.6.0a0 + - python_abi 3.14.* *_cp314 + license: BSD-3-Clause + license_family: BSD + size: 473605 + timestamp: 1762512687493 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstandard-0.25.0-py310hef25091_1.conda + sha256: 30202c0e21618a421d189c70b71c152f53a6f605f8fb053a7faf844dffd4843b + md5: ef07dc8296f6e4df546b8d41bfb0a1fe + depends: + - python + - cffi >=1.11 + - zstd >=1.5.7,<1.5.8.0a0 + - python 3.10.* *_cpython + - libgcc >=14 + - zstd >=1.5.7,<1.6.0a0 + - python_abi 3.10.* *_cp310 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/zstandard?source=hash-mapping + size: 447338 + timestamp: 1762512738321 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstandard-0.25.0-py311h51cfe5d_1.conda + sha256: ddeec193065b235166fb9f8ca4e5cbb931215ab90cbd17e9f9d753c8966b57b1 + md5: c8b3365fe290eeee3084274948012394 + depends: + - python + - cffi >=1.11 + - zstd >=1.5.7,<1.5.8.0a0 + - python 3.11.* *_cpython + - libgcc >=14 + - zstd >=1.5.7,<1.6.0a0 + - python_abi 3.11.* *_cp311 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/zstandard?source=hash-mapping + size: 459426 + timestamp: 1762512724303 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstandard-0.25.0-py314h2e8dab5_1.conda + sha256: 051f12494f28f9de8b1bf1a787646c1f675d8eba0ba0eac79ab96ef960d24746 + md5: db33d0e8888bef6ef78207c5e6106a5b + depends: + - python + - cffi >=1.11 + - zstd >=1.5.7,<1.5.8.0a0 + - python 3.14.* *_cp314 + - libgcc >=14 + - python_abi 3.14.* *_cp314 + - zstd >=1.5.7,<1.6.0a0 + license: BSD-3-Clause + license_family: BSD + size: 465094 + timestamp: 1762512736835 +- conda: https://conda.anaconda.org/conda-forge/osx-64/zstandard-0.22.0-py310hd88f66e_0.conda + sha256: cdc8b9fc1352f19c73f16b0b0b3595a5a70758b3dfbd0398eac1db69910389bd + md5: 88c991558201cae2b7e690c2e9d2e618 + depends: + - cffi >=1.11 + - python >=3.10,<3.11.0a0 + - python_abi 3.10.* *_cp310 + - zstd >=1.5.5,<1.5.6.0a0 + - zstd >=1.5.5,<1.6.0a0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/zstandard?source=hash-mapping + size: 399250 + timestamp: 1698830565851 +- conda: https://conda.anaconda.org/conda-forge/osx-64/zstandard-0.22.0-py311hed14148_0.conda + sha256: 97e4ba1fb5a0d4310262da602bf283f058d63ab40e1dd74d93440f27823b1be5 + md5: 027bd8663474659bb949785d4e2b8599 + depends: + - cffi >=1.11 + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + - zstd >=1.5.5,<1.5.6.0a0 + - zstd >=1.5.5,<1.6.0a0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/zstandard?source=hash-mapping + size: 410219 + timestamp: 1698830417763 +- conda: https://conda.anaconda.org/conda-forge/osx-64/zstandard-0.25.0-py314hd1e8ddb_1.conda + sha256: cf12b4c138eef5160b12990278ac77dec5ca91de60638dd6cf1e60e4331d8087 + md5: b94712955dc017da312e6f6b4c6d4866 + depends: + - python + - cffi >=1.11 + - zstd >=1.5.7,<1.5.8.0a0 + - __osx >=10.13 + - python_abi 3.14.* *_cp314 + - zstd >=1.5.7,<1.6.0a0 + license: BSD-3-Clause + license_family: BSD + size: 470136 + timestamp: 1762512696464 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstandard-0.22.0-py310h6289e41_0.conda + sha256: 806c1a7519dca20df58bce3b88392f2f4c2f04c0257789c2bd94b9c31b173dc2 + md5: f09fc5240964cceff0bbb2d68dbb6a5d + depends: + - cffi >=1.11 + - python >=3.10,<3.11.0a0 + - python >=3.10,<3.11.0a0 *_cpython + - python_abi 3.10.* *_cp310 + - zstd >=1.5.5,<1.5.6.0a0 + - zstd >=1.5.5,<1.6.0a0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/zstandard?source=hash-mapping + size: 320728 + timestamp: 1698830561905 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstandard-0.22.0-py311h67b91a1_0.conda + sha256: 0bbe223fc0b6cb37f5f2287295f610e73a50888401c865448ce6db7bf79ac416 + md5: 396d81ee96c6d91c3bdfe13a785f4636 + depends: + - cffi >=1.11 + - python >=3.11,<3.12.0a0 + - python >=3.11,<3.12.0a0 *_cpython + - python_abi 3.11.* *_cp311 + - zstd >=1.5.5,<1.5.6.0a0 + - zstd >=1.5.5,<1.6.0a0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/zstandard?source=hash-mapping + size: 332059 + timestamp: 1698830508653 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstandard-0.25.0-py314h9d33bd4_1.conda + sha256: cdeb350914094e15ec6310f4699fa81120700ca7ab7162a6b3421f9ea9c690b4 + md5: 8a92a736ab23b4633ac49dcbfcc81e14 + depends: + - python + - cffi >=1.11 + - zstd >=1.5.7,<1.5.8.0a0 + - python 3.14.* *_cp314 + - __osx >=11.0 + - python_abi 3.14.* *_cp314 + - zstd >=1.5.7,<1.6.0a0 + license: BSD-3-Clause + license_family: BSD + size: 397786 + timestamp: 1762512730914 +- conda: https://conda.anaconda.org/conda-forge/win-64/zstandard-0.25.0-py310h1637853_1.conda + sha256: db2a40dbe124b275fb0b8fdfd6e3b377963849897ab2b4d7696354040c52570b + md5: 1d261480977c268b3b209b7deaca0dd7 + depends: + - python + - cffi >=1.11 + - zstd >=1.5.7,<1.5.8.0a0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - python_abi 3.10.* *_cp310 + - zstd >=1.5.7,<1.6.0a0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/zstandard?source=hash-mapping + size: 364167 + timestamp: 1762512706699 +- conda: https://conda.anaconda.org/conda-forge/win-64/zstandard-0.25.0-py311hf893f09_1.conda + sha256: 10f089bedef1a28c663ef575fb9cec66b2058e342c4cf4a753083ab07591008f + md5: b2d90bca78b57c17205ce3ca1c427813 + depends: + - python + - cffi >=1.11 + - zstd >=1.5.7,<1.5.8.0a0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - python_abi 3.11.* *_cp311 + - zstd >=1.5.7,<1.6.0a0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/zstandard?source=hash-mapping + size: 375869 + timestamp: 1762512737575 +- conda: https://conda.anaconda.org/conda-forge/win-64/zstandard-0.25.0-py314hc5dbbe4_1.conda + sha256: 87bf6ba2dcc59dfbb8d977b9c29d19b6845ad54e092ea8204dcec62d7b461a30 + md5: c1ef46c3666be935fbb7460c24950cff + depends: + - python + - cffi >=1.11 + - zstd >=1.5.7,<1.5.8.0a0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - zstd >=1.5.7,<1.6.0a0 + - python_abi 3.14.* *_cp314 + license: BSD-3-Clause + license_family: BSD + size: 381179 + timestamp: 1762512709971 +- conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda + sha256: 68f0206ca6e98fea941e5717cec780ed2873ffabc0e1ed34428c061e2c6268c7 + md5: 4a13eeac0b5c8e5b8ab496e6c4ddd829 + depends: + - __glibc >=2.17,<3.0.a0 + - libzlib >=1.3.1,<2.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 601375 + timestamp: 1764777111296 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.7-h85ac4a6_6.conda + sha256: 569990cf12e46f9df540275146da567d9c618c1e9c7a0bc9d9cfefadaed20b75 + md5: c3655f82dcea2aa179b291e7099c1fcc + depends: + - libzlib >=1.3.1,<2.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 614429 + timestamp: 1764777145593 +- conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.5-h829000d_0.conda + sha256: d54e31d3d8de5e254c0804abd984807b8ae5cd3708d758a8bf1adff1f5df166c + md5: 80abc41d0c48b82fe0f04e7f42f5cb7e + depends: + - libzlib >=1.2.13,<2.0.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 499383 + timestamp: 1693151312586 +- conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.7-h3eecb57_6.conda + sha256: 47101a4055a70a4876ffc87b750ab2287b67eca793f21c8224be5e1ee6394d3f + md5: 727109b184d680772e3122f40136d5ca + depends: + - __osx >=10.13 + - libzlib >=1.3.1,<2.0a0 + license: BSD-3-Clause + license_family: BSD + size: 528148 + timestamp: 1764777156963 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.5-h4f39d0f_0.conda + sha256: 7e1fe6057628bbb56849a6741455bbb88705bae6d6646257e57904ac5ee5a481 + md5: 5b212cfb7f9d71d603ad891879dc7933 + depends: + - libzlib >=1.2.13,<2.0.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 400508 + timestamp: 1693151393180 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda + sha256: 9485ba49e8f47d2b597dd399e88f4802e100851b27c21d7525625b0b4025a5d9 + md5: ab136e4c34e97f34fb621d2592a393d8 + depends: + - __osx >=11.0 + - libzlib >=1.3.1,<2.0a0 + license: BSD-3-Clause + license_family: BSD + size: 433413 + timestamp: 1764777166076 +- conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.7-h534d264_6.conda + sha256: 368d8628424966fd8f9c8018326a9c779e06913dd39e646cf331226acc90e5b2 + md5: 053b84beec00b71ea8ff7a4f84b55207 + depends: + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - libzlib >=1.3.1,<2.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 388453 + timestamp: 1764777142545 diff --git a/pixi.toml b/pixi.toml new file mode 100644 index 00000000..d9e5c991 --- /dev/null +++ b/pixi.toml @@ -0,0 +1,183 @@ +[workspace] +authors = [ + "Insight Software Consortium <>", + "Matt McCormick ", + "Jean-Christophe Fillion-Robin ", + "Tom Birdsong ", + "Hans J. Johnson ", + "Dženan Zukić ", + "Simon Rit ", + "Francois Budin ", + "LucasGandel ", + "Davis Marc Vigneault ", + "Jon Haitz Legarreta Gorroño ", + "Lee Newberg ", + "Cavan Riley ", +] + +name = "ITKPythonPackage" +version = "0.1.0" +channels = ["conda-forge"] +platforms = ["linux-64", "linux-aarch64", "osx-64", "osx-arm64", "win-64"] + +######################################## +# Common features used by all envs +######################################## + +# Build tooling shared by all platforms +[feature.build-dev-tools] +[feature.build-dev-tools.dependencies] +cmake = ">=3.26,<4" +doxygen = "<2" +ninja = ">=1.11.1,<2" +pkginfo = ">=1.12.1.2,<2" + +# Python packaging/build support shared by all platforms +[feature.python-dev-pkgs] +[feature.python-dev-pkgs.dependencies] +numpy = ">=1.26" +packaging = ">=25.0,<26" +pathspec = "*" +pyproject-metadata = "*" +scikit-build-core = ">=0.11.6,<0.12.0" +setuptools_scm = ">=9.2.0" +setuptools = ">=61" +tomli = "*" +pip = "*" + +[feature.python-dev-pkgs.pypi-dependencies] +build = "*" + +######################################## +# Manylinux-specific features +######################################## + +# Shared dependencies for all manylinux wheel builds +# (might be helpful for including newer manylinux versions later) +[feature.manylinux-common-build] +platforms = ["linux-64", "linux-aarch64"] + +[feature.manylinux-common-build.dependencies] +auditwheel = "*" +patchelf = "*" # Needed for auditwheel +wheel = "*" + +[feature.manylinux-common-build.pypi-dependencies] +build = "*" + +[feature.linux-build] +platforms = ["linux-64", "linux-aarch64"] + +[feature.linux-build.dependencies] +cxx-compiler = "==1.11.0" +c-compiler = "==1.11.0" +libhwloc = "*" # Needed for tbb +auditwheel = "*" +patchelf = "*" # Needed for auditwheel +wheel = "*" + +[feature.manylinux228-build] +platforms = ["linux-64", "linux-aarch64"] + +[feature.manylinux228-build.system-requirements] +linux = "5.4" +libc = { family = "glibc", version = "2.28" } + +[feature.linux-build.activation.env] +PYTHONNOUSERSITE = "1" # Exclude system .local site packages + +######################################## +# macOS-specific feature +######################################## + +[feature.macosx-build] +platforms = ["osx-64", "osx-arm64"] +system-requirements = { macos = "10.7" } + +# delocate is a Python tool; cxx-compiler is the macOS toolchain meta-package +[feature.macosx-build.pypi-dependencies] +delocate = "*" + +[feature.macosx-build.dependencies] +cxx-compiler = "==1.10.0" # XCode 16.0 before castxml required updates +c-compiler = "==1.10.0" # XCode 16.0 before castxml required updates +#libhwloc = "*" # Needed for tbb + +[feature.windows-build] +platforms = ["win-64"] + +[feature.windows-build.dependencies] +git = "*" # Git is not always available in PowerShell by default +cxx-compiler = "==1.11.0" # MSVC 2022 +c-compiler = "==1.11.0" # MSVC 2022 + +[feature.windows-build.pypi-dependencies] +delvewheel = "*" +# windows = "*" + +[feature.py310] +[feature.py310.dependencies] +python = ">=3.10,<3.11" + +[feature.py311] +[feature.py311.dependencies] +python = ">=3.11,<3.12" + +#[feature.py312] +#[feature.py312.dependencies] +#python = ">=3.12,<3.13" +# +#[feature.py313] +#[feature.py313.dependencies] +#python = ">=3.13,<3.14" +# +#[feature.py314] +#[feature.py314.dependencies] +#python = ">=3.14,<3.15" + + +######################################## +# Environments: compose features per target +######################################## + +[environments] +linux-py310 = ["py310", "linux-build", "build-dev-tools", "python-dev-pkgs"] +linux-py311 = ["py311", "linux-build", "build-dev-tools", "python-dev-pkgs"] + +# Manylinux wheel-build env (docker manylinux228 images, CI, etc.) +manylinux228-py310 = [ + "py310", + "manylinux-common-build", + "manylinux228-build", + "build-dev-tools", + "python-dev-pkgs", +] +manylinux228-py311 = [ + "py311", + "manylinux-common-build", + "manylinux228-build", + "build-dev-tools", + "python-dev-pkgs", +] + + +# macOS build env (both Intel and Apple Silicon) +macosx-py310 = ["py310", "build-dev-tools", "python-dev-pkgs", "macosx-build"] +macosx-py311 = ["py311", "build-dev-tools", "python-dev-pkgs", "macosx-build"] + +# Windows build env +windows-py310 = ["py310", "build-dev-tools", "python-dev-pkgs", "windows-build"] +windows-py311 = ["py311", "build-dev-tools", "python-dev-pkgs", "windows-build"] + +[dependencies] +# pixi-pycharm and conda are only needed to support development in pycharm +# https://pixi.prefix.dev/v0.21.1/ide_integration/pycharm/#how-to-use +pixi-pycharm = ">=0.0.10,<0.0.11" +conda = "*" +taplo = ">=0.8.1,<0.11" + +[tasks] +taplo = "fmt pixi.toml" + +[tasks.build-itk-wheels] +cmd = ["python", "scripts/build_wheels.py"] diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..d6f36352 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,21 @@ +# Root-level pyproject.toml — developer tooling configuration only. +# This file configures linters/formatters for the ITKPythonPackage build scripts. +# It does NOT define a Python package; wheel-specific pyproject.toml files are +# generated dynamically by scripts/pyproject_configure.py into build subdirectories. + +[tool.black] +line-length = 88 +target-version = ["py310", "py311"] + +[tool.ruff] +line-length = 88 +target-version = "py310" + +[tool.ruff.lint] +# E/F: pycodestyle errors + pyflakes +# I: isort import ordering +# UP: pyupgrade (modernise syntax for Python 3.10+) +# B: flake8-bugbear (opinionated bug detection) +select = ["E", "F", "I", "UP", "B"] +# E501 (line-too-long) is handled by black; suppress here to avoid duplication +ignore = ["E501"] diff --git a/requirements-dev.txt b/requirements-dev.txt deleted file mode 100644 index 5fac7875..00000000 --- a/requirements-dev.txt +++ /dev/null @@ -1,6 +0,0 @@ -ninja==1.11.1.1 -scikit-build-core==0.10.7 -build==1.2.1 -pyproject-metadata -pathspec -setuptools_scm==8.1.0 diff --git a/scripts/BuildManager.py b/scripts/BuildManager.py new file mode 100644 index 00000000..a7fd9942 --- /dev/null +++ b/scripts/BuildManager.py @@ -0,0 +1,134 @@ +import json +import time +from datetime import datetime +from pathlib import Path + + +class BuildManager: + """Manage a JSON build report for multistep runs. + + Persists status and timing for each named step to a JSON file. + Steps already marked ``"done"`` are skipped on subsequent runs, + enabling resumable builds. + + Parameters + ---------- + report_path : Path + Path to the JSON report file (created if absent). + step_names : list[str] + Ordered names of build steps to track. + + Attributes + ---------- + report : dict + In-memory report structure with ``created_at``, ``updated_at``, + and ``steps`` keys. + """ + + def __init__(self, report_path: Path, step_names: list[str]): + self.report_path = Path(report_path) + self._init_structure(step_names) + self._load_if_exists() + + # ---- Public API ---- + def run_step(self, step_name: str, func, force_rerun=False) -> None: + """Execute a build step, recording timing and status. + + Parameters + ---------- + step_name : str + Key identifying the step in the report. + func : callable + Zero-argument callable that performs the step's work. + force_rerun : bool, optional + If True, re-execute even when the step is already ``"done"``. + + Raises + ------ + Exception + Re-raises any exception thrown by *func* after recording + the failure in the report. + """ + entry = self.report["steps"].setdefault(step_name, self._new_step_entry()) + if entry.get("status") == "done" and not force_rerun: + # Already completed in a previous run; skip + return + + # Mark start + entry["status"] = "running" + entry["started_at"] = self._now() + self.report["updated_at"] = entry["started_at"] + self.save() + + start = time.perf_counter() + try: + func() + except Exception as e: + # Record failure and re-raise + entry["status"] = "failed" + entry["finished_at"] = self._now() + entry["duration_sec"] = round(time.perf_counter() - start, 3) + entry["error"] = f"{type(e).__name__}: {e}" + self.report["updated_at"] = entry["finished_at"] + self.save() + raise + else: + # Record success + entry["status"] = "done" + entry["finished_at"] = self._now() + entry["duration_sec"] = round(time.perf_counter() - start, 3) + self.report["updated_at"] = entry["finished_at"] + self.save() + + def save(self) -> None: + """Write the current report to disk atomically.""" + self.report_path.parent.mkdir(parents=True, exist_ok=True) + tmp = self.report_path.with_suffix(self.report_path.suffix + ".tmp") + with open(tmp, "w", encoding="utf-8") as f: + json.dump(self.report, f, indent=2, sort_keys=True) + tmp.replace(self.report_path) + + # ---- Internal helpers ---- + def _init_structure(self, step_names: list[str]) -> None: + steps = {name: self._new_step_entry() for name in step_names} + now = self._now() + self.report = { + "created_at": now, + "updated_at": now, + "steps": steps, + } + + def _load_if_exists(self) -> None: + if not self.report_path.exists(): + return + try: + with open(self.report_path, encoding="utf-8") as f: + existing = json.load(f) + # Merge existing with current set of steps, preserving statuses + existing_steps = existing.get("steps", {}) + for name in self.report["steps"].keys(): + if name in existing_steps: + self.report["steps"][name] = existing_steps[name] + # Bring over timestamps + self.report["created_at"] = existing.get( + "created_at", self.report["created_at"] + ) + self.report["updated_at"] = existing.get( + "updated_at", self.report["updated_at"] + ) + except Exception as e: + # Corrupt or unreadable file; keep freshly initialized structure + raise RuntimeError(f"Failed to load build report: {e}") from e + + @staticmethod + def _now() -> str: + return datetime.now().isoformat(timespec="seconds") + + @staticmethod + def _new_step_entry() -> dict: + return { + "status": "pending", + "started_at": None, + "finished_at": None, + "duration_sec": None, + } diff --git a/scripts/build_python_instance_base.py b/scripts/build_python_instance_base.py new file mode 100644 index 00000000..b6a73c11 --- /dev/null +++ b/scripts/build_python_instance_base.py @@ -0,0 +1,1029 @@ +import os +import shutil +import subprocess +import sys +from abc import ABC, abstractmethod +from collections import OrderedDict +from collections.abc import Callable +from pathlib import Path + +from BuildManager import BuildManager +from cmake_argument_builder import CMakeArgumentBuilder +from pyproject_configure import configure_one_pyproject_file +from wheel_builder_utils import ( + _remove_tree, + _which, + get_default_platform_build, + run_commandLine_subprocess, +) + + +class BuildPythonInstanceBase(ABC): + """ + Abstract base class to build wheels for a single Python environment. + + Concrete subclasses implement platform-specific details by delegating to + injected helper functions. This avoids circular imports with the script + that defines those helpers. + """ + + def __init__( + self, + *, + platform_env, + build_dir_root, + package_env_config: dict, + cleanup: bool, + build_itk_tarball_cache: bool, + cmake_options: list[str], + windows_extra_lib_paths: list[str], + dist_dir: Path, + module_source_dir: Path | None = None, + module_dependencies_root_dir: Path | None = None, + itk_module_deps: str | None = None, + skip_itk_build: bool | None = None, + skip_itk_wheel_build: bool | None = None, + ) -> None: + self.build_node_cpu_count: int = os.cpu_count() or 1 + self.platform_env = platform_env + self.ipp_dir = Path(__file__).parent.parent + + self.build_dir_root = build_dir_root + self.cmake_itk_source_build_configurations: CMakeArgumentBuilder = ( + CMakeArgumentBuilder() + ) + self.cmake_compiler_configurations: CMakeArgumentBuilder = ( + CMakeArgumentBuilder() + ) + # TODO: Partial refactoring cleanup later + package_env_config["IPP_SOURCE_DIR"] = self.ipp_dir + IPP_BuildWheelsSupport_DIR: Path = self.ipp_dir / "BuildWheelsSupport" + package_env_config["IPP_BuildWheelsSupport_DIR"] = IPP_BuildWheelsSupport_DIR + + self.package_env_config = package_env_config + + # declare this dict before self.prepare_build_env() or dict will be empty in later functions + self.venv_info_dict = { + # Filled in for each platform and each pyenvs + # "python_executable": None, + # "python_include_dir": None, + # "python_library": None, + # "venv_bin_path": None, + # "venv_base_dir": None, + } + + with open( + IPP_BuildWheelsSupport_DIR / "WHEEL_NAMES.txt", + encoding="utf-8", + ) as content: + self.wheel_names = [ + wheel_name.strip() for wheel_name in content.readlines() + ] + del package_env_config + + self.cleanup = cleanup + self.build_itk_tarball_cache = build_itk_tarball_cache + self.cmake_options = cmake_options + self.windows_extra_lib_paths = windows_extra_lib_paths + self.dist_dir = dist_dir + # Needed for processing remote modules and their dependencies + self.module_source_dir: Path = ( + Path(module_source_dir) if module_source_dir else None + ) + self.module_dependencies_root_dir: Path = ( + Path(module_dependencies_root_dir) if module_dependencies_root_dir else None + ) + self.itk_module_deps = itk_module_deps + self.skip_itk_build = skip_itk_build + self.skip_itk_wheel_build = skip_itk_wheel_build + self.prepare_build_env() + + self.package_env_config["BUILD_TYPE"] = "Release" + # Unified place to collect cmake -D definitions for this instance + self.cmake_cmdline_definitions: CMakeArgumentBuilder = CMakeArgumentBuilder() + # Seed from legacy cmake_options if provided as ['-D=', ...] + if cmake_options: + for opt in cmake_options: + if not opt.startswith("-D"): + continue + # Strip leading -D, split on first '=' into key and value + try: + key, value = opt[2:].split("=", 1) + except ValueError: + # Malformed option; skip to avoid breaking build + continue + # Preserve value verbatim (may contain quotes) + self.cmake_cmdline_definitions.set(key, value) + + self.cmake_compiler_configurations.update( + { + "CMAKE_BUILD_TYPE:STRING": self.package_env_config["BUILD_TYPE"], + } + ) + # Set cmake flags for the compiler if CC or CXX are specified + cxx_compiler: str = self.package_env_config.get("CXX", "") + if cxx_compiler != "": + self.cmake_compiler_configurations.set( + "CMAKE_CXX_COMPILER:STRING", cxx_compiler + ) + + c_compiler: str = self.package_env_config.get("CC", "") + if c_compiler != "": + self.cmake_compiler_configurations.set( + "CMAKE_C_COMPILER:STRING", c_compiler + ) + + if self.package_env_config.get("USE_CCACHE", "OFF") == "ON": + ccache_exe: Path = _which("ccache") + self.cmake_compiler_configurations.set( + "CMAKE_C_COMPILER_LAUNCHER:FILEPATH", f"{ccache_exe}" + ) + self.cmake_compiler_configurations.set( + "CMAKE_CXX_COMPILER_LAUNCHER:FILEPATH", f"{ccache_exe}" + ) + + self.cmake_itk_source_build_configurations.update( + # ITK wrapping options + { + "ITK_SOURCE_DIR:PATH": f"{self.package_env_config['ITK_SOURCE_DIR']}", + "BUILD_TESTING:BOOL": "OFF", + "ITK_WRAP_unsigned_short:BOOL": "ON", + "ITK_WRAP_double:BOOL": "ON", + "ITK_WRAP_complex_double:BOOL": "ON", + "ITK_WRAP_IMAGE_DIMS:STRING": "2;3;4", + "WRAP_ITK_INSTALL_COMPONENT_IDENTIFIER:STRING": "PythonWheel", + "WRAP_ITK_INSTALL_COMPONENT_PER_MODULE:BOOL": "ON", + "PY_SITE_PACKAGES_PATH:PATH": ".", + "ITK_LEGACY_SILENT:BOOL": "ON", + "ITK_WRAP_PYTHON:BOOL": "ON", + "ITK_WRAP_DOC:BOOL": "ON", + "DOXYGEN_EXECUTABLE:FILEPATH": f"{self.package_env_config['DOXYGEN_EXECUTABLE']}", + "Module_ITKTBB:BOOL": self.package_env_config["USE_TBB"], + "TBB_DIR:PATH": self.package_env_config["TBB_DIR"], + # Python settings + "SKBUILD:BOOL": "ON", + } + ) + + def update_venv_itk_build_configurations(self) -> None: + # Python3_EXECUTABLE, Python3_INCLUDE_DIR, and Python3_LIBRARY are validated + # and resolved by find_package(Python3) in cmake/ITKPythonPackage_SuperBuild.cmake + # when not already defined. Python3_ROOT_DIR is set here to guide that search. + self.cmake_itk_source_build_configurations.set( + "Python3_ROOT_DIR:PATH", f"{self.venv_info_dict['python_root_dir']}" + ) + + def run(self) -> None: + """Run the full build flow for this Python instance.""" + # Use BuildManager to persist and resume build steps + + # HACK + if self.itk_module_deps: + self._build_module_dependencies() + + python_package_build_steps: OrderedDict[str, Callable] = OrderedDict( + { + "01_superbuild_support_components": self.build_superbuild_support_components, + "02_build_wrapped_itk_cplusplus": self.build_wrapped_itk_cplusplus, + "03_build_wheels": self.build_itk_python_wheels, + "04_post_build_fixup": self.post_build_fixup, + "05_final_import_test": self.final_import_test, + } + ) + + if self.skip_itk_build: + # Skip these steps if we are in the CI environment + python_package_build_steps = OrderedDict( + ( + ("02_build_wrapped_itk_cplusplus_skipped", (lambda: None)) + if k == "02_build_wrapped_itk_cplusplus" + else (k, v) + ) + for k, v in python_package_build_steps.items() + ) + if self.skip_itk_wheel_build: + python_package_build_steps = OrderedDict( + ( + ("03_build_wheels_skipped", (lambda: None)) + if k == "03_build_wheels" + else (k, v) + ) + for k, v in python_package_build_steps.items() + ) + + if self.module_source_dir is not None: + python_package_build_steps[ + f"06_build_external_module_wheel_{self.module_source_dir.name}" + ] = self.build_external_module_python_wheel + else: + python_package_build_steps["06_build_external_module_wheel_skipped"] = ( + lambda: None + ) + if self.build_itk_tarball_cache: + python_package_build_steps[ + f"07_build_itk_tarball_cache_{self.package_env_config['OS_NAME']}_{self.package_env_config['ARCH']}" + ] = self.build_tarball + + self.dist_dir.mkdir(parents=True, exist_ok=True) + build_report_fn: Path = self.dist_dir / f"build_log_{self.platform_env}.json" + build_manager: BuildManager = BuildManager( + build_report_fn, list(python_package_build_steps.keys()) + ) + build_manager.save() + for build_step_name, build_step_func in python_package_build_steps.items(): + print("=" * 80) + print( + f"Running build step: {build_step_name}: recording status in {build_report_fn}" + ) + # always force_rerun of the tarball step if requested + build_manager.run_step( + build_step_name, + build_step_func, + force_rerun=("tarball_cache" in build_step_name), + ) + build_manager.save() + print( + f"Build step {build_step_name} completed. Edit {build_report_fn} to rerun step." + ) + print("=" * 80) + + def build_superbuild_support_components(self): + # ----------------------------------------------------------------------- + # Build required components (optional local ITK source, TBB builds) used to populate the archive cache + + # Build up definitions using the builder + cmake_superbuild_argumets = CMakeArgumentBuilder() + if self.cmake_compiler_configurations: + cmake_superbuild_argumets.update(self.cmake_compiler_configurations.items()) + # Add superbuild-specific flags + cmake_superbuild_argumets.update( + { + "ITKPythonPackage_BUILD_PYTHON:BOOL": "OFF", + "ITKPythonPackage_USE_TBB:BOOL": self.package_env_config["USE_TBB"], + "ITK_SOURCE_DIR:PATH": f"{self.package_env_config['ITK_SOURCE_DIR']}", + "ITK_GIT_TAG:STRING": f"{self.package_env_config['ITK_GIT_TAG']}", + } + ) + # Start from any platform/user-provided defaults + if self.cmake_cmdline_definitions: + cmake_superbuild_argumets.update(self.cmake_cmdline_definitions.items()) + + cmd = [ + self.package_env_config["CMAKE_EXECUTABLE"], + "-G", + "Ninja", + ] + + cmd += cmake_superbuild_argumets.getCMakeCommandLineArguments() + + cmd += [ + "-S", + str(self.package_env_config["IPP_SOURCE_DIR"] / "SuperbuildSupport"), + "-B", + str(self.package_env_config["IPP_SUPERBUILD_BINARY_DIR"]), + ] + + self.echo_check_call(cmd) + self.echo_check_call( + [ + self.package_env_config["CMAKE_EXECUTABLE"], + "--build", + # "--load-average", + # str(self.build_node_cpu_count), + # "--parallel", + # str(self.build_node_cpu_count), + str(self.package_env_config["IPP_SUPERBUILD_BINARY_DIR"]), + ], + ) + + def fixup_wheels(self, lib_paths: str = ""): + # TBB library fix-up (applies to itk_core wheel) + tbb_wheel = "itk_core" + for wheel in (self.build_dir_root / "dist").glob(f"{tbb_wheel}*.whl"): + self.fixup_wheel(str(wheel), lib_paths) + + def final_wheel_import_test(self, installed_dist_dir: Path): + self.echo_check_call( + [ + self.package_env_config["PYTHON_EXECUTABLE"], + "-m", + "pip", + "install", + "itk", + "--no-cache-dir", + "--no-index", + "-f", + str(installed_dist_dir), + ] + ) + print("Wheel successfully installed.") + # Basic imports + self.echo_check_call( + [self.package_env_config["PYTHON_EXECUTABLE"], "-c", "import itk;"] + ) + self.echo_check_call( + [ + self.package_env_config["PYTHON_EXECUTABLE"], + "-c", + "import itk; image = itk.Image[itk.UC, 2].New()", + ] + ) + self.echo_check_call( + [ + self.package_env_config["PYTHON_EXECUTABLE"], + "-c", + "import itkConfig; itkConfig.LazyLoading=False; import itk;", + ] + ) + # Full doc tests + self.echo_check_call( + [ + self.package_env_config["PYTHON_EXECUTABLE"], + str( + self.package_env_config["IPP_SOURCE_DIR"] + / "docs" + / "code" + / "test.py" + ), + ] + ) + print("Documentation tests passed.") + + def _pip_uninstall_itk_wildcard(self, python_executable: str | Path): + """Uninstall all installed packages whose name starts with 'itk'. + + pip does not support shell-style wildcards directly for uninstall, so we: + - run 'pip list --format=freeze' + - collect package names whose normalized name starts with 'itk' + - call 'pip uninstall -y ' if any are found + """ + python_executable = str(python_executable) + try: + proc = subprocess.run( + [python_executable, "-m", "pip", "list", "--format=freeze"], + check=True, + capture_output=True, + text=True, + ) + except subprocess.CalledProcessError as e: + print( + f"Warning: failed to list packages with pip at {python_executable}: {e}" + ) + return + + packages = [] + for line in proc.stdout.splitlines(): + line = line.strip() + if not line or line.startswith("#"): + continue + # Formats like 'name==version' or 'name @ URL' + name = line.split("==")[0].split(" @ ")[0].strip() + if name.lower().startswith("itk"): + packages.append(name) + + if packages: + print(f"Uninstalling existing ITK-related packages: {' '.join(packages)}") + # Use echo_check_call for consistent logging/behavior + self.echo_check_call( + [python_executable, "-m", "pip", "uninstall", "-y", *packages] + ) + + def find_unix_exectable_paths( + self, + venv_dir: Path, + ) -> tuple[str, str, str, str, str]: + python_executable = venv_dir / "bin" / "python" + if not python_executable.exists(): + raise FileNotFoundError(f"Python executable not found: {python_executable}") + + # Compute Python include dir using sysconfig for the given interpreter + try: + python_include_dir = ( + subprocess.check_output( + [ + str(python_executable), + "-c", + "import sysconfig; print(sysconfig.get_paths()['include'])", + ], + text=True, + ).strip() + or "" + ) + except Exception as e: + print(f"Failed to compute Python include dir: {e}\n defaulting to empty") + python_include_dir = "" + + # modern CMake with Python3 can infer the library from executable; leave empty + python_library = "" + + # Update PATH + venv_bin_path = venv_dir / "bin" + return ( + str(python_executable), + str(python_include_dir), + str(python_library), + str(venv_bin_path), + str(venv_dir), + ) + + @abstractmethod + def clone(self): + # each subclass must implement this method that is used to clone itself + pass + + @abstractmethod + def venv_paths(self): + pass + + @abstractmethod + def fixup_wheel( + self, filepath, lib_paths: str = "", remote_module_wheel: bool = False + ): # pragma: no cover - abstract + pass + + @abstractmethod + def build_tarball(self): + pass + + @abstractmethod + def post_build_cleanup(self): + pass + + @abstractmethod + def prepare_build_env(self) -> None: # pragma: no cover - abstract + pass + + @abstractmethod + def post_build_fixup(self) -> None: # pragma: no cover - abstract + pass + + @abstractmethod + def final_import_test(self) -> None: # pragma: no cover - abstract + pass + + @abstractmethod + def discover_python_venvs( + self, platform_os_name: str, platform_architechure: str + ) -> list[str]: + pass + + def build_external_module_python_wheel(self): + self.module_source_dir = Path(self.module_source_dir) + out_dir = self.module_source_dir / "dist" + out_dir.mkdir(parents=True, exist_ok=True) + + # Ensure venv tools are first in PATH + py_exe = str(self.package_env_config["PYTHON_EXECUTABLE"]) # Python3_EXECUTABLE + + # Compute Python include directory (Python3_INCLUDE_DIR) + py_include = self.venv_info_dict.get("python_include_dir", "") + if not py_include: + try: + py_include = ( + subprocess.check_output( + [ + py_exe, + "-c", + "import sysconfig; print(sysconfig.get_paths()['include'])", + ], + text=True, + ).strip() + or "" + ) + except Exception: + py_include = "" + + # Determine platform-specific settings (macOS) + config_settings: dict[str, str] = {} + + # ITK build path for external modules: prefer configured ITK binary dir + itk_build_path = self.cmake_itk_source_build_configurations.get( + "ITK_BINARY_DIR:PATH", + "", + ) + + # wheel.py-api for stable ABI when Python >= 3.11 + try: + py_minor = int( + subprocess.check_output( + [py_exe, "-c", "import sys; print(sys.version_info.minor)"], + text=True, + ).strip() + ) + except Exception: + py_minor = 0 + wheel_py_api = f"cp3{py_minor}" if py_minor >= 11 else "" + + # Base build command + cmd = [ + py_exe, + "-m", + "build", + "--verbose", + "--wheel", + "--outdir", + str(out_dir), + "--no-isolation", + "--skip-dependency-check", + f"--config-setting=cmake.build-type={self.package_env_config['BUILD_TYPE']}", + ] + + # Collect scikit-build CMake definitions + defs = CMakeArgumentBuilder() + defs.update(self.cmake_compiler_configurations.items()) + # Propagate macOS specific defines if any were set above + for k, v in config_settings.items(): + defs.set(k, v) + + # Required defines for external module build + if itk_build_path: + defs.set("ITK_DIR:PATH", str(itk_build_path)) + defs.set("CMAKE_INSTALL_LIBDIR:STRING", "lib") + defs.set("WRAP_ITK_INSTALL_COMPONENT_IDENTIFIER:STRING", "PythonWheel") + defs.set("PY_SITE_PACKAGES_PATH:PATH", ".") + defs.set("BUILD_TESTING:BOOL", "OFF") + defs.set("Python3_EXECUTABLE:FILEPATH", py_exe) + if py_include: + defs.set("Python3_INCLUDE_DIR:PATH", py_include) + + # Allow command-line cmake -D overrides to win last + if self.cmake_cmdline_definitions: + defs.update(self.cmake_cmdline_definitions.items()) + + # Append all cmake.define entries to the build cmd + cmd += defs.getPythonBuildCommandLineArguments() + + # Stable ABI setting if applicable + if wheel_py_api: + cmd += [f"--config-setting=wheel.py-api={wheel_py_api}"] + + # Module source directory to build + cmd += [self.module_source_dir] + + self.echo_check_call(cmd) + + # Post-process produced wheels (e.g., delocate on macOS x86_64) + for wheel in out_dir.glob("*.whl"): + self.fixup_wheel(str(wheel), remote_module_wheel=True) + + def build_itk_python_wheels(self): + # Build wheels + for wheel_name in self.wheel_names: + print("#") + print(f"# Build ITK wheel {wheel_name} from {self.wheel_names}") + print("#") + # Configure pyproject.toml + wheel_configbuild_dir_root: Path = ( + self.build_dir_root + / "wheelbuilds" + / f"{wheel_name}_{self.get_pixi_environment_name()}" + ) + wheel_configbuild_dir_root.mkdir(parents=True, exist_ok=True) + configure_one_pyproject_file( + str(self.ipp_dir / "scripts"), + self.package_env_config, + wheel_configbuild_dir_root, + wheel_name, + ) + + # Generate wheel using + cmd = [ + str(self.package_env_config["PYTHON_EXECUTABLE"]), + "-m", + "build", + "--verbose", + "--wheel", + "--outdir", + str(self.build_dir_root / "dist"), + "--no-isolation", + "--skip-dependency-check", + f"--config-setting=cmake.build-type={self.package_env_config['BUILD_TYPE']}", + f"--config-setting=cmake.source-dir={self.package_env_config['IPP_SOURCE_DIR'] / 'BuildWheelsSupport'}", + f"--config-setting=build-dir={wheel_configbuild_dir_root/'build'}", + ] + # Build scikit-build defines via builder + scikitbuild_cmdline_args = CMakeArgumentBuilder() + scikitbuild_cmdline_args.update(self.cmake_compiler_configurations.items()) + scikitbuild_cmdline_args.update( + self.cmake_itk_source_build_configurations.items() + ) + scikitbuild_cmdline_args.update( + { + "ITKPythonPackage_USE_TBB:BOOL": self.package_env_config["USE_TBB"], + "ITKPythonPackage_ITK_BINARY_REUSE:BOOL": "ON", + "ITKPythonPackage_WHEEL_NAME:STRING": f"{wheel_name}", + "DOXYGEN_EXECUTABLE:FILEPATH": f"{self.package_env_config['DOXYGEN_EXECUTABLE']}", + } + ) + + if ( + self.cmake_cmdline_definitions + ): # Do last to override with command line items + scikitbuild_cmdline_args.update(self.cmake_cmdline_definitions.items()) + # Append all cmake.define entries + cmd += scikitbuild_cmdline_args.getPythonBuildCommandLineArguments() + # The location of the generated pyproject.toml file + cmd += [wheel_configbuild_dir_root] + self.echo_check_call(cmd) + + # Remove unnecessary files for building against ITK + if self.cleanup: + bp = Path( + self.cmake_itk_source_build_configurations["ITK_BINARY_DIR:PATH"] + ) + for p in bp.rglob("*"): + if p.is_file() and p.suffix in [".cpp", ".xml", ".obj", ".o"]: + try: + p.unlink() + except OSError: + pass + _remove_tree(bp / "Wrapping" / "Generators" / "CastXML") + + def build_wrapped_itk_cplusplus(self): + # Clean up previous invocations + if ( + self.cleanup + and Path( + self.cmake_itk_source_build_configurations["ITK_BINARY_DIR:PATH"] + ).exists() + ): + _remove_tree( + Path(self.cmake_itk_source_build_configurations["ITK_BINARY_DIR:PATH"]) + ) + + print("#") + print("# START-Build ITK C++") + print("#") + + # Build ITK python + cmd = [ + self.package_env_config["CMAKE_EXECUTABLE"], + "-G", + "Ninja", + ] + # Collect all -D definitions via builder + defs = CMakeArgumentBuilder() + defs.update(self.cmake_compiler_configurations.items()) + defs.update(self.cmake_itk_source_build_configurations.items()) + # NOTE Do cmake_cmdline_definitions last so they override internal defaults + defs.update(self.cmake_cmdline_definitions.items()) + cmd += defs.getCMakeCommandLineArguments() + cmd += [ + "-S", + self.package_env_config["ITK_SOURCE_DIR"], + "-B", + self.cmake_itk_source_build_configurations["ITK_BINARY_DIR:PATH"], + ] + self.echo_check_call(cmd) + self.echo_check_call( + [ + self.package_env_config["NINJA_EXECUTABLE"], + f"-j{self.build_node_cpu_count}", + f"-l{self.build_node_cpu_count}", + "-C", + self.cmake_itk_source_build_configurations["ITK_BINARY_DIR:PATH"], + ] + ) + print("# FINISHED-Build ITK C++") + + def _build_module_dependencies(self): + """ + Build prerequisite ITK external modules, mirroring the behavior of + the platform shell scripts that use the ITK_MODULE_PREQ environment. + + Accepted formats in self.itk_module_deps (colon-delimited): + - "MeshToPolyData@v0.10.0" -> defaults to + "InsightSoftwareConsortium/ITKMeshToPolyData@v0.10.0" + - "InsightSoftwareConsortium/ITKMeshToPolyData@v0.10.0" + + For each dependency, clone the repository, checkout the given tag, + invoke the platform download-cache-and-build script, then copy + headers and wrapping input files into the current module tree + (include/ and wrapping/), similar to the bash implementations. + """ + + if len(self.itk_module_deps) == 0: + return + print(f"Building module dependencies: {self.itk_module_deps}") + self.module_dependencies_root_dir.mkdir(parents=True, exist_ok=True) + + # Normalize entries to "Org/Repo@Tag" + def _normalize(entry: str) -> str: + entry = entry.strip() + if not entry: + return "" + if "/" in entry: + # Already Org/Repo@Tag + return entry + # Short form: Name@Tag -> InsightSoftwareConsortium/ITKName@Tag + try: + name, tag = entry.split("@", 1) + except ValueError: + # If no tag, pass-through (unexpected) + return entry + repo = f"ITK{name}" + return f"InsightSoftwareConsortium/{repo}@{tag}" + + # Ensure working directories exist + module_root = Path(self.module_source_dir).resolve() + include_dir = module_root / "include" + wrapping_dir = module_root / "wrapping" + include_dir.mkdir(parents=True, exist_ok=True) + wrapping_dir.mkdir(parents=True, exist_ok=True) + + dep_entries = [e for e in (s for s in self.itk_module_deps.split(":")) if e] + normalized = [_normalize(e) for e in dep_entries] + normalized = [e for e in normalized if e] + + # Build each dependency in order + for _current_entry, entry in enumerate(normalized): + if len(entry) == 0: + continue + print(f"Get dependency module information for {entry}") + org = entry.split("/", 1)[0] + repo_tag = entry.split("/", 1)[1] + repo = repo_tag.split("@", 1)[0] + tag = repo_tag.split("@", 1)[1] if "@" in repo_tag else "" + + upstream = f"https://github.com/{org}/{repo}.git" + dependant_module_clone_dir = ( + self.module_dependencies_root_dir / repo + if self.module_dependencies_root_dir + else module_root / repo + ) + if not dependant_module_clone_dir.exists(): + self.echo_check_call( + ["git", "clone", upstream, dependant_module_clone_dir] + ) + + # Checkout requested tag + self.echo_check_call( + [ + "git", + "-C", + dependant_module_clone_dir, + "fetch", + "--all", + "--tags", + ] + ) + if tag: + self.echo_check_call( + ["git", "-C", dependant_module_clone_dir, "checkout", tag] + ) + + if (dependant_module_clone_dir / "setup.py").exists(): + msg: str = ( + f"Old sci-kit-build with setup.py is no longer supported for {dependant_module_clone_dir} at {tag}" + ) + raise RuntimeError(msg) + + # Clone the current build environment and modify for the current module + dependent_module_build_setup = self.clone() + dependent_module_build_setup.module_source_dir = Path( + dependant_module_clone_dir + ) + dependent_module_build_setup.itk_module_deps = None # Prevent recursion + dependent_module_build_setup.run() + + # After building dependency, copy includes and wrapping files + # 1) Top-level include/* -> include/ + dep_include = dependant_module_clone_dir / "include" + if dep_include.exists(): + for src in dep_include.rglob("*"): + if src.is_file(): + rel = src.relative_to(dep_include) + dst = include_dir / rel + dst.parent.mkdir(parents=True, exist_ok=True) + try: + shutil.copy2(src, dst) + except Exception: + pass + + # 2) Any */build/*/include/* -> include/ + for sub in dependant_module_clone_dir.rglob("*build*/**/include"): + if sub.is_dir(): + for src in sub.rglob("*"): + if src.is_file(): + rel = src.relative_to(sub) + dst = include_dir / rel + dst.parent.mkdir(parents=True, exist_ok=True) + try: + shutil.copy2(src, dst) + except Exception: + pass + + # 3) Wrapping templates (*.in, *.init) -> wrapping/ + dep_wrapping = dependant_module_clone_dir / "wrapping" + if dep_wrapping.exists(): + for pattern in ("*.in", "*.init"): + for src in dep_wrapping.rglob(pattern): + if src.is_file(): + dst = wrapping_dir / src.name + try: + shutil.copy2(src, dst) + except Exception: + pass + + def create_posix_tarball(self): + """Create a compressed tarball of the ITK Python build tree. + + Mirrors the historical scripts/*-build-tarball.sh behavior: + - zstd compress with options (-10 -T6 --long=31) + + Warns if directory structure doesn't match expected layout for GitHub Actions. + """ + arch_postfix: str = f"{self.package_env_config['ARCH']}" + # Fixup platform name for macOS, eventually need to standardize on macosx naming convention + platform_name: str = get_default_platform_build().split("-")[0] + tar_name: str = f"ITKPythonBuilds-{platform_name}-{arch_postfix}.tar" + itk_packaging_reference_dir = self.build_dir_root.parent + + tar_path: Path = itk_packaging_reference_dir / tar_name + zst_path: Path = itk_packaging_reference_dir / f"{tar_name}.zst" + + itk_resources_build_dir: Path = self.build_dir_root + ipp_source_dir: Path = self.package_env_config["IPP_SOURCE_DIR"] + + # Validate directory structure and determine tarball strategy + issues = [] + + # Try to use relative paths first + try: + rel_build = itk_resources_build_dir.relative_to(itk_packaging_reference_dir) + rel_ipp = ipp_source_dir.relative_to(itk_packaging_reference_dir) + except ValueError: + # Fall back to absolute paths + rel_build = itk_resources_build_dir + rel_ipp = ipp_source_dir + itk_packaging_reference_dir = Path( + "/" + ) # Tar from root when using absolute paths + + if itk_resources_build_dir.parent != ipp_source_dir.parent: + issues.append("Build and source dirs are not siblings") + + if ipp_source_dir.name != "ITKPythonPackage": + issues.append( + f"Source dir is '{ipp_source_dir.name}', expected 'ITKPythonPackage'" + ) + + # Issue consolidated warning for compatibility issues + if issues: + print("\n" + "=" * 70) + print("WARNING: Tarball will NOT be compatible with GitHub Actions") + print("=" * 70) + for issue in issues: + print(f" * {issue}") + print( + "\nExpected structure: /{ITKPythonPackage, ITKPythonPackage-build}" + ) + print(f"Current: Build={itk_resources_build_dir}") + print(f" Source={ipp_source_dir}") + print( + "\nTarball will be created for local reuse but may not work in CI/CD." + ) + print("=" * 70 + "\n") + + # Build tarball include paths + tarball_include_paths = [ + str(rel_build), + str(rel_ipp), + ] + + if tar_path.exists(): + print(f"Removing existing tarball {tar_path}") + tar_path.unlink() + if zst_path.exists(): + print(f"Removing existing zstd tarball {zst_path}") + zst_path.unlink() + + # Create tarball + self.echo_check_call( + [ + "tar", + "-C", + str(itk_packaging_reference_dir), + "-cf", + str(tar_path), + "--exclude=*.o", + "--exclude=*.whl", # Do not include built wheels + "--exclude=*/dist/*", # Do not include the dist whl output directory + "--exclude=*/wheelbuilds/*", # Do not include the wheelbuild support directory + "--exclude=*/__pycache__/*", # Do not include __pycache__ + "--exclude=install_manifest_*.txt", # Do not include install manifest files + "--exclude=._*", # Exclude mac dot files + "--exclude=*/.git/*", + "--exclude=*/.idea/*", + "--exclude=*/.pixi/*", + "--exclude=*/castxml_inputs/*", + "--exclude=*/Wrapping/Modules/*", + *tarball_include_paths, + ] + ) + + # Compress with zstd + self.echo_check_call( + [ + "zstd", + "-f", + "-10", + "-T6", + "--long=31", + str(tar_path), + "-o", + str(zst_path), + ] + ) + + print(f"Tarball created: {zst_path}") + if issues: + print("Compatibility warnings above - review before using in CI/CD") + + @abstractmethod + def get_pixi_environment_name(self): + pass + + def echo_check_call( + self, + cmd: list[str | Path] | tuple[str | Path] | str | Path, + use_pixi_env: bool = True, + env=None, + **kwargs: dict, + ) -> int: + """Print the command, then run subprocess.check_call. + + Parameters + ---------- + cmd : + Command to execute, same as subprocess.check_call. + **kwargs : + Additional keyword arguments forwarded to subprocess.check_call. + """ + + pixi_environment: str = self.get_pixi_environment_name() + pixi_executable: Path = self.package_env_config["PIXI_EXECUTABLE"] + pixi_run_preamble: list[str] = [] + pixi_run_dir: Path = self.ipp_dir + pixi_env: dict[str, str] = os.environ.copy() + if env is not None: + pixi_env.update(env) + pixi_env.update( + { + "PIXI_HOME": str(pixi_run_dir / ".pixi"), + } + ) + # if self.pa == "windows": + # pixi_env.update( + # { + # "TEMP": "C:\Temp", + # "TMP": "C:\Temp", + # } + # ) + + if pixi_environment and use_pixi_env: + pixi_run_preamble = [ + str(pixi_executable), + "run", + "-e", + pixi_environment, + "--", + ] + + # convert all items to strings (i.e. Path() to str) + cmd = pixi_run_preamble + [str(c) for c in cmd] + # Prepare a friendly command-line string for display + try: + if isinstance(cmd, list | tuple): + display_cmd = " ".join(cmd) + else: + display_cmd = str(cmd) + except Exception as e: + display_cmd = f"{str(cmd)}\nERROR: {e}" + sys.exit(1) + print(f">>Start Running: cd {pixi_run_dir} && {display_cmd}") + print("^" * 60) + print(cmd) + print("^" * 60) + print(kwargs) + print("^" * 60) + process_completion_info: subprocess.CompletedProcess = ( + run_commandLine_subprocess(cmd, env=pixi_env, cwd=pixi_run_dir, **kwargs) + ) + cmd_return_status: int = process_completion_info.returncode + print("^" * 60) + print(f"< dict[str, str]: + """Collect GitHub Actions environment variables for remote module builds. + + The following environment variables are defined by the + ``ITKRemoteModuleBuildTestPackageAction`` GitHub Action. Variables + marked *active* are read from the environment with a default + fallback; those marked *not used* are documented here for + cross-reference but are no longer consumed at runtime. + + Environment Variables + --------------------- + ITK_PACKAGE_VERSION : str (active) + PEP 440 version string for ITK packages. + GitHub Action source: ``inputs.itk-wheel-tag``. + Default ``"auto"`` triggers automatic version computation. + ITKPYTHONPACKAGE_TAG : str (not used — GitHub Actions scripts only) + Git tag for ITKPythonPackage checkout. + GitHub Action source: ``inputs.itk-python-package-tag``. + ITKPYTHONPACKAGE_ORG : str (not used — GitHub Actions scripts only) + GitHub organization owning ITKPythonPackage. + GitHub Action source: ``inputs.itk-python-package-org``. + ITK_MODULE_PREQ : str (active) + Colon-delimited list of remote module dependencies. + GitHub Action source: ``inputs.itk-module-deps``. + CMAKE_OPTIONS : str (active) + Extra options forwarded to CMake. + GitHub Action source: ``inputs.cmake-options``. + MANYLINUX_PLATFORM : str (not used — computed internally) + Full manylinux platform string (e.g. ``"manylinux_2_28-x64"``). + GitHub Action source: ``matrix.manylinux-platform``. + MANYLINUX_VERSION : str (active) + Manylinux specification (e.g. ``"_2_28"``). Historically + computed as the first part of ``MANYLINUX_PLATFORM``. + TARGET_ARCH : str (not used — computed internally) + Target architecture (e.g. ``"x64"``). Historically computed + as the second part of ``MANYLINUX_PLATFORM``. + MACOSX_DEPLOYMENT_TARGET : str (active) + Minimum macOS version for wheel compatibility. + GitHub Action source: ``inputs.macosx-deployment-target``. + Default ``"10.7"`` is outdated but provides backward + compatibility. + + Returns + ------- + dict[str, str] + A mapping of active configuration keys to their values, sourced + from environment variables with sensible defaults. + """ + env_defaults: dict[str, str] = { + "ITK_PACKAGE_VERSION": "auto", + "ITK_MODULE_PREQ": "", + "CMAKE_OPTIONS": "", + "MANYLINUX_VERSION": "", + "MACOSX_DEPLOYMENT_TARGET": "10.7", + } + return {key: os.environ.get(key, default) for key, default in env_defaults.items()} + + +def in_pixi_env() -> bool: + """Check whether the process is running inside a pixi environment. + + Returns + ------- + bool + True if both ``PIXI_ENVIRONMENT_NAME`` and ``PIXI_PROJECT_ROOT`` + are set in the environment. + """ + return "PIXI_ENVIRONMENT_NAME" in os.environ and "PIXI_PROJECT_ROOT" in os.environ + + +def get_effective_command_line( + parser: argparse.ArgumentParser, args: argparse.Namespace +) -> str: + """Reconstruct a reproducible command line from parsed arguments. + + Parameters + ---------- + parser : argparse.ArgumentParser + The argument parser used to parse *args*. + args : argparse.Namespace + Parsed command-line arguments. + + Returns + ------- + str + A shell-safe command string suitable for logging or re-execution + inside a pixi environment. + """ + pixi_executable: str = os.environ.get("PIXI_EXE", "pixi") + effective_command = [ + pixi_executable, + "run", + "-e", + args.platform_env, + "--", + sys.executable, + sys.argv[0], + ] + for action in parser._actions: + if isinstance(action, argparse._HelpAction): + continue + dest = action.dest + value = getattr(args, dest, None) + if value is None: + continue + if action.option_strings: + option_string = action.option_strings[0] + if isinstance(action, argparse._StoreTrueAction): + if value: + effective_command.append(option_string) + elif isinstance(action, argparse._StoreFalseAction): + if not value: + effective_command.append(option_string) + else: + if isinstance(value, list): + if value: + effective_command.append(option_string) + effective_command.extend([str(v) for v in value]) + else: + effective_command.append(option_string) + effective_command.append(str(value)) + else: + if isinstance(value, list): + effective_command.extend([str(v) for v in value]) + else: + effective_command.append(str(value)) + return shlex.join(effective_command) + + +def build_wheels_main() -> None: + """Entry point: parse arguments, configure, and run the wheel build.""" + os_name, arch = detect_platform() + ipp_script_dir: Path = Path(__file__).parent + ipp_dir: Path = ipp_script_dir.parent + if (ipp_dir / ".pixi" / "bin").exists(): + os.environ["PATH"] = ( + str(ipp_dir / ".pixi" / "bin") + os.pathsep + os.environ["PATH"] + ) + + remote_module_build_dict = remotemodulebuildandtestaction() + parser = argparse.ArgumentParser( + description="Driver script to build ITK Python wheels." + ) + parser.add_argument( + "--platform-env", + default=get_default_platform_build("py311"), + help=( + """A platform environment name or path: + linux-py310, linux-py311, + manylinux228-py310, manylinux228-py311, + windows-py310, windows-py311, + macosx-py310, macosx-py311 + """ + ), + ) + parser.add_argument( + "--cleanup", + dest="cleanup", + action="store_true", + help=""" + 'ITK_MODULE_NO_CLEANUP': Option to skip cleanup steps. + =1 <- Leave temporary build files in place after completion, 0 <- remove temporary build files + """, + ) + parser.add_argument( + "--lib-paths", + nargs=1, + default="", + help=( + "Windows only: semicolon-delimited library directories for delvewheel to include in module wheel" + ), + ) + _cmake_options_default = remote_module_build_dict["CMAKE_OPTIONS"] + parser.add_argument( + "cmake_options", + nargs="*", + default=shlex.split(_cmake_options_default) if _cmake_options_default else [], + help="Extra options to pass to CMake, e.g. -DBUILD_SHARED_LIBS:BOOL=OFF.\n" + " These will override defaults if duplicated", + ) + parser.add_argument( + "--module-source-dir", + type=str, + default=None, + help="Path to the (remote) module source directory to build.", + ) + parser.add_argument( + "--module-dependencies-root-dir", + type=str, + default=None, + help="Path to the root directory for module dependencies.\n" + + "This is the path where a remote module dependencies (other remote modules)\n" + + "are searched for, or automatically git cloned to.", + ) + parser.add_argument( + "--itk-module-deps", + type=str, + default=remote_module_build_dict["ITK_MODULE_PREQ"], + help="Semicolon-delimited list of a remote modules dependencies.\n" + + "'gitorg/repo@tag:gitorg/repo@tag:gitorg/repo@tag'\n" + + "These are set in ITKRemoteModuleBuildTestPackageAction:itk-module-deps github actions." + + "and were historically set as an environment variable ITK_MODULE_PREQ.", + ) + + parser.add_argument( + "--build-itk-tarball-cache", + dest="build_itk_tarball_cache", + action="store_true", + default=False, + help="Build an uploadable tarball. The tarball can be used as a cache for remote module builds.", + ) + parser.add_argument( + "--no-build-itk-tarball-cache", + dest="build_itk_tarball_cache", + action="store_false", + help="Do not build an uploadable tarball. The tarball can be used as a cache for remote module builds.", + ) + + # set the default build_dir_root to a very short path on Windows to avoid path too long errors + default_build_dir_root = ( + ipp_dir.parent / "ITKPythonPackage-build" + if os_name != "windows" + else Path("C:/") / "BDR" + ) + parser.add_argument( + "--build-dir-root", + type=str, + default=f"{default_build_dir_root}", + help="The root of the build resources.", + ) + parser.add_argument( + "--manylinux-version", + type=str, + default=remote_module_build_dict["MANYLINUX_VERSION"], + help="default manylinux version (_2_28, _2_34, ...), if empty, build native linux instead of cross compiling", + ) + + parser.add_argument( + "--itk-git-tag", + type=str, + default=os.environ.get( + "ITK_GIT_TAG", os.environ.get("ITK_PACKAGE_VERSION", "main") + ), + help=""" + - 'ITK_GIT_TAG': Tag/branch/hash for the ITK source code to use in packaging. + Which ITK git tag/hash/branch to use as reference for building wheels/modules + https://github.com/InsightSoftwareConsortium/ITK.git@${ITK_GIT_TAG} + Examples: v5.4.0, v5.2.1.post1, 0ffcaed12552, my-testing-branch + See available release tags at https://github.com/InsightSoftwareConsortium/ITKPythonBuilds/tags + """, + ) + + # set the default build_dir_root to a very short path on Windows to avoid path too long errors + default_itk_source_dir = ( + ipp_dir.parent / "ITKPythonPackage-build" / "ITK" + if os_name != "windows" + else Path("C:/") / "BDR" / "ITK" + ) + parser.add_argument( + "--itk-source-dir", + type=str, + default=os.environ.get("ITK_SOURCE_DIR", str(default_itk_source_dir)), + help=""" + - 'ITK_SOURCE_DIR': When building different 'flavor' of ITK python packages + on a given platform, explicitly setting the ITK_SOURCE_DIR options allow to + speed up source-code downloads by re-using an existing repository. + If the requested directory does not exist, manually clone and checkout ${ITK_GIT_TAG}""", + ) + + parser.add_argument( + "--itk-package-version", + type=str, + default=remote_module_build_dict["ITK_PACKAGE_VERSION"], + help=""" + - 'ITK_PACKAGE_VERSION' A valid PEP440 version string for the itk packages generated. + The default is to automatically generate a PEP440 version automatically based on relative + versioning from the latest tagged release. + (in github action ITKRemoteModuleBuildTestPackage itk-wheel-tag is used to set this value) + """, + ) + + if os_name == "darwin": + parser.add_argument( + "--macosx-deployment-target", + type=str, + default=remote_module_build_dict["MACOSX_DEPLOYMENT_TARGET"], + help=""" + The MacOSX deployment target to use for building wheels. + """, + ) + + parser.add_argument( + "--use-sudo", + action="store_true", + dest="use_sudo", + default=False, + help=""" + - Enable if running docker requires sudo privileges + """, + ) + parser.add_argument( + "--no-use-sudo", + action="store_false", + dest="use_sudo", + help=""" + - Enable if running docker requires sudo privileges + """, + ) + + parser.add_argument( + "--use-ccache", + action="store_true", + dest="use_ccache", + default=False, + help=""" + - Option to indicate that ccache should be used + """, + ) + parser.add_argument( + "--no-use-ccache", + action="store_false", + dest="use_ccache", + help=""" + - Option to indicate that ccache should not be used + """, + ) + + parser.add_argument( + "--skip-itk-build", + action="store_true", + dest="skip_itk_build", + default=False, + help=""" + - Option to skip the ITK C++ build step (Step 2) + """, + ) + + parser.add_argument( + "--no-skip-itk-build", + action="store_false", + dest="skip_itk_build", + help=""" + - Option to not skip the ITK C++ build step (Step 2) + """, + ) + + parser.add_argument( + "--skip-itk-wheel-build", + action="store_true", + dest="skip_itk_wheel_build", + default=False, + help=""" + - Option to skip the ITK wheel build step (Step 3) + """, + ) + + parser.add_argument( + "--no-skip-itk-wheel-build", + action="store_false", + dest="skip_itk_wheel_build", + help=""" + - Option to not skip the ITK wheel build step (Step 3) + """, + ) + + args = parser.parse_args() + + # Historical dist_dir name for compatibility with ITKRemoteModuleBuildTestPackageAction + _ipp_dir_path: Path = Path(__file__).resolve().parent.parent + dist_dir: Path = Path(args.build_dir_root) / "dist" + + # Platform detection + binary_ext: str = ".exe" if os_name == "windows" else "" + env_bin_dir: str = "Scripts" if os_name == "windows" else "bin" + + env_path = _ipp_dir_path / ".pixi" / "envs" / args.platform_env + # multiple locations the executables can be at on Windows + env_subdirs = ( + [env_bin_dir, "Library/bin"] if os_name == "windows" else [env_bin_dir] + ) + + os.environ["PATH"] = os.pathsep.join( + [ + *[str(env_path / d) for d in env_subdirs], + str(_ipp_dir_path / ".pixi" / "bin"), + os.environ.get("PATH", ""), + ] + ) + pixi_exec_path: Path = _which("pixi" + binary_ext) + package_env_config: dict[str, str | Path | None] = {} + + args.build_dir_root = Path(args.build_dir_root) + if str(args.build_dir_root) != str(default_build_dir_root) and str( + args.itk_source_dir + ) == str(default_itk_source_dir): + args.itk_source_dir = args.build_dir_root / "ITK" + + args.itk_source_dir = Path(args.itk_source_dir) + package_env_config["ITK_SOURCE_DIR"] = Path(args.itk_source_dir) + + ipp_superbuild_binary_dir: Path = args.build_dir_root / "build" / "ITK-support-bld" + package_env_config["IPP_SUPERBUILD_BINARY_DIR"] = ipp_superbuild_binary_dir + + package_env_config["OS_NAME"] = os_name + package_env_config["ARCH"] = arch + + # ITK repo handling + + if not Path(args.itk_source_dir).exists(): + args.itk_source_dir.parent.mkdir(parents=True, exist_ok=True) + print(f"Cloning ITK into {args.itk_source_dir}...") + run_result = run_commandLine_subprocess( + [ + "git", + "clone", + "https://github.com/InsightSoftwareConsortium/ITK.git", + str(args.itk_source_dir), + ], + cwd=_ipp_dir_path, + env=os.environ.copy(), + ) + if run_result.returncode != 0: + raise RuntimeError(f"Failed to clone ITK: {run_result.stderr}") + + run_commandLine_subprocess( + ["git", "fetch", "--tags", "origin"], + cwd=args.itk_source_dir, + env=os.environ.copy(), + ) + try: + run_commandLine_subprocess( + ["git", "checkout", args.itk_git_tag], + cwd=args.itk_source_dir, + env=os.environ.copy(), + ) + except subprocess.CalledProcessError: + print(f"WARNING: Failed to checkout {args.itk_git_tag}, reverting to 'main':") + run_commandLine_subprocess( + ["git", "checkout", "main"], + cwd=args.itk_source_dir, + env=os.environ.copy(), + ) + + if ( + args.itk_package_version == "auto" + or args.itk_package_version is None + or len(args.itk_package_version) == 0 + ): + args.itk_package_version = os.environ.get( + "ITK_PACKAGE_VERSION", + compute_itk_package_version( + args.itk_source_dir, args.itk_git_tag, pixi_exec_path, os.environ + ), + ) + + # ITKPythonPackage origin/tag + # NO_SUDO, ITK_MODULE_NO_CLEANUP, USE_CCACHE + no_sudo = os.environ.get("NO_SUDO", "0") + module_no_cleanup = os.environ.get("ITK_MODULE_NO_CLEANUP", "1") + use_ccache = os.environ.get("USE_CCACHE", "0") + + package_env_config["BUILD_DIR_ROOT"] = str(args.build_dir_root) + package_env_config["ITK_GIT_TAG"] = args.itk_git_tag + package_env_config["ITK_SOURCE_DIR"] = args.itk_source_dir + package_env_config["ITK_PACKAGE_VERSION"] = args.itk_package_version + if os_name == "darwin": + package_env_config["MACOSX_DEPLOYMENT_TARGET"] = args.macosx_deployment_target + else: + package_env_config["MACOSX_DEPLOYMENT_TARGET"] = "RELEVANT_FOR_MACOS_ONLY" + package_env_config["ITK_MODULE_PREQ"] = args.itk_module_deps + package_env_config["NO_SUDO"] = no_sudo + package_env_config["ITK_MODULE_NO_CLEANUP"] = module_no_cleanup + package_env_config["USE_CCACHE"] = use_ccache + package_env_config["PIXI_EXECUTABLE"] = _which("pixi") + package_env_config["CMAKE_EXECUTABLE"] = _which("cmake") + package_env_config["NINJA_EXECUTABLE"] = _which("ninja") + package_env_config["DOXYGEN_EXECUTABLE"] = _which("doxygen") + package_env_config["GIT_EXECUTABLE"] = _which("git") + + # reliably find the python executable in pixi + cmd = [ + package_env_config["PIXI_EXECUTABLE"], + "run", + "-e", + args.platform_env, + "python", + "-c", + "import sys; print(sys.executable)", + ] + package_env_config["PYTHON_EXECUTABLE"] = run_commandLine_subprocess( + cmd, env=os.environ.copy() + ).stdout.strip() + + oci_exe = resolve_oci_exe(os.environ.copy()) + package_env_config["OCI_EXE"] = oci_exe + del oci_exe + + # ------------- + platform = package_env_config["OS_NAME"].lower() + if platform == "windows": + from windows_build_python_instance import WindowsBuildPythonInstance + + builder_cls = WindowsBuildPythonInstance + elif platform in ("darwin", "mac", "macos", "macosx", "osx"): + from macos_build_python_instance import MacOSBuildPythonInstance + + builder_cls = MacOSBuildPythonInstance + elif platform == "linux": + from linux_build_python_instance import LinuxBuildPythonInstance + + # Manylinux/docker bits for Linux + target_arch = os.environ.get("TARGET_ARCH") or arch + + manylinux_version: str = args.manylinux_version + if manylinux_version and len(manylinux_version) > 0: + if ( + os.environ.get("MANYLINUX_VERSION", manylinux_version) + != manylinux_version + ): + print( + f"WARNING: environment variable MANYLINUX_VERSION={manylinux_version} is changed to command line value of {manylinux_version}." + ) + package_env_config["MANYLINUX_VERSION"] = manylinux_version + image_tag, manylinux_image_name, container_source = default_manylinux( + manylinux_version, os_name, target_arch, os.environ.copy() + ) + package_env_config["IMAGE_TAG"] = image_tag + package_env_config["MANYLINUX_IMAGE_NAME"] = manylinux_image_name + package_env_config["CONTAINER_SOURCE"] = container_source + package_env_config["TARGET_ARCH"] = target_arch + + # Native builds without dockcross need a separate dist dir to avoid conflicts with manylinux + # dist_dir = IPP_SOURCE_DIR / f"{platform}_dist" + # For the aarch64 manylinux builds, the CROSS_TRIPLE environment variable is unset + if os.environ.get("CROSS_TRIPLE", None) is None and target_arch not in ( + "arm64", + "aarch64", + ): + msg: str = ( + f"ERROR: MANYLINUX_VERSION={manylinux_version} and TARGET_ARCH={target_arch} but not building in dockcross." + ) + raise RuntimeError(msg) + + builder_cls = LinuxBuildPythonInstance + else: + raise ValueError(f"Unknown platform {platform}") + + print("=" * 80) + print("=" * 80) + print("= Building Wheels with effective command line") + print("\n\n") + cmdline: str = f"{get_effective_command_line(parser, args)}" + args.build_dir_root.mkdir(parents=True, exist_ok=True) + with open( + args.build_dir_root / f"effective_cmdline_{args.platform_env}.sh", "w" + ) as f: + f.write("#!/bin/bash\n") + f.write( + "# Generated by build_wheels.py as documentation for describing how these wheels were created.\n" + ) + f.write(cmdline) + f.write("\n") + print(f"cmdline: {cmdline}") + print("\n\n\n\n") + print("=" * 80) + print("=" * 80) + print(f"Building wheels for platform: {args.platform_env}") + # Pass helper function callables and dist dir to avoid circular imports + builder = builder_cls( + platform_env=args.platform_env, + build_dir_root=args.build_dir_root, + package_env_config=package_env_config, + cleanup=args.cleanup, + build_itk_tarball_cache=args.build_itk_tarball_cache, + cmake_options=args.cmake_options, + windows_extra_lib_paths=args.lib_paths, + dist_dir=dist_dir, + module_source_dir=args.module_source_dir, + module_dependencies_root_dir=args.module_dependencies_root_dir, + itk_module_deps=args.itk_module_deps, + skip_itk_build=args.skip_itk_build, + skip_itk_wheel_build=args.skip_itk_wheel_build, + ) + builder.run() + + +if __name__ == "__main__": + build_wheels_main() diff --git a/scripts/cmake_argument_builder.py b/scripts/cmake_argument_builder.py new file mode 100644 index 00000000..22aee6d2 --- /dev/null +++ b/scripts/cmake_argument_builder.py @@ -0,0 +1,107 @@ +from collections.abc import Iterable, Iterator, Mapping + + +def drop_quotes(s: str) -> str: + """Strip surrounding double-quote characters from *s*.""" + return str(s).strip('"') + + +class CMakeArgumentBuilder: + """Manage CMake-style key/value definitions and render them as CLI args. + + Keys should include any CMake type suffix (e.g. + ``'CMAKE_BUILD_TYPE:STRING'``). Values are rendered verbatim. + + Parameters + ---------- + initial : Mapping[str, str], optional + Initial set of definitions to populate the builder. + + Examples + -------- + >>> flags = { + ... 'CMAKE_BUILD_TYPE:STRING': 'Release', + ... 'CMAKE_OSX_ARCHITECTURES:STRING': 'arm64', + ... } + >>> builder = CMakeArgumentBuilder(flags) + >>> builder.getCMakeCommandLineArguments() + ["-DCMAKE_BUILD_TYPE:STRING='Release'", "-DCMAKE_OSX_ARCHITECTURES:STRING='arm64'"] + >>> builder.getPythonBuildCommandLineArguments() + ['--config-setting=cmake.define.CMAKE_BUILD_TYPE:STRING=Release', + '--config-setting=cmake.define.CMAKE_OSX_ARCHITECTURES:STRING=arm64'] + """ + + def __init__(self, initial: Mapping[str, str] | None = None) -> None: + # dict preserves insertion order; keep user's order when possible + self._defs: dict[str, str] = dict(initial) if initial else {} + + # Basic mapping helpers (optional convenience) + def set(self, key: str, value: str) -> None: + """Set or replace a definition. + + Parameters + ---------- + key : str + CMake variable name, optionally with a type suffix + (e.g. ``'CMAKE_BUILD_TYPE:STRING'``). + value : str + Value for the definition. + """ + self._defs[key] = value + + def get(self, key: str, default: str | None = None) -> str | None: + """Return the value for *key*, or *default* if absent.""" + return self._defs.get(key, default) + + def update(self, other: Mapping[str, str] | Iterable[tuple[str, str]]) -> None: + """Merge definitions from *other* into this builder. + + Parameters + ---------- + other : Mapping[str, str] or Iterable[tuple[str, str]] + Definitions to merge. Existing keys are overwritten. + """ + if isinstance(other, Mapping): + self._defs.update(other) + else: + for k, v in other: + self._defs[k] = v + + def __contains__(self, key: str) -> bool: # pragma: no cover - trivial + return key in self._defs + + def __getitem__(self, key: str) -> str: # pragma: no cover - trivial + return self._defs[key] + + def __iter__(self) -> Iterator[str]: # pragma: no cover - trivial + return iter(self._defs) + + def items(self) -> Iterable[tuple[str, str]]: # pragma: no cover - trivial + """Return an iterable of ``(key, value)`` definition pairs.""" + return self._defs.items() + + # Renderers + def getCMakeCommandLineArguments(self) -> list[str]: + """Render definitions as CMake ``-D`` arguments. + + Returns + ------- + list[str] + A list like ``["-D=''", ...]``. + """ + return [f"""-D{k}='{drop_quotes(v)}'""" for k, v in self._defs.items()] + + def getPythonBuildCommandLineArguments(self) -> list[str]: + """Render definitions as scikit-build-core ``--config-setting`` arguments. + + Returns + ------- + list[str] + A list like + ``["--config-setting=cmake.define.=''", ...]``. + """ + prefix = "--config-setting=cmake.define." + return [f"""{prefix}{k}='{drop_quotes(v)}'""" for k, v in self._defs.items()] + + +__all__ = ["CMakeArgumentBuilder"] diff --git a/scripts/install_pixi.py b/scripts/install_pixi.py new file mode 100755 index 00000000..986e7629 --- /dev/null +++ b/scripts/install_pixi.py @@ -0,0 +1,153 @@ +#!/usr/bin/env python3 + +import os +from pathlib import Path + +from wheel_builder_utils import detect_platform, run_commandLine_subprocess + + +def download_and_install_pixi( + binary_ext: str, os_name: str, pixi_home: Path, platform_env: str = "default" +) -> Path: + """Download pixi (if not already present) and install a platform environment. + + Parameters + ---------- + binary_ext : str + Executable extension (``'.exe'`` on Windows, ``''`` elsewhere). + os_name : str + Operating system name (``'windows'``, ``'linux'``, ``'darwin'``). + pixi_home : Path + Directory where pixi is (or will be) installed. + platform_env : str, optional + Pixi environment name to install (default ``'default'``). + + Returns + ------- + pixi_exec_path : Path + Path to the pixi executable. + + Raises + ------ + RuntimeError + If the download, installation, or environment setup fails. + """ + pixi_bin_name: str = "pixi" + binary_ext + # Attempt to find an existing pixi binary on the system first (cross-platform) + pixi_exec_path: Path = Path(pixi_home) / "bin" / pixi_bin_name + + pixi_install_env = os.environ.copy() + pixi_install_env["PIXI_NO_PATH_UPDATE"] = "1" + pixi_install_env["PIXI_HOME"] = str(pixi_home) + + # If not found, we will install into the local build .pixi + if pixi_exec_path.is_file(): + print(f"Previous install of pixi will be used {pixi_exec_path}.") + else: + if os_name == "windows": + # Use PowerShell to install pixi on Windows + result = run_commandLine_subprocess( + [ + "powershell", + "-NoProfile", + "-ExecutionPolicy", + "Bypass", + "-Command", + "irm -UseBasicParsing https://pixi.sh/install.ps1 | iex", + ], + env=pixi_install_env, + ) + if result.returncode != 0: + raise RuntimeError(f"Failed to install pixi: {result.stderr}") + else: + pixi_install_script: Path = pixi_home / "pixi_install.sh" + result = run_commandLine_subprocess( + [ + "curl", + "-fsSL", + "https://pixi.sh/install.sh", + "-o", + str(pixi_install_script), + ] + ) + if result.returncode != 0: + raise RuntimeError( + f"Failed to download {pixi_install_script}: {result.stderr}" + ) + result = run_commandLine_subprocess( + [ + "/bin/sh", + str(pixi_install_script), + ], + env=pixi_install_env, + ) + if result.returncode != 0: + raise RuntimeError(f"Failed to install pixi: {result.stderr}") + del pixi_install_script + + if not pixi_exec_path.exists(): + raise RuntimeError( + f"Failed to install {pixi_exec_path} pixi into {pixi_exec_path}" + ) + # Now install the desired platform + if (pixi_home.parent / "pixi.toml").exists(): + result = run_commandLine_subprocess( + [pixi_exec_path, "install", "--environment", platform_env], + cwd=pixi_home.parent, + env=pixi_install_env, + ) + if result.returncode != 0: + raise RuntimeError( + f"Failed to install environment {platform_env}: {result.stderr}" + ) + else: + print( + f"pixi.toml not found {pixi_home.parent / 'pixi.toml'}, skipping environment install." + ) + return pixi_exec_path + + +def install_pixi_tools(platform_env: str = "default"): + """High-level helper: detect the platform, install pixi, and set up *platform_env*. + + Parameters + ---------- + platform_env : str, optional + Pixi environment name to install (default ``'default'``). + """ + _ipp_dir_path: Path = Path(__file__).resolve().parent.parent + os_name, arch = detect_platform() + binary_ext: str = ".exe" if os_name == "windows" else "" + + pixi_home: Path = Path( + os.environ.get("PIXI_HOME") + if "PIXI_HOME" in os.environ + else _ipp_dir_path / ".pixi" + ) + pixi_home.mkdir(parents=True, exist_ok=True) + pixi_exec_path = Path( + download_and_install_pixi(binary_ext, os_name, pixi_home, platform_env) + ) + print(f"Installed pixi locally to {pixi_home} with binary of {pixi_exec_path}") + + +if __name__ == "__main__": + import argparse + + parser = argparse.ArgumentParser( + description="Driver script to build ITK Python wheels." + ) + parser.add_argument( + "--platform-env", + default="default", + help=( + """A platform environment name or path: + linux-py310, linux-py311, + manylinux228-py310, manylinux228-py311, + windows-py310, windows-py311, + macosx-py310, macosx-py311 + """ + ), + ) + args = parser.parse_args() + install_pixi_tools(args.platform_env) diff --git a/scripts/internal/Support.cmake b/scripts/internal/Support.cmake deleted file mode 100644 index 84487a32..00000000 --- a/scripts/internal/Support.cmake +++ /dev/null @@ -1,2749 +0,0 @@ -# Distributed under the OSI-approved BSD 3-Clause License. See accompanying -# file Copyright.txt or https://cmake.org/licensing for details. - -# -# This file is a "template" file used by various FindPython modules. -# - -cmake_policy (GET CMP0094 _${_PYTHON_PREFIX}_LOOKUP_POLICY) - -cmake_policy (VERSION 3.7) - -if (_${_PYTHON_PREFIX}_LOOKUP_POLICY) - cmake_policy (SET CMP0094 ${_${_PYTHON_PREFIX}_LOOKUP_POLICY}) -endif() - -# -# Initial configuration -# -if (NOT DEFINED _PYTHON_PREFIX) - message (FATAL_ERROR "FindPython: INTERNAL ERROR") -endif() -if (NOT DEFINED _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR) - message (FATAL_ERROR "FindPython: INTERNAL ERROR") -endif() -if (_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR EQUAL "3") - set(_${_PYTHON_PREFIX}_VERSIONS 3.9 3.8 3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0) -elseif (_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR EQUAL "2") - set(_${_PYTHON_PREFIX}_VERSIONS 2.7 2.6 2.5 2.4 2.3 2.2 2.1 2.0) -else() - message (FATAL_ERROR "FindPython: INTERNAL ERROR") -endif() - -get_property(_${_PYTHON_PREFIX}_CMAKE_ROLE GLOBAL PROPERTY CMAKE_ROLE) - - -# -# helper commands -# -macro (_PYTHON_DISPLAY_FAILURE _PYTHON_MSG) - if (${_PYTHON_PREFIX}_FIND_REQUIRED) - message (FATAL_ERROR "${_PYTHON_MSG}") - else() - if (NOT ${_PYTHON_PREFIX}_FIND_QUIETLY) - message(STATUS "${_PYTHON_MSG}") - endif () - endif() - - set (${_PYTHON_PREFIX}_FOUND FALSE) - string (TOUPPER "${_PYTHON_PREFIX}" _${_PYTHON_PREFIX}_UPPER_PREFIX) - set (${_PYTHON_UPPER_PREFIX}_FOUND FALSE) - return() -endmacro() - - -function (_PYTHON_MARK_AS_INTERNAL) - foreach (var IN LISTS ARGV) - if (DEFINED CACHE{${var}}) - set_property (CACHE ${var} PROPERTY TYPE INTERNAL) - endif() - endforeach() -endfunction() - - -macro (_PYTHON_SELECT_LIBRARY_CONFIGURATIONS _PYTHON_BASENAME) - if(NOT DEFINED ${_PYTHON_BASENAME}_LIBRARY_RELEASE) - set(${_PYTHON_BASENAME}_LIBRARY_RELEASE "${_PYTHON_BASENAME}_LIBRARY_RELEASE-NOTFOUND") - endif() - if(NOT DEFINED ${_PYTHON_BASENAME}_LIBRARY_DEBUG) - set(${_PYTHON_BASENAME}_LIBRARY_DEBUG "${_PYTHON_BASENAME}_LIBRARY_DEBUG-NOTFOUND") - endif() - - get_property(_PYTHON_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) - if (${_PYTHON_BASENAME}_LIBRARY_DEBUG AND ${_PYTHON_BASENAME}_LIBRARY_RELEASE AND - NOT ${_PYTHON_BASENAME}_LIBRARY_DEBUG STREQUAL ${_PYTHON_BASENAME}_LIBRARY_RELEASE AND - (_PYTHON_isMultiConfig OR CMAKE_BUILD_TYPE)) - # if the generator is multi-config or if CMAKE_BUILD_TYPE is set for - # single-config generators, set optimized and debug libraries - set (${_PYTHON_BASENAME}_LIBRARIES "") - foreach (_PYTHON_libname IN LISTS ${_PYTHON_BASENAME}_LIBRARY_RELEASE) - list( APPEND ${_PYTHON_BASENAME}_LIBRARIES optimized "${_PYTHON_libname}") - endforeach() - foreach (_PYTHON_libname IN LISTS ${_PYTHON_BASENAME}_LIBRARY_DEBUG) - list( APPEND ${_PYTHON_BASENAME}_LIBRARIES debug "${_PYTHON_libname}") - endforeach() - elseif (${_PYTHON_BASENAME}_LIBRARY_RELEASE) - set (${_PYTHON_BASENAME}_LIBRARIES "${${_PYTHON_BASENAME}_LIBRARY_RELEASE}") - elseif (${_PYTHON_BASENAME}_LIBRARY_DEBUG) - set (${_PYTHON_BASENAME}_LIBRARIES "${${_PYTHON_BASENAME}_LIBRARY_DEBUG}") - else() - set (${_PYTHON_BASENAME}_LIBRARIES "${_PYTHON_BASENAME}_LIBRARY-NOTFOUND") - endif() -endmacro() - - -macro (_PYTHON_FIND_FRAMEWORKS) - set (${_PYTHON_PREFIX}_FRAMEWORKS) - if (CMAKE_HOST_APPLE OR APPLE) - file(TO_CMAKE_PATH "$ENV{CMAKE_FRAMEWORK_PATH}" _pff_CMAKE_FRAMEWORK_PATH) - set (_pff_frameworks ${CMAKE_FRAMEWORK_PATH} - ${_pff_CMAKE_FRAMEWORK_PATH} - ~/Library/Frameworks - /usr/local/Frameworks - ${CMAKE_SYSTEM_FRAMEWORK_PATH}) - list (REMOVE_DUPLICATES _pff_frameworks) - foreach (_pff_framework IN LISTS _pff_frameworks) - if (EXISTS ${_pff_framework}/Python${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR}.framework) - list (APPEND ${_PYTHON_PREFIX}_FRAMEWORKS ${_pff_framework}/Python${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR}.framework) - endif() - if (EXISTS ${_pff_framework}/Python.framework) - list (APPEND ${_PYTHON_PREFIX}_FRAMEWORKS ${_pff_framework}/Python.framework) - endif() - endforeach() - unset (_pff_frameworks) - unset (_pff_framework) - endif() -endmacro() - -function (_PYTHON_GET_FRAMEWORKS _PYTHON_PGF_FRAMEWORK_PATHS _PYTHON_VERSION) - set (_PYTHON_FRAMEWORK_PATHS) - foreach (_PYTHON_FRAMEWORK IN LISTS ${_PYTHON_PREFIX}_FRAMEWORKS) - list (APPEND _PYTHON_FRAMEWORK_PATHS - "${_PYTHON_FRAMEWORK}/Versions/${_PYTHON_VERSION}") - endforeach() - set (${_PYTHON_PGF_FRAMEWORK_PATHS} ${_PYTHON_FRAMEWORK_PATHS} PARENT_SCOPE) -endfunction() - -function (_PYTHON_GET_REGISTRIES _PYTHON_PGR_REGISTRY_PATHS _PYTHON_VERSION) - string (REPLACE "." "" _PYTHON_VERSION_NO_DOTS ${_PYTHON_VERSION}) - set (${_PYTHON_PGR_REGISTRY_PATHS} - [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_PYTHON_VERSION}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath] - [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_PYTHON_VERSION}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath] - [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_PYTHON_VERSION}\\InstallPath] - [HKEY_CURRENT_USER\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_PYTHON_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath] - [HKEY_CURRENT_USER\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_PYTHON_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath] - [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_PYTHON_VERSION}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath] - [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_PYTHON_VERSION}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath] - [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_PYTHON_VERSION}\\InstallPath] - [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_PYTHON_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath] - [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_PYTHON_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath] - PARENT_SCOPE) -endfunction() - - -function (_PYTHON_GET_ABIFLAGS _PGABIFLAGS) - set (abiflags) - list (GET _${_PYTHON_PREFIX}_FIND_ABI 0 pydebug) - list (GET _${_PYTHON_PREFIX}_FIND_ABI 1 pymalloc) - list (GET _${_PYTHON_PREFIX}_FIND_ABI 2 unicode) - - if (pymalloc STREQUAL "ANY" AND unicode STREQUAL "ANY") - set (abiflags "mu" "m" "u" "") - elseif (pymalloc STREQUAL "ANY" AND unicode STREQUAL "ON") - set (abiflags "mu" "u") - elseif (pymalloc STREQUAL "ANY" AND unicode STREQUAL "OFF") - set (abiflags "m" "") - elseif (pymalloc STREQUAL "ON" AND unicode STREQUAL "ANY") - set (abiflags "mu" "m") - elseif (pymalloc STREQUAL "ON" AND unicode STREQUAL "ON") - set (abiflags "mu") - elseif (pymalloc STREQUAL "ON" AND unicode STREQUAL "OFF") - set (abiflags "m") - elseif (pymalloc STREQUAL "ON" AND unicode STREQUAL "ANY") - set (abiflags "u" "") - elseif (pymalloc STREQUAL "OFF" AND unicode STREQUAL "ON") - set (abiflags "u") - endif() - - if (pydebug STREQUAL "ON") - if (abiflags) - list (TRANSFORM abiflags PREPEND "d") - else() - set (abiflags "d") - endif() - elseif (pydebug STREQUAL "ANY") - if (abiflags) - set (flags "${abiflags}") - list (TRANSFORM flags PREPEND "d") - list (APPEND abiflags "${flags}") - else() - set (abiflags "" "d") - endif() - endif() - - set (${_PGABIFLAGS} "${abiflags}" PARENT_SCOPE) -endfunction() - -function (_PYTHON_GET_PATH_SUFFIXES _PYTHON_PGPS_PATH_SUFFIXES) - cmake_parse_arguments (PARSE_ARGV 1 _PGPS "LIBRARY;INCLUDE" "VERSION" "") - - if (DEFINED _${_PYTHON_PREFIX}_ABIFLAGS) - set (abi "${_${_PYTHON_PREFIX}_ABIFLAGS}") - else() - set (abi "mu" "m" "u" "") - endif() - - set (path_suffixes) - if (_PGPS_LIBRARY) - if (CMAKE_LIBRARY_ARCHITECTURE) - list (APPEND path_suffixes lib/${CMAKE_LIBRARY_ARCHITECTURE}) - endif() - list (APPEND path_suffixes lib libs) - - if (CMAKE_LIBRARY_ARCHITECTURE) - set (suffixes "${abi}") - if (suffixes) - list (TRANSFORM suffixes PREPEND "lib/python${_PGPS_VERSION}/config-${_PGPS_VERSION}") - list (TRANSFORM suffixes APPEND "-${CMAKE_LIBRARY_ARCHITECTURE}") - else() - set (suffixes "lib/python${_PGPS_VERSION}/config-${_PGPS_VERSION}-${CMAKE_LIBRARY_ARCHITECTURE}") - endif() - list (APPEND path_suffixes ${suffixes}) - endif() - set (suffixes "${abi}") - if (suffixes) - list (TRANSFORM suffixes PREPEND "lib/python${_PGPS_VERSION}/config-${_PGPS_VERSION}") - else() - set (suffixes "lib/python${_PGPS_VERSION}/config-${_PGPS_VERSION}") - endif() - list (APPEND path_suffixes ${suffixes}) - elseif (_PGPS_INCLUDE) - set (suffixes "${abi}") - if (suffixes) - list (TRANSFORM suffixes PREPEND "include/python${_PGPS_VERSION}") - else() - set (suffixes "include/python${_PGPS_VERSION}") - endif() - list (APPEND path_suffixes ${suffixes} include) - endif() - - set (${_PYTHON_PGPS_PATH_SUFFIXES} ${path_suffixes} PARENT_SCOPE) -endfunction() - -function (_PYTHON_GET_NAMES _PYTHON_PGN_NAMES) - cmake_parse_arguments (PARSE_ARGV 1 _PGN "POSIX;EXECUTABLE;CONFIG;LIBRARY;WIN32;DEBUG" "VERSION" "") - - set (names) - - if (_PGN_WIN32) - string (REPLACE "." "" _PYTHON_VERSION_NO_DOTS ${_PGN_VERSION}) - - set (name python${_PYTHON_VERSION_NO_DOTS}) - if (_PGN_DEBUG) - string (APPEND name "_d") - endif() - - list (APPEND names "${name}") - endif() - - if (_PGN_POSIX) - if (DEFINED _${_PYTHON_PREFIX}_ABIFLAGS) - set (abi "${_${_PYTHON_PREFIX}_ABIFLAGS}") - else() - if (_PGN_EXECUTABLE OR _PGN_CONFIG) - set (abi "") - else() - set (abi "mu" "m" "u" "") - endif() - endif() - - if (abi) - if (_PGN_CONFIG AND DEFINED CMAKE_LIBRARY_ARCHITECTURE) - set (abinames "${abi}") - list (TRANSFORM abinames PREPEND "${CMAKE_LIBRARY_ARCHITECTURE}-python${_PGN_VERSION}") - list (TRANSFORM abinames APPEND "-config") - list (APPEND names ${abinames}) - endif() - set (abinames "${abi}") - list (TRANSFORM abinames PREPEND "python${_PGN_VERSION}") - if (_PGN_CONFIG) - list (TRANSFORM abinames APPEND "-config") - endif() - list (APPEND names ${abinames}) - else() - if (_PGN_CONFIG AND DEFINED CMAKE_LIBRARY_ARCHITECTURE) - set (abinames "${CMAKE_LIBRARY_ARCHITECTURE}-python${_PGN_VERSION}") - endif() - list (APPEND abinames "python${_PGN_VERSION}") - if (_PGN_CONFIG) - list (TRANSFORM abinames APPEND "-config") - endif() - list (APPEND names ${abinames}) - endif() - endif() - - set (${_PYTHON_PGN_NAMES} ${names} PARENT_SCOPE) -endfunction() - -function (_PYTHON_GET_CONFIG_VAR _PYTHON_PGCV_VALUE NAME) - unset (${_PYTHON_PGCV_VALUE} PARENT_SCOPE) - - if (NOT NAME MATCHES "^(PREFIX|ABIFLAGS|CONFIGDIR|INCLUDES|LIBS|SOABI)$") - return() - endif() - - if (_${_PYTHON_PREFIX}_CONFIG) - if (NAME STREQUAL "SOABI") - set (config_flag "--extension-suffix") - else() - set (config_flag "--${NAME}") - endif() - string (TOLOWER "${config_flag}" config_flag) - execute_process (COMMAND "${_${_PYTHON_PREFIX}_CONFIG}" ${config_flag} - RESULT_VARIABLE _result - OUTPUT_VARIABLE _values - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE) - if (_result) - unset (_values) - else() - if (NAME STREQUAL "INCLUDES") - # do some clean-up - string (REGEX MATCHALL "(-I|-iwithsysroot)[ ]*[^ ]+" _values "${_values}") - string (REGEX REPLACE "(-I|-iwithsysroot)[ ]*" "" _values "${_values}") - list (REMOVE_DUPLICATES _values) - elseif (NAME STREQUAL "SOABI") - # clean-up: remove prefix character and suffix - string (REGEX REPLACE "^[.-](.+)(${CMAKE_SHARED_LIBRARY_SUFFIX}|\\.(so|pyd))$" "\\1" _values "${_values}") - endif() - endif() - endif() - - if (_${_PYTHON_PREFIX}_EXECUTABLE AND NOT CMAKE_CROSSCOMPILING) - if (NAME STREQUAL "PREFIX") - execute_process (COMMAND "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c "import sys\ntry:\n from distutils import sysconfig\n sys.stdout.write(';'.join([sysconfig.PREFIX,sysconfig.EXEC_PREFIX,sysconfig.BASE_EXEC_PREFIX]))\nexcept Exception:\n import sysconfig\n sys.stdout.write(';'.join([sysconfig.get_config_var('base') or '', sysconfig.get_config_var('installed_base') or '']))" - RESULT_VARIABLE _result - OUTPUT_VARIABLE _values - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE) - if (_result) - unset (_values) - else() - list (REMOVE_DUPLICATES _values) - endif() - elseif (NAME STREQUAL "INCLUDES") - if (WIN32) - set (_scheme "nt") - else() - set (_scheme "posix_prefix") - endif() - execute_process (COMMAND "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c "import sys\ntry:\n from distutils import sysconfig\n sys.stdout.write(';'.join([sysconfig.get_python_inc(plat_specific=True),sysconfig.get_python_inc(plat_specific=False)]))\nexcept Exception:\n import sysconfig\n sys.stdout.write(';'.join([sysconfig.get_path('platinclude'),sysconfig.get_path('platinclude','${_scheme}'),sysconfig.get_path('include'),sysconfig.get_path('include','${_scheme}')]))" - RESULT_VARIABLE _result - OUTPUT_VARIABLE _values - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE) - if (_result) - unset (_values) - else() - list (REMOVE_DUPLICATES _values) - endif() - elseif (NAME STREQUAL "SOABI") - execute_process (COMMAND "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c "import sys\ntry:\n from distutils import sysconfig\n sys.stdout.write(';'.join([sysconfig.get_config_var('SOABI') or '',sysconfig.get_config_var('EXT_SUFFIX') or '']))\nexcept Exception:\n import sysconfig;sys.stdout.write(';'.join([sysconfig.get_config_var('SOABI') or '',sysconfig.get_config_var('EXT_SUFFIX') or '']))" - RESULT_VARIABLE _result - OUTPUT_VARIABLE _soabi - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE) - if (_result) - unset (_values) - else() - foreach (_item IN LISTS _soabi) - if (_item) - set (_values "${_item}") - break() - endif() - endforeach() - if (_values) - # clean-up: remove prefix character and suffix - string (REGEX REPLACE "^[.-](.+)(${CMAKE_SHARED_LIBRARY_SUFFIX}|\\.(so|pyd))$" "\\1" _values "${_values}") - endif() - endif() - else() - set (config_flag "${NAME}") - if (NAME STREQUAL "CONFIGDIR") - set (config_flag "LIBPL") - endif() - execute_process (COMMAND "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c "import sys\ntry:\n from distutils import sysconfig\n sys.stdout.write(sysconfig.get_config_var('${config_flag}'))\nexcept Exception:\n import sysconfig\n sys.stdout.write(sysconfig.get_config_var('${config_flag}'))" - RESULT_VARIABLE _result - OUTPUT_VARIABLE _values - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE) - if (_result) - unset (_values) - endif() - endif() - endif() - - if (config_flag STREQUAL "ABIFLAGS") - set (${_PYTHON_PGCV_VALUE} "${_values}" PARENT_SCOPE) - return() - endif() - - if (NOT _values OR _values STREQUAL "None") - return() - endif() - - if (NAME STREQUAL "LIBS") - # do some clean-up - string (REGEX MATCHALL "-(l|framework)[ ]*[^ ]+" _values "${_values}") - # remove elements relative to python library itself - list (FILTER _values EXCLUDE REGEX "-lpython") - list (REMOVE_DUPLICATES _values) - endif() - - if (WIN32 AND NAME MATCHES "^(PREFIX|CONFIGDIR|INCLUDES)$") - file (TO_CMAKE_PATH "${_values}" _values) - endif() - - set (${_PYTHON_PGCV_VALUE} "${_values}" PARENT_SCOPE) -endfunction() - -function (_PYTHON_GET_VERSION) - cmake_parse_arguments (PARSE_ARGV 0 _PGV "LIBRARY;INCLUDE" "PREFIX" "") - - unset (${_PGV_PREFIX}VERSION PARENT_SCOPE) - unset (${_PGV_PREFIX}VERSION_MAJOR PARENT_SCOPE) - unset (${_PGV_PREFIX}VERSION_MINOR PARENT_SCOPE) - unset (${_PGV_PREFIX}VERSION_PATCH PARENT_SCOPE) - unset (${_PGV_PREFIX}ABI PARENT_SCOPE) - - if (_PGV_LIBRARY) - # retrieve version and abi from library name - if (_${_PYTHON_PREFIX}_LIBRARY_RELEASE) - # extract version from library name - if (_${_PYTHON_PREFIX}_LIBRARY_RELEASE MATCHES "python([23])([0-9]+)") - set (${_PGV_PREFIX}VERSION_MAJOR "${CMAKE_MATCH_1}" PARENT_SCOPE) - set (${_PGV_PREFIX}VERSION_MINOR "${CMAKE_MATCH_2}" PARENT_SCOPE) - set (${_PGV_PREFIX}VERSION "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}" PARENT_SCOPE) - set (${_PGV_PREFIX}ABI "" PARENT_SCOPE) - elseif (_${_PYTHON_PREFIX}_LIBRARY_RELEASE MATCHES "python([23])\\.([0-9]+)([dmu]*)") - set (${_PGV_PREFIX}VERSION_MAJOR "${CMAKE_MATCH_1}" PARENT_SCOPE) - set (${_PGV_PREFIX}VERSION_MINOR "${CMAKE_MATCH_2}" PARENT_SCOPE) - set (${_PGV_PREFIX}VERSION "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}" PARENT_SCOPE) - set (${_PGV_PREFIX}ABI "${CMAKE_MATCH_3}" PARENT_SCOPE) - endif() - endif() - else() - if (_${_PYTHON_PREFIX}_INCLUDE_DIR) - # retrieve version from header file - file (STRINGS "${_${_PYTHON_PREFIX}_INCLUDE_DIR}/patchlevel.h" version - REGEX "^#define[ \t]+PY_VERSION[ \t]+\"[^\"]+\"") - string (REGEX REPLACE "^#define[ \t]+PY_VERSION[ \t]+\"([^\"]+)\".*" "\\1" - version "${version}") - string (REGEX MATCHALL "[0-9]+" versions "${version}") - list (GET versions 0 version_major) - list (GET versions 1 version_minor) - list (GET versions 2 version_patch) - - set (${_PGV_PREFIX}VERSION "${version_major}.${version_minor}" PARENT_SCOPE) - set (${_PGV_PREFIX}VERSION_MAJOR ${version_major} PARENT_SCOPE) - set (${_PGV_PREFIX}VERSION_MINOR ${version_minor} PARENT_SCOPE) - set (${_PGV_PREFIX}VERSION_PATCH ${version_patch} PARENT_SCOPE) - - # compute ABI flags - if (version_major VERSION_GREATER "2") - file (STRINGS "${_${_PYTHON_PREFIX}_INCLUDE_DIR}/pyconfig.h" config REGEX "(Py_DEBUG|WITH_PYMALLOC|Py_UNICODE_SIZE|MS_WIN32)") - set (abi) - if (config MATCHES "#[ ]*define[ ]+MS_WIN32") - # ABI not used on Windows - set (abi "") - else() - if (config MATCHES "#[ ]*define[ ]+Py_DEBUG[ ]+1") - string (APPEND abi "d") - endif() - if (config MATCHES "#[ ]*define[ ]+WITH_PYMALLOC[ ]+1") - string (APPEND abi "m") - endif() - if (config MATCHES "#[ ]*define[ ]+Py_UNICODE_SIZE[ ]+4") - string (APPEND abi "u") - endif() - set (${_PGV_PREFIX}ABI "${abi}" PARENT_SCOPE) - endif() - else() - # ABI not supported - set (${_PGV_PREFIX}ABI "" PARENT_SCOPE) - endif() - endif() - endif() -endfunction() - - -function (_PYTHON_VALIDATE_INTERPRETER) - if (NOT _${_PYTHON_PREFIX}_EXECUTABLE) - return() - endif() - - cmake_parse_arguments (PARSE_ARGV 0 _PVI "EXACT;CHECK_EXISTS" "" "") - if (_PVI_UNPARSED_ARGUMENTS) - set (expected_version ${_PVI_UNPARSED_ARGUMENTS}) - else() - unset (expected_version) - endif() - - if (_PVI_CHECK_EXISTS AND NOT EXISTS "${_${_PYTHON_PREFIX}_EXECUTABLE}") - # interpreter does not exist anymore - set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Cannot find the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"") - set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND") - return() - endif() - - # validate ABI compatibility - if (DEFINED _${_PYTHON_PREFIX}_FIND_ABI) - execute_process (COMMAND "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c - "import sys; sys.stdout.write(sys.abiflags)" - RESULT_VARIABLE result - OUTPUT_VARIABLE abi - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE) - if (result) - # assume ABI is not supported - set (abi "") - endif() - if (NOT abi IN_LIST _${_PYTHON_PREFIX}_ABIFLAGS) - # incompatible ABI - set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Wrong ABI for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"") - set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND") - return() - endif() - endif() - - get_filename_component (python_name "${_${_PYTHON_PREFIX}_EXECUTABLE}" NAME) - - if (expected_version AND NOT python_name STREQUAL "python${expected_version}${abi}${CMAKE_EXECUTABLE_SUFFIX}") - # executable found must have a specific version - execute_process (COMMAND "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c - "import sys; sys.stdout.write('.'.join([str(x) for x in sys.version_info[:2]]))" - RESULT_VARIABLE result - OUTPUT_VARIABLE version - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE) - if (result) - # interpreter is not usable - set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Cannot use the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"") - set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND") - else() - if (_PVI_EXACT AND NOT version VERSION_EQUAL expected_version) - # interpreter has wrong version - set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Wrong version for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"") - set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND") - else() - # check that version is OK - string(REGEX REPLACE "^([0-9]+)\\..*$" "\\1" major_version "${version}") - string(REGEX REPLACE "^([0-9]+)\\.?.*$" "\\1" expected_major_version "${expected_version}") - if (NOT major_version VERSION_EQUAL expected_major_version - OR NOT version VERSION_GREATER_EQUAL expected_version) - set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Wrong version for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"") - set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND") - endif() - endif() - endif() - if (NOT _${_PYTHON_PREFIX}_EXECUTABLE) - return() - endif() - else() - if (NOT python_name STREQUAL "python${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR}${CMAKE_EXECUTABLE_SUFFIX}") - # executable found do not have version in name - # ensure major version is OK - execute_process (COMMAND "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c - "import sys; sys.stdout.write(str(sys.version_info[0]))" - RESULT_VARIABLE result - OUTPUT_VARIABLE version - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE) - if (result OR NOT version EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR) - # interpreter not usable or has wrong major version - if (result) - set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Cannot use the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"") - else() - set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Wrong major version for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"") - endif() - set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND") - return() - endif() - endif() - endif() - - if (CMAKE_SIZEOF_VOID_P AND ("Development.Module" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS - OR "Development.Embed" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) - AND NOT CMAKE_CROSSCOMPILING) - # In this case, interpreter must have same architecture as environment - execute_process (COMMAND "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c - "import sys, struct; sys.stdout.write(str(struct.calcsize(\"P\")))" - RESULT_VARIABLE result - OUTPUT_VARIABLE size - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE) - if (result OR NOT size EQUAL CMAKE_SIZEOF_VOID_P) - # interpreter not usable or has wrong architecture - if (result) - set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Cannot use the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"") - else() - set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Wrong architecture for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"") - endif() - set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND") - return() - endif() - endif() -endfunction() - - -function (_PYTHON_VALIDATE_COMPILER expected_version) - if (NOT _${_PYTHON_PREFIX}_COMPILER) - return() - endif() - - cmake_parse_arguments (_PVC "EXACT;CHECK_EXISTS" "" "" ${ARGN}) - if (_PVC_UNPARSED_ARGUMENTS) - set (major_version FALSE) - set (expected_version ${_PVC_UNPARSED_ARGUMENTS}) - else() - set (major_version TRUE) - set (expected_version ${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR}) - set (_PVC_EXACT TRUE) - endif() - - if (_PVC_CHECK_EXISTS AND NOT EXISTS "${_${_PYTHON_PREFIX}_COMPILER}") - # Compiler does not exist anymore - set (_${_PYTHON_PREFIX}_Compiler_REASON_FAILURE "Cannot find the compiler \"${_${_PYTHON_PREFIX}_COMPILER}\"") - set_property (CACHE _${_PYTHON_PREFIX}_COMPILER PROPERTY VALUE "${_PYTHON_PREFIX}_COMPILER-NOTFOUND") - return() - endif() - - # retrieve python environment version from compiler - set (working_dir "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/PythonCompilerVersion.dir") - if (major_version) - # check only major version - file (WRITE "${working_dir}/version.py" "import sys; sys.stdout.write(str(sys.version_info[0]))") - else() - file (WRITE "${working_dir}/version.py" "import sys; sys.stdout.write('.'.join([str(x) for x in sys.version_info[:2]]))\n") - endif() - execute_process (COMMAND "${_${_PYTHON_PREFIX}_COMPILER}" /target:exe /embed "${working_dir}/version.py" - WORKING_DIRECTORY "${working_dir}" - OUTPUT_QUIET - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE) - execute_process (COMMAND "${working_dir}/version" - WORKING_DIRECTORY "${working_dir}" - RESULT_VARIABLE result - OUTPUT_VARIABLE version - ERROR_QUIET) - file (REMOVE_RECURSE "${_${_PYTHON_PREFIX}_VERSION_DIR}") - - if (result OR (_PVC_EXACT AND NOT version VERSION_EQUAL expected_version) OR (version VERSION_LESS expected_version)) - # Compiler not usable or has wrong version - if (result) - set (_${_PYTHON_PREFIX}_Compiler_REASON_FAILURE "Cannot use the compiler \"${_${_PYTHON_PREFIX}_COMPILER}\"") - else() - set (_${_PYTHON_PREFIX}_Compiler_REASON_FAILURE "Wrong version for the compiler \"${_${_PYTHON_PREFIX}_COMPILER}\"") - endif() - set_property (CACHE _${_PYTHON_PREFIX}_COMPILER PROPERTY VALUE "${_PYTHON_PREFIX}_COMPILER-NOTFOUND") - endif() -endfunction() - - -function (_PYTHON_VALIDATE_LIBRARY) - if (NOT _${_PYTHON_PREFIX}_LIBRARY_RELEASE) - unset (_${_PYTHON_PREFIX}_LIBRARY_DEBUG) - return() - endif() - - cmake_parse_arguments (PARSE_ARGV 0 _PVL "EXACT;CHECK_EXISTS" "" "") - if (_PVL_UNPARSED_ARGUMENTS) - set (expected_version ${_PVL_UNPARSED_ARGUMENTS}) - else() - unset (expected_version) - endif() - - if (_PVL_CHECK_EXISTS AND NOT EXISTS "${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}") - # library does not exist anymore - set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Cannot find the library \"${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}\"") - set_property (CACHE _${_PYTHON_PREFIX}_LIBRARY_RELEASE PROPERTY VALUE "${_PYTHON_PREFIX}_LIBRARY_RELEASE-NOTFOUND") - if (WIN32) - set_property (CACHE _${_PYTHON_PREFIX}_LIBRARY_DEBUG PROPERTY VALUE "${_PYTHON_PREFIX}_LIBRARY_DEBUG-NOTFOUND") - endif() - set_property (CACHE _${_PYTHON_PREFIX}_INCLUDE_DIR PROPERTY VALUE "${_PYTHON_PREFIX}_INCLUDE_DIR-NOTFOUND") - return() - endif() - - # retrieve version and abi from library name - _python_get_version (LIBRARY PREFIX lib_) - - if (DEFINED _${_PYTHON_PREFIX}_FIND_ABI AND NOT lib_ABI IN_LIST _${_PYTHON_PREFIX}_ABIFLAGS) - # incompatible ABI - set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Wrong ABI for the library \"${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}\"") - set_property (CACHE _${_PYTHON_PREFIX}_LIBRARY_RELEASE PROPERTY VALUE "${_PYTHON_PREFIX}_LIBRARY_RELEASE-NOTFOUND") - else() - if (expected_version) - if ((_PVL_EXACT AND NOT lib_VERSION VERSION_EQUAL expected_version) OR (lib_VERSION VERSION_LESS expected_version)) - # library has wrong version - set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Wrong version for the library \"${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}\"") - set_property (CACHE _${_PYTHON_PREFIX}_LIBRARY_RELEASE PROPERTY VALUE "${_PYTHON_PREFIX}_LIBRARY_RELEASE-NOTFOUND") - endif() - else() - if (NOT lib_VERSION_MAJOR VERSION_EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR) - # library has wrong major version - set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Wrong major version for the library \"${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}\"") - set_property (CACHE _${_PYTHON_PREFIX}_LIBRARY_RELEASE PROPERTY VALUE "${_PYTHON_PREFIX}_LIBRARY_RELEASE-NOTFOUND") - endif() - endif() - endif() - - if (NOT _${_PYTHON_PREFIX}_LIBRARY_RELEASE) - if (WIN32) - set_property (CACHE _${_PYTHON_PREFIX}_LIBRARY_DEBUG PROPERTY VALUE "${_PYTHON_PREFIX}_LIBRARY_DEBUG-NOTFOUND") - endif() - unset (_${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE CACHE) - unset (_${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG CACHE) - set_property (CACHE _${_PYTHON_PREFIX}_INCLUDE_DIR PROPERTY VALUE "${_PYTHON_PREFIX}_INCLUDE_DIR-NOTFOUND") - endif() -endfunction() - - -function (_PYTHON_VALIDATE_INCLUDE_DIR) - if (NOT _${_PYTHON_PREFIX}_INCLUDE_DIR) - return() - endif() - - cmake_parse_arguments (PARSE_ARGV 0 _PVID "EXACT;CHECK_EXISTS" "" "") - if (_PVID_UNPARSED_ARGUMENTS) - set (expected_version ${_PVID_UNPARSED_ARGUMENTS}) - else() - unset (expected_version) - endif() - - if (_PVID_CHECK_EXISTS AND NOT EXISTS "${_${_PYTHON_PREFIX}_INCLUDE_DIR}") - # include file does not exist anymore - set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Cannot find the directory \"${_${_PYTHON_PREFIX}_INCLUDE_DIR}\"") - set_property (CACHE _${_PYTHON_PREFIX}_INCLUDE_DIR PROPERTY VALUE "${_PYTHON_PREFIX}_INCLUDE_DIR-NOTFOUND") - return() - endif() - - # retrieve version from header file - _python_get_version (INCLUDE PREFIX inc_) - - if (DEFINED _${_PYTHON_PREFIX}_FIND_ABI AND NOT inc_ABI IN_LIST _${_PYTHON_PREFIX}_ABIFLAGS) - # incompatible ABI - set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Wrong ABI for the directory \"${_${_PYTHON_PREFIX}_INCLUDE_DIR}\"") - set_property (CACHE _${_PYTHON_PREFIX}_INCLUDE_DIR PROPERTY VALUE "${_PYTHON_PREFIX}_INCLUDE_DIR-NOTFOUND") - else() - if (expected_version) - if ((_PVID_EXACT AND NOT inc_VERSION VERSION_EQUAL expected_version) OR (inc_VERSION VERSION_LESS expected_version)) - # include dir has wrong version - set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Wrong version for the directory \"${_${_PYTHON_PREFIX}_INCLUDE_DIR}\"") - set_property (CACHE _${_PYTHON_PREFIX}_INCLUDE_DIR PROPERTY VALUE "${_PYTHON_PREFIX}_INCLUDE_DIR-NOTFOUND") - endif() - else() - if (NOT inc_VERSION_MAJOR VERSION_EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR) - # include dir has wrong major version - set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Wrong major version for the directory \"${_${_PYTHON_PREFIX}_INCLUDE_DIR}\"") - set_property (CACHE _${_PYTHON_PREFIX}_INCLUDE_DIR PROPERTY VALUE "${_PYTHON_PREFIX}_INCLUDE_DIR-NOTFOUND") - endif() - endif() - endif() -endfunction() - - -function (_PYTHON_FIND_RUNTIME_LIBRARY _PYTHON_LIB) - string (REPLACE "_RUNTIME" "" _PYTHON_LIB "${_PYTHON_LIB}") - # look at runtime part on systems supporting it - if (CMAKE_SYSTEM_NAME STREQUAL "Windows" OR - (CMAKE_SYSTEM_NAME MATCHES "MSYS|CYGWIN" - AND ${_PYTHON_LIB} MATCHES "${CMAKE_IMPORT_LIBRARY_SUFFIX}$")) - set (CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_SHARED_LIBRARY_SUFFIX}) - # MSYS has a special syntax for runtime libraries - if (CMAKE_SYSTEM_NAME MATCHES "MSYS") - list (APPEND CMAKE_FIND_LIBRARY_PREFIXES "msys-") - endif() - find_library (${ARGV}) - endif() -endfunction() - - -function (_PYTHON_SET_LIBRARY_DIRS _PYTHON_SLD_RESULT) - unset (_PYTHON_DIRS) - set (_PYTHON_LIBS ${ARGN}) - foreach (_PYTHON_LIB IN LISTS _PYTHON_LIBS) - if (${_PYTHON_LIB}) - get_filename_component (_PYTHON_DIR "${${_PYTHON_LIB}}" DIRECTORY) - list (APPEND _PYTHON_DIRS "${_PYTHON_DIR}") - endif() - endforeach() - list (REMOVE_DUPLICATES _PYTHON_DIRS) - set (${_PYTHON_SLD_RESULT} ${_PYTHON_DIRS} PARENT_SCOPE) -endfunction() - - -function (_PYTHON_SET_DEVELOPMENT_MODULE_FOUND module) - if ("Development.${module}" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) - string(TOUPPER "${module}" id) - set (module_found TRUE) - - if ("LIBRARY" IN_LIST _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_${id}_ARTIFACTS - AND NOT _${_PYTHON_PREFIX}_LIBRARY_RELEASE) - set (module_found FALSE) - endif() - if ("INCLUDE_DIR" IN_LIST _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_${id}_ARTIFACTS - AND NOT _${_PYTHON_PREFIX}_INCLUDE_DIR) - set (module_found FALSE) - endif() - - set (${_PYTHON_PREFIX}_Development.${module}_FOUND ${module_found} PARENT_SCOPE) - endif() -endfunction() - - -# If major version is specified, it must be the same as internal major version -if (DEFINED ${_PYTHON_PREFIX}_FIND_VERSION_MAJOR - AND NOT ${_PYTHON_PREFIX}_FIND_VERSION_MAJOR VERSION_EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR) - _python_display_failure ("Could NOT find ${_PYTHON_PREFIX}: Wrong major version specified is \"${${_PYTHON_PREFIX}_FIND_VERSION_MAJOR}\", but expected major version is \"${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR}\"") -endif() - - -# handle components -if (NOT ${_PYTHON_PREFIX}_FIND_COMPONENTS) - set (${_PYTHON_PREFIX}_FIND_COMPONENTS Interpreter) - set (${_PYTHON_PREFIX}_FIND_REQUIRED_Interpreter TRUE) -endif() -if ("NumPy" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) - list (APPEND ${_PYTHON_PREFIX}_FIND_COMPONENTS "Interpreter" "Development.Module") -endif() -if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) - list (APPEND ${_PYTHON_PREFIX}_FIND_COMPONENTS "Development.Module" "Development.Embed") -endif() -list (REMOVE_DUPLICATES ${_PYTHON_PREFIX}_FIND_COMPONENTS) -foreach (_${_PYTHON_PREFIX}_COMPONENT IN ITEMS Interpreter Compiler Development Development.Module Development.Embed NumPy) - set (${_PYTHON_PREFIX}_${_${_PYTHON_PREFIX}_COMPONENT}_FOUND FALSE) -endforeach() -if (${_PYTHON_PREFIX}_FIND_REQUIRED_Development) - set (${_PYTHON_PREFIX}_FIND_REQUIRED_Development.Module TRUE) - set (${_PYTHON_PREFIX}_FIND_REQUIRED_Development.Embed TRUE) -endif() - -unset (_${_PYTHON_PREFIX}_FIND_DEVELOPMENT_ARTIFACTS) -unset (_${_PYTHON_PREFIX}_FIND_DEVELOPMENT_MODULE_ARTIFACTS) -unset (_${_PYTHON_PREFIX}_FIND_DEVELOPMENT_EMBED_ARTIFACTS) -if ("Development.Module" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) - if (CMAKE_SYSTEM_NAME MATCHES "^(Windows.*|CYGWIN|MSYS)$") - list (APPEND _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_MODULE_ARTIFACTS "LIBRARY") - endif() - list (APPEND _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_MODULE_ARTIFACTS "INCLUDE_DIR") -endif() -if ("Development.Embed" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) - list (APPEND _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_EMBED_ARTIFACTS "LIBRARY" "INCLUDE_DIR") -endif() -set (_${_PYTHON_PREFIX}_FIND_DEVELOPMENT_ARTIFACTS ${_${_PYTHON_PREFIX}_FIND_DEVELOPMENT_MODULE_ARTIFACTS} ${_${_PYTHON_PREFIX}_FIND_DEVELOPMENT_EMBED_ARTIFACTS}) -list (REMOVE_DUPLICATES _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_ARTIFACTS) - -unset (_${_PYTHON_PREFIX}_FIND_VERSIONS) - -# Set versions to search -## default: search any version -set (_${_PYTHON_PREFIX}_FIND_VERSIONS ${_${_PYTHON_PREFIX}_VERSIONS}) - -if (${_PYTHON_PREFIX}_FIND_VERSION_COUNT GREATER "1") - if (${_PYTHON_PREFIX}_FIND_VERSION_EXACT) - set (_${_PYTHON_PREFIX}_FIND_VERSIONS ${${_PYTHON_PREFIX}_FIND_VERSION_MAJOR}.${${_PYTHON_PREFIX}_FIND_VERSION_MINOR}) - else() - unset (_${_PYTHON_PREFIX}_FIND_VERSIONS) - # add all compatible versions - foreach (_${_PYTHON_PREFIX}_VERSION IN LISTS _${_PYTHON_PREFIX}_VERSIONS) - if (_${_PYTHON_PREFIX}_VERSION VERSION_GREATER_EQUAL ${_PYTHON_PREFIX}_FIND_VERSION) - list (APPEND _${_PYTHON_PREFIX}_FIND_VERSIONS ${_${_PYTHON_PREFIX}_VERSION}) - endif() - endforeach() - endif() -endif() - -# Set ABIs to search -## default: search any ABI -if (_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR VERSION_LESS "3") - # ABI not supported - unset (_${_PYTHON_PREFIX}_FIND_ABI) - set (_${_PYTHON_PREFIX}_ABIFLAGS "") -else() - unset (_${_PYTHON_PREFIX}_FIND_ABI) - unset (_${_PYTHON_PREFIX}_ABIFLAGS) - if (DEFINED ${_PYTHON_PREFIX}_FIND_ABI) - # normalization - string (TOUPPER "${${_PYTHON_PREFIX}_FIND_ABI}" _${_PYTHON_PREFIX}_FIND_ABI) - list (TRANSFORM _${_PYTHON_PREFIX}_FIND_ABI REPLACE "^(TRUE|Y(ES)?|1)$" "ON") - list (TRANSFORM _${_PYTHON_PREFIX}_FIND_ABI REPLACE "^(FALSE|N(O)?|0)$" "OFF") - if (NOT _${_PYTHON_PREFIX}_FIND_ABI MATCHES "^(ON|OFF|ANY);(ON|OFF|ANY);(ON|OFF|ANY)$") - message (AUTHOR_WARNING "Find${_PYTHON_PREFIX}: ${${_PYTHON_PREFIX}_FIND_ABI}: invalid value for '${_PYTHON_PREFIX}_FIND_ABI'. Ignore it") - unset (_${_PYTHON_PREFIX}_FIND_ABI) - endif() - _python_get_abiflags (_${_PYTHON_PREFIX}_ABIFLAGS) - endif() -endif() -unset (${_PYTHON_PREFIX}_SOABI) - -# Define lookup strategy -if (_${_PYTHON_PREFIX}_LOOKUP_POLICY STREQUAL "NEW") - set (_${_PYTHON_PREFIX}_FIND_STRATEGY "LOCATION") -else() - set (_${_PYTHON_PREFIX}_FIND_STRATEGY "VERSION") -endif() -if (DEFINED ${_PYTHON_PREFIX}_FIND_STRATEGY) - if (NOT ${_PYTHON_PREFIX}_FIND_STRATEGY MATCHES "^(VERSION|LOCATION)$") - message (AUTHOR_WARNING "Find${_PYTHON_PREFIX}: ${${_PYTHON_PREFIX}_FIND_STRATEGY}: invalid value for '${_PYTHON_PREFIX}_FIND_STRATEGY'. 'VERSION' or 'LOCATION' expected.") - set (_${_PYTHON_PREFIX}_FIND_STRATEGY "VERSION") - else() - set (_${_PYTHON_PREFIX}_FIND_STRATEGY "${${_PYTHON_PREFIX}_FIND_STRATEGY}") - endif() -endif() - -# Python and Anaconda distributions: define which architectures can be used -if (CMAKE_SIZEOF_VOID_P) - # In this case, search only for 64bit or 32bit - math (EXPR _${_PYTHON_PREFIX}_ARCH "${CMAKE_SIZEOF_VOID_P} * 8") - set (_${_PYTHON_PREFIX}_ARCH2 ${_${_PYTHON_PREFIX}_ARCH}) -else() - # architecture unknown, search for both 64bit and 32bit - set (_${_PYTHON_PREFIX}_ARCH 64) - set (_${_PYTHON_PREFIX}_ARCH2 32) -endif() - -# IronPython support -if (CMAKE_SIZEOF_VOID_P) - # In this case, search only for 64bit or 32bit - math (EXPR _${_PYTHON_PREFIX}_ARCH "${CMAKE_SIZEOF_VOID_P} * 8") - set (_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES ipy${_${_PYTHON_PREFIX}_ARCH} ipy) -else() - # architecture unknown, search for natural interpreter - set (_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES ipy) -endif() -set (_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES net45 net40) - -# Apple frameworks handling -_python_find_frameworks () - -set (_${_PYTHON_PREFIX}_FIND_FRAMEWORK "FIRST") - -if (DEFINED ${_PYTHON_PREFIX}_FIND_FRAMEWORK) - if (NOT ${_PYTHON_PREFIX}_FIND_FRAMEWORK MATCHES "^(FIRST|LAST|NEVER)$") - message (AUTHOR_WARNING "Find${_PYTHON_PREFIX}: ${${_PYTHON_PREFIX}_FIND_FRAMEWORK}: invalid value for '${_PYTHON_PREFIX}_FIND_FRAMEWORK'. 'FIRST', 'LAST' or 'NEVER' expected. 'FIRST' will be used instead.") - else() - set (_${_PYTHON_PREFIX}_FIND_FRAMEWORK ${${_PYTHON_PREFIX}_FIND_FRAMEWORK}) - endif() -elseif (DEFINED CMAKE_FIND_FRAMEWORK) - if (CMAKE_FIND_FRAMEWORK STREQUAL "ONLY") - message (AUTHOR_WARNING "Find${_PYTHON_PREFIX}: CMAKE_FIND_FRAMEWORK: 'ONLY' value is not supported. 'FIRST' will be used instead.") - elseif (NOT CMAKE_FIND_FRAMEWORK MATCHES "^(FIRST|LAST|NEVER)$") - message (AUTHOR_WARNING "Find${_PYTHON_PREFIX}: ${CMAKE_FIND_FRAMEWORK}: invalid value for 'CMAKE_FIND_FRAMEWORK'. 'FIRST', 'LAST' or 'NEVER' expected. 'FIRST' will be used instead.") - else() - set (_${_PYTHON_PREFIX}_FIND_FRAMEWORK ${CMAKE_FIND_FRAMEWORK}) - endif() -endif() - -# Save CMAKE_FIND_APPBUNDLE -if (DEFINED CMAKE_FIND_APPBUNDLE) - set (_${_PYTHON_PREFIX}_CMAKE_FIND_APPBUNDLE ${CMAKE_FIND_APPBUNDLE}) -else() - unset (_${_PYTHON_PREFIX}_CMAKE_FIND_APPBUNDLE) -endif() -# To avoid app bundle lookup -set (CMAKE_FIND_APPBUNDLE "NEVER") - -# Save CMAKE_FIND_FRAMEWORK -if (DEFINED CMAKE_FIND_FRAMEWORK) - set (_${_PYTHON_PREFIX}_CMAKE_FIND_FRAMEWORK ${CMAKE_FIND_FRAMEWORK}) -else() - unset (_${_PYTHON_PREFIX}_CMAKE_FIND_FRAMEWORK) -endif() -# To avoid framework lookup -set (CMAKE_FIND_FRAMEWORK "NEVER") - -# Windows Registry handling -if (DEFINED ${_PYTHON_PREFIX}_FIND_REGISTRY) - if (NOT ${_PYTHON_PREFIX}_FIND_REGISTRY MATCHES "^(FIRST|LAST|NEVER)$") - message (AUTHOR_WARNING "Find${_PYTHON_PREFIX}: ${${_PYTHON_PREFIX}_FIND_REGISTRY}: invalid value for '${_PYTHON_PREFIX}_FIND_REGISTRY'. 'FIRST', 'LAST' or 'NEVER' expected. 'FIRST' will be used instead.") - set (_${_PYTHON_PREFIX}_FIND_REGISTRY "FIRST") - else() - set (_${_PYTHON_PREFIX}_FIND_REGISTRY ${${_PYTHON_PREFIX}_FIND_REGISTRY}) - endif() -else() - set (_${_PYTHON_PREFIX}_FIND_REGISTRY "FIRST") -endif() - -# virtual environments recognition -if (DEFINED ENV{VIRTUAL_ENV} OR DEFINED ENV{CONDA_PREFIX}) - if (DEFINED ${_PYTHON_PREFIX}_FIND_VIRTUALENV) - if (NOT ${_PYTHON_PREFIX}_FIND_VIRTUALENV MATCHES "^(FIRST|ONLY|STANDARD)$") - message (AUTHOR_WARNING "Find${_PYTHON_PREFIX}: ${${_PYTHON_PREFIX}_FIND_VIRTUALENV}: invalid value for '${_PYTHON_PREFIX}_FIND_VIRTUALENV'. 'FIRST', 'ONLY' or 'STANDARD' expected. 'FIRST' will be used instead.") - set (_${_PYTHON_PREFIX}_FIND_VIRTUALENV "FIRST") - else() - set (_${_PYTHON_PREFIX}_FIND_VIRTUALENV ${${_PYTHON_PREFIX}_FIND_VIRTUALENV}) - endif() - else() - set (_${_PYTHON_PREFIX}_FIND_VIRTUALENV FIRST) - endif() -else() - set (_${_PYTHON_PREFIX}_FIND_VIRTUALENV STANDARD) -endif() - - -# Compute search signature -# This signature will be used to check validity of cached variables on new search -set (_${_PYTHON_PREFIX}_SIGNATURE "${${_PYTHON_PREFIX}_ROOT_DIR}:${_${_PYTHON_PREFIX}_FIND_STRATEGY}:${${_PYTHON_PREFIX}_FIND_VIRTUALENV}") -if (NOT WIN32) - string (APPEND _${_PYTHON_PREFIX}_SIGNATURE ":${${_PYTHON_PREFIX}_USE_STATIC_LIBS}:") -endif() -if (CMAKE_HOST_APPLE) - string (APPEND _${_PYTHON_PREFIX}_SIGNATURE ":${_${_PYTHON_PREFIX}_FIND_FRAMEWORK}") -endif() -if (CMAKE_HOST_WIN32) - string (APPEND _${_PYTHON_PREFIX}_SIGNATURE ":${_${_PYTHON_PREFIX}_FIND_REGISTRY}") -endif() - -function (_PYTHON_CHECK_DEVELOPMENT_SIGNATURE module) - if ("Development.${module}" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) - string (TOUPPER "${module}" id) - set (signature "${_${_PYTHON_PREFIX}_SIGNATURE}:") - if ("LIBRARY" IN_LIST _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_${id}_ARTIFACTS) - list (APPEND signature "${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}:") - endif() - if ("INCLUDE_DIR" IN_LIST _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_${id}_ARTIFACTS) - list (APPEND signature "${_${_PYTHON_PREFIX}_INCLUDE_DIR}:") - endif() - string (MD5 signature "${signature}") - if (signature STREQUAL _${_PYTHON_PREFIX}_DEVELOPMENT_${id}_SIGNATURE) - if (${_PYTHON_PREFIX}_FIND_VERSION_EXACT) - set (exact EXACT) - endif() - if ("LIBRARY" IN_LIST _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_${id}_ARTIFACTS) - _python_validate_library (${${_PYTHON_PREFIX}_FIND_VERSION} ${exact} CHECK_EXISTS) - endif() - if ("INCLUDE_DIR" IN_LIST _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_${id}_ARTIFACTS) - _python_validate_include_dir (${${_PYTHON_PREFIX}_FIND_VERSION} ${exact} CHECK_EXISTS) - endif() - else() - if ("LIBRARY" IN_LIST _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_${id}_ARTIFACTS) - unset (_${_PYTHON_PREFIX}_LIBRARY_RELEASE CACHE) - unset (_${_PYTHON_PREFIX}_LIBRARY_DEBUG CACHE) - endif() - if ("INCLUDE_DIR" IN_LIST _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_${id}_ARTIFACTS) - unset (_${_PYTHON_PREFIX}_INCLUDE_DIR CACHE) - endif() - endif() - if (("LIBRARY" IN_LIST _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_${id}_ARTIFACTS - AND NOT _${_PYTHON_PREFIX}_LIBRARY_RELEASE) - OR ("INCLUDE_DIR" IN_LIST _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_${id}_ARTIFACTS - AND NOT _${_PYTHON_PREFIX}_INCLUDE_DIR)) - unset (_${_PYTHON_PREFIX}_CONFIG CACHE) - unset (_${_PYTHON_PREFIX}_DEVELOPMENT_${id}_SIGNATURE CACHE) - endif() - endif() -endfunction() - -function (_PYTHON_COMPUTE_DEVELOPMENT_SIGNATURE module) - string (TOUPPER "${module}" id) - if (${_PYTHON_PREFIX}_Development.${module}_FOUND) - set (signature "${_${_PYTHON_PREFIX}_SIGNATURE}:") - if ("LIBRARY" IN_LIST _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_${id}_ARTIFACTS) - list (APPEND signature "${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}:") - endif() - if ("INCLUDE_DIR" IN_LIST _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_${id}_ARTIFACTS) - list (APPEND signature "${_${_PYTHON_PREFIX}_INCLUDE_DIR}:") - endif() - string (MD5 signature "${signature}") - set (_${_PYTHON_PREFIX}_DEVELOPMENT_${id}_SIGNATURE "${signature}" CACHE INTERNAL "") - else() - unset (_${_PYTHON_PREFIX}_DEVELOPMENT_${id}_SIGNATURE CACHE) - endif() -endfunction() - - -unset (_${_PYTHON_PREFIX}_REQUIRED_VARS) -unset (_${_PYTHON_PREFIX}_CACHED_VARS) -unset (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE) -unset (_${_PYTHON_PREFIX}_Compiler_REASON_FAILURE) -unset (_${_PYTHON_PREFIX}_Development_REASON_FAILURE) -unset (_${_PYTHON_PREFIX}_NumPy_REASON_FAILURE) - - -# first step, search for the interpreter -if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) - list (APPEND _${_PYTHON_PREFIX}_CACHED_VARS _${_PYTHON_PREFIX}_EXECUTABLE) - if (${_PYTHON_PREFIX}_FIND_REQUIRED_Interpreter) - list (APPEND _${_PYTHON_PREFIX}_REQUIRED_VARS ${_PYTHON_PREFIX}_EXECUTABLE) - endif() - - if (DEFINED ${_PYTHON_PREFIX}_EXECUTABLE - AND IS_ABSOLUTE "${${_PYTHON_PREFIX}_EXECUTABLE}") - if (NOT ${_PYTHON_PREFIX}_EXECUTABLE STREQUAL _${_PYTHON_PREFIX}_EXECUTABLE) - # invalidate cache properties - unset (_${_PYTHON_PREFIX}_INTERPRETER_PROPERTIES CACHE) - endif() - set (_${_PYTHON_PREFIX}_EXECUTABLE "${${_PYTHON_PREFIX}_EXECUTABLE}" CACHE INTERNAL "") - elseif (DEFINED _${_PYTHON_PREFIX}_EXECUTABLE) - # compute interpreter signature and check validity of definition - string (MD5 __${_PYTHON_PREFIX}_INTERPRETER_SIGNATURE "${_${_PYTHON_PREFIX}_SIGNATURE}:${_${_PYTHON_PREFIX}_EXECUTABLE}") - if (__${_PYTHON_PREFIX}_INTERPRETER_SIGNATURE STREQUAL _${_PYTHON_PREFIX}_INTERPRETER_SIGNATURE) - # check version validity - if (${_PYTHON_PREFIX}_FIND_VERSION_EXACT) - _python_validate_interpreter (${${_PYTHON_PREFIX}_FIND_VERSION} EXACT CHECK_EXISTS) - else() - _python_validate_interpreter (${${_PYTHON_PREFIX}_FIND_VERSION} CHECK_EXISTS) - endif() - else() - unset (_${_PYTHON_PREFIX}_EXECUTABLE CACHE) - endif() - if (NOT _${_PYTHON_PREFIX}_EXECUTABLE) - unset (_${_PYTHON_PREFIX}_INTERPRETER_SIGNATURE CACHE) - unset (_${_PYTHON_PREFIX}_INTERPRETER_PROPERTIES CACHE) - endif() - endif() - - if (NOT _${_PYTHON_PREFIX}_EXECUTABLE) - set (_${_PYTHON_PREFIX}_HINTS "${${_PYTHON_PREFIX}_ROOT_DIR}" ENV ${_PYTHON_PREFIX}_ROOT_DIR) - - if (_${_PYTHON_PREFIX}_FIND_STRATEGY STREQUAL "LOCATION") - unset (_${_PYTHON_PREFIX}_NAMES) - unset (_${_PYTHON_PREFIX}_FRAMEWORK_PATHS) - unset (_${_PYTHON_PREFIX}_REGISTRY_PATHS) - - foreach (_${_PYTHON_PREFIX}_VERSION IN LISTS _${_PYTHON_PREFIX}_FIND_VERSIONS) - # build all executable names - _python_get_names (_${_PYTHON_PREFIX}_VERSION_NAMES VERSION ${_${_PYTHON_PREFIX}_VERSION} POSIX EXECUTABLE) - list (APPEND _${_PYTHON_PREFIX}_NAMES ${_${_PYTHON_PREFIX}_VERSION_NAMES}) - - # Framework Paths - _python_get_frameworks (_${_PYTHON_PREFIX}_VERSION_PATHS ${_${_PYTHON_PREFIX}_VERSION}) - list (APPEND _${_PYTHON_PREFIX}_FRAMEWORK_PATHS ${_${_PYTHON_PREFIX}_VERSION_PATHS}) - - # Registry Paths - _python_get_registries (_${_PYTHON_PREFIX}_VERSION_PATHS ${_${_PYTHON_PREFIX}_VERSION}) - list (APPEND _${_PYTHON_PREFIX}_REGISTRY_PATHS ${_${_PYTHON_PREFIX}_VERSION_PATHS} - [HKEY_LOCAL_MACHINE\\SOFTWARE\\IronPython\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath]) - endforeach() - list (APPEND _${_PYTHON_PREFIX}_NAMES python${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR} python) - - while (TRUE) - # Virtual environments handling - if (_${_PYTHON_PREFIX}_FIND_VIRTUALENV MATCHES "^(FIRST|ONLY)$") - find_program (_${_PYTHON_PREFIX}_EXECUTABLE - NAMES ${_${_PYTHON_PREFIX}_NAMES} - NAMES_PER_DIR - HINTS ${_${_PYTHON_PREFIX}_HINTS} - PATHS ENV VIRTUAL_ENV ENV CONDA_PREFIX - PATH_SUFFIXES bin Scripts - NO_CMAKE_PATH - NO_CMAKE_ENVIRONMENT_PATH - NO_SYSTEM_ENVIRONMENT_PATH - NO_CMAKE_SYSTEM_PATH) - - _python_validate_interpreter (${${_PYTHON_PREFIX}_FIND_VERSION}) - if (_${_PYTHON_PREFIX}_EXECUTABLE) - break() - endif() - if (_${_PYTHON_PREFIX}_FIND_VIRTUALENV STREQUAL "ONLY") - break() - endif() - endif() - - # Apple frameworks handling - if (CMAKE_HOST_APPLE AND _${_PYTHON_PREFIX}_FIND_FRAMEWORK STREQUAL "FIRST") - find_program (_${_PYTHON_PREFIX}_EXECUTABLE - NAMES ${_${_PYTHON_PREFIX}_NAMES} - NAMES_PER_DIR - HINTS ${_${_PYTHON_PREFIX}_HINTS} - PATHS ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS} - PATH_SUFFIXES bin - NO_CMAKE_PATH - NO_CMAKE_ENVIRONMENT_PATH - NO_SYSTEM_ENVIRONMENT_PATH - NO_CMAKE_SYSTEM_PATH) - _python_validate_interpreter (${${_PYTHON_PREFIX}_FIND_VERSION}) - if (_${_PYTHON_PREFIX}_EXECUTABLE) - break() - endif() - endif() - # Windows registry - if (CMAKE_HOST_WIN32 AND _${_PYTHON_PREFIX}_FIND_REGISTRY STREQUAL "FIRST") - find_program (_${_PYTHON_PREFIX}_EXECUTABLE - NAMES ${_${_PYTHON_PREFIX}_NAMES} - ${_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES} - NAMES_PER_DIR - HINTS ${_${_PYTHON_PREFIX}_HINTS} - PATHS ${_${_PYTHON_PREFIX}_REGISTRY_PATHS} - PATH_SUFFIXES bin ${_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES} - NO_SYSTEM_ENVIRONMENT_PATH - NO_CMAKE_SYSTEM_PATH) - _python_validate_interpreter (${${_PYTHON_PREFIX}_FIND_VERSION}) - if (_${_PYTHON_PREFIX}_EXECUTABLE) - break() - endif() - endif() - - # try using HINTS - find_program (_${_PYTHON_PREFIX}_EXECUTABLE - NAMES ${_${_PYTHON_PREFIX}_NAMES} - ${_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES} - NAMES_PER_DIR - HINTS ${_${_PYTHON_PREFIX}_HINTS} - PATH_SUFFIXES bin ${_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES} - NO_SYSTEM_ENVIRONMENT_PATH - NO_CMAKE_SYSTEM_PATH) - _python_validate_interpreter (${${_PYTHON_PREFIX}_FIND_VERSION}) - if (_${_PYTHON_PREFIX}_EXECUTABLE) - break() - endif() - # try using standard paths - find_program (_${_PYTHON_PREFIX}_EXECUTABLE - NAMES ${_${_PYTHON_PREFIX}_NAMES} - ${_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES} - NAMES_PER_DIR - PATH_SUFFIXES bin ${_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES}) - _python_validate_interpreter (${${_PYTHON_PREFIX}_FIND_VERSION}) - if (_${_PYTHON_PREFIX}_EXECUTABLE) - break() - endif() - - # Apple frameworks handling - if (CMAKE_HOST_APPLE AND _${_PYTHON_PREFIX}_FIND_FRAMEWORK STREQUAL "LAST") - find_program (_${_PYTHON_PREFIX}_EXECUTABLE - NAMES ${_${_PYTHON_PREFIX}_NAMES} - NAMES_PER_DIR - PATHS ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS} - PATH_SUFFIXES bin - NO_DEFAULT_PATH) - _python_validate_interpreter (${${_PYTHON_PREFIX}_FIND_VERSION}) - if (_${_PYTHON_PREFIX}_EXECUTABLE) - break() - endif() - endif() - # Windows registry - if (CMAKE_HOST_WIN32 AND _${_PYTHON_PREFIX}_FIND_REGISTRY STREQUAL "LAST") - find_program (_${_PYTHON_PREFIX}_EXECUTABLE - NAMES ${_${_PYTHON_PREFIX}_NAMES} - ${_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES} - NAMES_PER_DIR - PATHS ${_${_PYTHON_PREFIX}_REGISTRY_PATHS} - PATH_SUFFIXES bin ${_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES} - NO_DEFAULT_PATH) - _python_validate_interpreter (${${_PYTHON_PREFIX}_FIND_VERSION}) - if (_${_PYTHON_PREFIX}_EXECUTABLE) - break() - endif() - endif() - - break() - endwhile() - else() - # look-up for various versions and locations - foreach (_${_PYTHON_PREFIX}_VERSION IN LISTS _${_PYTHON_PREFIX}_FIND_VERSIONS) - _python_get_names (_${_PYTHON_PREFIX}_NAMES VERSION ${_${_PYTHON_PREFIX}_VERSION} POSIX EXECUTABLE) - list (APPEND _${_PYTHON_PREFIX}_NAMES python${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR} - python) - - _python_get_frameworks (_${_PYTHON_PREFIX}_FRAMEWORK_PATHS ${_${_PYTHON_PREFIX}_VERSION}) - _python_get_registries (_${_PYTHON_PREFIX}_REGISTRY_PATHS ${_${_PYTHON_PREFIX}_VERSION}) - - # Virtual environments handling - if (_${_PYTHON_PREFIX}_FIND_VIRTUALENV MATCHES "^(FIRST|ONLY)$") - find_program (_${_PYTHON_PREFIX}_EXECUTABLE - NAMES ${_${_PYTHON_PREFIX}_NAMES} - NAMES_PER_DIR - HINTS ${_${_PYTHON_PREFIX}_HINTS} - PATHS ENV VIRTUAL_ENV ENV CONDA_PREFIX - PATH_SUFFIXES bin Scripts - NO_CMAKE_PATH - NO_CMAKE_ENVIRONMENT_PATH - NO_SYSTEM_ENVIRONMENT_PATH - NO_CMAKE_SYSTEM_PATH) - _python_validate_interpreter (${_${_PYTHON_PREFIX}_VERSION} EXACT) - if (_${_PYTHON_PREFIX}_EXECUTABLE) - break() - endif() - if (_${_PYTHON_PREFIX}_FIND_VIRTUALENV STREQUAL "ONLY") - continue() - endif() - endif() - - # Apple frameworks handling - if (CMAKE_HOST_APPLE AND _${_PYTHON_PREFIX}_FIND_FRAMEWORK STREQUAL "FIRST") - find_program (_${_PYTHON_PREFIX}_EXECUTABLE - NAMES ${_${_PYTHON_PREFIX}_NAMES} - NAMES_PER_DIR - HINTS ${_${_PYTHON_PREFIX}_HINTS} - PATHS ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS} - PATH_SUFFIXES bin - NO_CMAKE_PATH - NO_CMAKE_ENVIRONMENT_PATH - NO_SYSTEM_ENVIRONMENT_PATH - NO_CMAKE_SYSTEM_PATH) - endif() - - # Windows registry - if (CMAKE_HOST_WIN32 AND _${_PYTHON_PREFIX}_FIND_REGISTRY STREQUAL "FIRST") - find_program (_${_PYTHON_PREFIX}_EXECUTABLE - NAMES ${_${_PYTHON_PREFIX}_NAMES} - ${_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES} - NAMES_PER_DIR - HINTS ${_${_PYTHON_PREFIX}_HINTS} - PATHS ${_${_PYTHON_PREFIX}_REGISTRY_PATHS} - [HKEY_LOCAL_MACHINE\\SOFTWARE\\IronPython\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath] - PATH_SUFFIXES bin ${_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES} - NO_SYSTEM_ENVIRONMENT_PATH - NO_CMAKE_SYSTEM_PATH) - endif() - - _python_validate_interpreter (${_${_PYTHON_PREFIX}_VERSION} EXACT) - if (_${_PYTHON_PREFIX}_EXECUTABLE) - break() - endif() - - # try using HINTS - find_program (_${_PYTHON_PREFIX}_EXECUTABLE - NAMES ${_${_PYTHON_PREFIX}_NAMES} - ${_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES} - NAMES_PER_DIR - HINTS ${_${_PYTHON_PREFIX}_HINTS} - PATH_SUFFIXES bin ${_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES} - NO_SYSTEM_ENVIRONMENT_PATH - NO_CMAKE_SYSTEM_PATH) - _python_validate_interpreter (${_${_PYTHON_PREFIX}_VERSION} EXACT) - if (_${_PYTHON_PREFIX}_EXECUTABLE) - break() - endif() - # try using standard paths. - # NAMES_PER_DIR is not defined on purpose to have a chance to find - # expected version. - # For example, typical systems have 'python' for version 2.* and 'python3' - # for version 3.*. So looking for names per dir will find, potentially, - # systematically 'python' (i.e. version 2) even if version 3 is searched. - if (CMAKE_HOST_WIN32) - find_program (_${_PYTHON_PREFIX}_EXECUTABLE - NAMES ${_${_PYTHON_PREFIX}_NAMES} - python - ${_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES}) - else() - find_program (_${_PYTHON_PREFIX}_EXECUTABLE - NAMES ${_${_PYTHON_PREFIX}_NAMES}) - endif() - _python_validate_interpreter (${_${_PYTHON_PREFIX}_VERSION} EXACT) - if (_${_PYTHON_PREFIX}_EXECUTABLE) - break() - endif() - - # Apple frameworks handling - if (CMAKE_HOST_APPLE AND _${_PYTHON_PREFIX}_FIND_FRAMEWORK STREQUAL "LAST") - find_program (_${_PYTHON_PREFIX}_EXECUTABLE - NAMES ${_${_PYTHON_PREFIX}_NAMES} - NAMES_PER_DIR - PATHS ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS} - PATH_SUFFIXES bin - NO_DEFAULT_PATH) - endif() - - # Windows registry - if (CMAKE_HOST_WIN32 AND _${_PYTHON_PREFIX}_FIND_REGISTRY STREQUAL "LAST") - find_program (_${_PYTHON_PREFIX}_EXECUTABLE - NAMES ${_${_PYTHON_PREFIX}_NAMES} - ${_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES} - NAMES_PER_DIR - PATHS ${_${_PYTHON_PREFIX}_REGISTRY_PATHS} - [HKEY_LOCAL_MACHINE\\SOFTWARE\\IronPython\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath] - PATH_SUFFIXES bin ${_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES} - NO_DEFAULT_PATH) - endif() - - _python_validate_interpreter (${_${_PYTHON_PREFIX}_VERSION} EXACT) - if (_${_PYTHON_PREFIX}_EXECUTABLE) - break() - endif() - endforeach() - - if (NOT _${_PYTHON_PREFIX}_EXECUTABLE AND - NOT _${_PYTHON_PREFIX}_FIND_VIRTUALENV STREQUAL "ONLY") - # No specific version found. Retry with generic names and standard paths. - # NAMES_PER_DIR is not defined on purpose to have a chance to find - # expected version. - # For example, typical systems have 'python' for version 2.* and 'python3' - # for version 3.*. So looking for names per dir will find, potentially, - # systematically 'python' (i.e. version 2) even if version 3 is searched. - find_program (_${_PYTHON_PREFIX}_EXECUTABLE - NAMES python${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR} - python - ${_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES}) - _python_validate_interpreter () - endif() - endif() - endif() - - set (${_PYTHON_PREFIX}_EXECUTABLE "${_${_PYTHON_PREFIX}_EXECUTABLE}") - - # retrieve exact version of executable found - if (_${_PYTHON_PREFIX}_EXECUTABLE) - execute_process (COMMAND "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c - "import sys; sys.stdout.write('.'.join([str(x) for x in sys.version_info[:3]]))" - RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT - OUTPUT_VARIABLE ${_PYTHON_PREFIX}_VERSION - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE) - if (NOT _${_PYTHON_PREFIX}_RESULT) - set (_${_PYTHON_PREFIX}_EXECUTABLE_USABLE TRUE) - else() - # Interpreter is not usable - set (_${_PYTHON_PREFIX}_EXECUTABLE_USABLE FALSE) - unset (${_PYTHON_PREFIX}_VERSION) - set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Cannot run the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"") - endif() - endif() - - if (_${_PYTHON_PREFIX}_EXECUTABLE AND _${_PYTHON_PREFIX}_EXECUTABLE_USABLE) - if (_${_PYTHON_PREFIX}_INTERPRETER_PROPERTIES) - set (${_PYTHON_PREFIX}_Interpreter_FOUND TRUE) - - list (GET _${_PYTHON_PREFIX}_INTERPRETER_PROPERTIES 0 ${_PYTHON_PREFIX}_INTERPRETER_ID) - - list (GET _${_PYTHON_PREFIX}_INTERPRETER_PROPERTIES 1 ${_PYTHON_PREFIX}_VERSION_MAJOR) - list (GET _${_PYTHON_PREFIX}_INTERPRETER_PROPERTIES 2 ${_PYTHON_PREFIX}_VERSION_MINOR) - list (GET _${_PYTHON_PREFIX}_INTERPRETER_PROPERTIES 3 ${_PYTHON_PREFIX}_VERSION_PATCH) - - list (GET _${_PYTHON_PREFIX}_INTERPRETER_PROPERTIES 4 _${_PYTHON_PREFIX}_ARCH) - set (_${_PYTHON_PREFIX}_ARCH2 ${_${_PYTHON_PREFIX}_ARCH}) - - list (GET _${_PYTHON_PREFIX}_INTERPRETER_PROPERTIES 5 _${_PYTHON_PREFIX}_ABIFLAGS) - list (GET _${_PYTHON_PREFIX}_INTERPRETER_PROPERTIES 6 ${_PYTHON_PREFIX}_SOABI) - - list (GET _${_PYTHON_PREFIX}_INTERPRETER_PROPERTIES 7 ${_PYTHON_PREFIX}_STDLIB) - list (GET _${_PYTHON_PREFIX}_INTERPRETER_PROPERTIES 8 ${_PYTHON_PREFIX}_STDARCH) - list (GET _${_PYTHON_PREFIX}_INTERPRETER_PROPERTIES 9 ${_PYTHON_PREFIX}_SITELIB) - list (GET _${_PYTHON_PREFIX}_INTERPRETER_PROPERTIES 10 ${_PYTHON_PREFIX}_SITEARCH) - else() - string (REGEX MATCHALL "[0-9]+" _${_PYTHON_PREFIX}_VERSIONS "${${_PYTHON_PREFIX}_VERSION}") - list (GET _${_PYTHON_PREFIX}_VERSIONS 0 ${_PYTHON_PREFIX}_VERSION_MAJOR) - list (GET _${_PYTHON_PREFIX}_VERSIONS 1 ${_PYTHON_PREFIX}_VERSION_MINOR) - list (GET _${_PYTHON_PREFIX}_VERSIONS 2 ${_PYTHON_PREFIX}_VERSION_PATCH) - - if (${_PYTHON_PREFIX}_VERSION_MAJOR VERSION_EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR) - set (${_PYTHON_PREFIX}_Interpreter_FOUND TRUE) - - # Use interpreter version and ABI for future searches to ensure consistency - set (_${_PYTHON_PREFIX}_FIND_VERSIONS ${${_PYTHON_PREFIX}_VERSION_MAJOR}.${${_PYTHON_PREFIX}_VERSION_MINOR}) - execute_process (COMMAND "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c "import sys; sys.stdout.write(sys.abiflags)" - RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT - OUTPUT_VARIABLE _${_PYTHON_PREFIX}_ABIFLAGS - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE) - if (_${_PYTHON_PREFIX}_RESULT) - # assunme ABI is not supported - set (_${_PYTHON_PREFIX}_ABIFLAGS "") - endif() - endif() - - if (${_PYTHON_PREFIX}_Interpreter_FOUND) - # compute and save interpreter signature - string (MD5 __${_PYTHON_PREFIX}_INTERPRETER_SIGNATURE "${_${_PYTHON_PREFIX}_SIGNATURE}:${_${_PYTHON_PREFIX}_EXECUTABLE}") - set (_${_PYTHON_PREFIX}_INTERPRETER_SIGNATURE "${__${_PYTHON_PREFIX}_INTERPRETER_SIGNATURE}" CACHE INTERNAL "") - - if (NOT CMAKE_SIZEOF_VOID_P) - # determine interpreter architecture - execute_process (COMMAND "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c "import sys; print(sys.maxsize > 2**32)" - RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT - OUTPUT_VARIABLE ${_PYTHON_PREFIX}_IS64BIT - ERROR_VARIABLE ${_PYTHON_PREFIX}_IS64BIT) - if (NOT _${_PYTHON_PREFIX}_RESULT) - if (${_PYTHON_PREFIX}_IS64BIT) - set (_${_PYTHON_PREFIX}_ARCH 64) - set (_${_PYTHON_PREFIX}_ARCH2 64) - else() - set (_${_PYTHON_PREFIX}_ARCH 32) - set (_${_PYTHON_PREFIX}_ARCH2 32) - endif() - endif() - endif() - - # retrieve interpreter identity - execute_process (COMMAND "${_${_PYTHON_PREFIX}_EXECUTABLE}" -V - RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT - OUTPUT_VARIABLE ${_PYTHON_PREFIX}_INTERPRETER_ID - ERROR_VARIABLE ${_PYTHON_PREFIX}_INTERPRETER_ID) - if (NOT _${_PYTHON_PREFIX}_RESULT) - if (${_PYTHON_PREFIX}_INTERPRETER_ID MATCHES "Anaconda") - set (${_PYTHON_PREFIX}_INTERPRETER_ID "Anaconda") - elseif (${_PYTHON_PREFIX}_INTERPRETER_ID MATCHES "Enthought") - set (${_PYTHON_PREFIX}_INTERPRETER_ID "Canopy") - else() - string (REGEX REPLACE "^([^ ]+).*" "\\1" ${_PYTHON_PREFIX}_INTERPRETER_ID "${${_PYTHON_PREFIX}_INTERPRETER_ID}") - if (${_PYTHON_PREFIX}_INTERPRETER_ID STREQUAL "Python") - # try to get a more precise ID - execute_process (COMMAND "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c "import sys; print(sys.copyright)" - RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT - OUTPUT_VARIABLE ${_PYTHON_PREFIX}_COPYRIGHT - ERROR_QUIET) - if (${_PYTHON_PREFIX}_COPYRIGHT MATCHES "ActiveState") - set (${_PYTHON_PREFIX}_INTERPRETER_ID "ActivePython") - endif() - endif() - endif() - else() - set (${_PYTHON_PREFIX}_INTERPRETER_ID Python) - endif() - - # retrieve various package installation directories - execute_process (COMMAND "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c "import sys\ntry:\n from distutils import sysconfig\n sys.stdout.write(';'.join([sysconfig.get_python_lib(plat_specific=False,standard_lib=True),sysconfig.get_python_lib(plat_specific=True,standard_lib=True),sysconfig.get_python_lib(plat_specific=False,standard_lib=False),sysconfig.get_python_lib(plat_specific=True,standard_lib=False)]))\nexcept Exception:\n import sysconfig\n sys.stdout.write(';'.join([sysconfig.get_path('stdlib'),sysconfig.get_path('platstdlib'),sysconfig.get_path('purelib'),sysconfig.get_path('platlib')]))" - RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT - OUTPUT_VARIABLE _${_PYTHON_PREFIX}_LIBPATHS - ERROR_QUIET) - if (NOT _${_PYTHON_PREFIX}_RESULT) - list (GET _${_PYTHON_PREFIX}_LIBPATHS 0 ${_PYTHON_PREFIX}_STDLIB) - list (GET _${_PYTHON_PREFIX}_LIBPATHS 1 ${_PYTHON_PREFIX}_STDARCH) - list (GET _${_PYTHON_PREFIX}_LIBPATHS 2 ${_PYTHON_PREFIX}_SITELIB) - list (GET _${_PYTHON_PREFIX}_LIBPATHS 3 ${_PYTHON_PREFIX}_SITEARCH) - else() - unset (${_PYTHON_PREFIX}_STDLIB) - unset (${_PYTHON_PREFIX}_STDARCH) - unset (${_PYTHON_PREFIX}_SITELIB) - unset (${_PYTHON_PREFIX}_SITEARCH) - endif() - - if (_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR VERSION_GREATER_EQUAL "3") - _python_get_config_var (${_PYTHON_PREFIX}_SOABI SOABI) - endif() - - # store properties in the cache to speed-up future searches - set (_${_PYTHON_PREFIX}_INTERPRETER_PROPERTIES - "${${_PYTHON_PREFIX}_INTERPRETER_ID};${${_PYTHON_PREFIX}_VERSION_MAJOR};${${_PYTHON_PREFIX}_VERSION_MINOR};${${_PYTHON_PREFIX}_VERSION_PATCH};${_${_PYTHON_PREFIX}_ARCH};${_${_PYTHON_PREFIX}_ABIFLAGS};${${_PYTHON_PREFIX}_SOABI};${${_PYTHON_PREFIX}_STDLIB};${${_PYTHON_PREFIX}_STDARCH};${${_PYTHON_PREFIX}_SITELIB};${${_PYTHON_PREFIX}_SITEARCH}" CACHE INTERNAL "${_PYTHON_PREFIX} Properties") - else() - unset (_${_PYTHON_PREFIX}_INTERPRETER_SIGNATURE CACHE) - unset (${_PYTHON_PREFIX}_INTERPRETER_ID) - endif() - endif() - endif() - - if (${_PYTHON_PREFIX}_ARTIFACTS_INTERACTIVE) - set (${_PYTHON_PREFIX}_EXECUTABLE "${_${_PYTHON_PREFIX}_EXECUTABLE}" CACHE FILEPATH "${_PYTHON_PREFIX} Interpreter") - endif() - - _python_mark_as_internal (_${_PYTHON_PREFIX}_EXECUTABLE - _${_PYTHON_PREFIX}_INTERPRETER_PROPERTIES - _${_PYTHON_PREFIX}_INTERPRETER_SIGNATURE) -endif() - - -# second step, search for compiler (IronPython) -if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) - list (APPEND _${_PYTHON_PREFIX}_CACHED_VARS _${_PYTHON_PREFIX}_COMPILER) - if (${_PYTHON_PREFIX}_FIND_REQUIRED_Compiler) - list (APPEND _${_PYTHON_PREFIX}_REQUIRED_VARS ${_PYTHON_PREFIX}_COMPILER) - endif() - - if (DEFINED ${_PYTHON_PREFIX}_COMPILER - AND IS_ABSOLUTE "${${_PYTHON_PREFIX}_COMPILER}") - set (_${_PYTHON_PREFIX}_COMPILER "${${_PYTHON_PREFIX}_COMPILER}" CACHE INTERNAL "") - elseif (DEFINED _${_PYTHON_PREFIX}_COMPILER) - # compute compiler signature and check validity of definition - string (MD5 __${_PYTHON_PREFIX}_COMPILER_SIGNATURE "${_${_PYTHON_PREFIX}_SIGNATURE}:${_${_PYTHON_PREFIX}_COMPILER}") - if (__${_PYTHON_PREFIX}_COMPILER_SIGNATURE STREQUAL _${_PYTHON_PREFIX}_COMPILER_SIGNATURE) - # check version validity - if (${_PYTHON_PREFIX}_FIND_VERSION_EXACT) - _python_validate_compiler (${${_PYTHON_PREFIX}_FIND_VERSION} EXACT CHECK_EXISTS) - else() - _python_validate_compiler (${${_PYTHON_PREFIX}_FIND_VERSION} CHECK_EXISTS) - endif() - else() - unset (_${_PYTHON_PREFIX}_COMPILER CACHE) - unset (_${_PYTHON_PREFIX}_COMPILER_SIGNATURE CACHE) - endif() - endif() - - if (NOT _${_PYTHON_PREFIX}_COMPILER) - # IronPython specific artifacts - # If IronPython interpreter is found, use its path - unset (_${_PYTHON_PREFIX}_IRON_ROOT) - if (${_PYTHON_PREFIX}_Interpreter_FOUND AND ${_PYTHON_PREFIX}_INTERPRETER_ID STREQUAL "IronPython") - get_filename_component (_${_PYTHON_PREFIX}_IRON_ROOT "${${_PYTHON_PREFIX}_EXECUTABLE}" DIRECTORY) - endif() - - if (_${_PYTHON_PREFIX}_FIND_STRATEGY STREQUAL "LOCATION") - set (_${_PYTHON_PREFIX}_REGISTRY_PATHS) - - foreach (_${_PYTHON_PREFIX}_VERSION IN LISTS _${_PYTHON_PREFIX}_FIND_VERSIONS) - # Registry Paths - list (APPEND _${_PYTHON_PREFIX}_REGISTRY_PATHS - [HKEY_LOCAL_MACHINE\\SOFTWARE\\IronPython\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath]) - endforeach() - - while (TRUE) - if (_${_PYTHON_PREFIX}_FIND_REGISTRY STREQUAL "FIRST") - find_program (_${_PYTHON_PREFIX}_COMPILER - NAMES ipyc - HINTS ${_${_PYTHON_PREFIX}_IRON_ROOT} ${_${_PYTHON_PREFIX}_HINTS} - PATHS ${_${_PYTHON_PREFIX}_REGISTRY_PATHS} - PATH_SUFFIXES ${_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES} - NO_SYSTEM_ENVIRONMENT_PATH - NO_CMAKE_SYSTEM_PATH) - _python_validate_compiler (${${_PYTHON_PREFIX}_FIND_VERSION}) - if (_${_PYTHON_PREFIX}_COMPILER) - break() - endif() - endif() - - find_program (_${_PYTHON_PREFIX}_COMPILER - NAMES ipyc - HINTS ${_${_PYTHON_PREFIX}_IRON_ROOT} ${_${_PYTHON_PREFIX}_HINTS} - PATH_SUFFIXES ${_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES} - NO_SYSTEM_ENVIRONMENT_PATH - NO_CMAKE_SYSTEM_PATH) - _python_validate_compiler (${${_PYTHON_PREFIX}_FIND_VERSION}) - if (_${_PYTHON_PREFIX}_COMPILER) - break() - endif() - - if (_${_PYTHON_PREFIX}_FIND_REGISTRY STREQUAL "LAST") - find_program (_${_PYTHON_PREFIX}_COMPILER - NAMES ipyc - PATHS ${_${_PYTHON_PREFIX}_REGISTRY_PATHS} - PATH_SUFFIXES ${_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES} - NO_DEFAULT_PATH) - endif() - - break() - endwhile() - else() - # try using root dir and registry - foreach (_${_PYTHON_PREFIX}_VERSION IN LISTS _${_PYTHON_PREFIX}_FIND_VERSIONS) - if (_${_PYTHON_PREFIX}_FIND_REGISTRY STREQUAL "FIRST") - find_program (_${_PYTHON_PREFIX}_COMPILER - NAMES ipyc - HINTS ${_${_PYTHON_PREFIX}_IRON_ROOT} ${_${_PYTHON_PREFIX}_HINTS} - PATHS [HKEY_LOCAL_MACHINE\\SOFTWARE\\IronPython\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath] - PATH_SUFFIXES ${_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES} - NO_SYSTEM_ENVIRONMENT_PATH - NO_CMAKE_SYSTEM_PATH) - _python_validate_compiler (${_${_PYTHON_PREFIX}_VERSION} EXACT) - if (_${_PYTHON_PREFIX}_COMPILER) - break() - endif() - endif() - - find_program (_${_PYTHON_PREFIX}_COMPILER - NAMES ipyc - HINTS ${_${_PYTHON_PREFIX}_IRON_ROOT} ${_${_PYTHON_PREFIX}_HINTS} - PATH_SUFFIXES ${_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES} - NO_SYSTEM_ENVIRONMENT_PATH - NO_CMAKE_SYSTEM_PATH) - _python_validate_compiler (${_${_PYTHON_PREFIX}_VERSION} EXACT) - if (_${_PYTHON_PREFIX}_COMPILER) - break() - endif() - - if (_${_PYTHON_PREFIX}_FIND_REGISTRY STREQUAL "LAST") - find_program (_${_PYTHON_PREFIX}_COMPILER - NAMES ipyc - PATHS [HKEY_LOCAL_MACHINE\\SOFTWARE\\IronPython\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath] - PATH_SUFFIXES ${_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES} - NO_DEFAULT_PATH) - _python_validate_compiler (${_${_PYTHON_PREFIX}_VERSION} EXACT) - if (_${_PYTHON_PREFIX}_COMPILER) - break() - endif() - endif() - endforeach() - - # no specific version found, re-try in standard paths - find_program (_${_PYTHON_PREFIX}_COMPILER - NAMES ipyc - HINTS ${_${_PYTHON_PREFIX}_IRON_ROOT} ${_${_PYTHON_PREFIX}_HINTS} - PATH_SUFFIXES ${_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES}) - endif() - endif() - - set (${_PYTHON_PREFIX}_COMPILER "${_${_PYTHON_PREFIX}_COMPILER}") - - if (_${_PYTHON_PREFIX}_COMPILER) - # retrieve python environment version from compiler - set (_${_PYTHON_PREFIX}_VERSION_DIR "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/PythonCompilerVersion.dir") - file (WRITE "${_${_PYTHON_PREFIX}_VERSION_DIR}/version.py" "import sys; sys.stdout.write('.'.join([str(x) for x in sys.version_info[:3]]))\n") - execute_process (COMMAND "${_${_PYTHON_PREFIX}_COMPILER}" /target:exe /embed "${_${_PYTHON_PREFIX}_VERSION_DIR}/version.py" - WORKING_DIRECTORY "${_${_PYTHON_PREFIX}_VERSION_DIR}" - OUTPUT_QUIET - ERROR_QUIET) - execute_process (COMMAND "${_${_PYTHON_PREFIX}_VERSION_DIR}/version" - WORKING_DIRECTORY "${_${_PYTHON_PREFIX}_VERSION_DIR}" - RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT - OUTPUT_VARIABLE _${_PYTHON_PREFIX}_VERSION - ERROR_QUIET) - if (NOT _${_PYTHON_PREFIX}_RESULT) - set (_${_PYTHON_PREFIX}_COMPILER_USABLE TRUE) - string (REGEX MATCHALL "[0-9]+" _${_PYTHON_PREFIX}_VERSIONS "${_${_PYTHON_PREFIX}_VERSION}") - list (GET _${_PYTHON_PREFIX}_VERSIONS 0 _${_PYTHON_PREFIX}_VERSION_MAJOR) - list (GET _${_PYTHON_PREFIX}_VERSIONS 1 _${_PYTHON_PREFIX}_VERSION_MINOR) - list (GET _${_PYTHON_PREFIX}_VERSIONS 2 _${_PYTHON_PREFIX}_VERSION_PATCH) - - if (NOT ${_PYTHON_PREFIX}_Interpreter_FOUND) - # set public version information - set (${_PYTHON_PREFIX}_VERSION ${_${_PYTHON_PREFIX}_VERSION}) - set (${_PYTHON_PREFIX}_VERSION_MAJOR ${_${_PYTHON_PREFIX}_VERSION_MAJOR}) - set (${_PYTHON_PREFIX}_VERSION_MINOR ${_${_PYTHON_PREFIX}_VERSION_MINOR}) - set (${_PYTHON_PREFIX}_VERSION_PATCH ${_${_PYTHON_PREFIX}_VERSION_PATCH}) - endif() - else() - # compiler not usable - set (_${_PYTHON_PREFIX}_COMPILER_USABLE FALSE) - set (_${_PYTHON_PREFIX}_Compiler_REASON_FAILURE "Cannot run the compiler \"${_${_PYTHON_PREFIX}_COMPILER}\"") - endif() - file (REMOVE_RECURSE "${_${_PYTHON_PREFIX}_VERSION_DIR}") - endif() - - if (_${_PYTHON_PREFIX}_COMPILER AND _${_PYTHON_PREFIX}_COMPILER_USABLE) - if (${_PYTHON_PREFIX}_Interpreter_FOUND) - # Compiler must be compatible with interpreter - if ("${_${_PYTHON_PREFIX}_VERSION_MAJOR}.${_${_PYTHON_PREFIX}_VERSION_MINOR}" VERSION_EQUAL "${${_PYTHON_PREFIX}_VERSION_MAJOR}.${${_PYTHON_PREFIX}_VERSION_MINOR}") - set (${_PYTHON_PREFIX}_Compiler_FOUND TRUE) - endif() - elseif (${_PYTHON_PREFIX}_VERSION_MAJOR VERSION_EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR) - set (${_PYTHON_PREFIX}_Compiler_FOUND TRUE) - # Use compiler version for future searches to ensure consistency - set (_${_PYTHON_PREFIX}_FIND_VERSIONS ${${_PYTHON_PREFIX}_VERSION_MAJOR}.${${_PYTHON_PREFIX}_VERSION_MINOR}) - endif() - endif() - - if (${_PYTHON_PREFIX}_Compiler_FOUND) - # compute and save compiler signature - string (MD5 __${_PYTHON_PREFIX}_COMPILER_SIGNATURE "${_${_PYTHON_PREFIX}_SIGNATURE}:${_${_PYTHON_PREFIX}_COMPILER}") - set (_${_PYTHON_PREFIX}_COMPILER_SIGNATURE "${__${_PYTHON_PREFIX}_COMPILER_SIGNATURE}" CACHE INTERNAL "") - - set (${_PYTHON_PREFIX}_COMPILER_ID IronPython) - else() - unset (_${_PYTHON_PREFIX}_COMPILER_SIGNATURE CACHE) - unset (${_PYTHON_PREFIX}_COMPILER_ID) - endif() - - if (${_PYTHON_PREFIX}_ARTIFACTS_INTERACTIVE) - set (${_PYTHON_PREFIX}_COMPILER "${_${_PYTHON_PREFIX}_COMPILER}" CACHE FILEPATH "${_PYTHON_PREFIX} Compiler") - endif() - - _python_mark_as_internal (_${_PYTHON_PREFIX}_COMPILER - _${_PYTHON_PREFIX}_COMPILER_SIGNATURE) -endif() - - -# third step, search for the development artifacts -## Development environment is not compatible with IronPython interpreter -if (("Development.Module" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS - OR "Development.Embed" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) - AND NOT ${_PYTHON_PREFIX}_INTERPRETER_ID STREQUAL "IronPython") - if ("LIBRARY" IN_LIST _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_ARTIFACTS) - list (APPEND _${_PYTHON_PREFIX}_CACHED_VARS _${_PYTHON_PREFIX}_LIBRARY_RELEASE - _${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE - _${_PYTHON_PREFIX}_LIBRARY_DEBUG - _${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG) - endif() - if ("INCLUDE_DIR" IN_LIST _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_ARTIFACTS) - list (APPEND _${_PYTHON_PREFIX}_CACHED_VARS _${_PYTHON_PREFIX}_INCLUDE_DIR) - endif() - if (${_PYTHON_PREFIX}_FIND_REQUIRED_Development.Module) - if ("LIBRARY" IN_LIST _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_MODULE_ARTIFACTS) - list (APPEND _${_PYTHON_PREFIX}_REQUIRED_VARS ${_PYTHON_PREFIX}_LIBRARIES) - endif() - if ("INCLUDE_DIR" IN_LIST _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_MODULE_ARTIFACTS) - list (APPEND _${_PYTHON_PREFIX}_REQUIRED_VARS ${_PYTHON_PREFIX}_INCLUDE_DIRS) - endif() - endif() - if (${_PYTHON_PREFIX}_FIND_REQUIRED_Development.Embed) - if ("LIBRARY" IN_LIST _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_EMBED_ARTIFACTS) - list (APPEND _${_PYTHON_PREFIX}_REQUIRED_VARS ${_PYTHON_PREFIX}_LIBRARIES) - endif() - if ("INCLUDE_DIR" IN_LIST _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_EMBED_ARTIFACTS) - list (APPEND _${_PYTHON_PREFIX}_REQUIRED_VARS ${_PYTHON_PREFIX}_INCLUDE_DIRS) - endif() - endif() - list (REMOVE_DUPLICATES _${_PYTHON_PREFIX}_REQUIRED_VARS) - - _python_check_development_signature (Module) - _python_check_development_signature (Embed) - - if (DEFINED ${_PYTHON_PREFIX}_LIBRARY - AND IS_ABSOLUTE "${${_PYTHON_PREFIX}_LIBRARY}") - set (_${_PYTHON_PREFIX}_LIBRARY_RELEASE "${${_PYTHON_PREFIX}_LIBRARY}" CACHE INTERNAL "") - unset (_${_PYTHON_PREFIX}_LIBRARY_DEBUG CACHE) - unset (_${_PYTHON_PREFIX}_INCLUDE_DIR CACHE) - endif() - if (DEFINED ${_PYTHON_PREFIX}_INCLUDE_DIR - AND IS_ABSOLUTE "${${_PYTHON_PREFIX}_INCLUDE_DIR}") - set (_${_PYTHON_PREFIX}_INCLUDE_DIR "${${_PYTHON_PREFIX}_INCLUDE_DIR}" CACHE INTERNAL "") - endif() - - # Support preference of static libs by adjusting CMAKE_FIND_LIBRARY_SUFFIXES - unset (_${_PYTHON_PREFIX}_CMAKE_FIND_LIBRARY_SUFFIXES) - if (DEFINED ${_PYTHON_PREFIX}_USE_STATIC_LIBS AND NOT WIN32) - set(_${_PYTHON_PREFIX}_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) - if(${_PYTHON_PREFIX}_USE_STATIC_LIBS) - set (CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_STATIC_LIBRARY_SUFFIX}) - else() - list (REMOVE_ITEM CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_STATIC_LIBRARY_SUFFIX}) - endif() - endif() - - if (NOT _${_PYTHON_PREFIX}_LIBRARY_RELEASE OR NOT _${_PYTHON_PREFIX}_INCLUDE_DIR) - # if python interpreter is found, use it to look-up for artifacts - # to ensure consistency between interpreter and development environments. - # If not, try to locate a compatible config tool - if (NOT ${_PYTHON_PREFIX}_Interpreter_FOUND OR CMAKE_CROSSCOMPILING) - set (_${_PYTHON_PREFIX}_HINTS "${${_PYTHON_PREFIX}_ROOT_DIR}" ENV ${_PYTHON_PREFIX}_ROOT_DIR) - unset (_${_PYTHON_PREFIX}_VIRTUALENV_PATHS) - if (_${_PYTHON_PREFIX}_FIND_VIRTUALENV MATCHES "^(FIRST|ONLY)$") - set (_${_PYTHON_PREFIX}_VIRTUALENV_PATHS ENV VIRTUAL_ENV ENV CONDA_PREFIX) - endif() - unset (_${_PYTHON_PREFIX}_FRAMEWORK_PATHS) - - if (_${_PYTHON_PREFIX}_FIND_STRATEGY STREQUAL "LOCATION") - set (_${_PYTHON_PREFIX}_CONFIG_NAMES) - - foreach (_${_PYTHON_PREFIX}_VERSION IN LISTS _${_PYTHON_PREFIX}_FIND_VERSIONS) - _python_get_names (_${_PYTHON_PREFIX}_VERSION_NAMES VERSION ${_${_PYTHON_PREFIX}_VERSION} POSIX CONFIG) - list (APPEND _${_PYTHON_PREFIX}_CONFIG_NAMES ${_${_PYTHON_PREFIX}_VERSION_NAMES}) - - # Framework Paths - _python_get_frameworks (_${_PYTHON_PREFIX}_VERSION_PATHS ${_${_PYTHON_PREFIX}_VERSION}) - list (APPEND _${_PYTHON_PREFIX}_FRAMEWORK_PATHS ${_${_PYTHON_PREFIX}_VERSION_PATHS}) - endforeach() - - # Apple frameworks handling - if (CMAKE_HOST_APPLE AND _${_PYTHON_PREFIX}_FIND_FRAMEWORK STREQUAL "FIRST") - find_program (_${_PYTHON_PREFIX}_CONFIG - NAMES ${_${_PYTHON_PREFIX}_CONFIG_NAMES} - NAMES_PER_DIR - HINTS ${_${_PYTHON_PREFIX}_HINTS} - PATHS ${_${_PYTHON_PREFIX}_VIRTUALENV_PATHS} - ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS} - PATH_SUFFIXES bin - NO_CMAKE_PATH - NO_CMAKE_ENVIRONMENT_PATH - NO_SYSTEM_ENVIRONMENT_PATH - NO_CMAKE_SYSTEM_PATH) - endif() - - find_program (_${_PYTHON_PREFIX}_CONFIG - NAMES ${_${_PYTHON_PREFIX}_CONFIG_NAMES} - NAMES_PER_DIR - HINTS ${_${_PYTHON_PREFIX}_HINTS} - PATHS ${_${_PYTHON_PREFIX}_VIRTUALENV_PATHS} - PATH_SUFFIXES bin) - - # Apple frameworks handling - if (CMAKE_HOST_APPLE AND _${_PYTHON_PREFIX}_FIND_FRAMEWORK STREQUAL "LAST") - find_program (_${_PYTHON_PREFIX}_CONFIG - NAMES ${_${_PYTHON_PREFIX}_CONFIG_NAMES} - NAMES_PER_DIR - PATHS ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS} - PATH_SUFFIXES bin - NO_DEFAULT_PATH) - endif() - - if (_${_PYTHON_PREFIX}_CONFIG) - execute_process (COMMAND "${_${_PYTHON_PREFIX}_CONFIG}" --help - RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT - OUTPUT_VARIABLE __${_PYTHON_PREFIX}_HELP - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE) - if (_${_PYTHON_PREFIX}_RESULT) - # assume config tool is not usable - unset (_${_PYTHON_PREFIX}_CONFIG CACHE) - endif() - endif() - - if (_${_PYTHON_PREFIX}_CONFIG) - execute_process (COMMAND "${_${_PYTHON_PREFIX}_CONFIG}" --abiflags - RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT - OUTPUT_VARIABLE __${_PYTHON_PREFIX}_ABIFLAGS - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE) - if (_${_PYTHON_PREFIX}_RESULT) - # assume ABI is not supported - set (__${_PYTHON_PREFIX}_ABIFLAGS "") - endif() - if (DEFINED _${_PYTHON_PREFIX}_FIND_ABI AND NOT __${_PYTHON_PREFIX}_ABIFLAGS IN_LIST _${_PYTHON_PREFIX}_ABIFLAGS) - # Wrong ABI - unset (_${_PYTHON_PREFIX}_CONFIG CACHE) - endif() - endif() - - if (_${_PYTHON_PREFIX}_CONFIG AND DEFINED CMAKE_LIBRARY_ARCHITECTURE) - # check that config tool match library architecture - execute_process (COMMAND "${_${_PYTHON_PREFIX}_CONFIG}" --configdir - RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT - OUTPUT_VARIABLE _${_PYTHON_PREFIX}_CONFIGDIR - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE) - if (_${_PYTHON_PREFIX}_RESULT) - unset (_${_PYTHON_PREFIX}_CONFIG CACHE) - else() - string(FIND "${_${_PYTHON_PREFIX}_CONFIGDIR}" "${CMAKE_LIBRARY_ARCHITECTURE}" _${_PYTHON_PREFIX}_RESULT) - if (_${_PYTHON_PREFIX}_RESULT EQUAL -1) - unset (_${_PYTHON_PREFIX}_CONFIG CACHE) - endif() - endif() - endif() - else() - foreach (_${_PYTHON_PREFIX}_VERSION IN LISTS _${_PYTHON_PREFIX}_FIND_VERSIONS) - # try to use pythonX.Y-config tool - _python_get_names (_${_PYTHON_PREFIX}_CONFIG_NAMES VERSION ${_${_PYTHON_PREFIX}_VERSION} POSIX CONFIG) - - # Framework Paths - _python_get_frameworks (_${_PYTHON_PREFIX}_FRAMEWORK_PATHS ${_${_PYTHON_PREFIX}_VERSION}) - - # Apple frameworks handling - if (CMAKE_HOST_APPLE AND _${_PYTHON_PREFIX}_FIND_FRAMEWORK STREQUAL "FIRST") - find_program (_${_PYTHON_PREFIX}_CONFIG - NAMES ${_${_PYTHON_PREFIX}_CONFIG_NAMES} - NAMES_PER_DIR - HINTS ${_${_PYTHON_PREFIX}_HINTS} - PATHS ${_${_PYTHON_PREFIX}_VIRTUALENV_PATHS} - ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS} - PATH_SUFFIXES bin - NO_CMAKE_PATH - NO_CMAKE_ENVIRONMENT_PATH - NO_SYSTEM_ENVIRONMENT_PATH - NO_CMAKE_SYSTEM_PATH) - endif() - - find_program (_${_PYTHON_PREFIX}_CONFIG - NAMES ${_${_PYTHON_PREFIX}_CONFIG_NAMES} - NAMES_PER_DIR - HINTS ${_${_PYTHON_PREFIX}_HINTS} - PATHS ${_${_PYTHON_PREFIX}_VIRTUALENV_PATHS} - PATH_SUFFIXES bin) - - # Apple frameworks handling - if (CMAKE_HOST_APPLE AND _${_PYTHON_PREFIX}_FIND_FRAMEWORK STREQUAL "LAST") - find_program (_${_PYTHON_PREFIX}_CONFIG - NAMES ${_${_PYTHON_PREFIX}_CONFIG_NAMES} - NAMES_PER_DIR - PATHS ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS} - PATH_SUFFIXES bin - NO_DEFAULT_PATH) - endif() - - unset (_${_PYTHON_PREFIX}_CONFIG_NAMES) - - if (_${_PYTHON_PREFIX}_CONFIG) - execute_process (COMMAND "${_${_PYTHON_PREFIX}_CONFIG}" --help - RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT - OUTPUT_VARIABLE __${_PYTHON_PREFIX}_HELP - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE) - if (_${_PYTHON_PREFIX}_RESULT) - # assume config tool is not usable - unset (_${_PYTHON_PREFIX}_CONFIG CACHE) - endif() - endif() - - if (NOT _${_PYTHON_PREFIX}_CONFIG) - continue() - endif() - - execute_process (COMMAND "${_${_PYTHON_PREFIX}_CONFIG}" --abiflags - RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT - OUTPUT_VARIABLE __${_PYTHON_PREFIX}_ABIFLAGS - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE) - if (_${_PYTHON_PREFIX}_RESULT) - # assume ABI is not supported - set (__${_PYTHON_PREFIX}_ABIFLAGS "") - endif() - if (DEFINED _${_PYTHON_PREFIX}_FIND_ABI AND NOT __${_PYTHON_PREFIX}_ABIFLAGS IN_LIST _${_PYTHON_PREFIX}_ABIFLAGS) - # Wrong ABI - unset (_${_PYTHON_PREFIX}_CONFIG CACHE) - continue() - endif() - - if (_${_PYTHON_PREFIX}_CONFIG AND DEFINED CMAKE_LIBRARY_ARCHITECTURE) - # check that config tool match library architecture - execute_process (COMMAND "${_${_PYTHON_PREFIX}_CONFIG}" --configdir - RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT - OUTPUT_VARIABLE _${_PYTHON_PREFIX}_CONFIGDIR - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE) - if (_${_PYTHON_PREFIX}_RESULT) - unset (_${_PYTHON_PREFIX}_CONFIG CACHE) - continue() - endif() - string (FIND "${_${_PYTHON_PREFIX}_CONFIGDIR}" "${CMAKE_LIBRARY_ARCHITECTURE}" _${_PYTHON_PREFIX}_RESULT) - if (_${_PYTHON_PREFIX}_RESULT EQUAL -1) - unset (_${_PYTHON_PREFIX}_CONFIG CACHE) - continue() - endif() - endif() - - if (_${_PYTHON_PREFIX}_CONFIG) - break() - endif() - endforeach() - endif() - endif() - endif() - - if ("LIBRARY" IN_LIST _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_ARTIFACTS) - if (NOT _${_PYTHON_PREFIX}_LIBRARY_RELEASE) - if ((${_PYTHON_PREFIX}_Interpreter_FOUND AND NOT CMAKE_CROSSCOMPILING) OR _${_PYTHON_PREFIX}_CONFIG) - # retrieve root install directory - _python_get_config_var (_${_PYTHON_PREFIX}_PREFIX PREFIX) - - # enforce current ABI - _python_get_config_var (_${_PYTHON_PREFIX}_ABIFLAGS ABIFLAGS) - - set (_${_PYTHON_PREFIX}_HINTS "${_${_PYTHON_PREFIX}_PREFIX}") - - # retrieve library - ## compute some paths and artifact names - if (_${_PYTHON_PREFIX}_CONFIG) - string (REGEX REPLACE "^.+python([0-9.]+)[a-z]*-config" "\\1" _${_PYTHON_PREFIX}_VERSION "${_${_PYTHON_PREFIX}_CONFIG}") - else() - set (_${_PYTHON_PREFIX}_VERSION "${${_PYTHON_PREFIX}_VERSION_MAJOR}.${${_PYTHON_PREFIX}_VERSION_MINOR}") - endif() - _python_get_path_suffixes (_${_PYTHON_PREFIX}_PATH_SUFFIXES VERSION ${_${_PYTHON_PREFIX}_VERSION} LIBRARY) - _python_get_names (_${_PYTHON_PREFIX}_LIB_NAMES VERSION ${_${_PYTHON_PREFIX}_VERSION} WIN32 POSIX LIBRARY) - - _python_get_config_var (_${_PYTHON_PREFIX}_CONFIGDIR CONFIGDIR) - list (APPEND _${_PYTHON_PREFIX}_HINTS "${_${_PYTHON_PREFIX}_CONFIGDIR}") - - list (APPEND _${_PYTHON_PREFIX}_HINTS "${${_PYTHON_PREFIX}_ROOT_DIR}" ENV ${_PYTHON_PREFIX}_ROOT_DIR) - - find_library (_${_PYTHON_PREFIX}_LIBRARY_RELEASE - NAMES ${_${_PYTHON_PREFIX}_LIB_NAMES} - NAMES_PER_DIR - HINTS ${_${_PYTHON_PREFIX}_HINTS} - PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES} - NO_SYSTEM_ENVIRONMENT_PATH - NO_CMAKE_SYSTEM_PATH) - endif() - - # Rely on HINTS and standard paths if interpreter or config tool failed to locate artifacts - if (NOT _${_PYTHON_PREFIX}_LIBRARY_RELEASE) - set (_${_PYTHON_PREFIX}_HINTS "${${_PYTHON_PREFIX}_ROOT_DIR}" ENV ${_PYTHON_PREFIX}_ROOT_DIR) - - unset (_${_PYTHON_PREFIX}_VIRTUALENV_PATHS) - if (_${_PYTHON_PREFIX}_FIND_VIRTUALENV MATCHES "^(FIRST|ONLY)$") - set (_${_PYTHON_PREFIX}_VIRTUALENV_PATHS ENV VIRTUAL_ENV ENV CONDA_PREFIX) - endif() - - if (_${_PYTHON_PREFIX}_FIND_STRATEGY STREQUAL "LOCATION") - unset (_${_PYTHON_PREFIX}_LIB_NAMES) - unset (_${_PYTHON_PREFIX}_LIB_NAMES_DEBUG) - unset (_${_PYTHON_PREFIX}_FRAMEWORK_PATHS) - unset (_${_PYTHON_PREFIX}_REGISTRY_PATHS) - unset (_${_PYTHON_PREFIX}_PATH_SUFFIXES) - - foreach (_${_PYTHON_PREFIX}_LIB_VERSION IN LISTS _${_PYTHON_PREFIX}_FIND_VERSIONS) - # library names - _python_get_names (_${_PYTHON_PREFIX}_VERSION_NAMES VERSION ${_${_PYTHON_PREFIX}_LIB_VERSION} WIN32 POSIX LIBRARY) - list (APPEND _${_PYTHON_PREFIX}_LIB_NAMES ${_${_PYTHON_PREFIX}_VERSION_NAMES}) - _python_get_names (_${_PYTHON_PREFIX}_VERSION_NAMES VERSION ${_${_PYTHON_PREFIX}_LIB_VERSION} WIN32 DEBUG) - list (APPEND _${_PYTHON_PREFIX}_LIB_NAMES_DEBUG ${_${_PYTHON_PREFIX}_VERSION_NAMES}) - - # Framework Paths - _python_get_frameworks (_${_PYTHON_PREFIX}_VERSION_PATHS ${_${_PYTHON_PREFIX}_LIB_VERSION}) - list (APPEND _${_PYTHON_PREFIX}_FRAMEWORK_PATHS ${_${_PYTHON_PREFIX}_VERSION_PATHS}) - - # Registry Paths - _python_get_registries (_${_PYTHON_PREFIX}_VERSION_PATHS ${_${_PYTHON_PREFIX}_LIB_VERSION}) - list (APPEND _${_PYTHON_PREFIX}_REGISTRY_PATHS ${_${_PYTHON_PREFIX}_VERSION_PATHS}) - - # Paths suffixes - _python_get_path_suffixes (_${_PYTHON_PREFIX}_VERSION_PATHS VERSION ${_${_PYTHON_PREFIX}_LIB_VERSION} LIBRARY) - list (APPEND _${_PYTHON_PREFIX}_PATH_SUFFIXES ${_${_PYTHON_PREFIX}_VERSION_PATHS}) - endforeach() - - if (APPLE AND _${_PYTHON_PREFIX}_FIND_FRAMEWORK STREQUAL "FIRST") - find_library (_${_PYTHON_PREFIX}_LIBRARY_RELEASE - NAMES ${_${_PYTHON_PREFIX}_LIB_NAMES} - NAMES_PER_DIR - HINTS ${_${_PYTHON_PREFIX}_HINTS} - PATHS ${_${_PYTHON_PREFIX}_VIRTUALENV_PATHS} - ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS} - PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES} - NO_CMAKE_PATH - NO_CMAKE_ENVIRONMENT_PATH - NO_SYSTEM_ENVIRONMENT_PATH - NO_CMAKE_SYSTEM_PATH) - endif() - - if (WIN32 AND _${_PYTHON_PREFIX}_FIND_REGISTRY STREQUAL "FIRST") - find_library (_${_PYTHON_PREFIX}_LIBRARY_RELEASE - NAMES ${_${_PYTHON_PREFIX}_LIB_NAMES} - NAMES_PER_DIR - HINTS ${_${_PYTHON_PREFIX}_HINTS} - PATHS ${_${_PYTHON_PREFIX}_VIRTUALENV_PATHS} - ${_${_PYTHON_PREFIX}_REGISTRY_PATHS} - PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES} - NO_SYSTEM_ENVIRONMENT_PATH - NO_CMAKE_SYSTEM_PATH) - endif() - - # search in HINTS locations - find_library (_${_PYTHON_PREFIX}_LIBRARY_RELEASE - NAMES ${_${_PYTHON_PREFIX}_LIB_NAMES} - NAMES_PER_DIR - HINTS ${_${_PYTHON_PREFIX}_HINTS} - PATHS ${_${_PYTHON_PREFIX}_VIRTUALENV_PATHS} - PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES} - NO_SYSTEM_ENVIRONMENT_PATH - NO_CMAKE_SYSTEM_PATH) - - if (APPLE AND _${_PYTHON_PREFIX}_FIND_FRAMEWORK STREQUAL "LAST") - set (__${_PYTHON_PREFIX}_FRAMEWORK_PATHS ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS}) - else() - unset (__${_PYTHON_PREFIX}_FRAMEWORK_PATHS) - endif() - - if (WIN32 AND _${_PYTHON_PREFIX}_FIND_REGISTRY STREQUAL "LAST") - set (__${_PYTHON_PREFIX}_REGISTRY_PATHS ${_${_PYTHON_PREFIX}_REGISTRY_PATHS}) - else() - unset (__${_PYTHON_PREFIX}_REGISTRY_PATHS) - endif() - - # search in all default paths - find_library (_${_PYTHON_PREFIX}_LIBRARY_RELEASE - NAMES ${_${_PYTHON_PREFIX}_LIB_NAMES} - NAMES_PER_DIR - PATHS ${__${_PYTHON_PREFIX}_FRAMEWORK_PATHS} - ${__${_PYTHON_PREFIX}_REGISTRY_PATHS} - PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES}) - else() - foreach (_${_PYTHON_PREFIX}_LIB_VERSION IN LISTS _${_PYTHON_PREFIX}_FIND_VERSIONS) - _python_get_names (_${_PYTHON_PREFIX}_LIB_NAMES VERSION ${_${_PYTHON_PREFIX}_LIB_VERSION} WIN32 POSIX LIBRARY) - _python_get_names (_${_PYTHON_PREFIX}_LIB_NAMES_DEBUG VERSION ${_${_PYTHON_PREFIX}_LIB_VERSION} WIN32 DEBUG) - - _python_get_frameworks (_${_PYTHON_PREFIX}_FRAMEWORK_PATHS ${_${_PYTHON_PREFIX}_LIB_VERSION}) - _python_get_registries (_${_PYTHON_PREFIX}_REGISTRY_PATHS ${_${_PYTHON_PREFIX}_LIB_VERSION}) - - _python_get_path_suffixes (_${_PYTHON_PREFIX}_PATH_SUFFIXES VERSION ${_${_PYTHON_PREFIX}_LIB_VERSION} LIBRARY) - - if (APPLE AND _${_PYTHON_PREFIX}_FIND_FRAMEWORK STREQUAL "FIRST") - find_library (_${_PYTHON_PREFIX}_LIBRARY_RELEASE - NAMES ${_${_PYTHON_PREFIX}_LIB_NAMES} - NAMES_PER_DIR - HINTS ${_${_PYTHON_PREFIX}_HINTS} - PATHS ${_${_PYTHON_PREFIX}_VIRTUALENV_PATHS} - ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS} - PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES} - NO_CMAKE_PATH - NO_CMAKE_ENVIRONMENT_PATH - NO_SYSTEM_ENVIRONMENT_PATH - NO_CMAKE_SYSTEM_PATH) - endif() - - if (WIN32 AND _${_PYTHON_PREFIX}_FIND_REGISTRY STREQUAL "FIRST") - find_library (_${_PYTHON_PREFIX}_LIBRARY_RELEASE - NAMES ${_${_PYTHON_PREFIX}_LIB_NAMES} - NAMES_PER_DIR - HINTS ${_${_PYTHON_PREFIX}_HINTS} - PATHS ${_${_PYTHON_PREFIX}_VIRTUALENV_PATHS} - ${_${_PYTHON_PREFIX}_REGISTRY_PATHS} - PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES} - NO_SYSTEM_ENVIRONMENT_PATH - NO_CMAKE_SYSTEM_PATH) - endif() - - # search in HINTS locations - find_library (_${_PYTHON_PREFIX}_LIBRARY_RELEASE - NAMES ${_${_PYTHON_PREFIX}_LIB_NAMES} - NAMES_PER_DIR - HINTS ${_${_PYTHON_PREFIX}_HINTS} - PATHS ${_${_PYTHON_PREFIX}_VIRTUALENV_PATHS} - PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES} - NO_SYSTEM_ENVIRONMENT_PATH - NO_CMAKE_SYSTEM_PATH) - - if (APPLE AND _${_PYTHON_PREFIX}_FIND_FRAMEWORK STREQUAL "LAST") - set (__${_PYTHON_PREFIX}_FRAMEWORK_PATHS ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS}) - else() - unset (__${_PYTHON_PREFIX}_FRAMEWORK_PATHS) - endif() - - if (WIN32 AND _${_PYTHON_PREFIX}_FIND_REGISTRY STREQUAL "LAST") - set (__${_PYTHON_PREFIX}_REGISTRY_PATHS ${_${_PYTHON_PREFIX}_REGISTRY_PATHS}) - else() - unset (__${_PYTHON_PREFIX}_REGISTRY_PATHS) - endif() - - # search in all default paths - find_library (_${_PYTHON_PREFIX}_LIBRARY_RELEASE - NAMES ${_${_PYTHON_PREFIX}_LIB_NAMES} - NAMES_PER_DIR - PATHS ${__${_PYTHON_PREFIX}_FRAMEWORK_PATHS} - ${__${_PYTHON_PREFIX}_REGISTRY_PATHS} - PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES}) - - if (_${_PYTHON_PREFIX}_LIBRARY_RELEASE) - break() - endif() - endforeach() - endif() - endif() - endif() - - # finalize library version information - _python_get_version (LIBRARY PREFIX _${_PYTHON_PREFIX}_) - - set (${_PYTHON_PREFIX}_LIBRARY_RELEASE "${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}") - - if (_${_PYTHON_PREFIX}_LIBRARY_RELEASE AND NOT EXISTS "${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}") - set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Cannot find the library \"${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}\"") - set_property (CACHE _${_PYTHON_PREFIX}_LIBRARY_RELEASE PROPERTY VALUE "${_PYTHON_PREFIX}_LIBRARY_RELEASE-NOTFOUND") - endif() - - set (_${_PYTHON_PREFIX}_HINTS "${${_PYTHON_PREFIX}_ROOT_DIR}" ENV ${_PYTHON_PREFIX}_ROOT_DIR) - - if (WIN32 AND _${_PYTHON_PREFIX}_LIBRARY_RELEASE) - # search for debug library - # use release library location as a hint - _python_get_names (_${_PYTHON_PREFIX}_LIB_NAMES_DEBUG VERSION ${_${_PYTHON_PREFIX}_VERSION} WIN32 DEBUG) - get_filename_component (_${_PYTHON_PREFIX}_PATH "${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}" DIRECTORY) - find_library (_${_PYTHON_PREFIX}_LIBRARY_DEBUG - NAMES ${_${_PYTHON_PREFIX}_LIB_NAMES_DEBUG} - NAMES_PER_DIR - HINTS "${_${_PYTHON_PREFIX}_PATH}" ${_${_PYTHON_PREFIX}_HINTS} - NO_DEFAULT_PATH) - endif() - - # retrieve runtime libraries - if (_${_PYTHON_PREFIX}_LIBRARY_RELEASE) - _python_get_names (_${_PYTHON_PREFIX}_LIB_NAMES VERSION ${_${_PYTHON_PREFIX}_VERSION} WIN32 POSIX LIBRARY) - get_filename_component (_${_PYTHON_PREFIX}_PATH "${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}" DIRECTORY) - get_filename_component (_${_PYTHON_PREFIX}_PATH2 "${_${_PYTHON_PREFIX}_PATH}" DIRECTORY) - _python_find_runtime_library (_${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE - NAMES ${_${_PYTHON_PREFIX}_LIB_NAMES} - NAMES_PER_DIR - HINTS "${_${_PYTHON_PREFIX}_PATH}" "${_${_PYTHON_PREFIX}_PATH2}" ${_${_PYTHON_PREFIX}_HINTS} - PATH_SUFFIXES bin) - endif() - if (_${_PYTHON_PREFIX}_LIBRARY_DEBUG) - _python_get_names (_${_PYTHON_PREFIX}_LIB_NAMES_DEBUG VERSION ${_${_PYTHON_PREFIX}_VERSION} WIN32 DEBUG) - get_filename_component (_${_PYTHON_PREFIX}_PATH "${_${_PYTHON_PREFIX}_LIBRARY_DEBUG}" DIRECTORY) - get_filename_component (_${_PYTHON_PREFIX}_PATH2 "${_${_PYTHON_PREFIX}_PATH}" DIRECTORY) - _python_find_runtime_library (_${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG - NAMES ${_${_PYTHON_PREFIX}_LIB_NAMES_DEBUG} - NAMES_PER_DIR - HINTS "${_${_PYTHON_PREFIX}_PATH}" "${_${_PYTHON_PREFIX}_PATH2}" ${_${_PYTHON_PREFIX}_HINTS} - PATH_SUFFIXES bin) - endif() - endif() - - if ("INCLUDE_DIR" IN_LIST _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_ARTIFACTS) - while (NOT _${_PYTHON_PREFIX}_INCLUDE_DIR) - if ("LIBRARY" IN_LIST _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_ARTIFACTS - AND NOT _${_PYTHON_PREFIX}_LIBRARY_RELEASE) - # Don't search for include dir if no library was founded - break() - endif() - - if ((${_PYTHON_PREFIX}_Interpreter_FOUND AND NOT CMAKE_CROSSCOMPILING) OR _${_PYTHON_PREFIX}_CONFIG) - _python_get_config_var (_${_PYTHON_PREFIX}_INCLUDE_DIRS INCLUDES) - - find_path (_${_PYTHON_PREFIX}_INCLUDE_DIR - NAMES Python.h - HINTS ${_${_PYTHON_PREFIX}_INCLUDE_DIRS} - NO_SYSTEM_ENVIRONMENT_PATH - NO_CMAKE_SYSTEM_PATH) - endif() - - # Rely on HINTS and standard paths if interpreter or config tool failed to locate artifacts - if (NOT _${_PYTHON_PREFIX}_INCLUDE_DIR) - unset (_${_PYTHON_PREFIX}_VIRTUALENV_PATHS) - if (_${_PYTHON_PREFIX}_FIND_VIRTUALENV MATCHES "^(FIRST|ONLY)$") - set (_${_PYTHON_PREFIX}_VIRTUALENV_PATHS ENV VIRTUAL_ENV ENV CONDA_PREFIX) - endif() - unset (_${_PYTHON_PREFIX}_INCLUDE_HINTS) - - if (_${_PYTHON_PREFIX}_LIBRARY_RELEASE) - # Use the library's install prefix as a hint - if (_${_PYTHON_PREFIX}_LIBRARY_RELEASE MATCHES "^(.+/Frameworks/Python.framework/Versions/[0-9.]+)") - list (APPEND _${_PYTHON_PREFIX}_INCLUDE_HINTS "${CMAKE_MATCH_1}") - elseif (_${_PYTHON_PREFIX}_LIBRARY_RELEASE MATCHES "^(.+)/lib(64|32)?/python[0-9.]+/config") - list (APPEND _${_PYTHON_PREFIX}_INCLUDE_HINTS "${CMAKE_MATCH_1}") - elseif (DEFINED CMAKE_LIBRARY_ARCHITECTURE AND ${_${_PYTHON_PREFIX}_LIBRARY_RELEASE} MATCHES "^(.+)/lib/${CMAKE_LIBRARY_ARCHITECTURE}") - list (APPEND _${_PYTHON_PREFIX}_INCLUDE_HINTS "${CMAKE_MATCH_1}") - else() - # assume library is in a directory under root - get_filename_component (_${_PYTHON_PREFIX}_PREFIX "${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}" DIRECTORY) - get_filename_component (_${_PYTHON_PREFIX}_PREFIX "${_${_PYTHON_PREFIX}_PREFIX}" DIRECTORY) - list (APPEND _${_PYTHON_PREFIX}_INCLUDE_HINTS "${_${_PYTHON_PREFIX}_PREFIX}") - endif() - endif() - - _python_get_frameworks (_${_PYTHON_PREFIX}_FRAMEWORK_PATHS ${_${_PYTHON_PREFIX}_VERSION}) - _python_get_registries (_${_PYTHON_PREFIX}_REGISTRY_PATHS ${_${_PYTHON_PREFIX}_VERSION}) - _python_get_path_suffixes (_${_PYTHON_PREFIX}_PATH_SUFFIXES VERSION ${_${_PYTHON_PREFIX}_VERSION} INCLUDE) - - if (APPLE AND _${_PYTHON_PREFIX}_FIND_FRAMEWORK STREQUAL "FIRST") - find_path (_${_PYTHON_PREFIX}_INCLUDE_DIR - NAMES Python.h - HINTS ${_${_PYTHON_PREFIX}_INCLUDE_HINTS} ${_${_PYTHON_PREFIX}_HINTS} - PATHS ${_${_PYTHON_PREFIX}_VIRTUALENV_PATHS} - ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS} - PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES} - NO_CMAKE_PATH - NO_CMAKE_ENVIRONMENT_PATH - NO_SYSTEM_ENVIRONMENT_PATH - NO_CMAKE_SYSTEM_PATH) - endif() - - if (WIN32 AND _${_PYTHON_PREFIX}_FIND_REGISTRY STREQUAL "FIRST") - find_path (_${_PYTHON_PREFIX}_INCLUDE_DIR - NAMES Python.h - HINTS ${_${_PYTHON_PREFIX}_INCLUDE_HINTS} ${_${_PYTHON_PREFIX}_HINTS} - PATHS ${_${_PYTHON_PREFIX}_VIRTUALENV_PATHS} - ${_${_PYTHON_PREFIX}_REGISTRY_PATHS} - PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES} - NO_SYSTEM_ENVIRONMENT_PATH - NO_CMAKE_SYSTEM_PATH) - endif() - - if (APPLE AND _${_PYTHON_PREFIX}_FIND_FRAMEWORK STREQUAL "LAST") - set (__${_PYTHON_PREFIX}_FRAMEWORK_PATHS ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS}) - else() - unset (__${_PYTHON_PREFIX}_FRAMEWORK_PATHS) - endif() - - if (WIN32 AND _${_PYTHON_PREFIX}_FIND_REGISTRY STREQUAL "LAST") - set (__${_PYTHON_PREFIX}_REGISTRY_PATHS ${_${_PYTHON_PREFIX}_REGISTRY_PATHS}) - else() - unset (__${_PYTHON_PREFIX}_REGISTRY_PATHS) - endif() - - find_path (_${_PYTHON_PREFIX}_INCLUDE_DIR - NAMES Python.h - HINTS ${_${_PYTHON_PREFIX}_INCLUDE_HINTS} ${_${_PYTHON_PREFIX}_HINTS} - PATHS ${_${_PYTHON_PREFIX}_VIRTUALENV_PATHS} - ${__${_PYTHON_PREFIX}_FRAMEWORK_PATHS} - ${__${_PYTHON_PREFIX}_REGISTRY_PATHS} - PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES} - NO_SYSTEM_ENVIRONMENT_PATH - NO_CMAKE_SYSTEM_PATH) - endif() - - # search header file in standard locations - find_path (_${_PYTHON_PREFIX}_INCLUDE_DIR - NAMES Python.h) - - break() - endwhile() - - set (${_PYTHON_PREFIX}_INCLUDE_DIRS "${_${_PYTHON_PREFIX}_INCLUDE_DIR}") - - if (_${_PYTHON_PREFIX}_INCLUDE_DIR AND NOT EXISTS "${_${_PYTHON_PREFIX}_INCLUDE_DIR}") - set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Cannot find the directory \"${_${_PYTHON_PREFIX}_INCLUDE_DIR}\"") - set_property (CACHE _${_PYTHON_PREFIX}_INCLUDE_DIR PROPERTY VALUE "${_PYTHON_PREFIX}_INCLUDE_DIR-NOTFOUND") - endif() - - if (_${_PYTHON_PREFIX}_INCLUDE_DIR) - # retrieve version from header file - _python_get_version (INCLUDE PREFIX _${_PYTHON_PREFIX}_INC_) - - if (_${_PYTHON_PREFIX}_LIBRARY_RELEASE) - # update versioning - if (_${_PYTHON_PREFIX}_INC_VERSION VERSION_EQUAL _${_PYTHON_PREFIX}_VERSION) - set (_${_PYTHON_PREFIX}_VERSION_PATCH ${_${_PYTHON_PREFIX}_INC_VERSION_PATCH}) - endif() - else() - set (_${_PYTHON_PREFIX}_VERSION ${_${_PYTHON_PREFIX}_INC_VERSION}) - set (_${_PYTHON_PREFIX}_VERSION_MAJOR ${_${_PYTHON_PREFIX}_INC_VERSION_MAJOR}) - set (_${_PYTHON_PREFIX}_VERSION_MINOR ${_${_PYTHON_PREFIX}_INC_VERSION_MINOR}) - set (_${_PYTHON_PREFIX}_VERSION_PATCH ${_${_PYTHON_PREFIX}_INC_VERSION_PATCH}) - endif() - endif() - endif() - - if (NOT ${_PYTHON_PREFIX}_Interpreter_FOUND AND NOT ${_PYTHON_PREFIX}_Compiler_FOUND) - # set public version information - set (${_PYTHON_PREFIX}_VERSION ${_${_PYTHON_PREFIX}_VERSION}) - set (${_PYTHON_PREFIX}_VERSION_MAJOR ${_${_PYTHON_PREFIX}_VERSION_MAJOR}) - set (${_PYTHON_PREFIX}_VERSION_MINOR ${_${_PYTHON_PREFIX}_VERSION_MINOR}) - set (${_PYTHON_PREFIX}_VERSION_PATCH ${_${_PYTHON_PREFIX}_VERSION_PATCH}) - endif() - - # define public variables - if ("LIBRARY" IN_LIST _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_ARTIFACTS) - set (${_PYTHON_PREFIX}_LIBRARY_DEBUG "${_${_PYTHON_PREFIX}_LIBRARY_DEBUG}") - _python_select_library_configurations (${_PYTHON_PREFIX}) - - set (${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE "${_${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE}") - set (${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG "${_${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG}") - - if (_${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE) - set (${_PYTHON_PREFIX}_RUNTIME_LIBRARY "${_${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE}") - elseif (_${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG) - set (${_PYTHON_PREFIX}_RUNTIME_LIBRARY "${_${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG}") - else() - set (${_PYTHON_PREFIX}_RUNTIME_LIBRARY "${_PYTHON_PREFIX}_RUNTIME_LIBRARY-NOTFOUND") - endif() - - _python_set_library_dirs (${_PYTHON_PREFIX}_LIBRARY_DIRS - _${_PYTHON_PREFIX}_LIBRARY_RELEASE _${_PYTHON_PREFIX}_LIBRARY_DEBUG) - if (UNIX) - if (_${_PYTHON_PREFIX}_LIBRARY_RELEASE MATCHES "${CMAKE_SHARED_LIBRARY_SUFFIX}$") - set (${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DIRS ${${_PYTHON_PREFIX}_LIBRARY_DIRS}) - endif() - else() - _python_set_library_dirs (${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DIRS - _${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE _${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG) - endif() - endif() - - if (_${_PYTHON_PREFIX}_LIBRARY_RELEASE OR _${_PYTHON_PREFIX}_INCLUDE_DIR) - if (${_PYTHON_PREFIX}_Interpreter_FOUND OR ${_PYTHON_PREFIX}_Compiler_FOUND) - # development environment must be compatible with interpreter/compiler - if ("${_${_PYTHON_PREFIX}_VERSION_MAJOR}.${_${_PYTHON_PREFIX}_VERSION_MINOR}" VERSION_EQUAL "${${_PYTHON_PREFIX}_VERSION_MAJOR}.${${_PYTHON_PREFIX}_VERSION_MINOR}" - AND "${_${_PYTHON_PREFIX}_INC_VERSION_MAJOR}.${_${_PYTHON_PREFIX}_INC_VERSION_MINOR}" VERSION_EQUAL "${_${_PYTHON_PREFIX}_VERSION_MAJOR}.${_${_PYTHON_PREFIX}_VERSION_MINOR}") - _python_set_development_module_found (Module) - _python_set_development_module_found (Embed) - endif() - elseif (${_PYTHON_PREFIX}_VERSION_MAJOR VERSION_EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR - AND "${_${_PYTHON_PREFIX}_INC_VERSION_MAJOR}.${_${_PYTHON_PREFIX}_INC_VERSION_MINOR}" VERSION_EQUAL "${_${_PYTHON_PREFIX}_VERSION_MAJOR}.${_${_PYTHON_PREFIX}_VERSION_MINOR}") - _python_set_development_module_found (Module) - _python_set_development_module_found (Embed) - endif() - if (DEFINED _${_PYTHON_PREFIX}_FIND_ABI AND - (NOT _${_PYTHON_PREFIX}_ABI IN_LIST _${_PYTHON_PREFIX}_ABIFLAGS - OR NOT _${_PYTHON_PREFIX}_INC_ABI IN_LIST _${_PYTHON_PREFIX}_ABIFLAGS)) - set (${_PYTHON_PREFIX}_Development.Module_FOUND FALSE) - set (${_PYTHON_PREFIX}_Development.Embed_FOUND FALSE) - endif() - endif() - - if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS - AND ${_PYTHON_PREFIX}_Development.Module_FOUND - AND ${_PYTHON_PREFIX}_Development.Embed_FOUND) - set (${_PYTHON_PREFIX}_Development_FOUND TRUE) - endif() - - if (_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR VERSION_GREATER_EQUAL "3" - AND NOT DEFINED ${_PYTHON_PREFIX}_SOABI) - _python_get_config_var (${_PYTHON_PREFIX}_SOABI SOABI) - endif() - - _python_compute_development_signature (Module) - _python_compute_development_signature (Embed) - - # Restore the original find library ordering - if (DEFINED _${_PYTHON_PREFIX}_CMAKE_FIND_LIBRARY_SUFFIXES) - set (CMAKE_FIND_LIBRARY_SUFFIXES ${_${_PYTHON_PREFIX}_CMAKE_FIND_LIBRARY_SUFFIXES}) - endif() - - if (${_PYTHON_PREFIX}_ARTIFACTS_INTERACTIVE) - if ("LIBRARY" IN_LIST _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_ARTIFACTS) - set (${_PYTHON_PREFIX}_LIBRARY "${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}" CACHE FILEPATH "${_PYTHON_PREFIX} Library") - endif() - if ("INCLUDE_DIR" IN_LIST _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_ARTIFACTS) - set (${_PYTHON_PREFIX}_INCLUDE_DIR "${_${_PYTHON_PREFIX}_INCLUDE_DIR}" CACHE FILEPATH "${_PYTHON_PREFIX} Include Directory") - endif() - endif() - - _python_mark_as_internal (_${_PYTHON_PREFIX}_LIBRARY_RELEASE - _${_PYTHON_PREFIX}_LIBRARY_DEBUG - _${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE - _${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG - _${_PYTHON_PREFIX}_INCLUDE_DIR - _${_PYTHON_PREFIX}_CONFIG - _${_PYTHON_PREFIX}_DEVELOPMENT_MODULE_SIGNATURE - _${_PYTHON_PREFIX}_DEVELOPMENT_EMBED_SIGNATURE) -endif() - -if ("NumPy" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS AND ${_PYTHON_PREFIX}_Interpreter_FOUND) - list (APPEND _${_PYTHON_PREFIX}_CACHED_VARS _${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR) - if (${_PYTHON_PREFIX}_FIND_REQUIRED_NumPy) - list (APPEND _${_PYTHON_PREFIX}_REQUIRED_VARS ${_PYTHON_PREFIX}_NumPy_INCLUDE_DIRS) - endif() - - if (DEFINED ${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR - AND IS_ABSOLUTE "${${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR}") - set (_${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR "${${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR}" CACHE INTERNAL "") - elseif (DEFINED _${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR) - # compute numpy signature. Depends on interpreter and development signatures - string (MD5 __${_PYTHON_PREFIX}_NUMPY_SIGNATURE "${_${_PYTHON_PREFIX}_INTERPRETER_SIGNATURE}:${_${_PYTHON_PREFIX}_DEVELOPMENT_MODULE_SIGNATURE}:${_${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR}") - if (NOT __${_PYTHON_PREFIX}_NUMPY_SIGNATURE STREQUAL _${_PYTHON_PREFIX}_NUMPY_SIGNATURE - OR NOT EXISTS "${_${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR}") - unset (_${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR CACHE) - unset (_${_PYTHON_PREFIX}_NUMPY_SIGNATURE CACHE) - endif() - endif() - - if (NOT _${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR) - execute_process( - COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -c - "from __future__ import print_function\ntry: import numpy; print(numpy.get_include(), end='')\nexcept:pass\n" - RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT - OUTPUT_VARIABLE _${_PYTHON_PREFIX}_NumPy_PATH - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE) - - if (NOT _${_PYTHON_PREFIX}_RESULT) - find_path (_${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR - NAMES "numpy/arrayobject.h" "numpy/numpyconfig.h" - HINTS "${_${_PYTHON_PREFIX}_NumPy_PATH}" - NO_DEFAULT_PATH) - endif() - endif() - - set (${_PYTHON_PREFIX}_NumPy_INCLUDE_DIRS "${_${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR}") - - if(_${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR AND NOT EXISTS "${_${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR}") - set (_${_PYTHON_PREFIX}_NumPy_REASON_FAILURE "Cannot find the directory \"${_${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR}\"") - set_property (CACHE _${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR PROPERTY VALUE "${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR-NOTFOUND") - endif() - - if (_${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR) - execute_process ( - COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -c - "from __future__ import print_function\ntry: import numpy; print(numpy.__version__, end='')\nexcept:pass\n" - RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT - OUTPUT_VARIABLE _${_PYTHON_PREFIX}_NumPy_VERSION) - if (NOT _${_PYTHON_PREFIX}_RESULT) - set (${_PYTHON_PREFIX}_NumPy_VERSION "${_${_PYTHON_PREFIX}_NumPy_VERSION}") - else() - unset (${_PYTHON_PREFIX}_NumPy_VERSION) - endif() - - # final step: set NumPy founded only if Development.Module component is founded as well - set(${_PYTHON_PREFIX}_NumPy_FOUND ${${_PYTHON_PREFIX}_Development.Module_FOUND}) - else() - set (${_PYTHON_PREFIX}_NumPy_FOUND FALSE) - endif() - - if (${_PYTHON_PREFIX}_NumPy_FOUND) - # compute and save numpy signature - string (MD5 __${_PYTHON_PREFIX}_NUMPY_SIGNATURE "${_${_PYTHON_PREFIX}_INTERPRETER_SIGNATURE}:${_${_PYTHON_PREFIX}_DEVELOPMENT_MODULE_SIGNATURE}:${${_PYTHON_PREFIX}_NumPyINCLUDE_DIR}") - set (_${_PYTHON_PREFIX}_NUMPY_SIGNATURE "${__${_PYTHON_PREFIX}_NUMPY_SIGNATURE}" CACHE INTERNAL "") - else() - unset (_${_PYTHON_PREFIX}_NUMPY_SIGNATURE CACHE) - endif() - - if (${_PYTHON_PREFIX}_ARTIFACTS_INTERACTIVE) - set (${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR "${_${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR}" CACHE FILEPATH "${_PYTHON_PREFIX} NumPy Include Directory") - endif() - - _python_mark_as_internal (_${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR - _${_PYTHON_PREFIX}_NUMPY_SIGNATURE) -endif() - -# final validation -if (${_PYTHON_PREFIX}_VERSION_MAJOR AND - NOT ${_PYTHON_PREFIX}_VERSION_MAJOR VERSION_EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR) - _python_display_failure ("Could NOT find ${_PYTHON_PREFIX}: Found unsuitable major version \"${${_PYTHON_PREFIX}_VERSION_MAJOR}\", but required major version is exact version \"${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR}\"") -endif() - -unset (_${_PYTHON_PREFIX}_REASON_FAILURE) -foreach (_${_PYTHON_PREFIX}_COMPONENT IN ITEMS Interpreter Compiler Development NumPy) - if (_${_PYTHON_PREFIX}_${_${_PYTHON_PREFIX}_COMPONENT}_REASON_FAILURE) - string (APPEND _${_PYTHON_PREFIX}_REASON_FAILURE "\n ${_${_PYTHON_PREFIX}_COMPONENT}: ${_${_PYTHON_PREFIX}_${_${_PYTHON_PREFIX}_COMPONENT}_REASON_FAILURE}") - endif() -endforeach() - -include (${CMAKE_CURRENT_LIST_DIR}/../FindPackageHandleStandardArgs.cmake) -find_package_handle_standard_args (${_PYTHON_PREFIX} - REQUIRED_VARS ${_${_PYTHON_PREFIX}_REQUIRED_VARS} - VERSION_VAR ${_PYTHON_PREFIX}_VERSION - HANDLE_COMPONENTS - REASON_FAILURE_MESSAGE "${_${_PYTHON_PREFIX}_REASON_FAILURE}") - -# Create imported targets and helper functions -if(_${_PYTHON_PREFIX}_CMAKE_ROLE STREQUAL "PROJECT") - if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS - AND ${_PYTHON_PREFIX}_Interpreter_FOUND - AND NOT TARGET ${_PYTHON_PREFIX}::Interpreter) - add_executable (${_PYTHON_PREFIX}::Interpreter IMPORTED) - set_property (TARGET ${_PYTHON_PREFIX}::Interpreter - PROPERTY IMPORTED_LOCATION "${${_PYTHON_PREFIX}_EXECUTABLE}") - endif() - - if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS - AND ${_PYTHON_PREFIX}_Compiler_FOUND - AND NOT TARGET ${_PYTHON_PREFIX}::Compiler) - add_executable (${_PYTHON_PREFIX}::Compiler IMPORTED) - set_property (TARGET ${_PYTHON_PREFIX}::Compiler - PROPERTY IMPORTED_LOCATION "${${_PYTHON_PREFIX}_COMPILER}") - endif() - - if (("Development.Module" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS - AND ${_PYTHON_PREFIX}_Development.Module_FOUND) - OR ("Development.Embed" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS - AND ${_PYTHON_PREFIX}_Development.Embed_FOUND)) - - macro (__PYTHON_IMPORT_LIBRARY __name) - if (${_PYTHON_PREFIX}_LIBRARY_RELEASE MATCHES "${CMAKE_SHARED_LIBRARY_SUFFIX}$" - OR ${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE) - set (_${_PYTHON_PREFIX}_LIBRARY_TYPE SHARED) - else() - set (_${_PYTHON_PREFIX}_LIBRARY_TYPE STATIC) - endif() - - if (NOT TARGET ${__name}) - add_library (${__name} ${_${_PYTHON_PREFIX}_LIBRARY_TYPE} IMPORTED) - endif() - - set_property (TARGET ${__name} - PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${${_PYTHON_PREFIX}_INCLUDE_DIRS}") - - if (${_PYTHON_PREFIX}_LIBRARY_RELEASE AND ${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE) - # System manage shared libraries in two parts: import and runtime - if (${_PYTHON_PREFIX}_LIBRARY_RELEASE AND ${_PYTHON_PREFIX}_LIBRARY_DEBUG) - set_property (TARGET ${__name} PROPERTY IMPORTED_CONFIGURATIONS RELEASE DEBUG) - set_target_properties (${__name} - PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "C" - IMPORTED_IMPLIB_RELEASE "${${_PYTHON_PREFIX}_LIBRARY_RELEASE}" - IMPORTED_LOCATION_RELEASE "${${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE}") - set_target_properties (${__name} - PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES_DEBUG "C" - IMPORTED_IMPLIB_DEBUG "${${_PYTHON_PREFIX}_LIBRARY_DEBUG}" - IMPORTED_LOCATION_DEBUG "${${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG}") - else() - set_target_properties (${__name} - PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES "C" - IMPORTED_IMPLIB "${${_PYTHON_PREFIX}_LIBRARIES}" - IMPORTED_LOCATION "${${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE}") - endif() - else() - if (${_PYTHON_PREFIX}_LIBRARY_RELEASE AND ${_PYTHON_PREFIX}_LIBRARY_DEBUG) - set_property (TARGET ${__name} PROPERTY IMPORTED_CONFIGURATIONS RELEASE DEBUG) - set_target_properties (${__name} - PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "C" - IMPORTED_LOCATION_RELEASE "${${_PYTHON_PREFIX}_LIBRARY_RELEASE}") - set_target_properties (${__name} - PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES_DEBUG "C" - IMPORTED_LOCATION_DEBUG "${${_PYTHON_PREFIX}_LIBRARY_DEBUG}") - else() - set_target_properties (${__name} - PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES "C" - IMPORTED_LOCATION "${${_PYTHON_PREFIX}_LIBRARY_RELEASE}") - endif() - endif() - - if (_${_PYTHON_PREFIX}_LIBRARY_TYPE STREQUAL "STATIC") - # extend link information with dependent libraries - _python_get_config_var (_${_PYTHON_PREFIX}_LINK_LIBRARIES LIBS) - if (_${_PYTHON_PREFIX}_LINK_LIBRARIES) - set_property (TARGET ${__name} - PROPERTY INTERFACE_LINK_LIBRARIES ${_${_PYTHON_PREFIX}_LINK_LIBRARIES}) - endif() - endif() - endmacro() - - if (${_PYTHON_PREFIX}_Development.Embed_FOUND) - __python_import_library (${_PYTHON_PREFIX}::Python) - endif() - - if (${_PYTHON_PREFIX}_Development.Module_FOUND) - if ("LIBRARY" IN_LIST _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_MODULE_ARTIFACTS) - # On Windows/CYGWIN/MSYS, Python::Module is the same as Python::Python - # but ALIAS cannot be used because the imported library is not GLOBAL. - __python_import_library (${_PYTHON_PREFIX}::Module) - else() - if (NOT TARGET ${_PYTHON_PREFIX}::Module) - add_library (${_PYTHON_PREFIX}::Module INTERFACE IMPORTED) - endif() - set_property (TARGET ${_PYTHON_PREFIX}::Module - PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${${_PYTHON_PREFIX}_INCLUDE_DIRS}") - - # When available, enforce shared library generation with undefined symbols - if (APPLE) - set_property (TARGET ${_PYTHON_PREFIX}::Module - PROPERTY INTERFACE_LINK_OPTIONS "LINKER:-undefined,dynamic_lookup") - endif() - if (CMAKE_SYSTEM_NAME STREQUAL "SunOS") - set_property (TARGET ${_PYTHON_PREFIX}::Module - PROPERTY INTERFACE_LINK_OPTIONS "LINKER:-z,nodefs") - endif() - if (CMAKE_SYSTEM_NAME STREQUAL "AIX") - set_property (TARGET ${_PYTHON_PREFIX}::Module - PROPERTY INTERFACE_LINK_OPTIONS "LINKER:-b,erok") - endif() - endif() - endif() - - # - # PYTHON_ADD_LIBRARY ( [STATIC|SHARED|MODULE] src1 src2 ... srcN) - # It is used to build modules for python. - # - function (__${_PYTHON_PREFIX}_ADD_LIBRARY prefix name) - cmake_parse_arguments (PARSE_ARGV 2 PYTHON_ADD_LIBRARY - "STATIC;SHARED;MODULE;WITH_SOABI" "" "") - - if (prefix STREQUAL "Python2" AND PYTHON_ADD_LIBRARY_WITH_SOABI) - message (AUTHOR_WARNING "FindPython2: Option `WITH_SOABI` is not supported for Python2 and will be ignored.") - unset (PYTHON_ADD_LIBRARY_WITH_SOABI) - endif() - - if (PYTHON_ADD_LIBRARY_STATIC) - set (type STATIC) - elseif (PYTHON_ADD_LIBRARY_SHARED) - set (type SHARED) - else() - set (type MODULE) - endif() - - if (type STREQUAL "MODULE" AND NOT TARGET ${prefix}::Module) - message (SEND_ERROR "${prefix}_ADD_LIBRARY: dependent target '${prefix}::Module' is not defined.\n Did you miss to request COMPONENT 'Development.Module'?") - return() - endif() - if (NOT type STREQUAL "MODULE" AND NOT TARGET ${prefix}::Python) - message (SEND_ERROR "${prefix}_ADD_LIBRARY: dependent target '${prefix}::Python' is not defined.\n Did you miss to request COMPONENT 'Development.Embed'?") - return() - endif() - - add_library (${name} ${type} ${PYTHON_ADD_LIBRARY_UNPARSED_ARGUMENTS}) - - get_property (type TARGET ${name} PROPERTY TYPE) - - if (type STREQUAL "MODULE_LIBRARY") - target_link_libraries (${name} PRIVATE ${prefix}::Module) - # customize library name to follow module name rules - set_property (TARGET ${name} PROPERTY PREFIX "") - if(CMAKE_SYSTEM_NAME STREQUAL "Windows") - set_property (TARGET ${name} PROPERTY SUFFIX ".pyd") - endif() - - if (PYTHON_ADD_LIBRARY_WITH_SOABI AND ${prefix}_SOABI) - get_property (suffix TARGET ${name} PROPERTY SUFFIX) - if (NOT suffix) - set (suffix "${CMAKE_SHARED_MODULE_SUFFIX}") - endif() - set_property (TARGET ${name} PROPERTY SUFFIX ".${${prefix}_SOABI}${suffix}") - endif() - else() - if (PYTHON_ADD_LIBRARY_WITH_SOABI) - message (AUTHOR_WARNING "Find${prefix}: Option `WITH_SOABI` is only supported for `MODULE` library type.") - endif() - target_link_libraries (${name} PRIVATE ${prefix}::Python) - endif() - endfunction() - endif() - - if ("NumPy" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS AND ${_PYTHON_PREFIX}_NumPy_FOUND - AND NOT TARGET ${_PYTHON_PREFIX}::NumPy AND TARGET ${_PYTHON_PREFIX}::Module) - add_library (${_PYTHON_PREFIX}::NumPy INTERFACE IMPORTED) - set_property (TARGET ${_PYTHON_PREFIX}::NumPy - PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${${_PYTHON_PREFIX}_NumPy_INCLUDE_DIRS}") - target_link_libraries (${_PYTHON_PREFIX}::NumPy INTERFACE ${_PYTHON_PREFIX}::Module) - endif() -endif() - -# final clean-up - -# Restore CMAKE_FIND_APPBUNDLE -if (DEFINED _${_PYTHON_PREFIX}_CMAKE_FIND_APPBUNDLE) - set (CMAKE_FIND_APPBUNDLE ${_${_PYTHON_PREFIX}_CMAKE_FIND_APPBUNDLE}) - unset (_${_PYTHON_PREFIX}_CMAKE_FIND_APPBUNDLE) -else() - unset (CMAKE_FIND_APPBUNDLE) -endif() -# Restore CMAKE_FIND_FRAMEWORK -if (DEFINED _${_PYTHON_PREFIX}_CMAKE_FIND_FRAMEWORK) - set (CMAKE_FIND_FRAMEWORK ${_${_PYTHON_PREFIX}_CMAKE_FIND_FRAMEWORK}) - unset (_${_PYTHON_PREFIX}_CMAKE_FIND_FRAMEWORK) -else() - unset (CMAKE_FIND_FRAMEWORK) -endif() diff --git a/scripts/internal/libpython-not-needed-symbols-exported-by-interpreter b/scripts/internal/libpython-not-needed-symbols-exported-by-interpreter deleted file mode 100644 index e69de29b..00000000 diff --git a/scripts/internal/wheel_builder_utils.py b/scripts/internal/wheel_builder_utils.py deleted file mode 100644 index 422d4f51..00000000 --- a/scripts/internal/wheel_builder_utils.py +++ /dev/null @@ -1,95 +0,0 @@ -"""This module provides convenient function facilitating scripting. - -These functions have been copied from scikit-build project. -See https://github.com/scikit-build/scikit-build -""" - -import errno -import os - -from contextlib import contextmanager -from functools import wraps - - -def mkdir_p(path): - """Ensure directory ``path`` exists. If needed, parent directories - are created. - - Adapted from http://stackoverflow.com/a/600612/1539918 - """ - try: - os.makedirs(path) - except OSError as exc: # Python >2.5 - if exc.errno == errno.EEXIST and os.path.isdir(path): - pass - else: # pragma: no cover - raise - - -@contextmanager -def push_env(**kwargs): - """This context manager allow to set/unset environment variables.""" - saved_env = dict(os.environ) - for var, value in kwargs.items(): - if value is not None: - os.environ[var] = value - elif var in os.environ: - del os.environ[var] - yield - os.environ.clear() - for saved_var, saved_value in saved_env.items(): - os.environ[saved_var] = saved_value - - -class ContextDecorator(object): - """A base class or mixin that enables context managers to work as - decorators.""" - - def __init__(self, **kwargs): - self.__dict__.update(kwargs) - - def __enter__(self): - # Note: Returning self means that in "with ... as x", x will be self - return self - - def __exit__(self, typ, val, traceback): - pass - - def __call__(self, func): - @wraps(func) - def inner(*args, **kwds): # pylint:disable=missing-docstring - with self: - return func(*args, **kwds) - - return inner - - -class push_dir(ContextDecorator): - """Context manager to change current directory.""" - - def __init__(self, directory=None, make_directory=False): - """ - :param directory: - Path to set as current working directory. If ``None`` - is passed, ``os.getcwd()`` is used instead. - - :param make_directory: - If True, ``directory`` is created. - """ - self.directory = None - self.make_directory = None - self.old_cwd = None - super(push_dir, self).__init__( - directory=directory, make_directory=make_directory - ) - - def __enter__(self): - self.old_cwd = os.getcwd() - if self.directory: - if self.make_directory: - mkdir_p(self.directory) - os.chdir(self.directory) - return self - - def __exit__(self, typ, val, traceback): - os.chdir(self.old_cwd) diff --git a/scripts/pyproject.toml.in b/scripts/pyproject.toml.in index 1ed3b17b..f583cc7e 100644 --- a/scripts/pyproject.toml.in +++ b/scripts/pyproject.toml.in @@ -9,7 +9,7 @@ name = "@PYPROJECT_NAME@" version = "@PYPROJECT_VERSION@" description = "@PYPROJECT_DESCRIPTION@" -readme = "ITK-source/ITK/README.md" +readme = "@ITK_SOURCE_README@" license = {file = "LICENSE"} authors = [ { name = "Insight Software Consortium", email = "community@itk.org" }, @@ -39,7 +39,7 @@ classifiers = [ "Topic :: Scientific/Engineering :: Medical Science Apps.", "Topic :: Software Development :: Libraries", ] -requires-python = ">=3.9" +requires-python = ">=3.10" dependencies = [ @PYPROJECT_DEPENDENCIES@ ] @@ -96,7 +96,7 @@ sdist.include = ["CMakeLists.txt", "cmake/*.cmake", "README.md", "itkVersion.py" sdist.exclude = ["scripts"] # The Python tags. The default (empty string) will use the default Python -# version. You can also set this to "cp37" to enable the CPython 3.7+ Stable ABI +# version. You can also set this to "cp310" to enable the CPython 3.10+ Stable ABI # / Limited API (only on CPython and if the version is sufficient, otherwise # this has no effect). Or you can set it to "py3" or "py2.py3" to ignore Python # ABI compatibility. The ABI tag is inferred from this tag. diff --git a/scripts/pyproject_configure.py b/scripts/pyproject_configure.py index 55ba9c2c..19b669a2 100755 --- a/scripts/pyproject_configure.py +++ b/scripts/pyproject_configure.py @@ -1,55 +1,48 @@ #!/usr/bin/env python - -"""CLI allowing to configure ``pyproject.toml`` found in ``ITKPythonPackage`` -source tree. - -Different version of ``pyproject.toml`` can be generated based on the value -of the `wheel_name` positional parameter. - -Usage:: - - pyproject_configure.py [-h] [--output-dir OUTPUT_DIR] wheel_name - - positional arguments: - wheel_name - - optional arguments: - -h, --help show this help message and exit - --output-dir OUTPUT_DIR - Output directory for configured 'pyproject.toml' - (default: /work) - - -Accepted values for `wheel_name` are ``itk`` and all values read from -``WHEEL_NAMES.txt``. -""" - import argparse import os import re +import shutil import sys +from pathlib import Path -sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) - -PARAMETER_OPTION_DEFAULTS = { - "indent": 0, - "newline_if_set": False, - "newline_indent": 0, - "remove_line_if_empty": False, -} - -PARAMETER_OPTIONS = { - "PYPROJECT_PY_MODULES": {"indent": 8, "newline_if_set": True, "newline_indent": 4}, - "PYPROJECT_DEPENDENCIES": {"indent": 8, "remove_line_if_empty": True}, -} +from packaging.version import Version +from wheel_builder_utils import read_env_file def parameter_option(key, option): - """Return value of `option` associated with parameter `key`. - - If no option is found in `PARAMETER_OPTIONS`, default value from - `PARAMETER_OPTION_DEFAULTS` is returned. + """Return a formatting option for a template parameter. + + Parameters + ---------- + key : str + Template parameter name (e.g. ``'PYPROJECT_PY_MODULES'``). + option : str + Option to look up (``'indent'``, ``'newline_if_set'``, + ``'newline_indent'``, or ``'remove_line_if_empty'``). + + Returns + ------- + int or bool + The option value from ``PARAMETER_OPTIONS`` if defined, + otherwise the default from ``PARAMETER_OPTION_DEFAULTS``. """ + PARAMETER_OPTION_DEFAULTS = { + "indent": 0, + "newline_if_set": False, + "newline_indent": 0, + "remove_line_if_empty": False, + } + + PARAMETER_OPTIONS = { + "PYPROJECT_PY_MODULES": { + "indent": 8, + "newline_if_set": True, + "newline_indent": 4, + }, + "PYPROJECT_DEPENDENCIES": {"indent": 8, "remove_line_if_empty": True}, + } + default = PARAMETER_OPTION_DEFAULTS.get(option) if key not in PARAMETER_OPTIONS.keys(): return default @@ -58,13 +51,24 @@ def parameter_option(key, option): # Copied from scikit-ci/ci/utils.py def indent(text, prefix, predicate=None): - """Adds 'prefix' to the beginning of selected lines in 'text'. - If 'predicate' is provided, 'prefix' will only be added to the lines - where 'predicate(line)' is True. If 'predicate' is not provided, - it will default to adding 'prefix' to all non-empty lines that do not - consist solely of whitespace characters. - - Copied from textwrap.py available in python 3 (cpython/cpython@a2d2bef) + """Add *prefix* to the beginning of selected lines in *text*. + + Copied from ``textwrap.py`` (cpython/cpython@a2d2bef). + + Parameters + ---------- + text : str + The multiline string to indent. + prefix : str + String prepended to each selected line. + predicate : callable, optional + Called with each line; *prefix* is added only when it returns + True. Defaults to adding *prefix* to all non-blank lines. + + Returns + ------- + str + The indented text. """ if predicate is None: @@ -73,29 +77,51 @@ def predicate(line): def prefixed_lines(): for line in text.splitlines(True): - yield (prefix + line if predicate(line) else line) + yield prefix + line if predicate(line) else line return "".join(prefixed_lines()) def list_to_str(list_, newline=True): + """Join a list of strings as quoted, comma-separated items. + + Parameters + ---------- + list_ : list[str] + Items to format. + newline : bool, optional + Use newline separators when True, spaces when False. + + Returns + ------- + str + Formatted string like ``'"a",\\n"b"'``. + """ sep = ", " if newline: sep = ",\n" - return sep.join(['"%s"' % item for item in list_]) + return sep.join([f'"{item}"' for item in list_]) def configure(template_file, parameters, output_file): - """Configure `template_file` into `output_file` given a dictionary of - `parameters`. + """Substitute ``@KEY@`` placeholders in *template_file* and write *output_file*. + + Parameters + ---------- + template_file : str or Path + Input template containing ``@KEY@`` placeholders. + parameters : dict[str, str] + Mapping of placeholder names to substitution values. + output_file : str or Path + Destination path for the configured file. """ updated_lines = [] - with open(template_file, "r") as file_: + with open(template_file) as file_: lines = file_.readlines() for line in lines: append = True for key in parameters.keys(): - value = parameters[key].strip() + value = str(parameters[key]).strip() if ( key in line and not value @@ -107,8 +133,10 @@ def configure(template_file, parameters, output_file): value = indent(value, block_indent) newline_indent = " " * parameter_option(key, "newline_indent") if value.strip() and parameter_option(key, "newline_if_set"): - value = "\n%s\n%s" % (value, newline_indent) - line = line.replace("@%s@" % key, value) + value = f"\n{value}\n{newline_indent}" + line = line.replace(f"@{key}@", value) + # Windows paths need to have backslashes escaped preserved in writing of files + line = line.replace("\\", "\\\\") if append: updated_lines.append(line) @@ -117,16 +145,56 @@ def configure(template_file, parameters, output_file): def from_group_to_wheel(group): - return "itk-%s" % group.lower() + """Convert an ITK group name to its wheel package name. + Parameters + ---------- + group : str + ITK group name (e.g. ``'Core'``, ``'Filtering'``). -def update_wheel_pyproject_toml_parameters(): - global PYPROJECT_PY_PARAMETERS - for wheel_name in get_wheel_names(): - params = dict(ITK_PYPROJECT_PY_PARAMETERS) + Returns + ------- + str + Wheel name like ``'itk-core'``. + """ + return f"itk-{group.lower()}" + + +def update_wheel_pyproject_toml_parameters( + base_params: dict, + package_env_config: dict, + SCRIPT_NAME: str, + wheel_names: list, + wheel_dependencies: dict, +): + """Build a mapping of wheel name to ``pyproject.toml`` template parameters. + + This is a pure transformation and does not mutate global state. + + Parameters + ---------- + base_params : dict + Shared base parameters common to all wheels. + package_env_config : dict + Build environment configuration (ITK paths, versions, etc.). + SCRIPT_NAME : str + Name of the calling script, embedded in the generator field. + wheel_names : list[str] + Ordered list of wheel package names to generate parameters for. + wheel_dependencies : dict[str, list[str]] + Mapping from wheel name to its dependency list. + + Returns + ------- + dict[str, dict] + ``{wheel_name: parameters_dict}`` for each wheel. + """ + PYPROJECT_PY_PARAMETERS = {} + for wheel_name in wheel_names: + params = dict(base_params) # generator - params["PYPROJECT_GENERATOR"] = "python %s '%s'" % (SCRIPT_NAME, wheel_name) + params["PYPROJECT_GENERATOR"] = f"python {SCRIPT_NAME} '{wheel_name}'" # name if wheel_name == "itk-meta": @@ -182,18 +250,21 @@ def update_wheel_pyproject_toml_parameters(): # cmake_args params["PYPROJECT_CMAKE_ARGS"] = list_to_str( [ + f"-DITK_SOURCE_DIR={package_env_config['ITK_SOURCE_DIR']}", + f"-DITK_GIT_TAG:STRING={package_env_config['ITK_GIT_TAG']}", + f"-DITK_PACKAGE_VERSION:STRING={package_env_config['ITK_PACKAGE_VERSION']}", "-DITK_WRAP_unsigned_short:BOOL=ON", "-DITK_WRAP_double:BOOL=ON", "-DITK_WRAP_complex_double:BOOL=ON", "-DITK_WRAP_IMAGE_DIMS:STRING=2;3;4", "-DITK_WRAP_DOC:BOOL=ON", - "-DITKPythonPackage_WHEEL_NAME:STRING=%s" % wheel_name, + f"-DITKPythonPackage_WHEEL_NAME:STRING={wheel_name}", ], True, ) # install_requires - wheel_depends = get_wheel_dependencies()[wheel_name] + wheel_depends = list(wheel_dependencies[wheel_name]) # py_modules if wheel_name != "itk-core": @@ -205,35 +276,63 @@ def update_wheel_pyproject_toml_parameters(): PYPROJECT_PY_PARAMETERS[wheel_name] = params + return PYPROJECT_PY_PARAMETERS -def get_wheel_names(): - with open(os.path.join(SCRIPT_DIR, "WHEEL_NAMES.txt"), "r") as _file: - return [wheel_name.strip() for wheel_name in _file.readlines()] +def get_wheel_names(IPP_BuildWheelsSupport_DIR: str): + """Read the ordered list of wheel names from ``WHEEL_NAMES.txt``. -def get_version(): - from itkVersion import get_versions + Parameters + ---------- + IPP_BuildWheelsSupport_DIR : str + Directory containing ``WHEEL_NAMES.txt``. - version = get_versions()["package-version"] - return version + Returns + ------- + list[str] + Stripped wheel names, one per line. + """ + with open(os.path.join(IPP_BuildWheelsSupport_DIR, "WHEEL_NAMES.txt")) as _file: + return [wheel_name.strip() for wheel_name in _file.readlines()] def get_py_api(): - import sys + """Return the stable ABI tag for the running Python, or empty string. + Returns + ------- + str + A tag like ``'cp311'`` for Python >= 3.11, or ``''`` otherwise. + """ + # Return empty for Python < 3.11, otherwise a cp tag like 'cp311' if sys.version_info < (3, 11): return "" - else: - return "cp" + str(sys.version_info.major) + str(sys.version_info.minor) + return f"cp{sys.version_info.major}{sys.version_info.minor}" -def get_wheel_dependencies(): - """Return a dictionary of ITK wheel dependencies.""" +def get_wheel_dependencies(SCRIPT_DIR: str, version: str, wheel_names: list): + """Parse ITK CMake files to build a wheel dependency graph. + + Parameters + ---------- + SCRIPT_DIR : str + Path to the ``scripts/`` directory. + version : str + PEP 440 version string pinned in each dependency. + wheel_names : list[str] + All known wheel names; used to build the ``itk-meta`` entry. + + Returns + ------- + dict[str, list[str]] + Mapping of wheel name to its list of pinned dependencies. + """ all_depends = {} regex_group_depends = r"set\s*\(\s*ITK\_GROUP\_([a-zA-Z0-9\_\-]+)\_DEPENDS\s*([a-zA-Z0-9\_\-\s]*)\s*" # noqa: E501 pattern = re.compile(regex_group_depends) - version = get_version() - with open(os.path.join(SCRIPT_DIR, "..", "CMakeLists.txt"), "r") as file_: + with open( + os.path.join(SCRIPT_DIR, "..", "cmake/ITKPythonPackage_BuildWheels.cmake") + ) as file_: for line in file_.readlines(): match = re.search(pattern, line) if not match: @@ -246,86 +345,226 @@ def get_wheel_dependencies(): all_depends[wheel] = _wheel_depends all_depends["itk-meta"] = [ wheel_name + "==" + version - for wheel_name in get_wheel_names() + for wheel_name in wheel_names if wheel_name != "itk-meta" ] all_depends["itk-meta"].append("numpy") return all_depends -SCRIPT_DIR = os.path.dirname(__file__) -SCRIPT_NAME = os.path.basename(__file__) - -ITK_PYPROJECT_PY_PARAMETERS = { - "PYPROJECT_GENERATOR": "python %s '%s'" % (SCRIPT_NAME, "itk"), - "PYPROJECT_NAME": r"itk", - "PYPROJECT_VERSION": get_version(), - "PYPROJECT_CMAKE_ARGS": r"", - "PYPROJECT_PY_API": get_py_api(), - "PYPROJECT_PLATLIB": r"true", - "PYPROJECT_PY_MODULES": list_to_str( - [ - "itkBase", - "itkConfig", - "itkExtras", - "itkHelpers", - "itkLazy", - "itkTemplate", - "itkTypes", - "itkVersion", - "itkBuildOptions", - ] - ), - "PYPROJECT_DOWNLOAD_URL": r"https://github.com/InsightSoftwareConsortium/ITK/releases", - "PYPROJECT_DESCRIPTION": r"ITK is an open-source toolkit for multidimensional image analysis", # noqa: E501 - "PYPROJECT_LONG_DESCRIPTION": r"ITK is an open-source, cross-platform library that " - "provides developers with an extensive suite of software " - "tools for image analysis. Developed through extreme " - "programming methodologies, ITK employs leading-edge " - "algorithms for registering and segmenting " - "multidimensional scientific images.", - "PYPROJECT_EXTRA_KEYWORDS": r'"scientific", "medical", "image", "imaging"', - "PYPROJECT_DEPENDENCIES": r"", -} - -PYPROJECT_PY_PARAMETERS = {"itk": ITK_PYPROJECT_PY_PARAMETERS} - -update_wheel_pyproject_toml_parameters() +def build_base_pyproject_parameters( + package_env_config: dict, SCRIPT_NAME: str, itk_package_version: str +): + """Return the base ``pyproject.toml`` template parameters for ITK. + + Parameters + ---------- + package_env_config : dict + Build environment configuration. + SCRIPT_NAME : str + Name of the calling script. + itk_package_version : str + PEP 440 version string for the ITK packages. + + Returns + ------- + dict[str, str] + Base parameter mapping shared across all wheel configurations. + """ + ITK_SOURCE_README: str = os.path.join( + package_env_config["ITK_SOURCE_DIR"], "README.md" + ) + return { + "PYPROJECT_GENERATOR": f"python {SCRIPT_NAME} 'itk'", + "PYPROJECT_NAME": r"itk", + "PYPROJECT_VERSION": itk_package_version, + "PYPROJECT_CMAKE_ARGS": r"", + "PYPROJECT_PY_API": get_py_api(), + "PYPROJECT_PLATLIB": r"true", + "ITK_SOURCE_DIR": package_env_config["ITK_SOURCE_DIR"], + "ITK_SOURCE_README": ITK_SOURCE_README, + "PYPROJECT_PY_MODULES": list_to_str( + [ + "itkBase", + "itkConfig", + "itkExtras", + "itkHelpers", + "itkLazy", + "itkTemplate", + "itkTypes", + "itkVersion", + "itkBuildOptions", + ] + ), + "PYPROJECT_DOWNLOAD_URL": r"https://github.com/InsightSoftwareConsortium/ITK/releases", + "PYPROJECT_DESCRIPTION": r"ITK is an open-source toolkit for multidimensional image analysis", # noqa: E501 + "PYPROJECT_LONG_DESCRIPTION": r"ITK is an open-source, cross-platform library that " + "provides developers with an extensive suite of software " + "tools for image analysis. Developed through extreme " + "programming methodologies, ITK employs leading-edge " + "algorithms for registering and segmenting " + "multidimensional scientific images.", + "PYPROJECT_EXTRA_KEYWORDS": r'"scientific", "medical", "image", "imaging"', + "PYPROJECT_DEPENDENCIES": r"", + } def main(): - # Defaults - default_output_dir = os.path.abspath(os.path.join(SCRIPT_DIR, "..")) - # Parse arguments + SCRIPT_DIR = os.path.dirname(__file__) parser = argparse.ArgumentParser( - formatter_class=argparse.ArgumentDefaultsHelpFormatter + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + description="""CLI allowing to configure ``pyproject.toml`` found in the `` ITKPythonPackage `` +source tree. + +Different versions of ``pyproject.toml`` can be generated based on the value +of the `wheel_name` positional parameter. + +Usage:: + + pyproject_configure.py [-h] [--output-dir OUTPUT_DIR] wheel_name + + positional arguments: + wheel_name + + optional arguments: + -h, --help show this help message and exit + --output-dir OUTPUT_DIR + Output directory for configured 'pyproject.toml' + (default: /work) + +Accepted values for `wheel_name` are ``itk`` and all values read from +``WHEEL_NAMES.txt``. +""", ) parser.add_argument("wheel_name") parser.add_argument( "--output-dir", type=str, help="Output directory for configured 'pyproject.toml'", - default=default_output_dir, + default=os.path.abspath(os.path.join(SCRIPT_DIR, "..")), + ) + parser.add_argument( + "--build-dir-root", + type=str, + default=f"{SCRIPT_DIR}/../", + help="The root of the build resources.", ) args = parser.parse_args() - template = os.path.join(SCRIPT_DIR, "pyproject.toml.in") - if args.wheel_name not in PYPROJECT_PY_PARAMETERS.keys(): - print("Unknown wheel name '%s'" % args.wheel_name) + print(f"Reading configuration settings from {args.env_file}") + package_env_config = read_env_file(args.env_file, args.build_dir_root) + + configure_one_pyproject_file( + SCRIPT_DIR, package_env_config, args.output_dir, args.wheel_name + ) + + +def configure_one_pyproject_file( + SCRIPT_DIR: str | bytes, package_env_config, output_dir, wheel_name: str = "itk" +): + """Generate a configured ``pyproject.toml`` for a single wheel. + + Parameters + ---------- + SCRIPT_DIR : str or bytes + Path to the ``scripts/`` directory containing templates. + package_env_config : dict + Build environment configuration. + output_dir : str or Path + Directory where ``pyproject.toml`` will be written. + wheel_name : str, optional + Which wheel to configure (default ``'itk'``). + """ + # Version needs to be python PEP 440 compliant (no leading v) + PEP440_VERSION: str = package_env_config["ITK_PACKAGE_VERSION"].removeprefix("v") + try: + Version( + PEP440_VERSION + ) # Raise InvalidVersion exception if not PEP 440 compliant + except ValueError: + print(f"Invalid PEP 440 version: {PEP440_VERSION}") + sys.exit(1) + + # Resolve script information locally + + IPP_BuildWheelsSupport_DIR = os.path.join(SCRIPT_DIR, "..", "BuildWheelsSupport") + SCRIPT_NAME = os.path.basename(__file__) + # Write itkVersion.py file to report ITK version in python. + write_itkVersion_py(Path(output_dir) / "itkVersion.py", PEP440_VERSION) + # Copy LICENSE file needed for each wheel + shutil.copy(Path(IPP_BuildWheelsSupport_DIR) / "LICENSE", output_dir) + + base_params = build_base_pyproject_parameters( + package_env_config, SCRIPT_NAME, PEP440_VERSION + ) + + wheel_names = get_wheel_names(IPP_BuildWheelsSupport_DIR) + wheel_dependencies = get_wheel_dependencies( + SCRIPT_DIR, base_params["PYPROJECT_VERSION"], wheel_names + ) + + PYPROJECT_PY_PARAMETERS = {"itk": dict(base_params)} + PYPROJECT_PY_PARAMETERS.update( + update_wheel_pyproject_toml_parameters( + base_params, + package_env_config, + SCRIPT_NAME, + wheel_names, + wheel_dependencies, + ) + ) + + if wheel_name not in PYPROJECT_PY_PARAMETERS.keys(): + print(f"Unknown wheel name '{wheel_name}'") sys.exit(1) # Configure 'pyproject.toml' - output_file = os.path.join(args.output_dir, "pyproject.toml") - configure(template, PYPROJECT_PY_PARAMETERS[args.wheel_name], output_file) - - # Configure or remove 'itk/__init__.py' - # init_py = os.path.join(args.output_dir, "itk", "__init__.py") - # if args.wheel_name in ["itk", "itk-core"]: - # with open(init_py, 'w') as file_: - # file_.write("# Stub required for package\n") - # else: - # if os.path.exists(init_py): - # os.remove(init_py) + output_file = os.path.join(output_dir, "pyproject.toml") + print(f"Generating: {output_file}") + template = os.path.join(SCRIPT_DIR, "pyproject.toml.in") + configure(template, PYPROJECT_PY_PARAMETERS[wheel_name], output_file) + + +def write_itkVersion_py(filename: str | Path, itk_package_version: str): + """Write an ``itkVersion.py`` file reporting the ITK package version. + + Parameters + ---------- + filename : str or Path + Output file path. + itk_package_version : str + PEP 440 version string to embed. + """ + itk_version_python_code = f""" +VERSION: str = '{itk_package_version}' + +def get_versions() -> str: + \"\"\"Returns versions for the ITK Python package. + + from itkVersion import get_versions + + # Returns the ITK repository version + get_versions()['version'] + + # Returns the package version. Since GitHub Releases do not support the '+' + # character in file names, this does not contain the local version + # identifier in nightly builds, i.e. + # + # '6.0.1.dev20251126' + # + # instead of + # + # '6.0.1.dev20251126+139.g922f2d9' + get_versions()['package-version'] + \"\"\" + + versions = {{}} + versions['version'] = VERSION + versions['package-version'] = VERSION.split('+')[0] + return versions +""" + with open(filename, "w") as wfid: + wfid.write(itk_version_python_code) if __name__ == "__main__": diff --git a/scripts/wheel_builder_utils.py b/scripts/wheel_builder_utils.py new file mode 100644 index 00000000..1c40dc77 --- /dev/null +++ b/scripts/wheel_builder_utils.py @@ -0,0 +1,752 @@ +"""This module provides convenient function facilitating scripting. + +These functions have been copied from scikit-build project. +See https://github.com/scikit-build/scikit-build +""" + +import filecmp +import os +import re +import shutil +import subprocess +import sys + +# from contextlib import contextmanager +from functools import wraps +from os import chdir as os_chdir +from os import environ +from pathlib import Path + +# @contextmanager +# def push_env(**kwargs): +# """This context manager allow to set/unset environment variables.""" +# saved_env = dict(os_environ) +# for var, value in kwargs.items(): +# if value is not None: +# os_environ[var] = value +# elif var in os_environ: +# del os_environ[var] +# yield +# os_environ.clear() +# for saved_var, saved_value in saved_env.items(): +# os_environ[saved_var] = saved_value + + +class ContextDecorator: + """A base class or mixin that enables context managers to work as + decorators.""" + + def __init__(self, **kwargs): + self.__dict__.update(kwargs) + + def __enter__(self): + # Note: Returning self means that in "with ... as x", x will be self + return self + + def __exit__(self, typ, val, traceback): + pass + + def __call__(self, func): + @wraps(func) + def inner(*args, **kwds): # pylint:disable=missing-docstring + with self: + return func(*args, **kwds) + + return inner + + +class push_dir(ContextDecorator): + """Context manager to change current directory.""" + + def __init__(self, directory=None, make_directory=False): + """ + :param directory: + Path to set as current working directory. If ``None`` + is passed, current working directory is used instead. + + :param make_directory: + If True, ``directory`` is created. + """ + self.directory = None + self.make_directory = None + self.old_cwd = None + super().__init__(directory=directory, make_directory=make_directory) + + def __enter__(self): + self.old_cwd = Path.cwd() + if self.directory: + if self.make_directory: + Path(self.directory).mkdir(parents=True, exist_ok=True) + os_chdir(self.directory) + return self + + def __exit__(self, typ, val, traceback): + os_chdir(self.old_cwd) + + +def _remove_tree(path: Path) -> None: + """Recursively delete a file or directory using pathlib only. + + Parameters + ---------- + path : Path + File or directory to remove. No error is raised if *path* + does not exist. + """ + if not path.exists(): + return + if path.is_file() or path.is_symlink(): + try: + path.unlink() + except OSError: + pass + return + for child in path.iterdir(): + _remove_tree(child) + try: + path.rmdir() + except OSError: + pass + + +def read_env_file( + file_path: os.PathLike | str, build_dir_root: os.PathLike | str +) -> dict[str, str]: + """Read a simple .env-style file and return a dict of key/value pairs. + + Supported syntax: + + - Blank lines and lines starting with ``#`` are ignored. + - Optional leading ``export`` prefix is stripped. + - ``KEY=VALUE`` pairs; surrounding single or double quotes are stripped. + - Whitespace around keys and the ``=`` is ignored. + - ``${BUILD_DIR_ROOT}`` in values is replaced with *build_dir_root*. + + This function does not perform variable expansion or modify ``os.environ``. + + Parameters + ---------- + file_path : os.PathLike or str + Path to the ``.env`` file. + build_dir_root : os.PathLike or str + Value substituted for ``${BUILD_DIR_ROOT}`` placeholders in values. + + Returns + ------- + dict[str, str] + Parsed key/value pairs. Returns an empty dict if the file does + not exist or cannot be read. + """ + result: dict[str, str] = {} + path = Path(file_path) + if not path.exists(): + return result + try: + content = path.read_text(encoding="utf-8") + except Exception: + return result + + for raw_line in content.splitlines(): + line = raw_line.strip() + if not line or line.startswith("#"): + continue + if line.startswith("export "): + line = line[len("export ") :].lstrip() + if "=" not in line: + continue + key, value = line.split("=", 1) + key = key.strip() + value = value.strip() + value = value.replace("${BUILD_DIR_ROOT}", str(build_dir_root)) + # Strip surrounding quotes if present + if (len(value) >= 2) and ( + (value[0] == value[-1] == '"') or (value[0] == value[-1] == "'") + ): + value = value[1:-1] + result[key] = value + return result + + +def _which(exe_name: str) -> Path | None: + """Locate an executable on ``PATH`` using pathlib. + + A custom implementation is used because ``shutil.which`` does not + reliably resolve executables on Windows before Python 3.12. + + Parameters + ---------- + exe_name : str + Name (or path fragment) of the executable to find. + + Returns + ------- + Path or None + Absolute path to the first matching executable, or ``None`` if + not found. + """ + # shutil.which only works on windows after python 3.12. + pathext: list[str] = environ.get("PATHEXT", ".EXE;.BAT;.CMD;.exe;.bat;.cmd").split( + ";" + ) + paths: list[str] = environ.get("PATH", "").split(os.pathsep) + exe: Path = Path(exe_name) + candidates: list[Path] = ( + [exe] if exe.suffix else [Path(exe_name + ext) for ext in pathext] + ) + candidates = [exe] + candidates + for p in paths: + if not p: + continue + base = Path(p) + for c in candidates: + fp = base / c + try: + if fp.exists(): + return fp + except OSError: + continue + return None + + +def detect_platform() -> tuple[str, str]: + """Detect the current operating system and CPU architecture. + + Returns + ------- + tuple[str, str] + A ``(os_name, arch)`` pair where *os_name* is one of + ``'linux'``, ``'darwin'``, ``'windows'``, or ``'unknown'``, and + *arch* is a normalized architecture string (e.g. ``'x64'``, + ``'arm64'``, ``'x86_64'``, ``'aarch64'``). + """ + uname = os.uname() if hasattr(os, "uname") else None + sysname = ( + uname.sysname if uname else ("Windows" if os.name == "nt" else sys.platform) + ) + machine = ( + uname.machine + if uname + else (os.environ.get("PROCESSOR_ARCHITECTURE", "").lower()) + ) + os_name = ( + "linux" + if sysname.lower().startswith("linux") + else ( + "darwin" + if sysname.lower().startswith("darwin") or sys.platform == "darwin" + else ("windows" if os.name == "nt" else "unknown") + ) + ) + # Normalize machine + arch = machine + if os_name == "darwin": + if machine in ("x86_64",): + arch = "x86_64" + elif machine in ("arm64", "aarch64"): + arch = "arm64" + elif os_name == "linux": + if machine in ("x86_64",): + arch = "x64" + elif machine in ("i686", "i386"): + arch = "x86" + elif machine in ("aarch64",): + arch = "aarch64" + return os_name, arch + + +def which_required(name: str) -> str: + path = shutil.which(name) + if not path: + raise RuntimeError( + f"MISSING: {name} not found in PATH; aborting until required executables can be found" + ) + return path + + +def run_commandLine_subprocess( + cmd: list[str | Path], + cwd: Path | None = None, + env: dict = None, + check: bool = False, +) -> subprocess.CompletedProcess: + """Run a command via ``subprocess.run`` with logging. + + Parameters + ---------- + cmd : list[str or Path] + Command and arguments to execute. + cwd : Path, optional + Working directory for the subprocess. + env : dict, optional + Environment variables for the subprocess. + check : bool, optional + If True, raise ``RuntimeError`` on non-zero exit codes. + + Returns + ------- + subprocess.CompletedProcess + Completed process information including stdout, stderr, and + return code. + + Raises + ------ + RuntimeError + If *check* is True and the command exits with a non-zero code. + """ + cmd = [str(x) for x in cmd] + print(f"Running >>>>>: {' '.join(cmd)} ; # in cwd={cwd} with check={check}\n") + completion_info = subprocess.run( + cmd, + cwd=str(cwd) if cwd else None, + capture_output=True, + text=True, + env=env if env else None, + ) + if completion_info.returncode != 0 and check: + error_msg = "!~" * 40 + if env: + error_msg += "ENVIRONMENT: =================" + for k, v in env.items(): + error_msg += f"\n{k}={v}" + error_msg += "==============================" + if completion_info.stdout: + error_msg += f"\nStdout:\n {completion_info.stdout}" + if completion_info.stderr: + error_msg += f"\nStderr:\n {completion_info.stderr}" + error_msg += f"Command failed with exit code {completion_info.returncode}: {' '.join(cmd)}" + print(error_msg) + raise RuntimeError(error_msg) + + return completion_info + + +def git_describe_to_pep440(desc: str) -> str: + """ + Convert `git describe --tags --long --dirty --always` output + + # v6.0b03-3-g1a2b3c4 + # │ | │ └── abbreviated commit hash + # │ | └────── commits since tag + # | └────────── pre-release type and number + # └────────────── nearest tag + to a PEP 440–compatible version string. + + [N!]N(.N)*[{a|b|rc}N][.postN][.devN]+ + 111122222233333333333444444445555555666666666666 + 1 Epoch segment: N! + 2 Release segment: N(.N)* + 3 Pre-release segment: {a|b|rc}N + 4 Post-release segment: .postN + 5 Development release segment: .devN + 6 local info not used in version ordering. I.e. ignored by package resolution rules + """ + desc = desc.strip() + semver_format = "0.0.0" + + m = re.match( + r"^(v)*(?P\d+)(?P\.\d+)(?P\.\d+)*(?Pa|b|rc|alpha|beta)*0*(?P\d*)-*(?P\d*)-*g*(?P[0-9a-fA-F]+)*(?P.dirty)*$", + desc, + ) + if m: + groupdict = m.groupdict() + + semver_format = ( + f"{groupdict.get('majorver','')}" + f"{groupdict.get('minor','')}" + ) + patch = groupdict.get("patch", None) + if patch: + semver_format += f"{patch}" + else: + semver_format += ".0" + + prereleasemapping = { + "alpha": "a", + "a": "a", + "beta": "b", + "b": "b", + "rc": "rc", + "": "", + } + prerelease_name = prereleasemapping.get(groupdict.get("pretype", ""), None) + prerelnum = groupdict.get("prerelnum", None) + if prerelease_name and prerelnum and len(prerelease_name) > 0: + semver_format += f"{prerelease_name}{prerelnum}" + posttagcount = groupdict.get("posttagcount", None) + dirty = groupdict.get("dirty", None) + if ( + len(posttagcount) > 0 + and int(posttagcount) == 0 + and (dirty is None or len(dirty) == 0) + ): + # If exactly on a tag, then do not add post, or sha + return semver_format + else: + if posttagcount and int(posttagcount) > 0: + semver_format += f".post{posttagcount}" + sha = groupdict.get("sha", None) + if sha: + semver_format += f"+g{sha.lower()}" + if dirty: + semver_format += ".dirty" + return semver_format + + +# def debug(msg: str, do_print=False) -> None: +# """Print *msg* only when *do_print* is True.""" +# if do_print: +# print(msg) +# +# +# def parse_kv_overrides(pairs: list[str]) -> dict[str, str]: +# """Parse a list of ``KEY=VALUE`` strings into a dict. +# +# A value of ``"UNSET"`` is stored as ``None`` so callers can remove +# the key from a target mapping. +# +# Parameters +# ---------- +# pairs : list[str] +# Strings of the form ``KEY=VALUE``. +# +# Returns +# ------- +# dict[str, str] +# Parsed overrides. +# +# Raises +# ------ +# SystemExit +# If an entry is not a valid ``KEY=VALUE`` pair or the key name +# is invalid. +# """ +# result: dict[str, str] = {} +# for kv in pairs: +# if "=" not in kv: +# raise SystemExit(f"ERROR: Trailing argument '{kv}' is not KEY=VALUE") +# key, value = kv.split("=", 1) +# if not key or not re.match(r"^[A-Za-z_][A-Za-z0-9_]*$", key): +# raise SystemExit(f"ERROR: Invalid variable name '{key}' in '{kv}'") +# if value == "UNSET": +# # Explicitly remove if present later +# result[key] = None # type: ignore +# else: +# result[key] = value +# return result + + +# def get_git_id( +# repo_dir: Path, pixi_exec_path, env, backup_version: str = "v0.0.0" +# ) -> str | None: +# """Return a human-readable Git identifier for *repo_dir*. +# +# Tries, in order: exact tag, branch name, short commit hash. +# Falls back to *backup_version* when none of these succeed. +# +# Parameters +# ---------- +# repo_dir : Path +# Root of the Git repository. +# pixi_exec_path : Path or str +# Path to the pixi executable (unused but kept for API compat). +# env : dict +# Environment variables passed to Git subprocesses. +# backup_version : str, optional +# Fallback identifier returned when Git queries fail. +# +# Returns +# ------- +# str or None +# A tag, branch name, short hash, or *backup_version*. +# """ +# # 1. exact tag +# try: +# run_result = run_commandLine_subprocess( +# ["git", "describe", "--tags", "--exact-match"], +# cwd=repo_dir, +# env=env, +# check=False, +# ) +# +# if run_result.returncode == 0: +# return run_result.stdout.strip() +# except subprocess.CalledProcessError: +# pass +# # 2. branch +# try: +# run_result = run_commandLine_subprocess( +# ["git", "rev-parse", "--abbrev-ref", "HEAD"], +# cwd=repo_dir, +# env=env, +# ) +# branch = run_result.stdout.strip() +# if run_result.returncode == 0 and branch != "HEAD": +# return branch +# except subprocess.CalledProcessError: +# pass +# # 3. short hash +# try: +# run_result = run_commandLine_subprocess( +# ["git", "rev-parse", "--short", "HEAD"], +# cwd=repo_dir, +# env=env, +# ) +# short_version = run_result.stdout.strip() +# if run_result.returncode == 0 and short_version != "HEAD": +# return short_version +# except subprocess.CalledProcessError: +# pass +# +# # 4. punt and give dummy backup_version identifier +# if not (repo_dir / ".git").is_dir(): +# if (repo_dir / ".git").is_file(): +# print( +# f"WARNING: {str(repo_dir)} is a secondary git worktree, and may not resolve from within dockcross build" +# ) +# return backup_version +# print(f"ERROR: {repo_dir} is not a primary git repository") +# return backup_version + + +def compute_itk_package_version( + itk_dir: Path, itk_git_tag: str, pixi_exec_path, env +) -> str: + """Compute a PEP 440 version string for the ITK package. + + Fetches tags, checks out *itk_git_tag*, and runs + ``git describe --tags --long --dirty --always`` to produce a version + via `git_describe_to_pep440`. + + Parameters + ---------- + itk_dir : Path + Path to the ITK source repository. + itk_git_tag : str + Git tag, branch, or commit to check out before describing. + pixi_exec_path : Path or str + Path to the pixi executable (unused but kept for API compat). + env : dict + Environment variables passed to Git subprocesses. + + Returns + ------- + str + PEP 440-compliant version string. + """ + # Try to compute from git describe + try: + run_commandLine_subprocess( + ["git", "fetch", "--tags"], + cwd=itk_dir, + env=env, + ) + try: + run_commandLine_subprocess( + ["git", "checkout", itk_git_tag], + cwd=itk_dir, + env=env, + ) + except Exception as e: + print( + f"WARNING: Failed to checkout {itk_git_tag}, reverting to 'main': {e}" + ) + itk_git_tag = "main" + run_commandLine_subprocess( + ["git", "checkout", itk_git_tag], + cwd=itk_dir, + env=env, + ) + desc = run_commandLine_subprocess( + [ + "git", + "describe", + "--tags", + "--long", + "--dirty", + "--always", + ], + cwd=itk_dir, + env=env, + ).stdout.strip() + version = git_describe_to_pep440(desc) + except subprocess.CalledProcessError: + version = itk_git_tag.lstrip("v") + + return version + + +def default_manylinux( + manylinux_version: str, os_name: str, arch: str, env: dict[str, str] +) -> tuple[str, str, str]: + """Resolve default manylinux container image details. + + Parameters + ---------- + manylinux_version : str + Manylinux specification (e.g. ``'_2_28'``, ``'_2_34'``). + os_name : str + Operating system name (only ``'linux'`` triggers resolution). + arch : str + Target architecture (``'x64'``, ``'aarch64'``). + env : dict[str, str] + Environment variables that may override image defaults + (``IMAGE_TAG``, ``CONTAINER_SOURCE``, ``MANYLINUX_IMAGE_NAME``). + + Returns + ------- + tuple[str, str, str] + ``(image_tag, image_name, container_source)``. + + Raises + ------ + RuntimeError + If *manylinux_version* or *arch* is unrecognized. + """ + image_tag = env.get("IMAGE_TAG", "") + container_source = env.get("CONTAINER_SOURCE", "") + image_name = env.get("MANYLINUX_IMAGE_NAME", "") + + if os_name == "linux": + if arch == "x64" and manylinux_version == "_2_34": + image_tag = image_tag or "latest" + elif arch == "x64" and manylinux_version == "_2_28": + image_tag = image_tag or "20250913-6ea98ba" + elif arch == "aarch64" and manylinux_version == "_2_28": + image_tag = image_tag or "2025.08.12-1" + elif manylinux_version == "": + image_tag = "" + else: + raise RuntimeError( + f"FAILURE: Unknown manylinux version {manylinux_version}" + ) + + if arch == "x64": + image_name = ( + image_name or f"manylinux{manylinux_version}-{arch}:{image_tag}" + ) + container_source = container_source or f"docker.io/dockcross/{image_name}" + elif arch == "aarch64": + image_name = ( + image_name or f"manylinux{manylinux_version}_{arch}:{image_tag}" + ) + container_source = container_source or f"quay.io/pypa/{image_name}" + else: + raise RuntimeError(f"Unknown target architecture {arch}") + + return image_tag, image_name, container_source + + +def resolve_oci_exe(env: dict[str, str]) -> str: + """Find an OCI container runtime (docker, podman, or nerdctl). + + Checks ``OCI_EXE`` in *env* first, then probes ``PATH`` for known + runtimes. Defaults to ``'docker'`` if nothing is found. + + Parameters + ---------- + env : dict[str, str] + Environment variables; ``OCI_EXE`` is checked first. + + Returns + ------- + str + Name or path of the OCI runtime executable. + """ + if env.get("OCI_EXE"): + return env["OCI_EXE"] + for cand in ("docker", "podman", "nerdctl"): + if _which(cand): # NOTE shutil.which ALWAYS RETURNS NONE ON WINDOWS before 3.12 + return cand + # Default to docker name if nothing found + return "docker" + + +# def cmake_compiler_defaults(build_dir: Path) -> tuple[str | None, str | None]: +# info = build_dir / "cmake_system_information" +# if not info.exists(): +# try: +# out = run_commandLine_subprocess(["cmake", "--system-information"]).stdout +# info.write_text(out, encoding="utf-8") +# except Exception as e: +# print(f"WARNING: Failed to generate cmake_system_information: {e}") +# return None, None +# text = info.read_text(encoding="utf-8", errors="ignore") +# cc = None +# cxx = None +# for line in text.splitlines(): +# if "CMAKE_C_COMPILER == " in line: +# parts = re.split(r"\s+", line.strip()) +# if len(parts) >= 4: +# cc = parts[3] +# if "CMAKE_CXX_COMPILER == " in line: +# parts = re.split(r"\s+", line.strip()) +# if len(parts) >= 4: +# cxx = parts[3] +# return cc, cxx + + +def give_relative_path(bin_exec: Path, build_dir_root: Path) -> str: + bin_exec = Path(bin_exec).resolve() + build_dir_root = Path(build_dir_root).resolve() + if bin_exec.is_relative_to(build_dir_root): + return "${BUILD_DIR_ROOT}" + os.sep + str(bin_exec.relative_to(build_dir_root)) + return str(bin_exec) + + +def safe_copy_if_different(src: Path, dst: Path) -> None: + """Copy file only if destination is missing or contents differ. + + This avoids unnecessary overwrites and timestamp churn when files are identical. + """ + src = Path(src) + dst = Path(dst) + if not dst.exists(): + dst.parent.mkdir(parents=True, exist_ok=True) + shutil.copyfile(src, dst) + return + try: + same = filecmp.cmp(src, dst, shallow=False) + except Exception as e: + # On any comparison failure, fall back to copying to be safe + same = False + print(f"WARNING: Failed to compare {src} to {dst}: {e}") + if not same: + shutil.copyfile(src, dst) + + +def get_default_platform_build(default_python_version: str = "py311") -> str: + """Return a default ``-`` build identifier. + + Inspects the ``PIXI_ENVIRONMENT_NAME`` environment variable first; + falls back to ``sys.platform`` detection. + + Parameters + ---------- + default_python_version : str, optional + Python version suffix used when not running inside pixi + (default ``'py311'``). + + Returns + ------- + str + A string like ``'manylinux_2_28-py311'`` or ``'macosx-py311'``. + """ + from_pixi = os.environ.get("PIXI_ENVIRONMENT_NAME", None) + if from_pixi and "-" in from_pixi: + manylinux_pixi_to_pattern_renaming: dict[str, str] = { + "manylinux228": "manylinux_2_28", + "manylinux234": "manylinux_2_34", + } + platform_prefix: str = from_pixi.split("-")[0] + python_version: str = from_pixi.split("-")[1] + platform_prefix = manylinux_pixi_to_pattern_renaming.get( + platform_prefix, platform_prefix + ) + return f"{platform_prefix}-{python_version}" + else: + if sys.platform == "darwin": + return f"macosx-{default_python_version}" + elif sys.platform.startswith("linux"): + return f"linux-{default_python_version}" + elif sys.platform == "win32": + return f"windows-{default_python_version}" + return f"unknown-{default_python_version}" From f5ccf4a3abd1cc23791c6a2e93b6f54ea3c75de3 Mon Sep 17 00:00:00 2001 From: Cavan Riley Date: Tue, 17 Mar 2026 15:34:12 -0500 Subject: [PATCH 03/27] ENH: Add platform-specific Python build scripts for Linux, macOS, and Windows Implements platform build scripts using the new Python infrastructure. Linux/manylinux builds use dockcross with auditwheel for manylinux compliance. macOS builds integrate delocate and respect MACOSX_DEPLOYMENT_TARGET. Windows builds use delvewheel for wheel repair. Removes legacy shell scripts superseded by the new Python implementations. Co-authored-by: Hans J. Johnson --- cmake/ITKPythonPackage_SuperBuild.cmake | 2 + scripts/build_python_instance_base.py | 244 +++++++++- .../dockcross-manylinux-build-module-deps.sh | 105 ----- ...dockcross-manylinux-build-module-wheels.sh | 200 +++++++-- scripts/dockcross-manylinux-build-wheels.sh | 155 +++++-- scripts/dockcross-manylinux-cleanup.sh | 46 -- ...-download-cache-and-build-module-wheels.sh | 94 +++- scripts/dockcross-manylinux-download-cache.sh | 127 +++--- scripts/dockcross-manylinux-set-vars.sh | 62 --- scripts/docker_build_environment_driver.sh | 100 +++++ .../manylinux-aarch64-build-module-wheels.sh | 15 - scripts/internal/manylinux-build-common.sh | 85 ---- .../internal/manylinux-build-module-wheels.sh | 144 ------ scripts/internal/manylinux-build-wheels.sh | 215 --------- scripts/internal/shellcheck-run.sh | 35 -- scripts/internal/windows_build_common.py | 60 --- scripts/linux_build_python_instance.py | 278 ++++++++++++ scripts/macos_build_python_instance.py | 140 ++++++ scripts/macpython-build-common.sh | 79 ---- scripts/macpython-build-module-deps.sh | 75 ---- scripts/macpython-build-module-wheels.sh | 134 ------ scripts/macpython-build-wheels.sh | 238 ---------- ...-download-cache-and-build-module-wheels.sh | 204 ++++++--- scripts/macpython-install-python.sh | 423 ------------------ scripts/oci_exe.sh | 23 - scripts/update_python_version.py | 96 ---- scripts/update_python_version.sh | 50 --- ...download-cache-and-build-module-wheels.ps1 | 294 ++++++++---- scripts/windows_build_module_wheels.py | 251 ----------- scripts/windows_build_python_instance.py | 256 +++++++++++ scripts/windows_build_wheels.py | 411 ----------------- 31 files changed, 1758 insertions(+), 2883 deletions(-) delete mode 100755 scripts/dockcross-manylinux-build-module-deps.sh delete mode 100755 scripts/dockcross-manylinux-cleanup.sh delete mode 100755 scripts/dockcross-manylinux-set-vars.sh create mode 100755 scripts/docker_build_environment_driver.sh delete mode 100755 scripts/internal/manylinux-aarch64-build-module-wheels.sh delete mode 100644 scripts/internal/manylinux-build-common.sh delete mode 100755 scripts/internal/manylinux-build-module-wheels.sh delete mode 100755 scripts/internal/manylinux-build-wheels.sh delete mode 100755 scripts/internal/shellcheck-run.sh delete mode 100644 scripts/internal/windows_build_common.py create mode 100644 scripts/linux_build_python_instance.py create mode 100644 scripts/macos_build_python_instance.py delete mode 100644 scripts/macpython-build-common.sh delete mode 100644 scripts/macpython-build-module-deps.sh delete mode 100755 scripts/macpython-build-module-wheels.sh delete mode 100755 scripts/macpython-build-wheels.sh delete mode 100755 scripts/macpython-install-python.sh delete mode 100644 scripts/oci_exe.sh delete mode 100755 scripts/update_python_version.py delete mode 100755 scripts/update_python_version.sh delete mode 100755 scripts/windows_build_module_wheels.py create mode 100644 scripts/windows_build_python_instance.py delete mode 100644 scripts/windows_build_wheels.py diff --git a/cmake/ITKPythonPackage_SuperBuild.cmake b/cmake/ITKPythonPackage_SuperBuild.cmake index 8f418bcd..1c59987b 100644 --- a/cmake/ITKPythonPackage_SuperBuild.cmake +++ b/cmake/ITKPythonPackage_SuperBuild.cmake @@ -243,6 +243,7 @@ endif() message(STATUS "SuperBuild - Python3_INCLUDE_DIR: ${Python3_INCLUDE_DIR}") message(STATUS "SuperBuild - Python3_INCLUDE_DIRS: ${Python3_INCLUDE_DIRS}") message(STATUS "SuperBuild - Python3_LIBRARY: ${Python3_LIBRARY}") +message(STATUS "SuperBuild - Python3_SABI_LIBRARY: ${Python3_SABI_LIBRARY}") message(STATUS "SuperBuild - Python3_EXECUTABLE: ${Python3_EXECUTABLE}") message(STATUS "SuperBuild - Searching for python[OK]") message(STATUS "SuperBuild - DOXYGEN_EXECUTABLE: ${DOXYGEN_EXECUTABLE}") @@ -306,6 +307,7 @@ if(NOT ITKPythonPackage_ITK_BINARY_REUSE) -DDOXYGEN_EXECUTABLE:FILEPATH=${DOXYGEN_EXECUTABLE} -DPython3_INCLUDE_DIR:PATH=${Python3_INCLUDE_DIR} -DPython3_LIBRARY:FILEPATH=${Python3_LIBRARY} + -DPython3_SABI_LIBRARY:FILEPATH=${Python3_SABI_LIBRARY} -DPython3_EXECUTABLE:FILEPATH=${Python3_EXECUTABLE} ${ep_common_cmake_cache_args} ${tbb_args} ${ep_itk_cmake_cache_args} ${ep_download_extract_timestamp_arg} diff --git a/scripts/build_python_instance_base.py b/scripts/build_python_instance_base.py index b6a73c11..33dac2e5 100644 --- a/scripts/build_python_instance_base.py +++ b/scripts/build_python_instance_base.py @@ -1,3 +1,4 @@ +import copy import os import shutil import subprocess @@ -5,6 +6,7 @@ from abc import ABC, abstractmethod from collections import OrderedDict from collections.abc import Callable +from os import environ from pathlib import Path from BuildManager import BuildManager @@ -19,12 +21,41 @@ class BuildPythonInstanceBase(ABC): - """ - Abstract base class to build wheels for a single Python environment. - - Concrete subclasses implement platform-specific details by delegating to - injected helper functions. This avoids circular imports with the script - that defines those helpers. + """Abstract base class to build wheels for a single Python environment. + + Concrete subclasses implement platform-specific details (environment + setup, wheel fixup, tarball creation) while this class provides the + shared build orchestration, CMake configuration, and wheel-building + logic. + + Parameters + ---------- + platform_env : str + Platform/environment identifier (e.g. ``'manylinux228-py311'``). + build_dir_root : Path + Root directory for all build artifacts. + package_env_config : dict + Mutable configuration dictionary populated throughout the build. + cleanup : bool + Whether to remove intermediate build artifacts. + build_itk_tarball_cache : bool + Whether to create a reusable tarball of the ITK build tree. + cmake_options : list[str] + Extra ``-D`` options forwarded to CMake. + windows_extra_lib_paths : list[str] + Additional library paths for Windows wheel fixup (delvewheel). + dist_dir : Path + Output directory for built wheel files. + module_source_dir : Path, optional + Path to an external ITK remote module to build. + module_dependencies_root_dir : Path, optional + Directory where remote module dependencies are cloned. + itk_module_deps : str, optional + Colon-delimited dependency specifications for remote modules. + skip_itk_build : bool, optional + Skip the ITK C++ build step. + skip_itk_wheel_build : bool, optional + Skip the ITK wheel build step. """ def __init__( @@ -166,6 +197,7 @@ def __init__( ) def update_venv_itk_build_configurations(self) -> None: + """Set ``Python3_ROOT_DIR`` in ITK build configurations from venv info.""" # Python3_EXECUTABLE, Python3_INCLUDE_DIR, and Python3_LIBRARY are validated # and resolved by find_package(Python3) in cmake/ITKPythonPackage_SuperBuild.cmake # when not already defined. Python3_ROOT_DIR is set here to guide that search. @@ -248,6 +280,7 @@ def run(self) -> None: print("=" * 80) def build_superbuild_support_components(self): + """Configure and build the superbuild support components (ITK source, TBB).""" # ----------------------------------------------------------------------- # Build required components (optional local ITK source, TBB builds) used to populate the archive cache @@ -297,13 +330,22 @@ def build_superbuild_support_components(self): ) def fixup_wheels(self, lib_paths: str = ""): + """Apply platform-specific fixups to ``itk_core`` wheels for TBB linkage.""" # TBB library fix-up (applies to itk_core wheel) tbb_wheel = "itk_core" for wheel in (self.build_dir_root / "dist").glob(f"{tbb_wheel}*.whl"): self.fixup_wheel(str(wheel), lib_paths) def final_wheel_import_test(self, installed_dist_dir: Path): - self.echo_check_call( + """Install and smoke-test all ITK wheels from *installed_dist_dir*. + + Parameters + ---------- + installed_dist_dir : Path + Directory containing the built ``.whl`` files to install and + verify. + """ + exit_status = self.echo_check_call( [ self.package_env_config["PYTHON_EXECUTABLE"], "-m", @@ -316,7 +358,10 @@ def final_wheel_import_test(self, installed_dist_dir: Path): str(installed_dist_dir), ] ) - print("Wheel successfully installed.") + if exit_status == 0: + print("Wheels successfully installed.") + else: + print(f"Failed to install wheels: {exit_status}") # Basic imports self.echo_check_call( [self.package_env_config["PYTHON_EXECUTABLE"], "-c", "import itk;"] @@ -392,6 +437,24 @@ def find_unix_exectable_paths( self, venv_dir: Path, ) -> tuple[str, str, str, str, str]: + """Resolve Python interpreter and virtualenv paths on Unix. + + Parameters + ---------- + venv_dir : Path + Root of the Python virtual environment. + + Returns + ------- + tuple[str, str, str, str, str] + ``(python_executable, python_include_dir, python_library, + venv_bin_path, venv_base_dir)``. + + Raises + ------ + FileNotFoundError + If the Python executable does not exist under *venv_dir*. + """ python_executable = venv_dir / "bin" / "python" if not python_executable.exists(): raise FileNotFoundError(f"Python executable not found: {python_executable}") @@ -426,48 +489,170 @@ def find_unix_exectable_paths( str(venv_dir), ) - @abstractmethod def clone(self): - # each subclass must implement this method that is used to clone itself - pass + """Return a deep copy of this instance for building a dependency. - @abstractmethod - def venv_paths(self): - pass + Uses ``self.__class__`` so the returned object is the same concrete + subclass as the original (e.g. ``LinuxBuildPythonInstance``). + """ + cls = self.__class__ + new = cls.__new__(cls) + new.__dict__ = copy.deepcopy(self.__dict__) + return new + + def venv_paths(self) -> None: + """Populate ``venv_info_dict`` from the pixi-managed Python interpreter. + + Default Unix implementation shared by Linux and macOS. Windows + overrides this method with its own path conventions. + """ + primary_python_base_dir = Path( + self.package_env_config["PYTHON_EXECUTABLE"] + ).parent.parent + ( + python_executable, + python_include_dir, + python_library, + venv_bin_path, + venv_base_dir, + ) = self.find_unix_exectable_paths(primary_python_base_dir) + self.venv_info_dict = { + "python_executable": python_executable, + "python_include_dir": python_include_dir, + "python_library": python_library, + "venv_bin_path": venv_bin_path, + "venv_base_dir": venv_base_dir, + "python_root_dir": primary_python_base_dir, + } @abstractmethod def fixup_wheel( self, filepath, lib_paths: str = "", remote_module_wheel: bool = False ): # pragma: no cover - abstract + """Apply platform-specific wheel repairs (auditwheel, delocate, delvewheel). + + Parameters + ---------- + filepath : str + Path to the ``.whl`` file to fix. + lib_paths : str, optional + Additional library search paths (semicolon-delimited on Windows). + remote_module_wheel : bool, optional + True when fixing a wheel for an external remote module. + """ pass @abstractmethod def build_tarball(self): + """Create a compressed archive of the ITK build tree for caching.""" pass - @abstractmethod - def post_build_cleanup(self): - pass + def post_build_cleanup(self) -> None: + """Remove intermediate build artifacts, leaving ``dist/`` intact. + + Actions: + - remove oneTBB-prefix (symlink or dir) + - remove ITKPythonPackage/, tools/, _skbuild/, build/ + - remove top-level *.egg-info + - remove ITK-* build tree and tarballs + - if ITK_MODULE_PREQ is set, remove cloned module dirs + """ + base = Path(self.package_env_config["IPP_SOURCE_DIR"]) + + def rm(tree_path: Path): + try: + _remove_tree(tree_path) + except Exception: + pass + + # 1) unlink oneTBB-prefix if it's a symlink or file + tbb_prefix_dir = base / "oneTBB-prefix" + try: + if tbb_prefix_dir.is_symlink() or tbb_prefix_dir.is_file(): + tbb_prefix_dir.unlink(missing_ok=True) # type: ignore[arg-type] + elif tbb_prefix_dir.exists(): + rm(tbb_prefix_dir) + except Exception: + pass + + # 2) standard build directories + for rel in ("ITKPythonPackage", "tools", "_skbuild", "build"): + rm(base / rel) + + # 3) egg-info folders at top-level + for p in base.glob("*.egg-info"): + rm(p) + + # 4) ITK build tree and tarballs + target_arch = self.package_env_config["ARCH"] + for p in base.glob(f"ITK-*-{self.package_env_config}_{target_arch}"): + rm(p) + + # Tarballs + for p in base.glob(f"ITKPythonBuilds-{self.package_env_config}*.tar.zst"): + rm(p) + + # 5) Optional module prerequisites cleanup (ITK_MODULE_PREQ) + # Format: "InsightSoftwareConsortium/ITKModuleA@v1.0:Kitware/ITKModuleB@sha" + itk_preq = self.package_env_config.get("ITK_MODULE_PREQ") or environ.get( + "ITK_MODULE_PREQ", "" + ) + if itk_preq: + for entry in itk_preq.split(":"): + entry = entry.strip() + if not entry: + continue + try: + module_name = entry.split("@", 1)[0].split("/", 1)[1] + except Exception: + continue + rm(base / module_name) @abstractmethod def prepare_build_env(self) -> None: # pragma: no cover - abstract + """Set up platform-specific build environment and CMake configurations. + + Must populate ``self.venv_info_dict``, configure TBB settings, + and set the ITK binary build directory in + ``self.cmake_itk_source_build_configurations``. + """ pass @abstractmethod def post_build_fixup(self) -> None: # pragma: no cover - abstract - pass + """Run platform-specific post-build wheel fixups. - @abstractmethod - def final_import_test(self) -> None: # pragma: no cover - abstract + Called after all wheels are built but before the final import + test. Typically invokes ``fixup_wheel`` or ``fixup_wheels``. + """ pass + def final_import_test(self) -> None: # pragma: no cover + """Install and smoke-test the built wheels.""" + self.final_wheel_import_test(installed_dist_dir=self.dist_dir) + @abstractmethod def discover_python_venvs( self, platform_os_name: str, platform_architechure: str ) -> list[str]: + """Return available Python environment names for the given platform. + + Parameters + ---------- + platform_os_name : str + Operating system identifier. + platform_architechure : str + CPU architecture identifier. + + Returns + ------- + list[str] + Sorted list of discovered environment names. + """ pass def build_external_module_python_wheel(self): + """Build a wheel for an external ITK remote module via scikit-build-core.""" self.module_source_dir = Path(self.module_source_dir) out_dir = self.module_source_dir / "dist" out_dir.mkdir(parents=True, exist_ok=True) @@ -546,6 +731,14 @@ def build_external_module_python_wheel(self): if py_include: defs.set("Python3_INCLUDE_DIR:PATH", py_include) + # Pass Python library paths when explicitly known (Windows) + py_library = self.venv_info_dict.get("python_library", "") + if py_library: + defs.set("Python3_LIBRARY:FILEPATH", str(py_library)) + py_sabi_library = self.venv_info_dict.get("python_sabi_library", "") + if py_sabi_library: + defs.set("Python3_SABI_LIBRARY:FILEPATH", str(py_sabi_library)) + # Allow command-line cmake -D overrides to win last if self.cmake_cmdline_definitions: defs.update(self.cmake_cmdline_definitions.items()) @@ -567,6 +760,7 @@ def build_external_module_python_wheel(self): self.fixup_wheel(str(wheel), remote_module_wheel=True) def build_itk_python_wheels(self): + """Build all ITK Python wheels listed in ``WHEEL_NAMES.txt``.""" # Build wheels for wheel_name in self.wheel_names: print("#") @@ -640,6 +834,7 @@ def build_itk_python_wheels(self): _remove_tree(bp / "Wrapping" / "Generators" / "CastXML") def build_wrapped_itk_cplusplus(self): + """Configure and build the ITK C++ libraries with Python wrapping.""" # Clean up previous invocations if ( self.cleanup @@ -940,9 +1135,14 @@ def create_posix_tarball(self): if issues: print("Compatibility warnings above - review before using in CI/CD") - @abstractmethod def get_pixi_environment_name(self): - pass + """Return the pixi environment name for this build instance. + + The pixi environment name is the same as the platform_env and + is related to the environment setups defined in pixi.toml + in the root of this git directory that contains these scripts. + """ + return self.platform_env def echo_check_call( self, diff --git a/scripts/dockcross-manylinux-build-module-deps.sh b/scripts/dockcross-manylinux-build-module-deps.sh deleted file mode 100755 index dede51d3..00000000 --- a/scripts/dockcross-manylinux-build-module-deps.sh +++ /dev/null @@ -1,105 +0,0 @@ -#!/bin/bash - -######################################################################## -# Run this script in an ITK external module directory to generate -# build artifacts for prerequisite ITK external modules. -# -# Module dependencies are built in a flat directory structure regardless -# of recursive dependencies. Prerequisite sources are required to be passed -# in the order in which they should be built. -# For example, if ITKTargetModule depends on ITKTargetModuleDep2 which -# depends on ITKTargetModuleDep1, the output directory structure -# will look like this: -# -# / ITKTargetModule -# -- / ITKTargetModuleDep1 -# -- / ITKTargetModuleDep2 -# .. -# -# =========================================== -# ENVIRONMENT VARIABLES -# -# - `ITK_MODULE_PREQ`: Prerequisite ITK modules that must be built before the requested module. -# Format is `/@:/@:...`. -# For instance, `export ITK_MODULE_PREQ=InsightSoftwareConsortium/ITKMeshToPolyData@v0.10.0` -# -######################################################################## - -# Initialize variables - -script_dir=$(cd $(dirname $0) || exit 1; pwd) -if [[ ! -f "${script_dir}/dockcross-manylinux-download-cache-and-build-module-wheels.sh" ]]; then - echo "Could not find download script to use for building module dependencies!" - exit 1 -fi - -source "${script_dir}/dockcross-manylinux-set-vars.sh" - -# Temporarily update prerequisite environment variable to prevent infinite recursion. -ITK_MODULE_PREQ_TOPLEVEL=${ITK_MODULE_PREQ} -ITK_MODULE_NO_CLEANUP_TOPLEVEL=${ITK_MODULE_NO_CLEANUP} -export ITK_MODULE_PREQ="" -export ITK_MODULE_NO_CLEANUP="ON" - -######################################################################## -# Build ITK module dependencies - -for MODULE_INFO in ${ITK_MODULE_PREQ_TOPLEVEL//:/ }; do - MODULE_ORG=`(echo ${MODULE_INFO} | cut -d'/' -f 1)` - MODULE_NAME=`(echo ${MODULE_INFO} | cut -d'@' -f 1 | cut -d'/' -f 2)` - MODULE_TAG=`(echo ${MODULE_INFO} | cut -d'@' -f 2)` - - MODULE_UPSTREAM=https://github.com/${MODULE_ORG}/${MODULE_NAME}.git - echo "Cloning from ${MODULE_UPSTREAM}" - git clone ${MODULE_UPSTREAM} - - # Reuse cached build archive instead of redownloading. - # Build archives are usually ~2GB so it is reasonable to move - # instead of redownloading. - if [[ `(compgen -G ./ITKPythonBuilds-linux*.tar.zst)` ]]; then - mv ITKPythonBuilds-linux*.tar.zst ${MODULE_NAME}/ - fi - - pushd ${MODULE_NAME} - git checkout ${MODULE_TAG} - cp ../dockcross-manylinux-download-cache-and-build-module-wheels.sh . - if [[ -d ../ITKPythonPackage ]]; then - ln -s ../ITKPythonPackage - ln -s ./ITKPythonPackage/oneTBB-prefix - fi - - echo "Building module dependency ${MODULE_NAME}" - ./dockcross-manylinux-download-cache-and-build-module-wheels.sh "$@" - popd - - echo "Cleaning up module dependency" - cp ./${MODULE_NAME}/include/* include/ - find ${MODULE_NAME}/wrapping -name '*.in' -print -exec cp {} wrapping \; - find ${MODULE_NAME}/wrapping -name '*.init' -print -exec cp {} wrapping \; - find ${MODULE_NAME}/*build/*/include -type f -print -exec cp {} include \; - - # Cache build archive - if [[ `(compgen -G ./ITKPythonBuilds-linux*.tar.zst)` ]]; then - rm -f ./${MODULE_NAME}/ITKPythonBuilds-linux*.tar.zst - else - mv ./${MODULE_NAME}/ITKPythonBuilds-linux*.tar.zst . - fi - - # Cache ITKPythonPackage build scripts - if [[ ! -d ./ITKPythonPackage ]]; then - mv ./${MODULE_NAME}/ITKPythonPackage . - ln -s ./ITKPythonPackage/oneTBB-prefix . - fi - -done - -# Restore environment variable -export ITK_MODULE_PREQ=${ITK_MODULE_PREQ_TOPLEVEL} -ITK_MODULE_PREQ_TOPLEVEL="" -export ITK_MODULE_NO_CLEANUP=${ITK_MODULE_NO_CLEANUP_TOPLEVEL} -ITK_MODULE_NO_CLEANUP_TOPLEVEL="" - -# Summarize disk usage for debugging -du -sh ./* | sort -hr | head -n 20 - -echo "Done building ITK external module dependencies" diff --git a/scripts/dockcross-manylinux-build-module-wheels.sh b/scripts/dockcross-manylinux-build-module-wheels.sh index 392a2190..4c6f04e4 100755 --- a/scripts/dockcross-manylinux-build-module-wheels.sh +++ b/scripts/dockcross-manylinux-build-module-wheels.sh @@ -4,9 +4,6 @@ # Run this script to build the Python wheel packages for Linux for an ITK # external module. # -# ======================================================================== -# PARAMETERS -# # Versions can be restricted by passing them in as arguments to the script # For example, # @@ -26,13 +23,13 @@ # # `MANYLINUX_VERSION`: Specialized manylinux image to use for building. Default is _2_28. # See https://github.com/dockcross/dockcross for available versions and tags. -# For instance, `export MANYLINUX_VERSION=2014` +# For instance, `export MANYLINUX_VERSION=_2_28` # # `TARGET_ARCH`: Target architecture for which wheels should be built. # For instance, `export MANYLINUX_VERSION=aarch64` # # `IMAGE_TAG`: Specialized manylinux image tag to use for building. -# For instance, `export IMAGE_TAG=20221205-459c9f0`. +# For instance, `export IMAGE_TAG=2025.08.12-1`. # Tagged images are available at: # - https://github.com/dockcross/dockcross (x64 architecture) # - https://quay.io/organization/pypa (ARM architecture) @@ -44,62 +41,179 @@ # # - `NO_SUDO`: Disable the use of superuser permissions for running docker. # +# DIRECTORY STRUCTURE (expected): +# ${IPP_DIR}/ <- ITKPythonPackage +# ${BUILD_DIR}/ <- ITKPythonPackage-manylinux${VERSION}-build +# ${MODULE_SOURCE_DIR}/ <- Module source (current directory) ######################################################################## -# Handle case where the script directory is not the working directory -script_dir=$(cd $(dirname $0) || exit 1; pwd) -source "${script_dir}/dockcross-manylinux-set-vars.sh" -source "${script_dir}/oci_exe.sh" +script_dir=$( + cd "$(dirname "$0")" || exit 1 + pwd +) +_ipp_dir=$(dirname "${script_dir}") + +# ----------------------------------------------------------------------- +# Find container runtime +for cand in nerdctl docker podman; do + if which "${cand}" >/dev/null 2>&1; then + export OCI_EXE=${OCI_EXE:-"$cand"} + break + fi +done -oci_exe=$(ociExe) +if [ -z "${OCI_EXE}" ]; then + echo "ERROR: No container runtime found. Please install docker, podman, or nerdctl." + exit 1 +fi +echo "Found OCI_EXE=$(which "${OCI_EXE}")" -if [[ -n ${ITK_MODULE_PREQ} ]]; then - echo "Building module dependencies ${ITK_MODULE_PREQ}" - source "${script_dir}/dockcross-manylinux-build-module-deps.sh" +# ----------------------------------------------------------------------- +# Set default values +MANYLINUX_VERSION=${MANYLINUX_VERSION:-_2_28} +TARGET_ARCH=${TARGET_ARCH:-x64} +# Default image tag differs by architecture: +# x64 → dockcross/manylinux image (docker.io/dockcross) +# aarch64 → pypa manylinux image (quay.io/pypa, native ARM64 / QEMU on x64) +if [[ "${TARGET_ARCH}" == "aarch64" ]]; then + IMAGE_TAG=${IMAGE_TAG:-2025.08.12-1} + CONTAINER_SOURCE=${CONTAINER_SOURCE:-"quay.io/pypa/manylinux${MANYLINUX_VERSION}_${TARGET_ARCH}:${IMAGE_TAG}"} +else + # if x64 arch then default manylinux version is _2_28 + IMAGE_TAG=${IMAGE_TAG:=20260203-3dfb3ff} + CONTAINER_SOURCE=${CONTAINER_SOURCE:-"docker.io/dockcross/manylinux${MANYLINUX_VERSION}-${TARGET_ARCH}:${IMAGE_TAG}"} fi +ITKPYTHONPACKAGE_ORG=${ITKPYTHONPACKAGE_ORG:-InsightSoftwareConsortium} +ITKPYTHONPACKAGE_TAG=${ITKPYTHONPACKAGE_TAG:-main} + +# For backwards compatibility +ITK_GIT_TAG=${ITK_GIT_TAG:-${ITK_PACKAGE_VERSION}} + +# Required environment variables +required_vars=( + ITK_GIT_TAG + MANYLINUX_VERSION + IMAGE_TAG + TARGET_ARCH + ITKPYTHONPACKAGE_ORG + ITKPYTHONPACKAGE_TAG +) +# Sanity Validation loop +_missing_required=0 +for v in "${required_vars[@]}"; do + if [ -z "${!v:-}" ]; then + _missing_required=1 + echo "ERROR: Required environment variable '$v' is not set or empty." + fi +done +if [ "${_missing_required}" -ne 0 ]; then + exit 1 +fi +unset _missing_required + +mkdir -p "${_ipp_dir}"/build +cd "$(dirname "${_ipp_dir}")" || exit + +HOST_MODULE_DIRECTORY=${MODULE_SRC_DIRECTORY} # Set up paths and variables for build -mkdir -p $(pwd)/tools -chmod 777 $(pwd)/tools -mkdir -p dist -DOCKER_ARGS="-v $(pwd)/dist:/work/dist/ -v ${script_dir}/..:/ITKPythonPackage -v $(pwd)/tools:/tools" -DOCKER_ARGS+=" -e MANYLINUX_VERSION" -DOCKER_ARGS+=" -e LD_LIBRARY_PATH" -# Mount any shared libraries +CONTAINER_WORK_DIR=/work +CONTAINER_PACKAGE_BUILD_DIR=${CONTAINER_WORK_DIR}/ITKPythonPackage-build +CONTAINER_PACKAGE_SCRIPTS_DIR=${CONTAINER_WORK_DIR}/ITKPythonPackage +HOST_PACKAGE_BUILD_DIR=$(dirname "${_ipp_dir}")/ITKPythonPackage-build +HOST_PACKAGE_SCRIPTS_DIR=${_ipp_dir} + +CONTAINER_ITK_SOURCE_DIR=${CONTAINER_PACKAGE_BUILD_DIR}/ITK +HOST_PACKAGE_DIST=${HOST_MODULE_DIRECTORY}/dist +mkdir -p "${HOST_PACKAGE_DIST}" +CONTAINER_MODULE_DIR=${CONTAINER_WORK_DIR}/$(basename "${MODULE_SRC_DIRECTORY}") +CONTAINER_MODULE_DEPS_DIR=${CONTAINER_WORK_DIR}/$(basename "${MODULE_DEPS_DIR}") + +# Build docker arguments +DOCKER_ARGS=" --network=host " +DOCKER_ARGS+=" -v ${HOST_PACKAGE_BUILD_DIR}:${CONTAINER_PACKAGE_BUILD_DIR} " +DOCKER_ARGS+=" -v ${HOST_PACKAGE_SCRIPTS_DIR}:${CONTAINER_PACKAGE_SCRIPTS_DIR} " +DOCKER_ARGS+=" -v ${MODULE_SRC_DIRECTORY}:${CONTAINER_MODULE_DIR} " +DOCKER_ARGS+=" -v ${MODULE_DEPS_DIR}:${CONTAINER_MODULE_DEPS_DIR} " + +if [ "${ITK_SOURCE_DIR}" != "" ]; then + DOCKER_ARGS+=" -v ${ITK_SOURCE_DIR}:${CONTAINER_ITK_SOURCE_DIR} " +fi + +# Environment variables for the container +DOCKER_ARGS+=" -e PYTHONUNBUFFERED=1 " +DOCKER_ARGS+=" -e CMAKE_OPTIONS='${CMAKE_OPTIONS}' " + +# Mount shared libraries if LD_LIBRARY_PATH is set if [[ -n ${LD_LIBRARY_PATH} ]]; then for libpath in ${LD_LIBRARY_PATH//:/ }; do - DOCKER_LIBRARY_PATH="/usr/lib64/$(basename -- ${libpath})" - DOCKER_ARGS+=" -v ${libpath}:${DOCKER_LIBRARY_PATH}" - if test -d ${libpath}; then - DOCKER_LD_LIBRARY_PATH+="${DOCKER_LIBRARY_PATH}:${DOCKER_LD_LIBRARY_PATH}" - fi + DOCKER_LIBRARY_PATH="/usr/lib64/$(basename -- "${libpath}")" + DOCKER_ARGS+=" -v ${libpath}:${DOCKER_LIBRARY_PATH}" + if test -d "${libpath}"; then + DOCKER_LD_LIBRARY_PATH+="${DOCKER_LIBRARY_PATH}:${DOCKER_LD_LIBRARY_PATH}" + fi done fi export LD_LIBRARY_PATH="${DOCKER_LD_LIBRARY_PATH}" -if [[ "${TARGET_ARCH}" = "aarch64" ]]; then - echo "Install aarch64 architecture emulation tools to perform build for ARM platform" +# To build tarballs in manylinux, use 'export BUILD_WHEELS_EXTRA_FLAGS=" --build-itk-tarball-cache "' +BUILD_WHEELS_EXTRA_FLAGS=${BUILD_WHEELS_EXTRA_FLAGS:=""} # No tarball by default +PY_ENVS=("${@:-py310 py311}") + +if [[ "${TARGET_ARCH}" == "aarch64" ]]; then + # aarch64: run the quay.io/pypa native image directly. + # On ARM64 hosts (e.g. Apple Silicon) this runs natively. + # On x64 hosts, first register QEMU binfmt emulation. if [[ ! ${NO_SUDO} ]]; then docker_prefix="sudo" fi + # Only install QEMU binfmt emulation on non-ARM64 hosts; ARM64 hosts run natively + if [[ "$(uname -m)" != "arm64" && "$(uname -m)" != "aarch64" ]]; then + echo "Installing aarch64 architecture emulation tools to perform build for ARM platform" + ${docker_prefix} "$OCI_EXE" run --privileged --rm tonistiigi/binfmt --install all + fi - ${docker_prefix} $oci_exe run --privileged --rm tonistiigi/binfmt --install all - - # Build wheels - DOCKER_ARGS+=" -v $(pwd):/work/ --rm" - ${docker_prefix} $oci_exe run $DOCKER_ARGS ${CONTAINER_SOURCE} "/ITKPythonPackage/scripts/internal/manylinux-aarch64-build-module-wheels.sh" "$@" + cmd="${docker_prefix} \"$OCI_EXE\" run --rm \ + ${DOCKER_ARGS} \ + -e PY_ENVS=\"${PY_ENVS[*]}\" \ + -e ITK_GIT_TAG=\"${ITK_GIT_TAG}\" \ + -e ITK_PACKAGE_VERSION=\"${ITK_PACKAGE_VERSION}\" \ + -e ITK_MODULE_PREQ=\"${ITK_MODULE_PREQ}\" \ + -e MODULE_SRC_DIRECTORY=\"${CONTAINER_MODULE_DIR}\" \ + -e MODULE_DEPS_DIR=\"${CONTAINER_MODULE_DEPS_DIR}\" \ + -e MANYLINUX_VERSION=\"${MANYLINUX_VERSION}\" \ + -e IMAGE_TAG=\"${IMAGE_TAG}\" \ + -e TARGET_ARCH=\"${TARGET_ARCH}\" \ + -e ITKPYTHONPACKAGE_ORG=\"${ITKPYTHONPACKAGE_ORG}\" \ + -e ITKPYTHONPACKAGE_TAG=\"${ITKPYTHONPACKAGE_TAG}\" \ + -e BUILD_WHEELS_EXTRA_FLAGS=\"${BUILD_WHEELS_EXTRA_FLAGS}\" \ + ${CONTAINER_SOURCE} \ + /bin/bash -x ${CONTAINER_PACKAGE_SCRIPTS_DIR}/scripts/docker_build_environment_driver.sh" else - # Generate dockcross scripts - $oci_exe run --rm ${CONTAINER_SOURCE} > /tmp/dockcross-manylinux-x64 - chmod u+x /tmp/dockcross-manylinux-x64 - - # Build wheels - /tmp/dockcross-manylinux-x64 \ - -a "$DOCKER_ARGS" \ - "/ITKPythonPackage/scripts/internal/manylinux-build-module-wheels.sh" "$@" -fi + # x64: generate the dockcross runner script from the image, then invoke it. + _local_dockcross_script=${_ipp_dir}/build/runner_dockcross-${MANYLINUX_VERSION}-${TARGET_ARCH}_${IMAGE_TAG}.sh + "$OCI_EXE" run --rm "${CONTAINER_SOURCE}" >"${_local_dockcross_script}" + chmod u+x "${_local_dockcross_script}" -if [[ -z ${ITK_MODULE_NO_CLEANUP} ]]; then - source "${script_dir}/dockcross-manylinux-cleanup.sh" + # When building ITK remote wheels, --module-source-dir, --module-dependencies-root-dir, and --itk-module-deps should be present + cmd="bash -x ${_local_dockcross_script} \ + -a \"$DOCKER_ARGS\" \ + /usr/bin/env \ + PY_ENVS=\"${PY_ENVS[*]}\" \ + ITK_GIT_TAG=\"${ITK_GIT_TAG}\" \ + ITK_PACKAGE_VERSION=\"${ITK_PACKAGE_VERSION}\" \ + ITK_MODULE_PREQ=\"${ITK_MODULE_PREQ}\" \ + MODULE_SRC_DIRECTORY=\"${CONTAINER_MODULE_DIR}\" \ + MODULE_DEPS_DIR=\"${CONTAINER_MODULE_DEPS_DIR}\" \ + MANYLINUX_VERSION=\"${MANYLINUX_VERSION}\" \ + IMAGE_TAG=\"${IMAGE_TAG}\" \ + TARGET_ARCH=\"${TARGET_ARCH}\" \ + ITKPYTHONPACKAGE_ORG=\"${ITKPYTHONPACKAGE_ORG}\" \ + ITKPYTHONPACKAGE_TAG=\"${ITKPYTHONPACKAGE_TAG}\" \ + BUILD_WHEELS_EXTRA_FLAGS=\"${BUILD_WHEELS_EXTRA_FLAGS}\" \ + /bin/bash -x ${CONTAINER_PACKAGE_SCRIPTS_DIR}/scripts/docker_build_environment_driver.sh" fi + +echo "RUNNING: $cmd" +eval "$cmd" diff --git a/scripts/dockcross-manylinux-build-wheels.sh b/scripts/dockcross-manylinux-build-wheels.sh index 0619b301..eadba903 100755 --- a/scripts/dockcross-manylinux-build-wheels.sh +++ b/scripts/dockcross-manylinux-build-wheels.sh @@ -1,5 +1,4 @@ #!/bin/bash - # Run this script to build the ITK Python wheel packages for Linux. # # Versions can be restricted by passing them in as arguments to the script @@ -7,42 +6,144 @@ # # scripts/dockcross-manylinux-build-wheels.sh cp310 # -# A specialized manylinux image and tag can be used by exporting to -# MANYLINUX_VERSION and IMAGE_TAG before running this script. -# See https://github.com/dockcross/dockcross for available versions and tags. +# A specialized manylinux image and tag can be used by setting +# MANYLINUX_VERSION and IMAGE_TAG # # For example, # -# export MANYLINUX_VERSION=2014 -# export IMAGE_TAG=20221205-459c9f0 +# export MANYLINUX_VERSION=_2_28 +# export IMAGE_TAG=20260203-3dfb3ff # scripts/dockcross-manylinux-build-module-wheels.sh cp310 # -script_dir=$(cd $(dirname $0) || exit 1; pwd) -source "${script_dir}/oci_exe.sh" +script_dir=$( + cd "$(dirname "$0")" || exit 1 + pwd +) +_ipp_dir=$(dirname "${script_dir}") -oci_exe=$(ociExe) +for cand in nerdctl docker podman; do + if which "${cand}" >/dev/null; then + export OCI_EXE=${OCI_EXE:="$cand"} + break + fi +done +echo "FOUND OCI_EXE=$(which "${OCI_EXE}")" +#For backwards compatibility when the ITK_GIT_TAG was required to match the ITK_PACKAGE_VERSION +ITK_PACKAGE_VERSION=${ITK_PACKAGE_VERSION:="v6.0b02"} +ITK_GIT_TAG=${ITK_GIT_TAG:=${ITK_PACKAGE_VERSION}} MANYLINUX_VERSION=${MANYLINUX_VERSION:=_2_28} -if [[ ${MANYLINUX_VERSION} == _2_28 ]]; then +# Default image tag differs by architecture: +# x64 → dockcross/manylinux image (docker.io/dockcross) +# aarch64 → pypa manylinux image (quay.io/pypa, native ARM64 / QEMU on x64) +if [[ "${TARGET_ARCH}" == "aarch64" ]]; then + IMAGE_TAG=${IMAGE_TAG:=2025.08.12-1} + CONTAINER_SOURCE=${CONTAINER_SOURCE:="quay.io/pypa/manylinux${MANYLINUX_VERSION}_${TARGET_ARCH}:${IMAGE_TAG}"} +else + # if x64 arch then default manylinux version is _2_28 IMAGE_TAG=${IMAGE_TAG:=20260203-3dfb3ff} -elif [[ ${MANYLINUX_VERSION} == 2014 ]]; then - IMAGE_TAG=${IMAGE_TAG:=20240304-9e57d2b} + CONTAINER_SOURCE=${CONTAINER_SOURCE:="docker.io/dockcross/manylinux${MANYLINUX_VERSION}-${TARGET_ARCH}:${IMAGE_TAG}"} +fi +ITKPYTHONPACKAGE_ORG=${ITKPYTHONPACKAGE_ORG:=InsightSoftwareConsortium} +ITKPYTHONPACKAGE_TAG=${ITKPYTHONPACKAGE_TAG:=main} + +# Required environment variables +required_vars=( + ITK_GIT_TAG + MANYLINUX_VERSION + IMAGE_TAG + TARGET_ARCH + ITKPYTHONPACKAGE_ORG + ITKPYTHONPACKAGE_TAG +) +# Sanity Validation loop +_missing_required=0 +for v in "${required_vars[@]}"; do + if [ -z "${!v:-}" ]; then + _missing_required=1 + echo "ERROR: Required environment variable '$v' is not set or empty." + fi +done +if [ "${_missing_required}" -ne 0 ]; then + exit 1 +fi +unset _missing_required + +mkdir -p "${_ipp_dir}/build" +cd "$(dirname "${_ipp_dir}")" || exit + +# Build wheels in dockcross environment +CONTAINER_WORK_DIR=/work +CONTAINER_PACKAGE_BUILD_DIR=${CONTAINER_WORK_DIR}/ITKPythonPackage-build +CONTAINER_PACKAGE_SCRIPTS_DIR=${CONTAINER_WORK_DIR}/ITKPythonPackage +CONTAINER_ITK_SOURCE_DIR=${CONTAINER_PACKAGE_BUILD_DIR}/ITK + +HOST_PACKAGE_SCRIPTS_DIR=${_ipp_dir} +HOST_PACKAGE_BUILD_DIR=$(dirname "${_ipp_dir}")/ITKPythonPackage-manylinux${MANYLINUX_VERSION}-build +mkdir -p "${HOST_PACKAGE_BUILD_DIR}" + +DOCKER_ARGS=" -v ${HOST_PACKAGE_BUILD_DIR}:${CONTAINER_PACKAGE_BUILD_DIR} " +DOCKER_ARGS+=" -v ${HOST_PACKAGE_SCRIPTS_DIR}:${CONTAINER_PACKAGE_SCRIPTS_DIR} " +if [ "${ITK_SOURCE_DIR}" != "" ]; then + DOCKER_ARGS+=" -v${ITK_SOURCE_DIR}:${CONTAINER_ITK_SOURCE_DIR} " +fi +DOCKER_ARGS+=" -e PYTHONUNBUFFERED=1 " # Turn off buffering of outputs in python + +# To build tarballs in manylinux, use 'export BUILD_WHEELS_EXTRA_FLAGS=" --build-itk-tarball-cache "' +BUILD_WHEELS_EXTRA_FLAGS=${BUILD_WHEELS_EXTRA_FLAGS:=""} # No tarball by default + +# If args are given, use them. Otherwise use default python environments +PY_ENVS=("${@:-py310 py311}") + +if [[ "${TARGET_ARCH}" == "aarch64" ]]; then + # aarch64: run the quay.io/pypa native image directly. + # On ARM64 hosts (e.g. Apple Silicon) this runs natively. + # On x64 hosts, first register QEMU binfmt emulation. + if [[ ! ${NO_SUDO} ]]; then + docker_prefix="sudo" + fi + # Only install QEMU binfmt emulation on non-ARM64 hosts; ARM64 hosts run natively + if [[ "$(uname -m)" != "arm64" && "$(uname -m)" != "aarch64" ]]; then + echo "Installing aarch64 architecture emulation tools to perform build for ARM platform" + ${docker_prefix} "$OCI_EXE" run --privileged --rm tonistiigi/binfmt --install all + fi + + # When building ITK wheels, module-related vars are empty + cmd="${docker_prefix} \"$OCI_EXE\" run --rm \ + ${DOCKER_ARGS} \ + -e PY_ENVS=\"${PY_ENVS[*]}\" \ + -e ITK_GIT_TAG=\"${ITK_GIT_TAG}\" \ + -e ITK_PACKAGE_VERSION=\"${ITK_PACKAGE_VERSION:-}\" \ + -e MANYLINUX_VERSION=\"${MANYLINUX_VERSION}\" \ + -e IMAGE_TAG=\"${IMAGE_TAG}\" \ + -e TARGET_ARCH=\"${TARGET_ARCH}\" \ + -e ITKPYTHONPACKAGE_ORG=\"${ITKPYTHONPACKAGE_ORG}\" \ + -e ITKPYTHONPACKAGE_TAG=\"${ITKPYTHONPACKAGE_TAG}\" \ + -e BUILD_WHEELS_EXTRA_FLAGS=\"${BUILD_WHEELS_EXTRA_FLAGS}\" \ + ${CONTAINER_SOURCE} \ + /bin/bash -x ${CONTAINER_PACKAGE_SCRIPTS_DIR}/scripts/docker_build_environment_driver.sh" else - echo "Unknown manylinux version ${MANYLINUX_VERSION}" - exit 1; + # x64: generate the dockcross runner script from the image, then invoke it. + _local_dockercross_script=${_ipp_dir}/build/runner_dockcross-${MANYLINUX_VERSION}-${TARGET_ARCH}_${IMAGE_TAG}.sh + "$OCI_EXE" run --rm "${CONTAINER_SOURCE}" >"${_local_dockercross_script}" + chmod u+x "${_local_dockercross_script}" + + # When building ITK wheels, --module-source-dir, --module-dependancies-root-dir, and --itk-module-deps to be empty + cmd="bash -x ${_local_dockercross_script} \ + -a \"$DOCKER_ARGS\" \ + /usr/bin/env \ + PY_ENVS=\"${PY_ENVS[*]}\" \ + ITK_GIT_TAG=\"${ITK_GIT_TAG}\" \ + ITK_PACKAGE_VERSION=\"${ITK_PACKAGE_VERSION:-}\" \ + MANYLINUX_VERSION=\"${MANYLINUX_VERSION}\" \ + IMAGE_TAG=\"${IMAGE_TAG}\" \ + TARGET_ARCH=\"${TARGET_ARCH}\" \ + ITKPYTHONPACKAGE_ORG=\"${ITKPYTHONPACKAGE_ORG}\" \ + ITKPYTHONPACKAGE_TAG=\"${ITKPYTHONPACKAGE_TAG}\" \ + BUILD_WHEELS_EXTRA_FLAGS=\"${BUILD_WHEELS_EXTRA_FLAGS}\" \ + /bin/bash -x ${CONTAINER_PACKAGE_SCRIPTS_DIR}/scripts/docker_build_environment_driver.sh" fi -# Generate dockcross scripts -$oci_exe run --rm docker.io/dockcross/manylinux${MANYLINUX_VERSION}-x64:${IMAGE_TAG} > /tmp/dockcross-manylinux-x64 -chmod u+x /tmp/dockcross-manylinux-x64 - -# Build wheels -pushd $script_dir/.. -mkdir -p dist -DOCKER_ARGS="-v $(pwd)/dist:/work/dist/" -DOCKER_ARGS+=" -e MANYLINUX_VERSION" -/tmp/dockcross-manylinux-x64 \ - -a "$DOCKER_ARGS" \ - ./scripts/internal/manylinux-build-wheels.sh "$@" -popd +echo "RUNNING: $cmd" +eval "$cmd" diff --git a/scripts/dockcross-manylinux-cleanup.sh b/scripts/dockcross-manylinux-cleanup.sh deleted file mode 100755 index 52702518..00000000 --- a/scripts/dockcross-manylinux-cleanup.sh +++ /dev/null @@ -1,46 +0,0 @@ -#!/bin/bash - -######################################################################## -# Run this script in an ITK external module directory to clean up -# Linux Python build artifacts. -# -# Typically required for building multiple types of module wheels in the same -# directory, such as using different toolsets or targeting different -# architectures. -# -# =========================================== -# ENVIRONMENT VARIABLES -# -# - `ITK_MODULE_PREQ`: Prerequisite ITK modules that must be built before the requested module. -# Format is `/@:/@:...`. -# For instance, `export ITK_MODULE_PREQ=InsightSoftwareConsortium/ITKMeshToPolyData@v0.10.0` -# -# - `NO_SUDO`: Disable the use of superuser permissions for removing directories. -# `sudo` is required by default for cleanup on Github Actions runners. -# -######################################################################## - -echo "Cleaning up artifacts from module build" - -# ARM platform observed to require sudo for removing ITKPythonPackage sources -rm_prefix="" -if [[ ! ${NO_SUDO} ]]; then - rm_prefix="sudo " -fi - -unlink oneTBB-prefix -${rm_prefix} rm -rf ITKPythonPackage/ -${rm_prefix} rm -rf tools/ -${rm_prefix} rm -rf _skbuild/ build/ -${rm_prefix} rm -rf ./*.egg-info/ -${rm_prefix} rm -rf ./ITK-*-manylinux${MANYLINUX_VERSION}_${TARGET_ARCH}/ -${rm_prefix} rm -rf ./ITKPythonBuilds-linux-manylinux*${MANYLINUX_VERSION}*.tar.zst - -if [[ -n ${ITK_MODULE_PREQ} ]]; then - for MODULE_INFO in ${ITK_MODULE_PREQ//:/ }; do - MODULE_NAME=`(echo ${MODULE_INFO} | cut -d'@' -f 1 | cut -d'/' -f 2)` - ${rm_prefix} rm -rf ${MODULE_NAME}/ - done -fi - -# Leave dist/ and download scripts intact diff --git a/scripts/dockcross-manylinux-download-cache-and-build-module-wheels.sh b/scripts/dockcross-manylinux-download-cache-and-build-module-wheels.sh index 37166edd..2381c459 100755 --- a/scripts/dockcross-manylinux-download-cache-and-build-module-wheels.sh +++ b/scripts/dockcross-manylinux-download-cache-and-build-module-wheels.sh @@ -16,9 +16,6 @@ # ENVIRONMENT VARIABLES # # These variables are set with the `export` bash command before calling the script. -# For example, -# -# scripts/dockcross-manylinux-build-module-wheels.sh cp310 # # `ITKPYTHONPACKAGE_ORG`: Github organization for fetching ITKPythonPackage build scripts. # @@ -28,11 +25,18 @@ # ######################################################################## +download_script_dir=$( + cd "$(dirname "$0")" || exit 1 + pwd +) +# if not specified, use the current directory for MODULE_SRC_DIRECTORY +MODULE_SRC_DIRECTORY=${MODULE_SRC_DIRECTORY:=${download_script_dir}} +# if not specified then use the a dummy MODULE_DEPENDENCIES directory in the build dashboard +MODULE_DEPS_DIR=${MODULE_DEPS_DIR:=${DASHBOARD_BUILD_DIRECTORY}/MODULE_DEPENDENCIES} # ----------------------------------------------------------------------- # Script argument parsing # -usage() -{ +usage() { echo "Usage: dockcross-manylinux-download-cache-and-build-module-wheels [ -h | --help ] show usage @@ -42,34 +46,86 @@ usage() exit 2 } -FORWARD_ARGS=("$@") # Store arguments to forward them later PARSED_ARGS=$(getopt -a -n dockcross-manylinux-download-cache-and-build-module-wheels \ -o hc:x: --long help,cmake_options:,exclude_libs: -- "$@") eval set -- "$PARSED_ARGS" -while : -do +while :; do case "$1" in - -h | --help) usage; break ;; - -c | --cmake_options) CMAKE_OPTIONS="$2" ; shift 2 ;; - -x | --exclude_libs) EXCLUDE_LIBS="$2" ; shift 2 ;; - --) shift; break ;; - *) echo "Unexpected option: $1."; - usage; break ;; + -h | --help) + usage + ;; + -c | --cmake_options) + export CMAKE_OPTIONS="$2" + shift 2 + ;; + -x | --exclude_libs) + export EXCLUDE_LIBS="$2" + shift 2 + ;; + --) + shift + break + ;; + *) + echo "Unexpected option: $1." + usage + ;; esac done +#For backwards compatibility when the ITK_GIT_TAG was required to match the ITK_PACKAGE_VERSION +ITK_PACKAGE_VERSION=${ITK_PACKAGE_VERSION:="v6.0b02"} +ITK_GIT_TAG=${ITK_GIT_TAG:=${ITK_PACKAGE_VERSION}} + +# ----------------------------------------------------------------------- +# Set default values +MANYLINUX_VERSION=${MANYLINUX_VERSION:-_2_28} +TARGET_ARCH=${TARGET_ARCH:-x64} + +ITKPYTHONPACKAGE_ORG=${ITKPYTHONPACKAGE_ORG:-InsightSoftwareConsortium} +ITKPYTHONPACKAGE_TAG=${ITKPYTHONPACKAGE_TAG:-main} + # ----------------------------------------------------------------------- # Download and extract cache -echo "Fetching https://raw.githubusercontent.com/${ITKPYTHONPACKAGE_ORG:=InsightSoftwareConsortium}/ITKPythonPackage/${ITKPYTHONPACKAGE_TAG:=v5.4.0}/scripts/dockcross-manylinux-download-cache.sh" -curl -L https://raw.githubusercontent.com/${ITKPYTHONPACKAGE_ORG:=InsightSoftwareConsortium}/ITKPythonPackage/${ITKPYTHONPACKAGE_TAG:=v5.4.0}/scripts/dockcross-manylinux-download-cache.sh -O +echo "Fetching https://raw.githubusercontent.com/${ITKPYTHONPACKAGE_ORG}/ITKPythonPackage/${ITKPYTHONPACKAGE_TAG}/scripts/dockcross-manylinux-download-cache.sh" +curl -L "https://raw.githubusercontent.com/${ITKPYTHONPACKAGE_ORG}/ITKPythonPackage/${ITKPYTHONPACKAGE_TAG}/scripts/dockcross-manylinux-download-cache.sh" -O chmod u+x dockcross-manylinux-download-cache.sh -./dockcross-manylinux-download-cache.sh $1 +_download_cmd="ITK_GIT_TAG=${ITK_GIT_TAG} \ + ITK_PACKAGE_VERSION=${ITK_PACKAGE_VERSION} \ + ITKPYTHONPACKAGE_ORG=${ITKPYTHONPACKAGE_ORG} \ + ITKPYTHONPACKAGE_TAG=${ITKPYTHONPACKAGE_TAG} \ + MANYLINUX_VERSION=${MANYLINUX_VERSION} \ + TARGET_ARCH=${TARGET_ARCH} \ + bash -x \ + ${download_script_dir}/dockcross-manylinux-download-cache.sh $1" +echo "Running: ${_download_cmd}" +eval "${_download_cmd}" + +#NOTE: in this scenario, untarred_ipp_dir is extracted from tarball +# during ${download_script_dir}/dockcross-manylinux-download-cache.sh +untarred_ipp_dir=${download_script_dir}/ITKPythonPackage + +ITK_SOURCE_DIR=${download_script_dir}/ITKPythonPackage-build/ITK # ----------------------------------------------------------------------- # Build module wheels echo "Building module wheels" -set -- "${FORWARD_ARGS[@]}"; # Restore initial argument list -./ITKPythonPackage/scripts/dockcross-manylinux-build-module-wheels.sh "$@" + +_bld_cmd="NO_SUDO=${NO_SUDO} \ + LD_LIBRARY_PATH=${LD_LIBRARY_PATH} \ + IMAGE_TAG=${IMAGE_TAG} \ + TARGET_ARCH=${TARGET_ARCH} \ + ITK_SOURCE_DIR=${ITK_SOURCE_DIR} \ + ITK_GIT_TAG=${ITK_GIT_TAG} \ + ITK_PACKAGE_VERSION=${ITK_PACKAGE_VERSION} \ + ITK_MODULE_PREQ=${ITK_MODULE_PREQ} \ + ITK_MODULE_NO_CLEANUP=${ITK_MODULE_NO_CLEANUP} \ + MODULE_SRC_DIRECTORY=${MODULE_SRC_DIRECTORY} \ + MODULE_DEPS_DIR=${MODULE_DEPS_DIR} \ + MANYLINUX_VERSION=${MANYLINUX_VERSION} \ + ${untarred_ipp_dir}/scripts/dockcross-manylinux-build-module-wheels.sh $*" +echo "Running: ${_bld_cmd}" +eval "${_bld_cmd}" diff --git a/scripts/dockcross-manylinux-download-cache.sh b/scripts/dockcross-manylinux-download-cache.sh index 10d17e2d..d3571228 100755 --- a/scripts/dockcross-manylinux-download-cache.sh +++ b/scripts/dockcross-manylinux-download-cache.sh @@ -11,31 +11,13 @@ # steps not present in `dockcross-manylinux-download-cache-and-build-module-wheels.sh`. # # =========================================== -# ENVIRONMENT VARIABLES -# -# `ITK_PACKAGE_VERSION`: Tag for ITKPythonBuilds build cache to use -# Examples: "v5.4.0", "v5.2.1.post1" -# See available tags at https://github.com/InsightSoftwareConsortium/ITKPythonBuilds/tags -# -# `MANYLINUX_VERSION`: manylinux specialization used to build ITK for cache -# Examples: "_2_28", "2014", "_2_28_aarch64" -# See https://github.com/dockcross/dockcross -# -# `ITKPYTHONPACKAGE_TAG`: Tag for ITKPythonPackage build scripts to use. -# If ITKPYTHONPACKAGE_TAG is empty then the default scripts distributed -# with the ITKPythonBuilds archive will be used. -# -# `ITKPYTHONPACKAGE_ORG`: Github organization or user to use for ITKPythonPackage -# build script source. Default is InsightSoftwareConsortium. -# Ignored if ITKPYTHONPACKAGE_TAG is empty. -# +# ENVIRONMENT VARIABLES: ITK_GIT_TAG, MANYLINUX_VERSION, ITKPYTHONPACKAGE_TAG, ITKPYTHONPACKAGE_ORG ######################################################################## # ----------------------------------------------------------------------- # Script argument parsing # -usage() -{ +usage() { echo "Usage: dockcross-manylinux-download-cache.sh [ -h | --help ] show usage @@ -43,25 +25,53 @@ usage() exit 2 } -FORWARD_ARGS=("$@") # Store arguments to forward them later +# Required environment variables +required_vars=( + ITK_GIT_TAG + ITK_PACKAGE_VERSION + ITKPYTHONPACKAGE_ORG + ITKPYTHONPACKAGE_TAG + MANYLINUX_VERSION + TARGET_ARCH +) + +# Sanity Validation loop +_missing_required=0 +for v in "${required_vars[@]}"; do + if [ -z "${!v:-}" ]; then + _missing_required=1 + echo "ERROR: Required environment variable '$v' is not set or empty." + fi +done +if [ "${_missing_required}" -ne 0 ]; then + exit 1 +fi +unset _missing_required + PARSED_ARGS=$(getopt -a -n dockcross-manylinux-download-cache-and-build-module-wheels \ -o hc:x: --long help,cmake_options:,exclude_libs: -- "$@") eval set -- "$PARSED_ARGS" -while : -do +while :; do case "$1" in - -h | --help) usage; break ;; - --) shift; break ;; - *) echo "Unexpected option: $1."; - usage; break ;; + -h | --help) + usage + ;; + --) + shift + break + ;; + *) + echo "Unexpected option: $1." + usage + ;; esac done # ----------------------------------------------------------------------- # Verify that unzstd binary is available to decompress ITK build archives. -unzstd_exe=`(which unzstd)` +unzstd_exe=$(which unzstd) if [[ -z ${unzstd_exe} ]]; then echo "ERROR: can not find required binary 'unzstd' " @@ -73,42 +83,27 @@ ${unzstd_exe} --version # ----------------------------------------------------------------------- # Fetch build archive - -MANYLINUX_VERSION=${MANYLINUX_VERSION:=_2_28} -TARGET_ARCH=${TARGET_ARCH:=x64} - -case ${TARGET_ARCH} in - x64) - TARBALL_SPECIALIZATION="-manylinux${MANYLINUX_VERSION}" - ;; - *) - TARBALL_SPECIALIZATION="-manylinux${MANYLINUX_VERSION}_${TARGET_ARCH}" - ;; -esac -TARBALL_NAME="ITKPythonBuilds-linux${TARBALL_SPECIALIZATION}.tar" +TARBALL_NAME="ITKPythonBuilds-manylinux${MANYLINUX_VERSION}-${TARGET_ARCH}.tar" if [[ ! -f ${TARBALL_NAME}.zst ]]; then - echo "Fetching https://github.com/InsightSoftwareConsortium/ITKPythonBuilds/releases/download/${ITK_PACKAGE_VERSION:=v5.4.0}/${TARBALL_NAME}.zst" - curl -L https://github.com/InsightSoftwareConsortium/ITKPythonBuilds/releases/download/${ITK_PACKAGE_VERSION:=v5.4.0}/${TARBALL_NAME}.zst -O + echo "Local ITK cache tarball file not found..." + echo "Fetching https://github.com/InsightSoftwareConsortium/ITKPythonBuilds/releases/download/${ITK_PACKAGE_VERSION}/${TARBALL_NAME}.zst" + if ! curl -L "https://github.com/InsightSoftwareConsortium/ITKPythonBuilds/releases/download/${ITK_PACKAGE_VERSION}/${TARBALL_NAME}.zst" -O; then + echo "FAILED Download:" + echo "curl -L https://github.com/InsightSoftwareConsortium/ITKPythonBuilds/releases/download/${ITK_PACKAGE_VERSION}/${TARBALL_NAME}.zst -O" + exit 1 + fi fi if [[ ! -f ./${TARBALL_NAME}.zst ]]; then echo "ERROR: can not find required binary './${TARBALL_NAME}.zst'" exit 255 fi -${unzstd_exe} --long=31 ./${TARBALL_NAME}.zst -o ${TARBALL_NAME} -if [ "$#" -lt 1 ]; then - echo "Extracting all files"; - tar xf ${TARBALL_NAME} -else - echo "Extracting files relevant for: $1"; - tar xf ${TARBALL_NAME} ITKPythonPackage/scripts/ - tar xf ${TARBALL_NAME} ITKPythonPackage/ITK-source/ - tar xf ${TARBALL_NAME} ITKPythonPackage/oneTBB-prefix/ - tar xf ${TARBALL_NAME} --wildcards ITKPythonPackage/ITK-$1* -fi -rm ${TARBALL_NAME} +"${unzstd_exe}" --long=31 "./${TARBALL_NAME}.zst" -o "${TARBALL_NAME}" -ln -s ITKPythonPackage/oneTBB-prefix ./ +current_dir=$(pwd) +echo "Extracting all cache files from ${TARBALL_NAME} in ${current_dir}" +tar xf "${TARBALL_NAME}" --warning=no-unknown-keyword +rm "${TARBALL_NAME}" # ----------------------------------------------------------------------- # Optional: Update build scripts @@ -118,22 +113,22 @@ ln -s ITKPythonPackage/oneTBB-prefix ./ # since the archives were generated. if [[ -n ${ITKPYTHONPACKAGE_TAG} ]]; then - echo "Updating build scripts to ${ITKPYTHONPACKAGE_ORG:=InsightSoftwareConsortium}/ITKPythonPackage@${ITKPYTHONPACKAGE_TAG}" - git clone "https://github.com/${ITKPYTHONPACKAGE_ORG}/ITKPythonPackage.git" "IPP-tmp" + # shellcheck disable=SC2153 + echo "Updating build scripts to ${ITKPYTHONPACKAGE_ORG}/ITKPythonPackage@${ITKPYTHONPACKAGE_TAG}" + git clone "https://github.com/${ITKPYTHONPACKAGE_ORG}/ITKPythonPackage.git" "${current_dir}/IPP-tmp" - pushd IPP-tmp/ + pushd "${current_dir}/IPP-tmp/" || exit git checkout "${ITKPYTHONPACKAGE_TAG}" git status - popd + popd || exit - rm -rf ITKPythonPackage/scripts/ - cp -r IPP-tmp/scripts ITKPythonPackage/ - cp IPP-tmp/requirements-dev.txt ITKPythonPackage/ - rm -rf IPP-tmp/ + rm -rf "${current_dir}/ITKPythonPackage/scripts/" + rsync -av "${current_dir}"/IPP-tmp/ "${current_dir}/ITKPythonPackage/" + rm -rf "${current_dir}/IPP-tmp/" fi -if [[ ! -f ./ITKPythonPackage/scripts/dockcross-manylinux-build-module-wheels.sh ]]; then - echo "ERROR: can not find required binary './ITKPythonPackage/scripts/dockcross-manylinux-build-module-wheels.sh'" +if [[ ! -f ${current_dir}/ITKPythonPackage/scripts/dockcross-manylinux-build-module-wheels.sh ]]; then + echo "ERROR: can not find required binary '${current_dir}/ITKPythonPackage/scripts/dockcross-manylinux-build-module-wheels.sh'" exit 255 fi diff --git a/scripts/dockcross-manylinux-set-vars.sh b/scripts/dockcross-manylinux-set-vars.sh deleted file mode 100755 index f39ce7ab..00000000 --- a/scripts/dockcross-manylinux-set-vars.sh +++ /dev/null @@ -1,62 +0,0 @@ -#!/bin/bash - -######################################################################## -# Run this script to set common enviroment variables used in building the -# ITK Python wheel packages for Linux. -# -# ENVIRONMENT VARIABLES -# These environment variables will be populated by the script when invoked with `source` -# if their value is not set with `export` before invocation. -# For example, -# -# export ITK_PACKAGE_VERSION=v5.4.0 -# scripts/dockcross-manylinux-set-vars.sh cp310 -# -######################################################################## - -######################################################################## -# ITKPythonBuilds parameters - -# ITKPythonBuilds archive tag to use for ITK build artifacts. -# See https://github.com/insightSoftwareConsortium/ITKpythonbuilds for available tags. -ITK_PACKAGE_VERSION=${ITK_PACKAGE_VERSION:=v6.0b01} - -# Github organization for fetching ITKPythonPackage build scripts -ITKPYTHONPACKAGE_ORG=${ITKPYTHONPACKAGE_ORG:=InsightSoftwareConsortium} - -# ITKPythonPackage tag for fetching build scripts -ITKPYTHONPACKAGE_TAG=${ITKPYTHONPACKAGE_TAG:=main} - -######################################################################## -# Docker image parameters - -# Specialized manylinux image to use for building. Default is _2_28. -# See https://github.com/dockcross/dockcross for available versions and tags. -MANYLINUX_VERSION=${MANYLINUX_VERSION:=_2_28} - -# Target platform architecture (x64, aarch64) -TARGET_ARCH=${TARGET_ARCH:=x64} - -# Specialized manylinux image tag to use for building. -if [[ ${MANYLINUX_VERSION} == _2_28 && ${TARGET_ARCH} == x64 ]]; then - IMAGE_TAG=${IMAGE_TAG:=20260203-3dfb3ff} -elif [[ ${MANYLINUX_VERSION} == _2_28 && ${TARGET_ARCH} == aarch64 ]]; then - IMAGE_TAG=${IMAGE_TAG:=2025.08.12-1} -elif [[ ${MANYLINUX_VERSION} == 2014 ]]; then - IMAGE_TAG=${IMAGE_TAG:=20240304-9e57d2b} -else - echo "Unknown manylinux version ${MANYLINUX_VERSION}" - exit 1; -fi - -# Set container for requested version/arch/tag. -if [[ ${TARGET_ARCH} == x64 ]]; then - MANYLINUX_IMAGE_NAME=${MANYLINUX_IMAGE_NAME:="manylinux${MANYLINUX_VERSION}-${TARGET_ARCH}:${IMAGE_TAG}"} - CONTAINER_SOURCE="docker.io/dockcross/${MANYLINUX_IMAGE_NAME}" -elif [[ ${TARGET_ARCH} == aarch64 ]]; then - MANYLINUX_IMAGE_NAME=${MANYLINUX_IMAGE_NAME:="manylinux${MANYLINUX_VERSION}_${TARGET_ARCH}:${IMAGE_TAG}"} - CONTAINER_SOURCE="quay.io/pypa/${MANYLINUX_IMAGE_NAME}" -else - echo "Unknown target architecture ${TARGET_ARCH}" - exit 1; -fi diff --git a/scripts/docker_build_environment_driver.sh b/scripts/docker_build_environment_driver.sh new file mode 100755 index 00000000..47dc611a --- /dev/null +++ b/scripts/docker_build_environment_driver.sh @@ -0,0 +1,100 @@ +#!/bin/bash + +# Required environment variables +required_vars=( + ITK_GIT_TAG + MANYLINUX_VERSION + IMAGE_TAG + TARGET_ARCH + ITKPYTHONPACKAGE_ORG + ITKPYTHONPACKAGE_TAG + PY_ENVS +) +# Sanity Validation loop +_missing_required=0 +for v in "${required_vars[@]}"; do + if [ -z "${!v:-}" ]; then + _missing_required=1 + echo "ERROR: Required environment variable '$v' is not set or empty." + fi +done +if [ "${_missing_required}" -ne 0 ]; then + exit 1 +fi +unset _missing_required + +# ----------------------------------------------------------------------- +# Set up paths +# These paths are inside the container + +CONTAINER_WORK_DIR=/work +cd "${CONTAINER_WORK_DIR}" || exit +CONTAINER_PACKAGE_BUILD_DIR=${CONTAINER_WORK_DIR}/ITKPythonPackage-build +CONTAINER_PACKAGE_SCRIPTS_DIR=${CONTAINER_WORK_DIR}/ITKPythonPackage +CONTAINER_MODULE_SRC_DIRECTORY=${CONTAINER_WORK_DIR}/$(basename "${MODULE_SRC_DIRECTORY}") +CONTAINER_ITK_SOURCE_DIR=${CONTAINER_PACKAGE_BUILD_DIR}/ITK +BUILD_WHEELS_EXTRA_FLAGS=${BUILD_WHEELS_EXTRA_FLAGS:=""} +read -ra BUILD_WHEELS_EXTRA_FLAGS_ARRAY <<<"${BUILD_WHEELS_EXTRA_FLAGS}" + +echo "BUILD FOR ${PY_ENVS}" +read -ra PY_ENVS_ARRAY <<<"${PY_ENVS}" + +for py_indicator in "${PY_ENVS_ARRAY[@]}"; do + py_squashed_numeric="${py_indicator//py/}" + py_squashed_numeric="${py_squashed_numeric//cp/}" + py_squashed_numeric="${py_squashed_numeric//./}" + manylinux_vername="${MANYLINUX_VERSION//_/}" + PIXI_ENV="manylinux${manylinux_vername}-py${py_squashed_numeric}" + + # Use pixi to ensure all required tools are installed and + # visible in the PATH + export PIXI_HOME=${CONTAINER_PACKAGE_SCRIPTS_DIR}/.pixi + export PATH="${PIXI_HOME}/bin:${PATH}" + python3.12 "${CONTAINER_PACKAGE_SCRIPTS_DIR}/scripts/install_pixi.py" --platform-env "${PIXI_ENV}" + + cd "${CONTAINER_PACKAGE_SCRIPTS_DIR}" || exit + if [ -n "${MODULE_SRC_DIRECTORY}" ]; then + pixi run -e "${PIXI_ENV}" python3 \ + "${CONTAINER_PACKAGE_SCRIPTS_DIR}/scripts/build_wheels.py" \ + --platform-env "${PIXI_ENV}" \ + "${BUILD_WHEELS_EXTRA_FLAGS_ARRAY[@]}" \ + --module-source-dir "${CONTAINER_MODULE_SRC_DIRECTORY}" \ + --module-dependencies-root-dir "${CONTAINER_MODULES_ROOT_DIRECTORY}" \ + --itk-module-deps "${ITK_MODULE_PREQ}" \ + --no-build-itk-tarball-cache \ + --build-dir-root "${CONTAINER_PACKAGE_BUILD_DIR}" \ + --itk-source-dir "${CONTAINER_ITK_SOURCE_DIR}" \ + --itk-git-tag "${ITK_GIT_TAG}" \ + --itk-package-version "${ITK_PACKAGE_VERSION:-}" \ + --manylinux-version "${MANYLINUX_VERSION}" \ + --no-use-sudo \ + --no-use-ccache \ + --skip-itk-build \ + --skip-itk-wheel-build + else + pixi run -e "${PIXI_ENV}" python3 \ + "${CONTAINER_PACKAGE_SCRIPTS_DIR}/scripts/build_wheels.py" \ + --platform-env "${PIXI_ENV}" \ + "${BUILD_WHEELS_EXTRA_FLAGS_ARRAY[@]}" \ + --build-itk-tarball-cache \ + --build-dir-root "${CONTAINER_PACKAGE_BUILD_DIR}" \ + --itk-source-dir "${CONTAINER_ITK_SOURCE_DIR}" \ + --itk-git-tag "${ITK_GIT_TAG}" \ + --itk-package-version "${ITK_PACKAGE_VERSION:-}" \ + --manylinux-version "${MANYLINUX_VERSION}" \ + --no-use-sudo \ + --no-use-ccache + fi + build_status=$? + if [ "${build_status}" -ne 0 ]; then + echo "ERROR: Build failed for ${py_indicator} with exit code ${build_status}" + exit "${build_status}" + fi + + echo "Successfully built wheel for ${py_indicator}" +done + +echo "" +echo "========================================" +echo "All builds completed successfully!" +echo "========================================" diff --git a/scripts/internal/manylinux-aarch64-build-module-wheels.sh b/scripts/internal/manylinux-aarch64-build-module-wheels.sh deleted file mode 100755 index f43a7f87..00000000 --- a/scripts/internal/manylinux-aarch64-build-module-wheels.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env bash - -# Run this script inside a dockcross container to build Python wheels for an aarch ITK module. -cd /work -# Update GPG keys -dnf upgrade -y almalinux-release -# Newer Python.cmake module required for SABI -pipx upgrade cmake -yum -y install sudo ninja-build -/opt/python/cp310-cp310/bin/python -m pip install -r /ITKPythonPackage/requirements-dev.txt -for PYBIN in "${PYBINARIES[@]}"; do - ${PYBIN}/pip install -r /ITKPythonPackage/requirements-dev.txt -done - -"/ITKPythonPackage/scripts/internal/manylinux-build-module-wheels.sh" "$@" diff --git a/scripts/internal/manylinux-build-common.sh b/scripts/internal/manylinux-build-common.sh deleted file mode 100644 index 6443b4c0..00000000 --- a/scripts/internal/manylinux-build-common.sh +++ /dev/null @@ -1,85 +0,0 @@ -# Content common to manylinux-build-wheels.sh and -# manylinux-build-module-wheels.sh - -set -e -x - -script_dir=$(cd $(dirname $0) || exit 1; pwd) - -# Versions can be restricted by passing them in as arguments to the script -# For example, -# manylinux-build-wheels.sh cp310 -if [[ $# -eq 0 ]]; then - PYBIN=(/opt/python/*/bin) - PYBINARIES=() - for version in "${PYBIN[@]}"; do - if [[ ${version} == *"cp310"* || ${version} == *"cp311"* ]]; then - PYBINARIES+=(${version}) - fi - done -else - PYBINARIES=() - for version in "$@"; do - PYBINARIES+=(/opt/python/*${version}*/bin) - done -fi - -# i686 or x86_64 ? -case $(uname -m) in - i686) - ARCH=x86 - ;; - x86_64) - ARCH=x64 - ;; - aarch64) - ARCH=aarch64 - ;; - *) - die "Unknown architecture $(uname -m)" - ;; -esac - -# Install prerequirements -export PATH=/work/tools/doxygen-1.8.16/bin:$PATH -case $(uname -m) in - i686) - ARCH=x86 - ;; - x86_64) - if ! type doxygen > /dev/null 2>&1; then - mkdir -p /work/tools - pushd /work/tools > /dev/null 2>&1 - curl https://data.kitware.com/api/v1/file/62c4d615bddec9d0c46cb705/download -o doxygen-1.8.16.linux.bin.tar.gz - tar -xvzf doxygen-1.8.16.linux.bin.tar.gz - popd > /dev/null 2>&1 - fi - ;; - aarch64) - ARCH=aarch64 - if ! type doxygen > /dev/null 2>&1; then - mkdir -p /work/tools - pushd /work/tools > /dev/null 2>&1 - curl https://data.kitware.com/api/v1/file/62c4ed58bddec9d0c46f1388/download -o doxygen-1.8.16.linux.aarch64.bin.tar.gz - tar -xvzf doxygen-1.8.16.linux.aarch64.bin.tar.gz - popd > /dev/null 2>&1 - fi - ;; - *) - die "Unknown architecture $(uname -m)" - ;; -esac -if ! type ninja > /dev/null 2>&1; then - if test ! -d ninja; then - git clone https://github.com/ninja-build/ninja.git - fi - pushd ninja - git checkout release - cmake -Bbuild-cmake -H. - cmake --build build-cmake - cp build-cmake/ninja /usr/local/bin/ - popd -fi - -MANYLINUX_VERSION=${MANYLINUX_VERSION:=_2_28} - -echo "Building wheels for $ARCH using manylinux${MANYLINUX_VERSION}" diff --git a/scripts/internal/manylinux-build-module-wheels.sh b/scripts/internal/manylinux-build-module-wheels.sh deleted file mode 100755 index 37ab0382..00000000 --- a/scripts/internal/manylinux-build-module-wheels.sh +++ /dev/null @@ -1,144 +0,0 @@ -#!/usr/bin/env bash - -# Run this script inside a dockcross container to build Python wheels for an ITK module. -# -# Versions can be restricted by passing them in as arguments to the script. -# For example, -# -# /tmp/dockcross-manylinux-x64 manylinux-build-module-wheels.sh cp310 -# -# Shared library dependencies can be included in the wheel by mounting them to /usr/lib64 or /usr/local/lib64 -# before running this script. -# -# For example, -# -# DOCKER_ARGS="-v /path/to/lib.so:/usr/local/lib64/lib.so" -# /tmp/dockcross-manylinux-x64 -a "$DOCKER_ARGS" manylinux-build-module-wheels.sh -# -# The specialized manylinux container version should be set prior to running this script. -# See https://github.com/dockcross/dockcross for available versions and tags. -# -# For example, `docker run -e ` can be used to set an environment variable when launching a container: -# -# export MANYLINUX_VERSION=2014 -# docker run --rm dockcross/manylinux${MANYLINUX_VERSION}-x64:${IMAGE_TAG} > /tmp/dockcross-manylinux-x64 -# chmod u+x /tmp/dockcross-manylinux-x64 -# /tmp/dockcross-manylinux-x64 -e MANYLINUX_VERSION manylinux-build-module-wheels.sh cp310 -# - -# ----------------------------------------------------------------------- -# Script argument parsing -# -usage() -{ - echo "Usage: - manylinux-build-module-wheels - [ -h | --help ] show usage - [ -c | --cmake_options ] space-separated string of CMake options to forward to the module (e.g. \"--config-setting=cmake.define.BUILD_TESTING=OFF\") - [ -x | --exclude_libs ] semicolon-separated library names to exclude when repairing wheel (e.g. \"libcuda.so\") - [ python_version ] build wheel for a specific python version. (e.g. cp310)" - exit 2 -} - -PARSED_ARGS=$(getopt -a -n dockcross-manylinux-download-cache-and-build-module-wheels \ - -o hc:x: --long help,cmake_options:,exclude_libs: -- "$@") -eval set -- "$PARSED_ARGS" - -while : -do - case "$1" in - -h | --help) usage; break ;; - -c | --cmake_options) CMAKE_OPTIONS="$2" ; shift 2 ;; - -x | --exclude_libs) EXCLUDE_LIBS="$2" ; shift 2 ;; - --) shift; break ;; - *) echo "Unexpected option: $1."; - usage; break ;; - esac -done - -PYTHON_VERSION="$@" -# ----------------------------------------------------------------------- - -# ----------------------------------------------------------------------- -# These variables are set in common script: -# -ARCH="" -PYBINARIES="" - -script_dir=$(cd $(dirname $0) || exit 1; pwd) -source "${script_dir}/manylinux-build-common.sh" -# ----------------------------------------------------------------------- - -# Set up library paths in container so that shared libraries can be added to wheels -sudo ldconfig -export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/work/oneTBB-prefix/lib:/usr/lib:/usr/lib64:/usr/local/lib:/usr/local/lib64 - -# Compile wheels re-using standalone project and archive cache -for PYBIN in "${PYBINARIES[@]}"; do - Python3_EXECUTABLE=${PYBIN}/python - Python3_INCLUDE_DIR=$( find -L ${PYBIN}/../include/ -name Python.h -exec dirname {} \; ) - - echo "" - echo "Python3_EXECUTABLE:${Python3_EXECUTABLE}" - echo "Python3_INCLUDE_DIR:${Python3_INCLUDE_DIR}" - - if [[ -e /work/requirements-dev.txt ]]; then - sudo ${PYBIN}/pip install --upgrade -r /work/requirements-dev.txt - fi - if [[ -e /ITKPythonPackage/requirements-dev.txt ]]; then - sudo ${PYBIN}/pip install --upgrade -r /ITKPythonPackage/requirements-dev.txt - fi - version=$(basename $(dirname ${PYBIN})) - # Remove "m" -- not present in Python 3.8 and later - version=${version:0:9} - itk_build_dir=/work/$(basename /ITKPythonPackage/ITK-${version}*-manylinux${MANYLINUX_VERSION}_${ARCH}) - ln -fs /ITKPythonPackage/ITK-${version}*-manylinux${MANYLINUX_VERSION}_${ARCH} $itk_build_dir - if [[ ! -d ${itk_build_dir} ]]; then - echo 'ITK build tree not available!' 1>&2 - exit 1 - fi - itk_source_dir=/work/ITK-source/ITK - ln -fs /ITKPythonPackage/ITK-source/ /work/ITK-source - if [[ ! -d ${itk_source_dir} ]]; then - echo 'ITK source tree not available!' 1>&2 - exit 1 - fi - py_minor=$(echo $version | cut -d '-' -f 1 | cut -d '3' -f 2) - wheel_py_api="" - if test $py_minor -ge 11; then - wheel_py_api=cp3$py_minor - fi - ${PYBIN}/python -m build \ - --verbose \ - --wheel \ - --outdir dist \ - --no-isolation \ - --skip-dependency-check \ - --config-setting=cmake.define.ITK_DIR:PATH=${itk_build_dir} \ - --config-setting=cmake.define.WRAP_ITK_INSTALL_COMPONENT_IDENTIFIER:STRING=PythonWheel \ - --config-setting=cmake.define.CMAKE_CXX_COMPILER_TARGET:STRING=$(uname -m)-linux-gnu \ - --config-setting=cmake.define.CMAKE_INSTALL_LIBDIR:STRING=lib \ - --config-setting=cmake.define.PY_SITE_PACKAGES_PATH:PATH="." \ - --config-setting=wheel.py-api=$wheel_py_api \ - --config-setting=cmake.define.BUILD_TESTING:BOOL=OFF \ - --config-setting=cmake.define.Python3_EXECUTABLE:FILEPATH=${Python3_EXECUTABLE} \ - --config-setting=cmake.define.Python3_INCLUDE_DIR:PATH=${Python3_INCLUDE_DIR} \ - ${CMAKE_OPTIONS//'-D'/'--config-setting=cmake.define.'} \ - || exit 1 -done - -# Convert list of excluded libs in --exclude_libs to auditwheel --exclude options -if test -n "$EXCLUDE_LIBS"; then - AUDITWHEEL_EXCLUDE_ARGS="--exclude ${EXCLUDE_LIBS//;/ --exclude }" -fi - -sudo ${Python3_EXECUTABLE} -m pip install auditwheel -for whl in dist/*linux*$(uname -m).whl; do - auditwheel repair ${whl} -w /work/dist/ ${AUDITWHEEL_EXCLUDE_ARGS} -done - -if compgen -G "dist/itk*-linux*.whl" > /dev/null; then - for itk_wheel in dist/itk*-linux*.whl; do - rm ${itk_wheel} - done -fi diff --git a/scripts/internal/manylinux-build-wheels.sh b/scripts/internal/manylinux-build-wheels.sh deleted file mode 100755 index 2ebacbec..00000000 --- a/scripts/internal/manylinux-build-wheels.sh +++ /dev/null @@ -1,215 +0,0 @@ -#!/usr/bin/env bash - -# Run this script inside a dockcross container to build Python wheels for ITK. -# -# Versions can be restricted by passing them in as arguments to the script. -# For example, -# -# /tmp/dockcross-manylinux-x64 manylinux-build-wheels.sh cp310 -# -# Shared library dependencies can be included wheels by mounting them to /usr/lib64 or /usr/local/lib64 -# before running this script. -# -# For example, -# -# DOCKER_ARGS="-v /path/to/lib.so:/usr/local/lib64/lib.so" -# /tmp/dockcross-manylinux-x64 -a "$DOCKER_ARGS" manylinux-build-wheels.sh -# -# The specialized manylinux container version should be set prior to running this script. -# See https://github.com/dockcross/dockcross for available versions and tags. -# -# For example, `docker run -e ` can be used to set an environment variable when launching a container: -# -# export MANYLINUX_VERSION=2014 -# docker run --rm dockcross/manylinux${MANYLINUX_VERSION}-x64:${IMAGE_TAG} > /tmp/dockcross-manylinux-x64 -# chmod u+x /tmp/dockcross-manylinux-x64 -# /tmp/dockcross-manylinux-x64 -e MANYLINUX_VERSION manylinux-build-module-wheels.sh cp310 -# - -# ----------------------------------------------------------------------- -# These variables are set in common script: -# -ARCH="" -PYBINARIES="" -Python3_LIBRARY="" - -script_dir=$(cd $(dirname $0) || exit 1; pwd) -source "${script_dir}/manylinux-build-common.sh" - -# ----------------------------------------------------------------------- - -# Build standalone project and populate archive cache -mkdir -p /work/ITK-source -pushd /work/ITK-source > /dev/null 2>&1 - cmake -DITKPythonPackage_BUILD_PYTHON:PATH=0 -G Ninja ../ - ninja -popd > /dev/null 2>&1 -tbb_dir=/work/oneTBB-prefix/lib/cmake/TBB -# So auditwheel can find the libs -sudo ldconfig -export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/work/oneTBB-prefix/lib:/usr/lib:/usr/lib64 - -# TODO: More work is required to re-enable this feature. -SINGLE_WHEEL=0 - -# Compile wheels re-using standalone project and archive cache -for PYBIN in "${PYBINARIES[@]}"; do - export Python3_EXECUTABLE=${PYBIN}/python3 - Python3_INCLUDE_DIR=$( find -L ${PYBIN}/../include/ -name Python.h -exec dirname {} \; ) - - echo "" - echo "Python3_EXECUTABLE:${Python3_EXECUTABLE}" - echo "Python3_INCLUDE_DIR:${Python3_INCLUDE_DIR}" - - # Install dependencies - sudo ${PYBIN}/pip install --upgrade -r /work/requirements-dev.txt - - build_type="Release" - compile_flags="-O3 -DNDEBUG" - source_path=/work/ITK-source/ITK - build_path=/work/ITK-$(basename $(dirname ${PYBIN}))-manylinux${MANYLINUX_VERSION}_${ARCH} - PYPROJECT_CONFIGURE="${script_dir}/../pyproject_configure.py" - - # Clean up previous invocations - # rm -rf ${build_path} - - if [[ ${SINGLE_WHEEL} == 1 ]]; then - - echo "#" - echo "# Build single ITK wheel" - echo "#" - - # Configure pyproject.toml - ${PYBIN}/python ${PYPROJECT_CONFIGURE} "itk" - # Generate wheel - ${PYBIN}/python -m build \ - --verbose \ - --wheel \ - --outdir dist \ - --no-isolation \ - --skip-dependency-check \ - --config-setting=cmake.define.ITK_SOURCE_DIR:PATH=${source_path} \ - --config-setting=cmake.define.ITK_BINARY_DIR:PATH=${build_path} \ - --config-setting=cmake.define.ITKPythonPackage_ITK_BINARY_REUSE:BOOL=OFF \ - --config-setting=cmake.define.ITKPythonPackage_WHEEL_NAME:STRING=itk \ - --config-setting=cmake.define.CMAKE_CXX_COMPILER_TARGET:STRING=$(uname -m)-linux-gnu \ - "--config-setting=cmake.define.CMAKE_CXX_FLAGS:STRING=$compile_flags" \ - "--config-setting=cmake.define.CMAKE_C_FLAGS:STRING=$compile_flags" \ - "--config-setting=cmake.define.CMAKE_BUILD_TYPE:STRING=${build_type}" \ - --config-setting=cmake.define.Python3_EXECUTABLE:FILEPATH=${Python3_EXECUTABLE} \ - --config-setting=cmake.define.Python3_INCLUDE_DIR:PATH=${Python3_INCLUDE_DIR} \ - --config-setting=cmake.define.Module_ITKTBB:BOOL=ON \ - --config-setting=cmake.define.TBB_DIR:PATH=${tbb_dir} \ - . - - else - - echo "#" - echo "# Build multiple ITK wheels" - echo "#" - - # Build ITK python - ( - mkdir -p ${build_path} \ - && cd ${build_path} \ - && cmake \ - -DCMAKE_BUILD_TYPE:STRING=${build_type} \ - -DITK_SOURCE_DIR:PATH=${source_path} \ - -DITK_BINARY_DIR:PATH=${build_path} \ - -DBUILD_TESTING:BOOL=OFF \ - -DPython3_EXECUTABLE:FILEPATH=${Python3_EXECUTABLE} \ - -DPython3_INCLUDE_DIR:PATH=${Python3_INCLUDE_DIR} \ - -DCMAKE_CXX_COMPILER_TARGET:STRING=$(uname -m)-linux-gnu \ - -DCMAKE_CXX_FLAGS:STRING="$compile_flags" \ - -DCMAKE_C_FLAGS:STRING="$compile_flags" \ - -DCMAKE_BUILD_TYPE:STRING="${build_type}" \ - -DWRAP_ITK_INSTALL_COMPONENT_IDENTIFIER:STRING=PythonWheel \ - -DWRAP_ITK_INSTALL_COMPONENT_PER_MODULE:BOOL=ON \ - -DITK_WRAP_unsigned_short:BOOL=ON \ - -DITK_WRAP_double:BOOL=ON \ - -DITK_WRAP_complex_double:BOOL=ON \ - -DITK_WRAP_IMAGE_DIMS:STRING="2;3;4" \ - -DPY_SITE_PACKAGES_PATH:PATH="." \ - -DITK_LEGACY_SILENT:BOOL=ON \ - -DITK_WRAP_PYTHON:BOOL=ON \ - -DITK_WRAP_DOC:BOOL=ON \ - -DModule_ITKTBB:BOOL=ON \ - -DTBB_DIR:PATH=${tbb_dir} \ - -G Ninja \ - ${source_path} \ - && ninja \ - || exit 1 - ) - - wheel_names=$(cat ${script_dir}/../WHEEL_NAMES.txt) - for wheel_name in ${wheel_names}; do - # Configure pyproject.toml - ${PYBIN}/python ${PYPROJECT_CONFIGURE} ${wheel_name} - # Generate wheel - ${PYBIN}/python -m build \ - --verbose \ - --wheel \ - --outdir dist \ - --no-isolation \ - --skip-dependency-check \ - --config-setting=cmake.define.ITK_SOURCE_DIR:PATH=${source_path} \ - --config-setting=cmake.define.ITK_BINARY_DIR:PATH=${build_path} \ - --config-setting=cmake.define.ITKPythonPackage_ITK_BINARY_REUSE:BOOL=ON \ - --config-setting=cmake.define.ITKPythonPackage_WHEEL_NAME:STRING=${wheel_name} \ - --config-setting=cmake.define.Python3_EXECUTABLE:FILEPATH=${Python3_EXECUTABLE} \ - --config-setting=cmake.define.Python3_INCLUDE_DIR:PATH=${Python3_INCLUDE_DIR} \ - --config-setting=cmake.define.CMAKE_CXX_FLAGS:STRING="${compile_flags}" \ - --config-setting=cmake.define.CMAKE_C_FLAGS:STRING="${compile_flags}" \ - . \ - || exit 1 - done - fi - - # Remove unnecessary files for building against ITK - find ${build_path} -name '*.cpp' -delete -o -name '*.xml' -delete - rm -rf ${build_path}/Wrapping/Generators/castxml* - find ${build_path} -name '*.o' -delete - -done - -sudo /opt/python/cp311-cp311/bin/pip3 install auditwheel wheel - -if test "${ARCH}" == "x64"; then - # This step will fixup the wheel switching from 'linux' to 'manylinux' tag - for whl in dist/itk_*linux_*.whl; do - /opt/python/cp311-cp311/bin/auditwheel repair --plat manylinux${MANYLINUX_VERSION}_x86_64 ${whl} -w /work/dist/ - done -else - for whl in dist/itk_*$(uname -m).whl; do - /opt/python/cp311-cp311/bin/auditwheel repair ${whl} -w /work/dist/ - done -fi - -# auditwheel does not process this "metawheel" correctly since it does not -# have any native SO's. -mkdir -p metawheel-dist -for whl in dist/itk-*linux_*.whl; do - /opt/python/cp311-cp311/bin/wheel unpack --dest metawheel ${whl} - manylinux_version=manylinux${MANYLINUX_VERSION} - new_tag=$(basename ${whl/linux/${manylinux_version}} .whl) - sed -i "s/Tag: .*/Tag: ${new_tag}/" metawheel/itk-*/itk*.dist-info/WHEEL - /opt/python/cp311-cp311/bin/wheel pack --dest metawheel-dist metawheel/itk-* - mv metawheel-dist/*.whl dist/${new_tag}.whl - rm -rf metawheel -done -rm -rf metawheel-dist -rm dist/itk-*-linux_*.whl -rm dist/itk_*-linux_*.whl - -# Install packages and test -for PYBIN in "${PYBINARIES[@]}"; do - ${PYBIN}/pip install --user numpy - sudo ${PYBIN}/pip install --upgrade pip - ${PYBIN}/pip install itk --user --no-cache-dir --no-index -f /work/dist - (cd $HOME && ${PYBIN}/python -c 'from itk import ITKCommon;') - (cd $HOME && ${PYBIN}/python -c 'import itk; image = itk.Image[itk.UC, 2].New()') - (cd $HOME && ${PYBIN}/python -c 'import itkConfig; itkConfig.LazyLoading = False; import itk;') - (cd $HOME && ${PYBIN}/python ${script_dir}/../../docs/code/test.py ) -done - -rm -f dist/numpy*.whl diff --git a/scripts/internal/shellcheck-run.sh b/scripts/internal/shellcheck-run.sh deleted file mode 100755 index e110bb79..00000000 --- a/scripts/internal/shellcheck-run.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/bin/bash - -set -e -set -o pipefail - -( -exit_code=0 - -# -# SC1090: Can't follow non-constant source. Use a directive to specify location. -# SC2006: Use $(..) instead of legacy `..`. -# SC2046: Quote this to prevent word splitting. -# SC2086: Double quote to prevent globbing and word splitting. -# SC2153: Possible misspelling: SCRIPT_DIR may not be assigned, but script_dir is. -# SC2155: Declare and assign separately to avoid masking return values. -# - -# find all executables and run `shellcheck` -for f in $(find . -type f -not -iwholename '*.git*' | sort -u); do - if file "$f" | grep --quiet -e shell -e bash; then - shellcheck \ - -e SC1090 \ - -e SC2046 \ - -e SC2086 \ - "$f" \ - && echo "[OK]: successfully linted $f" || echo "[FAILED]: found issues linting $f" - current_exit_code=$? - if [[ $current_exit_code != 0 ]]; then - exit_code=$current_exit_code - fi - fi -done - -exit $exit_code -) diff --git a/scripts/internal/windows_build_common.py b/scripts/internal/windows_build_common.py deleted file mode 100644 index 4cf2c739..00000000 --- a/scripts/internal/windows_build_common.py +++ /dev/null @@ -1,60 +0,0 @@ -__all__ = ["DEFAULT_PY_ENVS", "venv_paths"] - -from subprocess import check_call -import os -import shutil - -DEFAULT_PY_ENVS = ["310-x64", "311-x64"] - -SCRIPT_DIR = os.path.dirname(__file__) -ROOT_DIR = os.path.abspath(os.path.join(SCRIPT_DIR, "..", "..")) - - -def venv_paths(python_version): - # Create venv - venv_executable = "C:/Python%s/Scripts/virtualenv.exe" % (python_version) - venv_dir = os.path.join(ROOT_DIR, "venv-%s" % python_version) - check_call([venv_executable, venv_dir]) - - python_executable = os.path.join(venv_dir, "Scripts", "python.exe") - python_include_dir = "C:/Python%s/include" % (python_version) - - # XXX It should be possible to query skbuild for the library dir associated - # with a given interpreter. - xy_ver = python_version.split("-")[0] - - # Version-specific library (e.g., python311.lib) - required for - # CMake's FindPython3 to extract version info for Development.Module - python_library = "C:/Python%s/libs/python%s.lib" % (python_version, xy_ver) - - # Stable ABI library (python3.lib) - for Development.SABIModule - if int(xy_ver[1:]) >= 11: - python_sabi_library = "C:/Python%s/libs/python3.lib" % (python_version) - else: - python_sabi_library = python_library - - print("") - print("Python3_EXECUTABLE: %s" % python_executable) - print("Python3_INCLUDE_DIR: %s" % python_include_dir) - print("Python3_LIBRARY: %s" % python_library) - print("Python3_SABI_LIBRARY: %s" % python_sabi_library) - - pip = os.path.join(venv_dir, "Scripts", "pip.exe") - - ninja_executable = os.path.join(venv_dir, "Scripts", "ninja.exe") - if not os.path.exists(ninja_executable): - ninja_executable = shutil.which("ninja.exe") - print("NINJA_EXECUTABLE:%s" % ninja_executable) - - # Update PATH - path = os.path.join(venv_dir, "Scripts") - - return ( - python_executable, - python_include_dir, - python_library, - python_sabi_library, - pip, - ninja_executable, - path, - ) diff --git a/scripts/linux_build_python_instance.py b/scripts/linux_build_python_instance.py new file mode 100644 index 00000000..4f2ea72e --- /dev/null +++ b/scripts/linux_build_python_instance.py @@ -0,0 +1,278 @@ +import os +import shutil +from pathlib import Path + +from build_python_instance_base import BuildPythonInstanceBase +from wheel_builder_utils import ( + _remove_tree, +) + + +class LinuxBuildPythonInstance(BuildPythonInstanceBase): + """Linux-specific wheel builder. + + Handles manylinux container builds, ``auditwheel`` wheel repair, and + Linux-specific compiler/target triple configuration. + """ + + def prepare_build_env(self) -> None: + """Set up the Linux build environment, TBB paths, and compiler targets.""" + # ############################################# + # ### Setup build tools + self.package_env_config["USE_TBB"] = "ON" + self.package_env_config["TBB_DIR"] = ( + self.build_dir_root / "build" / "oneTBB-prefix" / "lib" / "cmake" / "TBB" + ) + + # The interpreter is provided; ensure basic tools are available + self.venv_paths() + self.update_venv_itk_build_configurations() + if self.package_env_config["ARCH"] == "x64": + target_triple = "x86_64-linux-gnu" + elif self.package_env_config["ARCH"] in ("aarch64", "arm64"): + target_triple = "aarch64-linux-gnu" + elif self.package_env_config["ARCH"] == "x86": + target_triple = "i686-linux-gnu" + else: + target_triple = f"{self.package_env_config['ARCH']}-linux-gnu" + + target_arch = self.package_env_config["ARCH"] + + self.cmake_compiler_configurations.set( + "CMAKE_CXX_COMPILER_TARGET:STRING", target_triple + ) + + # build will be here is downloaded + itk_binary_build_name: Path = ( + self.build_dir_root + / "build" + / f"ITK-{self.platform_env}-{self.get_pixi_environment_name()}_{target_arch}" + ) + + self.cmake_itk_source_build_configurations.set( + "ITK_BINARY_DIR:PATH", itk_binary_build_name.as_posix() + ) + + # Keep values consistent with prior quoting behavior + # self.cmake_compiler_configurations.set("CMAKE_CXX_FLAGS:STRING", "-O3 -DNDEBUG") + # self.cmake_compiler_configurations.set("CMAKE_C_FLAGS:STRING", "-O3 -DNDEBUG") + + def post_build_fixup(self) -> None: + """Repair wheels with ``auditwheel`` and retag the ITK meta-wheel.""" + manylinux_ver: str | None = self.package_env_config.get( + "MANYLINUX_VERSION", None + ) + if manylinux_ver: + # Repair all produced wheels with auditwheel for packages with so elements (starts with itk_) + whl = None + # cp39-cp39-linux itk_segmentation-6.0.0b2-cp39-cp39-linux_x86_64.whl + # Extract Python version from platform_env + if "-" in self.platform_env: + # in manylinux case, platform env is manylinux-cp310, for example, don't want anything before '-' + py_version = self.platform_env.split("-")[-1] + else: + py_version = self.platform_env + cp_prefix: str = py_version.replace("py", "cp").replace(".", "") + binary_wheel_glob_pattern: str = f"itk_*-*{cp_prefix}*-linux_*.whl" + dist_path: Path = self.build_dir_root / "dist" + for whl in dist_path.glob(binary_wheel_glob_pattern): + if whl.name.startswith("itk-"): + print( + f"Skipping the itk-meta wheel that has nothing to fixup {whl}" + ) + continue + self.fixup_wheel(str(whl)) + del whl + # Retag meta-wheel: Special handling for the itk meta wheel to adjust tag + # auditwheel does not process this "metawheel" correctly since it does not + # have any native SO's. + meta_wheel_glob_pattern: str = f"itk-*-*{cp_prefix}*-linux_*.whl" + for metawhl in dist_path.glob(meta_wheel_glob_pattern): + # Unpack, edit WHEEL tag, repack + metawheel_dir = self.build_dir_root / "metawheel" + metawheel_dir.mkdir(parents=True, exist_ok=True) + self.echo_check_call( + [ + self.package_env_config["PYTHON_EXECUTABLE"], + "-m", + "wheel", + "unpack", + "--dest", + str(metawheel_dir), + str(metawhl), + ] + ) + # Find unpacked dir + unpacked_dirs = list(metawheel_dir.glob("itk-*/itk*.dist-info/WHEEL")) + for wheel_file in unpacked_dirs: + content = wheel_file.read_text(encoding="utf-8").splitlines() + base = metawhl.name + if len(manylinux_ver) > 0: + base = metawhl.name.replace( + "linux", f"manylinux{manylinux_ver}" + ) + # Wheel filename: {name}-{version}-{python}-{abi}-{platform}.whl + # Tag must be only "{python}-{abi}-{platform}", not the full stem. + stem = Path(base).stem + parts = stem.split("-") + tag = "-".join(parts[-3:]) + new = [] + for line in content: + if line.startswith("Tag: "): + new.append(f"Tag: {tag}") + else: + new.append(line) + wheel_file.write_text("\n".join(new) + "\n", encoding="utf-8") + for fixed_dir in metawheel_dir.glob("itk-*"): + metawheel_dist = self.build_dir_root / "metawheel-dist" + metawheel_dist.mkdir(parents=True, exist_ok=True) + self.echo_check_call( + [ + self.package_env_config["PYTHON_EXECUTABLE"], + "-m", + "wheel", + "pack", + "--dest", + str(metawheel_dist), + str(fixed_dir), + ] + ) + # Move and clean + for new_whl in metawheel_dist.glob("*.whl"): + shutil.move( + str(new_whl), + str((self.build_dir_root / "dist") / new_whl.name), + ) + # Remove old and temp + try: + metawhl.unlink() + except OSError: + pass + _remove_tree(metawheel_dir) + _remove_tree(metawheel_dist) + + def fixup_wheel( + self, filepath, lib_paths: str = "", remote_module_wheel: bool = False + ) -> None: + """Repair a wheel with ``auditwheel`` and apply manylinux platform tags. + + Parameters + ---------- + filepath : str + Path to the ``.whl`` file. + lib_paths : str, optional + Unused on Linux (kept for interface compatibility). + remote_module_wheel : bool, optional + If True, output repaired wheel to the remote module's ``dist/`` + directory instead of the main build ``dist/``. + """ + # Use auditwheel to repair wheels and set manylinux tags + manylinux_ver = self.package_env_config.get("MANYLINUX_VERSION", "") + if len(manylinux_ver) > 1: + plat = None + if self.package_env_config["ARCH"] == "x64" and manylinux_ver: + plat = f"manylinux{manylinux_ver}_x86_64" + cmd = [ + self.package_env_config["PYTHON_EXECUTABLE"], + "-m", + "auditwheel", + "repair", + ] + if plat: + cmd += ["--plat", plat] + cmd += [ + str(filepath), + "-w", + ( + str(self.module_source_dir / "dist") + if remote_module_wheel + else str(self.build_dir_root / "dist") + ), + ] + # Provide LD_LIBRARY_PATH for oneTBB and common system paths + extra_lib = str( + self.package_env_config["IPP_SUPERBUILD_BINARY_DIR"].parent + / "oneTBB-prefix" + / "lib" + ) + env = dict(self.package_env_config) + env["LD_LIBRARY_PATH"] = ":".join( + [ + env.get("LD_LIBRARY_PATH", ""), + extra_lib, + "/usr/lib64", + "/usr/lib", + ] + ) + print(f'RUNNING WITH PATH {os.environ["PATH"]}') + env["PATH"] = os.environ["PATH"] + self.echo_check_call(cmd, env=env) + + # Remove the original linux_*.whl after successful repair + filepath_obj = Path(filepath) + if ( + filepath_obj.exists() + and "-linux_" in filepath_obj.name + and filepath_obj.suffix == ".whl" + ): + print( + f"Removing original linux wheel after repair: {filepath_obj.name}" + ) + try: + _remove_tree(filepath_obj) + except OSError as e: + print(f"Warning: Could not remove {filepath_obj.name}: {e}") + else: + print( + "Building outside of manylinux environment does not require wheel fixups." + ) + return + + def build_tarball(self): + """Create a zstd-compressed tarball of the ITK build tree.""" + self.create_posix_tarball() + + def discover_python_venvs( + self, platform_os_name: str, platform_architechure: str + ) -> list[str]: + """Discover available CPython installs on Linux. + + Checks ``/opt/python`` (manylinux) and the project ``venvs/`` + directory. + + Parameters + ---------- + platform_os_name : str + Operating system identifier (unused, kept for interface). + platform_architechure : str + Architecture identifier (unused, kept for interface). + + Returns + ------- + list[str] + Sorted list of discovered environment names. + """ + names = [] + + # Discover virtualenvs under project 'venvs' folder + def _discover_ipp_venvs() -> list[str]: + venvs_dir = self.build_dir_root / "venvs" + if not venvs_dir.exists(): + return [] + names.extend([p.name for p in venvs_dir.iterdir() if p.is_dir()]) + # Sort for stable order + return sorted(names) + + # Discover available manylinux CPython installs under /opt/python + def _discover_manylinuxlocal_pythons() -> list[str]: + base = Path("/opt/python") + if not base.exists(): + return [] + names.extend([p.name for p in base.iterdir() if p.is_dir()]) + return sorted(names) + + default_platform_envs = ( + _discover_manylinuxlocal_pythons() + _discover_ipp_venvs() + ) + + return default_platform_envs diff --git a/scripts/macos_build_python_instance.py b/scripts/macos_build_python_instance.py new file mode 100644 index 00000000..4b04fcc8 --- /dev/null +++ b/scripts/macos_build_python_instance.py @@ -0,0 +1,140 @@ +from pathlib import Path + +from build_python_instance_base import BuildPythonInstanceBase + + +class MacOSBuildPythonInstance(BuildPythonInstanceBase): + """macOS-specific wheel builder. + + Handles macOS deployment target and architecture settings, and uses + ``delocate`` for wheel repair on x86_64 builds. + """ + + def prepare_build_env(self) -> None: + """Set up the macOS build environment, deployment target, and architecture.""" + # ############################################# + # ### Setup build tools + self.package_env_config["USE_TBB"] = "OFF" + self.package_env_config["TBB_DIR"] = "NOT_FOUND" + + # The interpreter is provided; ensure basic tools are available + self.venv_paths() + self.update_venv_itk_build_configurations() + macosx_target = self.package_env_config.get("MACOSX_DEPLOYMENT_TARGET", "") + if macosx_target: + self.cmake_compiler_configurations.set( + "CMAKE_OSX_DEPLOYMENT_TARGET:STRING", macosx_target + ) + + target_arch = self.package_env_config["ARCH"] + + self.cmake_compiler_configurations.set( + "CMAKE_OSX_ARCHITECTURES:STRING", target_arch + ) + + # build will be here if downloaded + binaries_path = Path( + self.build_dir_root + / "build" + / f"ITK-{self.platform_env}-{self.platform_env}_{target_arch}" + ) + + if Path(binaries_path).exists(): + itk_binary_build_name = binaries_path + else: + itk_binary_build_name: Path = ( + self.build_dir_root + / "build" + / f"ITK-{self.platform_env}-{self.get_pixi_environment_name()}_{target_arch}" + ) + + self.cmake_itk_source_build_configurations.set( + "ITK_BINARY_DIR:PATH", itk_binary_build_name.as_posix() + ) + + # Keep values consistent with prior quoting behavior + # self.cmake_compiler_configurations.set("CMAKE_CXX_FLAGS:STRING", "-O3 -DNDEBUG") + # self.cmake_compiler_configurations.set("CMAKE_C_FLAGS:STRING", "-O3 -DNDEBUG") + + def post_build_fixup(self) -> None: + """Run ``delocate`` on x86_64 wheels to bundle shared libraries.""" + # delocate on macOS x86_64 only + if self.package_env_config["ARCH"] == "x86_64": + self.fixup_wheels() + + def build_tarball(self): + """Create a zstd-compressed tarball of the ITK build tree.""" + self.create_posix_tarball() + + def discover_python_venvs( + self, platform_os_name: str, platform_architechure: str + ) -> list[str]: + """Discover available Python environments under the project ``venvs/`` dir. + + Parameters + ---------- + platform_os_name : str + Operating system identifier (unused, kept for interface). + platform_architechure : str + Architecture identifier (unused, kept for interface). + + Returns + ------- + list[str] + Sorted list of discovered environment names. + """ + names = [] + + # Discover virtualenvs under project 'venvs' folder + def _discover_ipp_venvs() -> list[str]: + venvs_dir = self.build_dir_root / "venvs" + if not venvs_dir.exists(): + return [] + names.extend([p.name for p in venvs_dir.iterdir() if p.is_dir()]) + # Sort for stable order + return sorted(names) + + default_platform_envs = _discover_ipp_venvs() + + return default_platform_envs + + def fixup_wheel( + self, filepath, lib_paths: str = "", remote_module_wheel: bool = False + ) -> None: + """Repair a wheel using ``delocate`` on x86_64, cleaning AppleDouble files first. + + Parameters + ---------- + filepath : str + Path to the ``.whl`` file. + lib_paths : str, optional + Unused on macOS (kept for interface compatibility). + remote_module_wheel : bool, optional + Unused on macOS (kept for interface compatibility). + """ + self.remove_apple_double_files() + # macOS fix-up with delocate (only needed for x86_64) + if self.package_env_config["ARCH"] != "arm64": + venv_bin_path = self.venv_info_dict.get("venv_bin_path", None) + if venv_bin_path: + delocate_listdeps = f"{venv_bin_path}/delocate-listdeps" + delocate_wheel = f"{venv_bin_path}/delocate-wheel" + self.echo_check_call([str(delocate_listdeps), str(filepath)]) + self.echo_check_call([str(delocate_wheel), str(filepath)]) + else: + print( + "=" * 20 + + "WARNING: Could not find venv binary to delocate wheel" + + "=" * 20 + ) + + def remove_apple_double_files(self): + """Remove AppleDouble ``._*`` files using ``dot_clean`` if available.""" + try: + # Optional: clean AppleDouble files if tool is available + self.echo_check_call( + ["dot_clean", str(self.package_env_config["IPP_SOURCE_DIR"])] + ) + except Exception: + # dot_clean may not be available; continue without it + pass diff --git a/scripts/macpython-build-common.sh b/scripts/macpython-build-common.sh deleted file mode 100644 index 123ced58..00000000 --- a/scripts/macpython-build-common.sh +++ /dev/null @@ -1,79 +0,0 @@ -# Content common to macpython-build-wheels.sh and -# macpython-build-module-wheels.sh - -set -e -x - -SCRIPT_DIR=$(cd $(dirname $0) || exit 1; pwd) - -MACPYTHON_PY_PREFIX=/Library/Frameworks/Python.framework/Versions - -# ----------------------------------------------------------------------- -# Script argument parsing -# -usage() -{ - echo "Usage: - macpython-build-common - [ -h | --help ] show usage - [ -c | --cmake_options ] space-separated string of CMake options to forward to the module (e.g. \"--config-setting=cmake.define.BUILD_TESTING=OFF\") - [ -- python_versions ] build wheel for a specific python version(s). (e.g. -- 3.10 3.11)" - exit 2 -} - -PYTHON_VERSIONS="" -CMAKE_OPTIONS="" - -while (( "$#" )); do - case "$1" in - -c|--cmake_options) - CMAKE_OPTIONS="$2"; - shift 2;; - -h|--help) - usage; - break;; - --) - shift; - break;; - *) - # Parse any unrecognized arguments as python versions - PYTHON_VERSIONS="${PYTHON_VERSIONS} $1"; - shift;; - esac -done - -# Parse all arguments after "--" as python versions -PYTHON_VERSIONS="${PYTHON_VERSIONS} $@" -# Trim whitespace -PYTHON_VERSIONS=$(xargs <<< "${PYTHON_VERSIONS}") - -# Versions can be restricted by passing them in as arguments to the script -# For example, -# macpython-build-wheels.sh 3.10 -if [[ -z "${PYTHON_VERSIONS}" ]]; then - PYBINARIES=(${MACPYTHON_PY_PREFIX}/*) -else - PYBINARIES=() - for version in "$PYTHON_VERSIONS"; do - PYBINARIES+=(${MACPYTHON_PY_PREFIX}/*${version}*) - done -fi - -VENVS=() -mkdir -p ${SCRIPT_DIR}/../venvs -for PYBIN in "${PYBINARIES[@]}"; do - if [[ $(basename $PYBIN) = "Current" ]]; then - continue - fi - py_mm=$(basename ${PYBIN}) - VENV=${SCRIPT_DIR}/../venvs/${py_mm} - VENVS+=(${VENV}) -done - -# ----------------------------------------------------------------------- -# Ensure that requirements are met -brew update -brew info doxygen | grep --quiet 'Not installed' && brew install doxygen -brew info ninja | grep --quiet 'Not installed' && brew install ninja -NINJA_EXECUTABLE=$(which ninja) -brew info cmake | grep --quiet 'Not installed' && brew install cmake -CMAKE_EXECUTABLE=$(which cmake) diff --git a/scripts/macpython-build-module-deps.sh b/scripts/macpython-build-module-deps.sh deleted file mode 100644 index a74e9da7..00000000 --- a/scripts/macpython-build-module-deps.sh +++ /dev/null @@ -1,75 +0,0 @@ -#!/bin/bash - -######################################################################## -# Run this script in an ITK external module directory to generate -# build artifacts for prerequisite ITK MacOS modules. -# -# Module dependencies are built in a flat directory structure regardless -# of recursive dependencies. Prerequisite sources are required to be passed -# in the order in which they should be built. -# For example, if ITKTargetModule depends on ITKTargetModuleDep2 which -# depends on ITKTargetModuleDep1, the output directory structure -# will look like this: -# -# / ITKTargetModule -# -- / ITKTargetModuleDep1 -# -- / ITKTargetModuleDep2 -# .. -# -# =========================================== -# ENVIRONMENT VARIABLES -# -# - `ITK_MODULE_PREQ`: Prerequisite ITK modules that must be built before the requested module. -# Format is `/@:/@:...`. -# For instance, `export ITK_MODULE_PREQ=InsightSoftwareConsortium/ITKMeshToPolyData@v0.10.0` -# -######################################################################## - -script_dir=$(cd $(dirname $0) || exit 1; pwd) -if [[ ! -f "${script_dir}/macpython-download-cache-and-build-module-wheels.sh" ]]; then - echo "Could not find download script to use for building module dependencies!" - exit 1 -fi - -# Temporarily update prerequisite environment variable to prevent infinite recursion. -ITK_MODULE_PREQ_TOPLEVEL=${ITK_MODULE_PREQ} -ITK_USE_LOCAL_PYTHON_TOPLEVEL=${ITK_USE_LOCAL_PYTHON} -export ITK_MODULE_PREQ="" -export ITK_USE_LOCAL_PYTHON="ON" - -######################################################################## -echo "Building ITK module dependencies: ${ITK_MODULE_PREQ_TOPLEVEL}" - -for MODULE_INFO in ${ITK_MODULE_PREQ_TOPLEVEL//:/ }; do - MODULE_ORG=`(echo ${MODULE_INFO} | cut -d'/' -f 1)` - MODULE_NAME=`(echo ${MODULE_INFO} | cut -d'@' -f 1 | cut -d'/' -f 2)` - MODULE_TAG=`(echo ${MODULE_INFO} | cut -d'@' -f 2)` - - MODULE_UPSTREAM=https://github.com/${MODULE_ORG}/${MODULE_NAME}.git - echo "Cloning from ${MODULE_UPSTREAM}" - git clone ${MODULE_UPSTREAM} - - pushd ${MODULE_NAME} - git checkout ${MODULE_TAG} - cp ${script_dir}/macpython-download-cache-and-build-module-wheels.sh . - echo "Building dependency ${MODULE_NAME}" - ./macpython-download-cache-and-build-module-wheels.sh $@ - popd - - cp ./${MODULE_NAME}/include/* include/ - find ${MODULE_NAME}/wrapping -name '*.in' -print -exec cp {} wrapping \; - find ${MODULE_NAME}/wrapping -name '*.init' -print -exec cp {} wrapping \; - find ${MODULE_NAME}/*build/*/include -type f -print -exec cp {} include \; - rm -f ./${MODULE_NAME}/ITKPythonBuilds-macosx.tar.zst -done - -# Restore environment variable -export ITK_MODULE_PREQ=${ITK_MODULE_PREQ_TOPLEVEL} -export ITK_USE_LOCAL_PYTHON=${ITK_USE_LOCAL_PYTHON_TOPLEVEL} -ITK_MODULE_PREQ_TOPLEVEL="" -ITK_USE_LOCAL_PYTHON_TOPLEVEL="" - -# Summarize disk usage for debugging -du -sh ./* | sort -hr | head -n 20 - -echo "Done building ITK external module dependencies" diff --git a/scripts/macpython-build-module-wheels.sh b/scripts/macpython-build-module-wheels.sh deleted file mode 100755 index 3c583d4d..00000000 --- a/scripts/macpython-build-module-wheels.sh +++ /dev/null @@ -1,134 +0,0 @@ -#!/usr/bin/env bash - -######################################################################## -# Run this script in an ITK external module directory to build the -# Python wheel packages for macOS for an ITK external module. -# -# ======================================================================== -# PARAMETERS -# -# Versions can be restricted by passing them in as arguments to the script. -# For example, -# -# scripts/macpython-build-module-wheels.sh 3.10 3.11 -# Shared libraries can be included in the wheel by exporting them to DYLD_LIBRARY_PATH before -# running this script. -# -# =========================================== -# ENVIRONMENT VARIABLES -# -# These variables are set with the `export` bash command before calling the script. -# For example, -# -# export DYLD_LIBRARY_PATH="/path/to/libs" -# scripts/macpython-build-module-wheels.sh 3.10 3.11 -# -# `DYLD_LIBRARY_PATH`: Shared libraries to be included in the resulting wheel. -# For instance, `export DYLD_LIBRARY_PATH="/path/to/OpenCL.so:/path/to/OpenCL.so.1.2"` -# -# `ITK_MODULE_PREQ`: Prerequisite ITK modules that must be built before the requested module. -# Format is `/@:/@:...`. -# For instance, `export ITK_MODULE_PREQ=InsightSoftwareConsortium/ITKMeshToPolyData@v0.10.0` -# -######################################################################## - - -# ----------------------------------------------------------------------- -# (Optional) Build ITK module dependencies - -script_dir=$(cd $(dirname $0) || exit 1; pwd) - -if [[ -n ${ITK_MODULE_PREQ} ]]; then - source "${script_dir}/macpython-build-module-deps.sh" -fi - -# ----------------------------------------------------------------------- -# These variables are set in common script: -# -# * CMAKE_EXECUTABLE -# * CMAKE_OPTIONS -# * MACPYTHON_PY_PREFIX -# * PYBINARIES -# * PYTHON_VERSIONS -# * NINJA_EXECUTABLE -# * SCRIPT_DIR -# * SKBUILD_DIR -# * VENVS=() - -MACPYTHON_PY_PREFIX="" -SCRIPT_DIR="" -VENVS=() - -source "${script_dir}/macpython-build-common.sh" -# ----------------------------------------------------------------------- - -VENV="${VENVS[0]}" -Python3_EXECUTABLE=${VENV}/bin/python3 -dot_clean ${VENV} -${Python3_EXECUTABLE} -m pip install --no-cache delocate -DELOCATE_LISTDEPS=${VENV}/bin/delocate-listdeps -DELOCATE_WHEEL=${VENV}/bin/delocate-wheel -DELOCATE_PATCH=${VENV}/bin/delocate-patch -# So delocate can find the libs -export DYLD_LIBRARY_PATH=${DYLD_LIBRARY_PATH}:${script_dir}/../oneTBB-prefix/lib - -# Compile wheels re-using standalone project and archive cache -for VENV in "${VENVS[@]}"; do - py_mm=$(basename ${VENV}) - Python3_EXECUTABLE=${VENV}/bin/python - Python3_INCLUDE_DIR=$( find -L ${MACPYTHON_PY_PREFIX}/${py_mm}/include -name Python.h -exec dirname {} \; ) - - echo "" - echo "Python3_EXECUTABLE:${Python3_EXECUTABLE}" - echo "Python3_INCLUDE_DIR:${Python3_INCLUDE_DIR}" - - if [[ $(arch) == "arm64" ]]; then - plat_name="macosx-15.0-arm64" - osx_target="15.0" - osx_arch="arm64" - build_path="${SCRIPT_DIR}/../ITK-${py_mm}-macosx_arm64" - else - plat_name="macosx-15.0-x86_64" - osx_target="15.0" - osx_arch="x86_64" - build_path="${SCRIPT_DIR}/../ITK-${py_mm}-macosx_x86_64" - fi - if [[ ! -z "${MACOSX_DEPLOYMENT_TARGET}" ]]; then - osx_target="${MACOSX_DEPLOYMENT_TARGET}" - fi - export MACOSX_DEPLOYMENT_TARGET=${osx_target} - - if [[ -e $PWD/requirements-dev.txt ]]; then - ${Python3_EXECUTABLE} -m pip install --upgrade -r $PWD/requirements-dev.txt - fi - itk_build_path="${build_path}" - py_minor=$(echo $py_mm | cut -d '.' -f 2) - wheel_py_api="" - if test $py_minor -ge 11; then - wheel_py_api=cp3$py_minor - fi - ${Python3_EXECUTABLE} -m build \ - --verbose \ - --wheel \ - --outdir dist \ - --no-isolation \ - --skip-dependency-check \ - --config-setting=cmake.define.CMAKE_MAKE_PROGRAM:FILEPATH=${NINJA_EXECUTABLE} \ - --config-setting=cmake.define.ITK_DIR:PATH=${itk_build_path} \ - --config-setting=cmake.define.CMAKE_INSTALL_LIBDIR:STRING=lib \ - --config-setting=cmake.define.WRAP_ITK_INSTALL_COMPONENT_IDENTIFIER:STRING=PythonWheel \ - --config-setting=cmake.define.CMAKE_OSX_DEPLOYMENT_TARGET:STRING=${osx_target} \ - --config-setting=cmake.define.CMAKE_OSX_ARCHITECTURES:STRING=${osx_arch} \ - --config-setting=cmake.define.PY_SITE_PACKAGES_PATH:PATH="." \ - --config-setting=wheel.py-api=$wheel_py_api \ - --config-setting=cmake.define.BUILD_TESTING:BOOL=OFF \ - --config-setting=cmake.define.Python3_EXECUTABLE:FILEPATH=${Python3_EXECUTABLE} \ - --config-setting=cmake.define.Python3_INCLUDE_DIR:PATH=${Python3_INCLUDE_DIR} \ - ${CMAKE_OPTIONS//'-D'/'--config-setting=cmake.define.'} \ - || exit 1 -done - -for wheel in $PWD/dist/*.whl; do - ${DELOCATE_LISTDEPS} $wheel # lists library dependencies - ${DELOCATE_WHEEL} $wheel # copies library dependencies into wheel -done diff --git a/scripts/macpython-build-wheels.sh b/scripts/macpython-build-wheels.sh deleted file mode 100755 index 60307e16..00000000 --- a/scripts/macpython-build-wheels.sh +++ /dev/null @@ -1,238 +0,0 @@ -#!/usr/bin/env bash - -# Run this script to build the ITK Python wheel packages for macOS. -# -# Versions can be restricted by passing them in as arguments to the script -# For example, -# -# scripts/macpython-build-wheels.sh 3.10 -# -# Shared libraries can be included in the wheel by exporting them to DYLD_LIBRARY_PATH before -# running this script. -# -# For example, -# -# export DYLD_LIBRARY_PATH="/path/to/libs" -# scripts/macpython-build-module-wheels.sh 3.10 -# - -# ----------------------------------------------------------------------- -# These variables are set in common script: -# -# * CMAKE_EXECUTABLE -# * CMAKE_OPTIONS -# * MACPYTHON_PY_PREFIX -# * PYBINARIES -# * PYTHON_VERSIONS -# * NINJA_EXECUTABLE -# * SCRIPT_DIR -# * VENVS=() - -MACPYTHON_PY_PREFIX="" -PYBINARIES="" -SCRIPT_DIR="" - -script_dir=$(cd $(dirname $0) || exit 1; pwd) -source "${script_dir}/macpython-build-common.sh" - -# ----------------------------------------------------------------------- -# Remove previous virtualenv's -rm -rf ${SCRIPT_DIR}/../venvs -# Create virtualenv's -VENVS=() -mkdir -p ${SCRIPT_DIR}/../venvs -for PYBIN in "${PYBINARIES[@]}"; do - if [[ $(basename $PYBIN) = "Current" ]]; then - continue - fi - py_mm=$(basename ${PYBIN}) - VENV=${SCRIPT_DIR}/../venvs/${py_mm} - VIRTUALENV_EXECUTABLE="${PYBIN}/bin/python3 -m venv" - ${VIRTUALENV_EXECUTABLE} ${VENV} - VENVS+=(${VENV}) -done - -VENV="${VENVS[0]}" -Python3_EXECUTABLE=${VENV}/bin/python3 -${Python3_EXECUTABLE} -m pip install --upgrade pip -${Python3_EXECUTABLE} -m pip install --no-cache delocate -DELOCATE_LISTDEPS=${VENV}/bin/delocate-listdeps -DELOCATE_WHEEL=${VENV}/bin/delocate-wheel -DELOCATE_PATCH=${VENV}/bin/delocate-patch - -build_type="Release" - -if [[ $(arch) == "arm64" ]]; then - osx_target="15.0" - osx_arch="arm64" - use_tbb="OFF" -else - osx_target="15.0" - osx_arch="x86_64" - use_tbb="OFF" -fi - -export MACOSX_DEPLOYMENT_TARGET=${osx_target} - -# Build standalone project and populate archive cache -tbb_dir=$PWD/oneTBB-prefix/lib/cmake/TBB -n_processors=$(sysctl -n hw.ncpu) -# So delocate can find the libs -export DYLD_LIBRARY_PATH=${DYLD_LIBRARY_PATH}:$PWD/oneTBB-prefix/lib -mkdir -p ITK-source -pushd ITK-source > /dev/null 2>&1 - ${CMAKE_EXECUTABLE} -DITKPythonPackage_BUILD_PYTHON:PATH=0 \ - -DITKPythonPackage_USE_TBB:BOOL=${use_tbb} \ - -G Ninja \ - -DCMAKE_BUILD_TYPE:STRING=${build_type} \ - -DCMAKE_MAKE_PROGRAM:FILEPATH=${NINJA_EXECUTABLE} \ - -DCMAKE_OSX_DEPLOYMENT_TARGET:STRING=${osx_target} \ - -DCMAKE_OSX_ARCHITECTURES:STRING=${osx_arch} \ - ${SCRIPT_DIR}/../ - ${NINJA_EXECUTABLE} -j$n_processors -l$n_processors -popd > /dev/null 2>&1 - -SINGLE_WHEEL=0 - -# Compile wheels re-using standalone project and archive cache -for VENV in "${VENVS[@]}"; do - py_mm=$(basename ${VENV}) - export Python3_EXECUTABLE=${VENV}/bin/python - Python3_INCLUDE_DIR=$( find -L ${MACPYTHON_PY_PREFIX}/${py_mm}/include -name Python.h -exec dirname {} \; ) - - echo "" - echo "Python3_EXECUTABLE:${Python3_EXECUTABLE}" - echo "Python3_INCLUDE_DIR:${Python3_INCLUDE_DIR}" - - ${Python3_EXECUTABLE} -m pip install --upgrade -r ${SCRIPT_DIR}/../requirements-dev.txt - - if [[ $(arch) == "arm64" ]]; then - plat_name="macosx-15.0-arm64" - build_path="${SCRIPT_DIR}/../ITK-${py_mm}-macosx_arm64" - else - plat_name="macosx-15.0-x86_64" - build_path="${SCRIPT_DIR}/../ITK-${py_mm}-macosx_x86_64" - fi - if [[ ! -z "${MACOSX_DEPLOYMENT_TARGET}" ]]; then - osx_target="${MACOSX_DEPLOYMENT_TARGET}" - fi - source_path=${SCRIPT_DIR}/../ITK-source/ITK - PYPROJECT_CONFIGURE="${script_dir}/pyproject_configure.py" - - # Clean up previous invocations - rm -rf ${build_path} - - if [[ ${SINGLE_WHEEL} == 1 ]]; then - - echo "#" - echo "# Build single ITK wheel" - echo "#" - - # Configure pyproject.toml - ${Python3_EXECUTABLE} ${PYPROJECT_CONFIGURE} "itk" - # Generate wheel - ${Python3_EXECUTABLE} -m build \ - --verbose \ - --wheel \ - --outdir dist \ - --no-isolation \ - --skip-dependency-check \ - --config-setting=cmake.define.CMAKE_MAKE_PROGRAM:FILEPATH=${NINJA_EXECUTABLE} \ - --config-setting=cmake.define.ITK_SOURCE_DIR:PATH=${source_path} \ - --config-setting=cmake.define.ITK_BINARY_DIR:PATH=${build_path} \ - --config-setting=cmake.define.CMAKE_OSX_DEPLOYMENT_TARGET:STRING=${osx_target} \ - --config-setting=cmake.define.CMAKE_OSX_ARCHITECTURES:STRING=${osx_arch} \ - --config-setting=cmake.define.Python3_EXECUTABLE:FILEPATH=${Python3_EXECUTABLE} \ - --config-setting=cmake.define.Python3_INCLUDE_DIR:PATH=${Python3_INCLUDE_DIR} \ - --config-setting=cmake.define.Module_ITKTBB:BOOL=${use_tbb} \ - --config-setting=cmake.define.TBB_DIR:PATH=${tbb_dir} \ - . \ - ${CMAKE_OPTIONS} - - else - - echo "#" - echo "# Build multiple ITK wheels" - echo "#" - - # Build ITK python - ( - mkdir -p ${build_path} \ - && cd ${build_path} \ - && cmake \ - -DCMAKE_BUILD_TYPE:STRING=${build_type} \ - -DITK_SOURCE_DIR:PATH=${source_path} \ - -DITK_BINARY_DIR:PATH=${build_path} \ - -DBUILD_TESTING:BOOL=OFF \ - -DCMAKE_OSX_DEPLOYMENT_TARGET:STRING=${osx_target} \ - -DCMAKE_OSX_ARCHITECTURES:STRING=${osx_arch} \ - -DITK_WRAP_unsigned_short:BOOL=ON \ - -DITK_WRAP_double:BOOL=ON \ - -DITK_WRAP_complex_double:BOOL=ON \ - -DITK_WRAP_IMAGE_DIMS:STRING="2;3;4" \ - -DPython3_EXECUTABLE:FILEPATH=${Python3_EXECUTABLE} \ - -DPython3_INCLUDE_DIR:PATH=${Python3_INCLUDE_DIR} \ - -DWRAP_ITK_INSTALL_COMPONENT_IDENTIFIER:STRING=PythonWheel \ - -DWRAP_ITK_INSTALL_COMPONENT_PER_MODULE:BOOL=ON \ - "-DPY_SITE_PACKAGES_PATH:PATH=." \ - -DITK_LEGACY_SILENT:BOOL=ON \ - -DITK_WRAP_PYTHON:BOOL=ON \ - -DITK_WRAP_DOC:BOOL=ON \ - -DModule_ITKTBB:BOOL=${use_tbb} \ - -DTBB_DIR:PATH=${tbb_dir} \ - ${CMAKE_OPTIONS} \ - -G Ninja \ - ${source_path} \ - && ninja -j$n_processors -l$n_processors \ - || exit 1 - ) - - wheel_names=$(cat ${SCRIPT_DIR}/WHEEL_NAMES.txt) - for wheel_name in ${wheel_names}; do - # Configure pyproject.toml - ${Python3_EXECUTABLE} ${PYPROJECT_CONFIGURE} ${wheel_name} - # Generate wheel - ${Python3_EXECUTABLE} -m build \ - --verbose \ - --wheel \ - --outdir dist \ - --no-isolation \ - --skip-dependency-check \ - --config-setting=cmake.define.ITK_SOURCE_DIR:PATH=${source_path} \ - --config-setting=cmake.define.ITK_BINARY_DIR:PATH=${build_path} \ - --config-setting=cmake.define.CMAKE_OSX_DEPLOYMENT_TARGET:STRING=${osx_target} \ - --config-setting=cmake.define.CMAKE_OSX_ARCHITECTURES:STRING=${osx_arch} \ - --config-setting=cmake.define.ITKPythonPackage_USE_TBB:BOOL=${use_tbb} \ - --config-setting=cmake.define.ITKPythonPackage_ITK_BINARY_REUSE:BOOL=ON \ - --config-setting=cmake.define.ITKPythonPackage_WHEEL_NAME:STRING=${wheel_name} \ - --config-setting=cmake.define.Python3_EXECUTABLE:FILEPATH=${Python3_EXECUTABLE} \ - --config-setting=cmake.define.Python3_INCLUDE_DIR:PATH=${Python3_INCLUDE_DIR} \ - . \ - ${CMAKE_OPTIONS} \ - || exit 1 - done - - fi - - # Remove unnecessary files for building against ITK - find ${build_path} -name '*.cpp' -delete -o -name '*.xml' -delete - rm -rf ${build_path}/Wrapping/Generators/castxml* - find ${build_path} -name '*.o' -delete -done - -if [[ $(arch) != "arm64" ]]; then - for wheel in dist/itk_*.whl; do - echo "Delocating $wheel" - ${DELOCATE_LISTDEPS} $wheel # lists library dependencies - ${DELOCATE_WHEEL} $wheel # copies library dependencies into wheel - done -fi - -for VENV in "${VENVS[@]}"; do - ${VENV}/bin/pip install numpy - ${VENV}/bin/pip install itk --no-cache-dir --no-index -f ${SCRIPT_DIR}/../dist - (cd $HOME && ${VENV}/bin/python -c 'import itk;') - (cd $HOME && ${VENV}/bin/python -c 'import itk; image = itk.Image[itk.UC, 2].New()') - (cd $HOME && ${VENV}/bin/python -c 'import itkConfig; itkConfig.LazyLoading = False; import itk;') - (cd $HOME && ${VENV}/bin/python ${SCRIPT_DIR}/../docs/code/test.py ) -done diff --git a/scripts/macpython-download-cache-and-build-module-wheels.sh b/scripts/macpython-download-cache-and-build-module-wheels.sh index 297e827d..a21bc854 100755 --- a/scripts/macpython-download-cache-and-build-module-wheels.sh +++ b/scripts/macpython-download-cache-and-build-module-wheels.sh @@ -10,93 +10,165 @@ # Versions can be restricted by passing them in as arguments to the script. # For example, # -# scripts/macpython-download-cache-and-build-module-wheels.sh 3.9 3.11 +# scripts/macpython-download-cache-and-build-module-wheels.sh 3.11 # # Shared libraries can be included in the wheel by setting DYLD_LIBRARY_PATH before # running this script. -# + # =========================================== -# ENVIRONMENT VARIABLES +# ENVIRONMENT VARIABLES: ITK_GIT_TAG ITKPYTHONPACKAGE_ORG ITK_USE_LOCAL_PYTHON ITK_PACKAGE_VERSION # # These variables are set with the `export` bash command before calling the script. # For example, -# -# export DYLD_LIBRARY_PATH="/path/to/libs" -# -# `ITK_PACKAGE_VERSION`: ITKPythonBuilds archive tag to use for ITK build artifacts. -# See https://github.com/InsightSoftwareConsortium/ITKPythonBuilds for available tags. -# For instance, `export ITK_PACKAGE_VERSION=v5.4.0`. -# -# `ITKPYTHONPACKAGE_ORG`: Github organization for fetching ITKPythonPackage build scripts. -# -# `ITKPYTHONPACKAGE_TAG`: ITKPythonPackage tag for fetching build scripts. -# -# `ITK_USE_LOCAL_PYTHON`: Determine how to get Python framework for build. -# - If empty, Python frameworks will be fetched from python.org -# - If not empty, frameworks already on machine will be used without fetching. +# scripts/macpython-build-module-wheels.sh 3.10 3.11 # ######################################################################## +DEFAULT_MODULE_DIRECTORY=$( + cd "$(dirname "$0")" || exit 1 + pwd +) +# if not specified, use the current directory for MODULE_SRC_DIRECTORY +MODULE_SRC_DIRECTORY=${MODULE_SRC_DIRECTORY:=${DEFAULT_MODULE_DIRECTORY}} -# Install dependencies -brew update -brew install --quiet zstd aria2 gnu-tar doxygen ninja -brew upgrade --quiet cmake rustup +usage() { + echo "Usage: + macpython-download-cache-and-build-module-wheels + [ -h | --help ] show usage + [ -c | --cmake_options ] space-delimited string containing CMake options to forward to the module (e.g. \"-DBUILD_TESTING=OFF\") + [ python_version ] build wheel for a specific python version. (e.g. 3.11)" + exit 2 +} -if [[ $(arch) == "arm64" ]]; then - tarball_arch="-arm64" -else - tarball_arch="" +CMAKE_OPTIONS="" +while [ $# -gt 0 ]; do + case "$1" in + -h | --help) usage ;; + -c | --cmake_options) + CMAKE_OPTIONS="$2" + shift 2 + ;; + --) + shift + break + ;; + *) + break + ;; + esac +done + +if [ -z "${ITK_PACKAGE_VERSION}" ]; then + echo "MUST SET ITK_PACKAGE_VERSION BEFORE RUNNING THIS SCRIPT" + exit 1 fi -# Fetch ITKPythonBuilds archive containing ITK build artifacts -rm -fr ITKPythonPackage -echo "Fetching https://github.com/InsightSoftwareConsortium/ITKPythonBuilds/releases/download/${ITK_PACKAGE_VERSION:=v5.4.0}/ITKPythonBuilds-macosx${tarball_arch}.tar.zst" -if [[ ! -f ITKPythonBuilds-macosx${tarball_arch}.tar.zst ]]; then - aria2c -c --file-allocation=none -o ITKPythonBuilds-macosx${tarball_arch}.tar.zst -s 10 -x 10 https://github.com/InsightSoftwareConsortium/ITKPythonBuilds/releases/download/${ITK_PACKAGE_VERSION:=v5.4.0}/ITKPythonBuilds-macosx${tarball_arch}.tar.zst + +# For backwards compatibility when the ITK_GIT_TAG was required to match the ITK_PACKAGE_VERSION +ITK_GIT_TAG=${ITK_GIT_TAG:=${ITK_PACKAGE_VERSION}} + +DASHBOARD_BUILD_DIRECTORY=${DASHBOARD_BUILD_DIRECTORY:=/Users/svc-dashboard/D/P} +ITKPYTHONPACKAGE_ORG=${ITKPYTHONPACKAGE_ORG:=InsightSoftwareConsortium} +# Run build scripts +if [ -z "${NO_SUDO}" ] || [ "${NO_SUDO}" -ne 1 ]; then + sudo_exec=sudo +fi +if [ ! -d "${DASHBOARD_BUILD_DIRECTORY}" ]; then + ${sudo_exec} mkdir -p "${DASHBOARD_BUILD_DIRECTORY}" && ${sudo_exec} chown "$UID:$GID" "${DASHBOARD_BUILD_DIRECTORY}" fi -unzstd --long=31 ITKPythonBuilds-macosx${tarball_arch}.tar.zst -o ITKPythonBuilds-macosx${tarball_arch}.tar -PATH="$(dirname $(brew list gnu-tar | grep gnubin)):$PATH" -gtar xf ITKPythonBuilds-macosx${tarball_arch}.tar --warning=no-unknown-keyword --checkpoint=10000 --checkpoint-action=dot \ - ITKPythonPackage/ITK-source \ - ITKPythonPackageRequiredExtractionDir.txt \ - ITKPythonPackage/scripts +cd "${DASHBOARD_BUILD_DIRECTORY}" || exit -# Extract subdirectories specific to the compiled python versions -args=( "$@" ) -source ITKPythonPackage/scripts/macpython-build-common.sh -for version in "$PYTHON_VERSIONS"; do - gtar xf ITKPythonBuilds-macosx${tarball_arch}.tar --warning=no-unknown-keyword --checkpoint=10000 --checkpoint-action=dot \ - --wildcards "ITKPythonPackage/ITK-${version}-macosx*" \ - "ITKPythonPackage/venvs/${version}" -done +# NOTE: download phase will install pixi in the DASHBOARD_BUILD_DIRECTORY (which is separate from the pixi +# environment used by ITKPythonPackage). +export PIXI_HOME=${DASHBOARD_BUILD_DIRECTORY}/.pixi +if [ ! -f "${PIXI_HOME}/.pixi/bin/pixi" ]; then + # Install pixi + curl -fsSL https://pixi.sh/install.sh | sh + # These are the tools needed for cross platform downloads of the ITK build caches stored in https://github.com/InsightSoftwareConsortium/ITKPythonBuilds + pixi global install zstd + pixi global install aria2 + pixi global install gnu-tar + pixi global install git + pixi global install rsync +fi +export PATH="${PIXI_HOME}/bin:$PATH" -rm ITKPythonBuilds-macosx${tarball_arch}.tar +tarball_arch="-$(arch)" +TARBALL_NAME="ITKPythonBuilds-macosx${tarball_arch}.tar" -# Optional: Update build scripts -if [[ -n ${ITKPYTHONPACKAGE_TAG} ]]; then - echo "Updating build scripts to ${ITKPYTHONPACKAGE_ORG:=InsightSoftwareConsortium}/ITKPythonPackage@${ITKPYTHONPACKAGE_TAG}" - git clone "https://github.com/${ITKPYTHONPACKAGE_ORG}/ITKPythonPackage.git" "IPP-tmp" - pushd IPP-tmp/ - git checkout "${ITKPYTHONPACKAGE_TAG}" - git status - popd +if [[ ! -f ${TARBALL_NAME}.zst ]]; then + echo "Local ITK cache tarball file not found..." + # Fetch ITKPythonBuilds archive containing ITK build artifacts + echo "Fetching https://github.com/InsightSoftwareConsortium/ITKPythonBuilds/releases/download/${ITK_PACKAGE_VERSION}/ITKPythonBuilds-macosx${tarball_arch}.tar.zst" + if ! curl -L "https://github.com/InsightSoftwareConsortium/ITKPythonBuilds/releases/download/${ITK_PACKAGE_VERSION}/ITKPythonBuilds-macosx${tarball_arch}.tar.zst" -O; then + echo "FAILED Download:" + echo "curl -L https://github.com/InsightSoftwareConsortium/ITKPythonBuilds/releases/download/${ITK_PACKAGE_VERSION}/${TARBALL_NAME}.zst -O" + exit 1 + fi +fi - rm -rf ITKPythonPackage/scripts/ - cp -r IPP-tmp/scripts ITKPythonPackage/ - rm -rf IPP-tmp/ +if [[ ! -f ./${TARBALL_NAME}.zst ]]; then + echo "ERROR: can not find required binary './${TARBALL_NAME}.zst'" + exit 255 fi -# Run build scripts -sudo mkdir -p /Users/svc-dashboard/D/P && sudo chown $UID:$GID /Users/svc-dashboard/D/P -if [[ ! -d /Users/svc-dashboard/D/P/ITKPythonPackage ]]; then - mv ITKPythonPackage /Users/svc-dashboard/D/P/ +local_compress_tarball_name=${DASHBOARD_BUILD_DIRECTORY}/ITKPythonBuilds-macosx${tarball_arch}.tar.zst +if [[ ! -f ${local_compress_tarball_name} ]]; then + aria2c -c --file-allocation=none -d "$(dirname "${local_compress_tarball_name}")" -o "$(basename "${local_compress_tarball_name}")" -s 10 -x 10 "https://github.com/InsightSoftwareConsortium/ITKPythonBuilds/releases/download/${ITK_PACKAGE_VERSION}/ITKPythonBuilds-macosx${tarball_arch}.tar.zst" fi +local_tarball_name=${DASHBOARD_BUILD_DIRECTORY}/ITKPythonBuilds-macosx${tarball_arch}.tar +unzstd --long=31 "${local_compress_tarball_name}" -o "${local_tarball_name}" +# Find GNU tar (gtar from pixi or brew) for reliable extraction +if command -v gtar >/dev/null 2>&1; then + TAR_CMD=gtar + TAR_FLAGS=(--warning=no-unknown-keyword --checkpoint=10000 --checkpoint-action=dot) +elif tar --version 2>/dev/null | grep -q "GNU tar"; then + TAR_CMD=tar + TAR_FLAGS=(--warning=no-unknown-keyword --checkpoint=10000 --checkpoint-action=dot) +else + TAR_CMD=tar + TAR_FLAGS=() +fi +"${TAR_CMD}" xf "${local_tarball_name}" "${TAR_FLAGS[@]}" +rm "${local_tarball_name}" -# Optionally install baseline Python versions -if [[ ! ${ITK_USE_LOCAL_PYTHON} ]]; then - echo "Fetching Python frameworks" - sudo rm -rf /Library/Frameworks/Python.framework/Versions/* - /Users/svc-dashboard/D/P/ITKPythonPackage/scripts/macpython-install-python.sh +# Optional: Update build scripts +if [[ -n ${ITKPYTHONPACKAGE_TAG} ]]; then + echo "Updating build scripts to ${ITKPYTHONPACKAGE_ORG}/ITKPythonPackage@${ITKPYTHONPACKAGE_TAG}" + local_clone_ipp=${DASHBOARD_BUILD_DIRECTORY}/ITKPythonPackage_${ITKPYTHONPACKAGE_TAG} + if [ ! -d "${local_clone_ipp}/.git" ]; then + git clone "https://github.com/${ITKPYTHONPACKAGE_ORG}/ITKPythonPackage.git" "${local_clone_ipp}" + fi + pushd "${local_clone_ipp}" || exit + git checkout "${ITKPYTHONPACKAGE_TAG}" + git reset "origin/${ITKPYTHONPACKAGE_TAG}" --hard + git status + popd || exit + rsync -av "${local_clone_ipp}/" "${DASHBOARD_BUILD_DIRECTORY}/ITKPythonPackage/" fi echo "Building module wheels" -/Users/svc-dashboard/D/P/ITKPythonPackage/scripts/macpython-build-module-wheels.sh "${args[@]}" +cd "${DASHBOARD_BUILD_DIRECTORY}/ITKPythonPackage" || exit +echo "$@" +for py_indicator in "$@"; do + # The following line is to convert "py3.11|py311|cp311|3.11" -> py311 normalized form + py_squashed_numeric=$(echo "${py_indicator}" | sed 's/py//g' | sed 's/cp//g' | sed 's/\.//g') + pyenv=py${py_squashed_numeric} + pixi run -e "macosx-${pyenv}" -- python \ + "${DASHBOARD_BUILD_DIRECTORY}/ITKPythonPackage/scripts/build_wheels.py" \ + --platform-env "macosx-${pyenv}" \ + --lib-paths '' '' \ + --module-source-dir "${MODULE_SRC_DIRECTORY}" \ + --module-dependencies-root-dir "${DASHBOARD_BUILD_DIRECTORY}/MODULE_DEPENDENCIES" \ + --itk-module-deps "${ITK_MODULE_PREQ}" \ + --no-build-itk-tarball-cache \ + --build-dir-root "${DASHBOARD_BUILD_DIRECTORY}/ITKPythonPackage-build" \ + --manylinux-version '' \ + --itk-git-tag "${ITK_GIT_TAG}" \ + --itk-source-dir "${DASHBOARD_BUILD_DIRECTORY}/ITKPythonPackage-build/ITK" \ + --itk-package-version "${ITK_PACKAGE_VERSION}" \ + --no-use-sudo \ + --no-use-ccache \ + --skip-itk-build \ + --skip-itk-wheel-build \ + ${CMAKE_OPTIONS:+-- ${CMAKE_OPTIONS}} + #Let this be automatically selected --macosx-deployment-target 10.7 \ +done diff --git a/scripts/macpython-install-python.sh b/scripts/macpython-install-python.sh deleted file mode 100755 index 70a57b7a..00000000 --- a/scripts/macpython-install-python.sh +++ /dev/null @@ -1,423 +0,0 @@ -#!/usr/bin/env bash - -# Download and install Python.org's MacPython and install Pip - -# Adapted from https://github.com/matthew-brett/multibuild -# osx_utils.sh -#The multibuild package, including all examples, code snippets and attached -#documentation is covered by the 2-clause BSD license. - - #Copyright (c) 2013-2016, Matt Terry and Matthew Brett; all rights - #reserved. - - #Redistribution and use in source and binary forms, with or without - #modification, are permitted provided that the following conditions are - #met: - - #1. Redistributions of source code must retain the above copyright notice, - #this list of conditions and the following disclaimer. - - #2. Redistributions in binary form must reproduce the above copyright - #notice, this list of conditions and the following disclaimer in the - #documentation and/or other materials provided with the distribution. - - #THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - #IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - #THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - #PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - #CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - #EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - #PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - #PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - #LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - #NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - #SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -set -x - -MACPYTHON_URL=https://www.python.org/ftp/python -MACPYTHON_PY_PREFIX=/Library/Frameworks/Python.framework/Versions -MACPYTHON_DEFAULT_OSX="10.6" -MB_PYTHON_OSX_VER=${MB_PYTHON_OSX_VER:-$MACPYTHON_DEFAULT_OSX} -GET_PIP_URL=https://bootstrap.pypa.io/get-pip.py -DOWNLOADS_SDIR=downloads -WORKING_SDIR=working - -# As of 2 November 2022 - latest Python of each version with binary download -# available. -# See: https://www.python.org/downloads/mac-osx/ -LATEST_2p7=2.7.18 -LATEST_3p5=3.5.4 -LATEST_3p6=3.6.8 -LATEST_3p7=3.7.9 -LATEST_3p8=3.8.10 -LATEST_3p9=3.9.13 -LATEST_3p10=3.10.11 -LATEST_3p11=3.11.4 -LATEST_3p12=3.12.0 - - -function check_python { - if [ -z "$PYTHON_EXE" ]; then - echo "PYTHON_EXE variable not defined" - exit 1 - fi -} - -function check_pip { - if [ -z "$PIP_CMD" ]; then - echo "PIP_CMD variable not defined" - exit 1 - fi -} - -function check_var { - if [ -z "$1" ]; then - echo "required variable not defined" - exit 1 - fi -} - -function get_py_digit { - check_python - $PYTHON_EXE -c "import sys; print(sys.version_info[0])" -} - -function get_py_mm { - check_python - $PYTHON_EXE -c "import sys; print('{0}.{1}'.format(*sys.version_info[0:2]))" -} - -function get_py_mm_nodot { - check_python - $PYTHON_EXE -c "import sys; print('{0}{1}'.format(*sys.version_info[0:2]))" -} - -function get_py_prefix { - check_python - $PYTHON_EXE -c "import sys; print(sys.prefix)" -} - -function fill_pyver { - # Convert major or major.minor format to major.minor.micro - # - # Hence: - # 2 -> 2.7.11 (depending on LATEST_2p7 value) - # 2.7 -> 2.7.11 (depending on LATEST_2p7 value) - local ver=$1 - check_var $ver - if [[ $ver =~ [0-9]+\.[0-9]+\.[0-9]+ ]]; then - # Major.minor.micro format already - echo $ver - elif [ $ver == 2 ] || [ $ver == "2.7" ]; then - echo $LATEST_2p7 - elif [ $ver == 3 ] || [ $ver == "3.11" ]; then - echo $LATEST_3p11 - elif [ $ver == "3.12" ]; then - echo $LATEST_3p12 - elif [ $ver == "3.10" ]; then - echo $LATEST_3p10 - elif [ $ver == "3.9" ]; then - echo $LATEST_3p9 - elif [ $ver == "3.8" ]; then - echo $LATEST_3p8 - elif [ $ver == "3.7" ]; then - echo $LATEST_3p7 - elif [ $ver == "3.6" ]; then - echo $LATEST_3p6 - elif [ $ver == "3.5" ]; then - echo $LATEST_3p5 - else - echo "Can't fill version $ver" 1>&2 - exit 1 - fi -} - -function macpython_sdk_list_for_version { - # return a list of SDK targets supported for a given CPython version - # Parameters - # $py_version (python version in major.minor.extra format) - # eg - # macpython_sdks_for_version 2.7.15 - # >> 10.6 10.9 - local _ver=$(fill_pyver $1) - local _major=${_ver%%.*} - local _return - - if [ "${PLAT}" = "arm64" ]; then - _return="11.0" - elif [ "$_major" -eq "2" ]; then - [ $(lex_ver $_ver) -lt $(lex_ver 2.7.18) ] && _return="10.6" - [ $(lex_ver $_ver) -ge $(lex_ver 2.7.15) ] && _return="$_return 10.9" - elif [ "$_major" -eq "3" ]; then - [ $(lex_ver $_ver) -lt $(lex_ver 3.8) ] && _return="10.6" - [ $(lex_ver $_ver) -ge $(lex_ver 3.6.5) ] && _return="$_return 10.9" - else - echo "Error version=${_ver}, expecting 2.x or 3.x" 1>&2 - exit 1 - fi - echo $_return -} - -function macpython_sdk_for_version { - # assumes the output of macpython_sdk_list_for_version is a list - # of SDK versions XX.Y in sorted order, eg "10.6 10.9" or "10.9" - echo $(macpython_sdk_list_for_version $1) | awk -F' ' '{print $NF}' -} - -function pyinst_ext_for_version { - # echo "pkg" or "dmg" depending on the passed Python version - # Parameters - # $py_version (python version in major.minor.extra format) - # - # Earlier Python installers are .dmg, later are .pkg. - local py_version=$1 - check_var $py_version - py_version=$(fill_pyver $py_version) - local py_0=${py_version:0:1} - if [ $py_0 -eq 2 ]; then - if [ "$(lex_ver $py_version)" -ge "$(lex_ver 2.7.9)" ]; then - echo "pkg" - else - echo "dmg" - fi - elif [ $py_0 -ge 3 ]; then - echo "pkg" - fi -} - -function pyinst_fname_for_version { - # echo filename for OSX installer file given Python and minimum - # macOS versions - # Parameters - # $py_version (Python version in major.minor.extra format) - # $py_osx_ver: {major.minor | not defined} - # if defined, the minimum macOS SDK version that Python is - # built for, eg: "10.6" or "10.9", if not defined, infers - # this from $py_version using macpython_sdk_for_version - local py_version=$1 - local py_osx_ver=${2:-$(macpython_sdk_for_version $py_version)} - local inst_ext=$(pyinst_ext_for_version $py_version) - if [ "${PLAT:-}" == "arm64" ] || [ "${PLAT:-}" == "universal2" ]; then - if [ "$py_version" == "3.9.1" ]; then - echo "python-${py_version}-macos11.0.${inst_ext}" - else - echo "python-${py_version}-macos11.${inst_ext}" - fi - else - if [ "$py_version" == "3.7.9" ]; then - echo "python-${py_version}-macosx${py_osx_ver}.${inst_ext}" - else - echo "python-${py_version}-macos${py_osx_ver}.${inst_ext}" - fi - fi -} - -function get_macpython_arch { - # echo arch (e.g. intel or x86_64), extracted from the distutils platform tag - # Parameters - # $distutils_plat PEP425 style platform tag, or if not provided, calls - # the function get_distutils_platform, provided by - # common_utils.sh. Fails if this is not a mac platform - # - # Note: MUST only be called after the version of Python used to build the - # target wheel has been installed and is on the path - local distutils_plat=${1:-$(get_distutils_platform)} - if [[ $distutils_plat =~ macosx-(1[0-9]\.[0-9]+)-(.*) ]]; then - echo ${BASH_REMATCH[2]} - else - echo "Error parsing macOS distutils platform '$distutils_plat'" - exit 1 - fi -} - -function get_macpython_osx_ver { - # echo minimum macOS version (e.g. 10.9) from the distutils platform tag - # Parameters - # $distutils_plat PEP425 style platform tag, or if not provided, calls - # the function get_distutils_platform, provided by - # common_utils.sh. Fails if this is not a mac platform - # - # Note: MUST only be called after the version of Python used to build the - # target wheel has been installed and is on the path - local distutils_plat=${1:-$(get_distutils_platform)} - if [[ $distutils_plat =~ macosx-(1[0-9]\.[0-9]+)-(.*) ]]; then - echo ${BASH_REMATCH[1]} - else - echo "Error parsing macOS distutils platform '$distutils_plat'" - exit 1 - fi -} - -function macpython_arch_for_version { - # echo arch (intel or x86_64) that a version of Python is expected - # to be built for - # Parameters - # $py_ver Python version, in the format (major.minor.patch) for - # CPython, or pypy-(major.minor) for PyPy - # $py_osx_ver minimum macOS version the target Python is built for - # (major.minor) - local py_ver=$1 - local py_osx_ver=${2:-$MB_PYTHON_OSX_VER} - check_var $1 - if [[ $(macpython_impl_for_version $py_ver) == "cp" ]]; then - if [[ "$py_osx_ver" == "10.6" ]]; then - echo "intel" - elif [[ "$py_osx_ver" == "10.9" ]]; then - echo "x86_64" - else - echo "Unexpected CPython macOS version: ${py_osx_ver}, supported values: 10.6 and 10.9" - exit 1 - fi - else - echo "x86_64" - fi -} - -function macpython_impl_for_version { - # echo Python implementation (cp for CPython, pp for PyPy) given a - # suitably formatted version string - # Parameters: - # $version : [implementation-]major[.minor[.patch]] - # Python implementation, e.g. "3.6" for CPython or - # "pypy-5.4" for PyPy - local version=$1 - check_var $1 - if [[ "$version" =~ ^pypy ]]; then - echo pp - elif [[ "$version" =~ ([0-9\.]+) ]]; then - echo cp - else - echo "config error: Issue parsing this implementation in install_python:" - echo " version=$version" - exit 1 - fi -} - -function strip_macpython_ver_prefix { - # strip any implementation prefix from a Python version string - # Parameters: - # $version : [implementation-]major[.minor[.patch]] - # Python implementation, e.g. "3.6" for CPython or - # "pypy-5.4" for PyPy - local version=$1 - check_var $1 - if [[ "$version" =~ (pypy-)?([0-9\.]+) ]]; then - echo ${BASH_REMATCH[2]} - fi -} - -function install_macpython { - # Install Python and set $PYTHON_EXE to the installed executable - # Parameters: - # $version : [implementation-]major[.minor[.patch]] - # The Python implementation to install, e.g. "3.6", "pypy-5.4" or "pypy3.6-7.2" - # $py_osx_ver: {major.minor | not defined} - # if defined, the macOS version that CPython is built for, e.g. - # "10.6" or "10.9". Ignored for PyPy - local version=$1 - local py_osx_ver=$2 - local impl=$(macpython_impl_for_version $version) - if [[ "$impl" == "pp" ]]; then - install_pypy $version - elif [[ "$impl" == "cp" ]]; then - local stripped_ver=$(strip_macpython_ver_prefix $version) - install_mac_cpython $stripped_ver $py_osx_ver - else - echo "Unexpected Python impl: ${impl}" - exit 1 - fi -} - -function install_mac_cpython { - # Installs Python.org Python - # Parameters - # $py_version - # Version given in major or major.minor or major.minor.micro e.g - # "3" or "3.7" or "3.7.1". - # $py_osx_ver - # {major.minor | not defined} - # if defined, the macOS version that Python is built for, e.g. - # "10.6" or "10.9" - # sets $PYTHON_EXE variable to Python executable - local py_version=$(fill_pyver $1) - local py_osx_ver=$2 - #local py_stripped=$(strip_ver_suffix $py_version) - local py_stripped=$py_version - local py_inst=$(pyinst_fname_for_version $py_version $py_osx_ver) - local inst_path=$DOWNLOADS_SDIR/$py_inst - local retval="" - mkdir -p $DOWNLOADS_SDIR - # exit early on curl errors, but don't let it exit the shell - curl -f $MACPYTHON_URL/$py_stripped/${py_inst} > $inst_path || retval=$? - if [ ${retval:-0} -ne 0 ]; then - echo "Python download failed! Check ${py_inst} exists on the server." - exit $retval - fi - - if [ "${py_inst: -3}" == "dmg" ]; then - hdiutil attach $inst_path -mountpoint /Volumes/Python - inst_path=/Volumes/Python/Python.mpkg - fi - sudo installer -pkg $inst_path -target / - local py_mm=${py_version%.*} - PYTHON_EXE=$MACPYTHON_PY_PREFIX/$py_mm/bin/python$py_mm - # Install certificates for Python 3.6 - local inst_cmd="/Applications/Python ${py_mm}/Install Certificates.command" - if [ -e "$inst_cmd" ]; then - sh "$inst_cmd" - fi - PIP_CMD="$MACPYTHON_PY_PREFIX/$py_mm/bin/python$py_mm -m pip" - $PIP_CMD install --upgrade pip - export PIP_CMD -} - -function install_virtualenv { - # Generic install of virtualenv - # Installs virtualenv into python given by $PYTHON_EXE - # Assumes virtualenv will be installed into same directory as $PYTHON_EXE - check_pip - # Travis VMS install virtualenv for system python by default - force - # install even if installed already - $PIP_CMD install virtualenv --ignore-installed - check_python - VIRTUALENV_CMD="$(dirname $PYTHON_EXE)/virtualenv" - export VIRTUALENV_CMD -} - -function make_workon_venv { - # Make a virtualenv in given directory ('venv' default) - # Set $PYTHON_EXE, $PIP_CMD to virtualenv versions - # Parameter $venv_dir - # directory for virtualenv - local venv_dir=$1 - if [ -z "$venv_dir" ]; then - venv_dir="venv" - fi - venv_dir=`abspath $venv_dir` - check_python - $PYTHON_EXE -m virtualenv $venv_dir - PYTHON_EXE=$venv_dir/bin/python - PIP_CMD=$venv_dir/bin/pip -} - -# Remove previous versions -#echo "Remove and update Python files at ${MACPYTHON_FRAMEWORK}" -#sudo rm -rf ${MACPYTHON_FRAMEWORK} - -if test "$(arch)" == "arm64"; then - echo "we are arm" - PLAT=arm64 - for pyversion in $LATEST_3p10 $LATEST_3p11; do - install_macpython $pyversion 11 - install_virtualenv - done -else - # Deployment target requirements: - # * 10.9: Python 3.7 - # * 11: Python >= 3.8 - for pyversion in $LATEST_3p10 $LATEST_3p11; do - install_macpython $pyversion 11 - install_virtualenv - done -fi diff --git a/scripts/oci_exe.sh b/scripts/oci_exe.sh deleted file mode 100644 index f3d7cffb..00000000 --- a/scripts/oci_exe.sh +++ /dev/null @@ -1,23 +0,0 @@ -function ociExe() { - # Check for OCI_EXE environmental variable - if [[ -n "$OCI_EXE" && -x "$OCI_EXE" ]]; then - echo "$OCI_EXE" - return - fi - - # Check for podman executable - if which podman > /dev/null 2>&1; then - echo "podman" - return - fi - - # Check for docker executable - if which docker > /dev/null 2>&1; then - echo "docker" - return - fi - - # If none of the above exist, return nothing - echo "Could not find podman or docker executable" >&2 - exit 1 -} \ No newline at end of file diff --git a/scripts/update_python_version.py b/scripts/update_python_version.py deleted file mode 100755 index f69207d3..00000000 --- a/scripts/update_python_version.py +++ /dev/null @@ -1,96 +0,0 @@ -#!/usr/bin/env python - -"""Update the ITKPythonPackage version based off the ITK Git nightly-master -branch.""" - -import argparse -import sys -import os -import subprocess -from datetime import datetime -from packaging.version import Version - -argparser = argparse.ArgumentParser(description=__doc__) -argparser.add_argument("itkSourceDir") - -args = argparser.parse_args() -itkSourceDir = args.itkSourceDir -if not os.path.exists(os.path.join(itkSourceDir, ".git")): - print("itkSourceDir does not appear to be a git repository!") - sys.exit(1) - -itkPythonPackageDir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) - - -os.chdir(itkSourceDir) -# "Wed Feb 8 15:21:09 2017"\n -commitDate = subprocess.check_output( - ["git", "show", "-s", "--date=local", '--format="%cd"'] -) -# Wed Feb 8 15:21:09 2017 -commitDate = commitDate.strip()[1:-1] -# Wed Feb 08 15:21:09 2017 -commitDate = commitDate.split(" ") -commitDate[2] = "{:02d}".format(int(commitDate[2])) -commitDate = " ".join(commitDate) -# 2017-02-08 -commitDateDashes = datetime.strptime(commitDate, "%a %b %d %H:%M:%S %Y").strftime( - "%Y-%m-%d" -) -# 20170208 -commitDate = commitDateDashes.replace("-", "") - -# v4.11.0-139-g922f2d9 -# -revision = subprocess.check_output(["git", "describe", "--tags", "--long"]) -revision.strip() -# 4.11.0-139-g922f2d9 -revision = revision[1:] -version, numberOfCommits, gHash = revision.split("-") -version = version.strip() -numberOfCommits = numberOfCommits.strip() -gHash = gHash.strip() - -pythonRevision = version -if int(numberOfCommits) > 0: - pythonRevision += ".dev" - pythonRevision += commitDate - pythonRevision += "+" - pythonRevision += numberOfCommits - pythonRevision += "." - pythonRevision += gHash - -os.chdir(itkPythonPackageDir) -itkVersionPath = os.path.join(itkPythonPackageDir, "itkVersion.py") - -Version(VERSION) # Raise InvalidVersion exception if not PEP 440 compliant - -if not os.path.exists(itkVersionPath): - print("Expected file " + itkVersionPath + " not found!") - sys.exit(1) -with open(itkVersionPath, "r") as fp: - lines = fp.readlines() -with open(itkVersionPath, "w") as fp: - for line in lines: - if line.startswith("VERSION = "): - fp.write("VERSION = '") - fp.write(pythonRevision) - fp.write("'\n") - else: - fp.write(line) - - -with open("CMakeLists.txt", "r") as fp: - lines = fp.readlines() -with open("CMakeLists.txt", "w") as fp: - for line in lines: - if line.startswith(" # ITK nightly-master"): - fp.write(" # ITK nightly-master ") - fp.write(commitDateDashes) - fp.write("\n") - elif line.startswith(" set(ITK_GIT_TAG"): - fp.write(' set(ITK_GIT_TAG "') - fp.write(gHash[1:]) - fp.write('")\n') - else: - fp.write(line) diff --git a/scripts/update_python_version.sh b/scripts/update_python_version.sh deleted file mode 100755 index 9773056e..00000000 --- a/scripts/update_python_version.sh +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/env bash - -# This script is use to update the version of ITK used by ITKPythonPackage. It -# is run nightly by a system with push permissions to the -# -# git@github.com:InsightSoftwareConsortium/ITKPythonPackage.git -# -# repository. - -set -x -e - -workdir=/tmp/ - -cd $workdir - -if test ! -d ITKNightlyMaster; then - git clone --branch nightly-master \ - https://github.com/InsightSoftwareConsortium/ITK.git ITKNightlyMaster -fi -pushd ITKNightlyMaster/ -git checkout nightly-master -git fetch -git reset --hard origin/nightly-master -ITK_SHA=$(git rev-parse --short HEAD) -popd - -if test ! -d ITKPythonPackage; then - git clone --branch master \ - git@github.com:InsightSoftwareConsortium/ITKPythonPackage.git ITKPythonPackage -fi -pushd ITKPythonPackage/ -git checkout master -git fetch -git reset --hard origin/master -git config user.name 'Kitware Robot' -git config user.email 'kwrobot@kitware.com' -ITKPythonPackage_SHA=$(git rev-parse --short HEAD) -./scripts/update_python_version.py ../ITKNightlyMaster -git add -- CMakeLists.txt itkVersion.py -git commit -m "ITK nightly version update - -This commit updates: - (1) SHA used in CMakeLists.txt to checkout ITK sources - (InsightSoftwareConsortium/ITK@${ITK_SHA}) - (2) VERSION variable set in itkVersion.py - -It was automatically generated by the script ``update_python_version.sh`` [1] - -[1] https://github.com/InsightSoftwareConsortium/ITKPythonPackage/blob/${ITKPythonPackage_SHA}/scripts/update_python_version.py" -git push origin master diff --git a/scripts/windows-download-cache-and-build-module-wheels.ps1 b/scripts/windows-download-cache-and-build-module-wheels.ps1 index 0d7b8fe2..7f9a2ef7 100644 --- a/scripts/windows-download-cache-and-build-module-wheels.ps1 +++ b/scripts/windows-download-cache-and-build-module-wheels.ps1 @@ -1,134 +1,242 @@ ######################################################################## -# Pull build dependencies and build an ITK external module. +# Pull build dependencies and build an ITK external module on Windows. # -# This script must be run in an x64 Developer Powershell. +# This script must be run in an x64 Developer PowerShell. # See https://learn.microsoft.com/en-us/visualstudio/ide/reference/command-prompt-powershell?view=vs-2022#developer-powershell # # ----------------------------------------------------------------------- -# Positional parameters: -# - 0th parameter or -python_version_minor option: Python minor version. +# Positional parameters / named options: +# +# -python_version_minor Python minor version (required). # For instance, for Python 3.11: -# > windows-download-cache-and-build-module-wheels.ps1 11 -# or equivalently: # > windows-download-cache-and-build-module-wheels.ps1 -python_version_minor 11 +# or positionally: +# > windows-download-cache-and-build-module-wheels.ps1 11 # -# - 1st parameter or -setup_options: pyproject.toml options. -# For instance, for Python 3.11, excluding nvcuda.dll during packaging: -# > windows-download-cache-and-build-module-wheels.ps1 11 "--exclude-libs nvcuda.dll" -# or equivalently: -# > windows-download-cache-and-build-module-wheels.ps1 -python_version_minor 11 -setup_options "--exclude-libs nvcuda.dll" -# -# - 2nd parameter or -cmake_options: CMake options passed to pyproject.tom for project configuration. -# For instance, for Python 3.11, excluding nvcuda.dll during packaging -# and setting RTK_USE_CUDA ON during configuration: -# > windows-download-cache-and-build-module-wheels.ps1 11 "--exclude-libs nvcuda.dll" "-DRTK_USE_CUDA:BOOL=ON" -# or equivalently: -# > windows-download-cache-and-build-module-wheels.ps1 -python_version_minor 11 -setup_options "--exclude-libs nvcuda.dll" -cmake-options "-DRTK_USE_CUDA:BOOL=ON" +# -setup_options pyproject.toml options forwarded to the build script. +# For instance, to exclude a library during packaging: +# > ... -setup_options "--exclude-libs nvcuda.dll" # +# -cmake_options CMake options passed to pyproject.toml for project configuration. +# For instance: +# > ... -cmake_options "-DRTK_USE_CUDA:BOOL=ON" # # ----------------------------------------------------------------------- # Environment variables used in this script: # -# `$env:ITK_PACKAGE_VERSION`: Tag for ITKPythonBuilds build archive to use +# `$env:ITK_PACKAGE_VERSION` +# Tag for the ITKPythonBuilds archive to download/use. Required. # -# `$env:ITKPYTHONPACKAGE_TAG`: Tag for ITKPythonPackage build scripts to use. -# If ITKPYTHONPACKAGE_TAG is empty then the default scripts distributed -# with the ITKPythonBuilds archive will be used. +# `$env:ITKPYTHONPACKAGE_TAG` +# Tag for ITKPythonPackage build scripts to use. +# If empty, the scripts bundled in the archive will be used. # -# `$env:ITKPYTHONPACKAGE_ORG`: Github organization or user to use for ITKPythonPackage -# build script source. Default is InsightSoftwareConsortium. +# `$env:ITKPYTHONPACKAGE_ORG` +# GitHub organization/user for ITKPythonPackage. Default: InsightSoftwareConsortium. # Ignored if ITKPYTHONPACKAGE_TAG is empty. # -# `$env:ITK_MODULE_PREQ`: Delimited list of ITK module dependencies to build before building the target module. -# Format is `/@:/@:...`. -# For instance, `export ITK_MODULE_PREQ=InsightSoftwareConsortium/ITKMeshToPolyData@v0.10.0` +# `$env:ITK_MODULE_PREQ` +# Colon-delimited list of ITK module dependencies. +# Format: `/@:/@:...` +# Example: `InsightSoftwareConsortium/ITKMeshToPolyData@v0.10.0` +# Passed directly to build_wheels.py via --itk-module-deps. +# +# `$env:MODULE_SRC_DIRECTORY` +# Path to the ITK external module source. Defaults to the directory +# containing this script. # ######################################################################## param ( [int]$python_version_minor, - [string]$setup_options, - [string]$cmake_options + [string]$setup_options = "", + [string]$cmake_options = "" ) -$pythonArch = "64" -$pythonVersion = "3.$python_version_minor" -echo "Pulling Python $pythonVersion-x$pythonArch" -iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/scikit-build/scikit-ci-addons/master/windows/install-python.ps1')) +Set-StrictMode -Version Latest +$ErrorActionPreference = "Stop" -if (-not $env:ITK_PACKAGE_VERSION) { $env:ITK_PACKAGE_VERSION = 'v5.4.0' } -echo "Fetching build archive $env:ITK_PACKAGE_VERSION" -if (Test-Path C:\P) { - Remove-Item -Recurse -Force C:\P +# Validate required inputs +if (-not $python_version_minor) { + Write-Error "ERROR: -python_version_minor is required. Example: -python_version_minor 11" + exit 1 } -if (-not (Test-Path ITKPythonBuilds-windows.zip)) { - Invoke-WebRequest -Uri "https://github.com/InsightSoftwareConsortium/ITKPythonBuilds/releases/download/$env:ITK_PACKAGE_VERSION/ITKPythonBuilds-windows.zip" -OutFile "ITKPythonBuilds-windows.zip" +if (-not $env:ITK_PACKAGE_VERSION) { + Write-Error "ERROR: `$env:ITK_PACKAGE_VERSION must be set before running this script." + exit 1 } -7z x ITKPythonBuilds-windows.zip -oC:\P -aoa -r -# Optional: Update ITKPythonPackage build scripts -if ($env:ITKPYTHONPACKAGE_TAG) { - if(-not $env:ITKPYTHONPACKAGE_ORG) { - $env:ITKPYTHONPACKAGE_ORG="InsightSoftwareConsortium" - } +# Resolve configuration +$MODULE_SRC_DIRECTORY = if ($env:MODULE_SRC_DIRECTORY) { + $env:MODULE_SRC_DIRECTORY +} else { + $PSScriptRoot +} +echo "MODULE_SRC_DIRECTORY: $MODULE_SRC_DIRECTORY" - echo "Updating build scripts to $env:ITKPYTHONPACKAGE_ORG/ITKPythonPackage@$env:ITKPYTHONPACKAGE_TAG" +$ITK_PACKAGE_VERSION = $env:ITK_PACKAGE_VERSION +# For backwards compatibility when the ITK_GIT_TAG was required to match the ITK_PACKAGE_VERSION +$ITK_GIT_TAG = if ($env:ITK_GIT_TAG) { $env:ITK_GIT_TAG } else { $ITK_PACKAGE_VERSION } +$ITKPYTHONPACKAGE_ORG = if ($env:ITKPYTHONPACKAGE_ORG) { $env:ITKPYTHONPACKAGE_ORG } else { "InsightSoftwareConsortium" } +$ITKPYTHONPACKAGE_TAG = if ($env:ITKPYTHONPACKAGE_TAG) { $env:ITKPYTHONPACKAGE_TAG } else { "" } - pushd C:\P - git clone "https://github.com/$env:ITKPYTHONPACKAGE_ORG/ITKPythonPackage.git" "IPP-tmp" - pushd "IPP-tmp" - git checkout "$env:ITKPYTHONPACKAGE_TAG" - git status - popd +$DASHBOARD_BUILD_DIRECTORY = "C:\BDR" +$platformEnv = "windows-py3$python_version_minor" - Remove-Item -Recurse -Force IPP/scripts/ - Copy-Item -Recurse IPP-tmp/scripts IPP/ - Copy-Item IPP-tmp/requirements-dev.txt IPP/ - Remove-Item -Recurse -Force IPP-tmp/ - popd +echo "Python version : 3.$python_version_minor" +echo "ITK_PACKAGE_VERSION: $ITK_PACKAGE_VERSION" +echo "ITK_GIT_TAG : $ITK_GIT_TAG" +echo "Platform env : $platformEnv" + +# Install pixi and required global tools +# NOTE: Python and Doxygen are provided by the pixi environment; no need to +# install them separately here. +$env:PIXI_HOME = "$DASHBOARD_BUILD_DIRECTORY\.pixi" +if (-not (Test-Path "$env:PIXI_HOME\bin\pixi.exe")) { + echo "Installing pixi..." + Invoke-WebRequest -Uri "https://pixi.sh/install.ps1" -OutFile "install-pixi.ps1" + powershell -ExecutionPolicy Bypass -File "install-pixi.ps1" } +$env:Path = "$env:PIXI_HOME\bin;$env:Path" -# Get other build dependencies -if (-not (Test-Path doxygen-1.16.1.windows.bin.zip)) { - Invoke-WebRequest -Uri "https://github.com/doxygen/doxygen/releases/download/Release_1_16_1/doxygen-1.16.1.windows.x64.bin.zip" -OutFile "doxygen-1.16.1.windows.bin.zip" +# Install global packages via pixi for use in this script +# Note: Using conda-forge packages that are available on Windows +echo "Installing global tools via pixi..." +$globalPackages = @( + "git", # Required for cloning ITKPythonPackage repo + "aria2" # Fast download utility (cross-platform) +) + +foreach ($pkg in $globalPackages) { + echo " Installing $pkg..." + try { + & pixi global install $pkg + if ($LASTEXITCODE -ne 0) { + echo " Warning: Failed to install $pkg (exit code: $LASTEXITCODE)" + } + } catch { + echo " Warning: Failed to install $pkg - $($_.Exception.Message)" + } +} + +# Refresh PATH to include pixi global binaries +$env:Path = "$env:PIXI_HOME\bin;$env:Path" + +# --------------------------------------------------------------------------- +# Download ITKPythonBuilds archive +# --------------------------------------------------------------------------- +$zipName = "ITKPythonBuilds-windows.zip" +$zipDownloadUrl = "https://github.com/InsightSoftwareConsortium/ITKPythonBuilds/releases/download/$ITK_PACKAGE_VERSION/$zipName" +$localZipName = "ITKPythonBuilds-windows.zip" + +if (Test-Path $localZipName) { + echo "Found cached archive: $localZipName -- skipping download." +} else { + echo "Downloading $zipDownloadUrl ..." + + # Try first (faster, resumable), fall back to Invoke-WebRequest + $aria2Path = Get-Command aria2c -ErrorAction SilentlyContinue + if ($aria2Path) { + echo " Using aria2c for download..." + & aria2c -c --file-allocation=none -s 10 -x 10 -o $localZipName $zipDownloadUrl + } else { + echo " Using Invoke-WebRequest for download..." + Invoke-WebRequest -Uri $zipDownloadUrl -OutFile $localZipName + } } -7z x doxygen-1.16.1.windows.bin.zip -oC:\P\doxygen -aoa -r -if (-not (Test-Path grep-win.zip)) { - Invoke-WebRequest -Uri "https://data.kitware.com/api/v1/file/5bbf87ba8d777f06b91f27d6/download/grep-win.zip" -OutFile "grep-win.zip" + +# Unpack archive +# Expected layout after extraction under $DASHBOARD_BUILD_DIRECTORY: +# \ITK ITK source tree +# \build\ pre-built ITK artifacts +# \IPP ITKPythonPackage scripts + +echo "Extracting archive to $DASHBOARD_BUILD_DIRECTORY ..." +# Use 7-Zip to extract (matches the format it was created in) +$sevenZipPath = "C:\Program Files\7-Zip\7z.exe" +if (-not (Test-Path $sevenZipPath)) { + Write-Error "7-Zip not found at $sevenZipPath. Please install 7-Zip." + exit 1 } -7z x grep-win.zip -oC:\P\grep -aoa -r -$env:Path += ";C:\P\grep" -# Build ITK module dependencies, if any -$build_command = "& `"C:\Python$pythonVersion-x$pythonArch\python.exe`" `"C:\P\IPP\scripts\windows_build_module_wheels.py`" --no-cleanup --py-envs `"3$python_version_minor-x64`"" -if ("$setup_options".length -gt 0) { - $build_command = "$build_command $setup_options" +& $sevenZipPath x $localZipName -o"$DASHBOARD_BUILD_DIRECTORY" -y +if ($LASTEXITCODE -ne 0) { + Write-Error "Failed to extract archive (exit code: $LASTEXITCODE)" + exit 1 } -if("$cmake_options".length -gt 0) { - $build_command = "$build_command -- $cmake_options" +# Optional: overlay ITKPythonPackage build scripts from a specific tag +cd "$DASHBOARD_BUILD_DIRECTORY\IPP" +$env:PATH += ";C:\Program Files\Git\bin" +if ($ITKPYTHONPACKAGE_TAG) { + echo "Updating build scripts to $ITKPYTHONPACKAGE_ORG/ITKPythonPackage@$ITKPYTHONPACKAGE_TAG" + + $ippTmpDir = "$DASHBOARD_BUILD_DIRECTORY\IPP-tmp" + $ippCloneUrl = "https://github.com/$ITKPYTHONPACKAGE_ORG/ITKPythonPackage.git" + + if (-not (Test-Path "$ippTmpDir\.git")) { + echo " Cloning repository..." + & git clone $ippCloneUrl $ippTmpDir + + # Check if clone succeeded + if ($LASTEXITCODE -ne 0 -or -not (Test-Path $ippTmpDir)) { + Write-Error "Failed to clone ITKPythonPackage repository" + exit 1 + } + } + + pushd $ippTmpDir + echo " Checking out $ITKPYTHONPACKAGE_TAG..." + & git checkout $ITKPYTHONPACKAGE_TAG + & git reset "origin/$ITKPYTHONPACKAGE_TAG" --hard + & git status + popd + + echo " Copying updated scripts..." + Copy-Item -Recurse -Force "$ippTmpDir\*" "$DASHBOARD_BUILD_DIRECTORY\IPP\" + Remove-Item -Recurse -Force $ippTmpDir } -echo $build_command -echo "ITK_MODULE_PREQ: $env:ITK_MODULE_PREQ $ITK_MODULE_PREQ" +# Build the module wheel +# Assemble paths used by build_wheels.py +$ippDir = "$DASHBOARD_BUILD_DIRECTORY\IPP" +$buildScript = "$ippDir\scripts\build_wheels.py" +# build_wheels.py expects the cached ITK build at \build\ITK-windows-py3XX-... +# Since the zip extracts directly into BDR (i.e. BDR\build\ITK-windows-py311-...), BDR is the root. +$buildDirRoot = $DASHBOARD_BUILD_DIRECTORY +$itkSourceDir = "$DASHBOARD_BUILD_DIRECTORY\ITK" +$moduleDepsDir = "$DASHBOARD_BUILD_DIRECTORY\MDEPS" + +# Instead of building a string and using iex, build an argument array +$buildArgs = @( + "run", "-e", $platformEnv, + "python", $buildScript, + "--platform-env", $platformEnv, + "--module-source-dir", $MODULE_SRC_DIRECTORY, + "--module-dependencies-root-dir", $moduleDepsDir +) + if ($env:ITK_MODULE_PREQ) { - $MODULES_LIST = $env:ITK_MODULE_PREQ.split(":") - foreach($MODULE_INFO in $MODULES_LIST) { - $MODULE_ORG = $MODULE_INFO.split("/")[0] - $MODULE_NAME = $MODULE_INFO.split("@")[0].split("/")[1] - $MODULE_TAG = $MODULE_INFO.split("@")[1] - - $MODULE_UPSTREAM = "https://github.com/$MODULE_ORG/$MODULE_NAME.git" - echo "Cloning from $MODULE_UPSTREAM" - git clone $MODULE_UPSTREAM - - pushd $MODULE_NAME - git checkout $MODULE_TAG - echo "Building $MODULE_NAME" - iex $build_command - popd - - Copy-Item $MODULE_NAME/include/* include/ - } + $buildArgs += @("--itk-module-deps", $env:ITK_MODULE_PREQ) +} + +$buildArgs += @( + "--no-build-itk-tarball-cache", + "--build-dir-root", $buildDirRoot, + "--itk-git-tag", $ITK_GIT_TAG, + "--itk-source-dir", $itkSourceDir, + "--itk-package-version", $ITK_PACKAGE_VERSION, + "--no-use-ccache", + "--skip-itk-build", + "--skip-itk-wheel-build" +) + +if ($setup_options.Length -gt 0) { + $buildArgs += $setup_options.Split(" ") +} + +if ($cmake_options.Length -gt 0) { + $buildArgs += @("--") + $buildArgs += $cmake_options.Split(" ") } -# Run build scripts -iex $build_command +echo "Building target module..." +& pixi @buildArgs diff --git a/scripts/windows_build_module_wheels.py b/scripts/windows_build_module_wheels.py deleted file mode 100755 index 0a8f54f3..00000000 --- a/scripts/windows_build_module_wheels.py +++ /dev/null @@ -1,251 +0,0 @@ -#!/usr/bin/env python - -# See usage with .\scripts\windows_build_module_wheels.py --help - -from subprocess import check_call -import os -import glob -import sys -import argparse -import shutil -from pathlib import Path - -SCRIPT_DIR = os.path.dirname(__file__) -ROOT_DIR = os.path.abspath(os.getcwd()) - -print("SCRIPT_DIR: %s" % SCRIPT_DIR) -print("ROOT_DIR: %s" % ROOT_DIR) - -sys.path.insert(0, os.path.join(SCRIPT_DIR, "internal")) - -from wheel_builder_utils import push_dir, push_env -from windows_build_common import DEFAULT_PY_ENVS, venv_paths - - -def install_and_import(package): - """ - Install package with pip and import in current script. - """ - import importlib - - try: - importlib.import_module(package) - except ImportError: - import pip - - pip.main(["install", package]) - finally: - globals()[package] = importlib.import_module(package) - - -def build_wheels(py_envs=DEFAULT_PY_ENVS, cleanup=True, cmake_options=[]): - for py_env in py_envs: - ( - python_executable, - python_include_dir, - python_library, - python_sabi_library, - pip, - ninja_executable, - path, - ) = venv_paths(py_env) - - with push_env(PATH="%s%s%s" % (path, os.pathsep, os.environ["PATH"])): - # Install dependencies - check_call([python_executable, "-m", "pip", "install", "pip", "--upgrade"]) - requirements_file = os.path.join(ROOT_DIR, "requirements-dev.txt") - if os.path.exists(requirements_file): - check_call([pip, "install", "--upgrade", "-r", requirements_file]) - check_call([pip, "install", "cmake"]) - check_call([pip, "install", "scikit-build-core", "--upgrade"]) - - check_call([pip, "install", "ninja", "--upgrade"]) - check_call([pip, "install", "delvewheel"]) - - source_path = ROOT_DIR - itk_build_path = os.path.abspath( - "%s/ITK-win_%s" % (os.path.join(SCRIPT_DIR, ".."), py_env) - ) - print("ITKDIR: %s" % itk_build_path) - - minor_version = py_env.split("-")[0][1:] - if int(minor_version) >= 11: - # Stable ABI - wheel_py_api = "cp3%s" % minor_version - else: - wheel_py_api = "" - # Generate wheel - check_call( - [ - python_executable, - "-m", - "build", - "--verbose", - "--wheel", - "--outdir", - "dist", - "--no-isolation", - "--skip-dependency-check", - "--config-setting=wheel.py-api=%s" % wheel_py_api, - "--config-setting=cmake.define.SKBUILD:BOOL=ON", - "--config-setting=cmake.define.PY_SITE_PACKAGES_PATH:PATH=.", - "--config-setting=cmake.args=-G Ninja", - "--config-setting=cmake.define.CMAKE_BUILD_TYPE:STRING=Release", - "--config-setting=cmake.define.CMAKE_MAKE_PROGRAM:FILEPATH=%s" - % ninja_executable, - "--config-setting=cmake.define.ITK_DIR:PATH=%s" - % itk_build_path, - "--config-setting=cmake.define.WRAP_ITK_INSTALL_COMPONENT_IDENTIFIER:STRING=PythonWheel", - "--config-setting=cmake.define.SWIG_EXECUTABLE:FILEPATH=%s/Wrapping/Generators/SwigInterface/swig/bin/swig.exe" - % itk_build_path, - "--config-setting=cmake.define.BUILD_TESTING:BOOL=OFF", - "--config-setting=cmake.define.CMAKE_INSTALL_LIBDIR:STRING=lib", - "--config-setting=cmake.define.Python3_EXECUTABLE:FILEPATH=%s" - % python_executable, - "--config-setting=cmake.define.Python3_INCLUDE_DIR:PATH=%s" - % python_include_dir, - "--config-setting=cmake.define.Python3_INCLUDE_DIRS:PATH=%s" - % python_include_dir, - "--config-setting=cmake.define.Python3_LIBRARY:FILEPATH=%s" - % python_library, - "--config-setting=cmake.define.Python3_SABI_LIBRARY:FILEPATH=%s" - % python_sabi_library, - ] - + [ - o.replace("-D", "--config-setting=cmake.define.") - for o in cmake_options - ] - + [ - ".", - ] - ) - - -def rename_wheel_init(py_env, filepath, add_module_name=True): - """ - Rename module __init__ (if add_module_name is True) or __init_module__ (if - add_module_name is False) file in wheel. This is required to prevent - modules to override ITK's __init__ file on install or to prevent delvewheel - to override __init_module__ file. If the module ships its own __init__ - file, it is automatically renamed to __init_{module_name}__ by this - function. The renamed __init__ file will be executed by ITK's __init__ file - when loading ITK. - """ - ( - python_executable, - python_include_dir, - python_library, - python_sabi_library, - pip, - ninja_executable, - path, - ) = venv_paths(py_env) - - # Get module info - install_and_import("pkginfo") - w = pkginfo.Wheel(filepath) - module_name = w.name.split("itk-")[-1] - module_version = w.version - - dist_dir = os.path.dirname(filepath) - wheel_dir = os.path.join( - dist_dir, "itk_" + module_name.replace("-", "_") + "-" + module_version - ) - init_dir = os.path.join(wheel_dir, "itk") - init_file = os.path.join(init_dir, "__init__.py") - init_file_module = os.path.join( - init_dir, "__init_" + module_name.split("-")[0] + "__.py" - ) - - # Unpack wheel and rename __init__ file if it exists. - check_call([python_executable, "-m", "wheel", "unpack", filepath, "-d", dist_dir]) - if add_module_name and os.path.isfile(init_file): - shutil.move(init_file, init_file_module) - if not add_module_name and os.path.isfile(init_file_module): - shutil.move(init_file_module, init_file) - - # Pack wheel and clean wheel folder - check_call([python_executable, "-m", "wheel", "pack", wheel_dir, "-d", dist_dir]) - shutil.rmtree(wheel_dir) - - -def fixup_wheel(py_envs, filepath, lib_paths: str = "", exclude_libs: str = ""): - lib_paths = ";".join(["C:/P/IPP/oneTBB-prefix/bin", lib_paths.strip()]).strip(";") - print(f"Library paths for fixup: {lib_paths}") - - py_env = py_envs[0] - - # Make sure the module __init_module__.py file has the expected name for - # delvewheel, i.e., __init__.py. - rename_wheel_init(py_env, filepath, False) - - delve_wheel = os.path.join( - "C:/P/IPP", "venv-" + py_env, "Scripts", "delvewheel.exe" - ) - check_call( - [ - delve_wheel, - "repair", - "--no-mangle-all", - "--add-path", - lib_paths, - "--no-dll", - exclude_libs, - "--ignore-in-wheel", - "-w", - os.path.join(ROOT_DIR, "dist"), - filepath, - ] - ) - - # The delve_wheel patch loading shared libraries is added to the module - # __init__ file. Rename this file here to prevent conflicts on installation. - # The renamed __init__ file will be executed when loading ITK. - rename_wheel_init(py_env, filepath) - - -def fixup_wheels(py_envs, lib_paths: str = "", exclude_libs: str = ""): - # shared library fix-up - for wheel in glob.glob(os.path.join(ROOT_DIR, "dist", "*.whl")): - fixup_wheel(py_envs, wheel, lib_paths, exclude_libs) - - -if __name__ == "__main__": - parser = argparse.ArgumentParser( - description="Driver script to build ITK Python module wheels." - ) - parser.add_argument( - "--py-envs", - nargs="+", - default=DEFAULT_PY_ENVS, - help='Target Python environment versions, e.g. "310-x64".', - ) - parser.add_argument( - "--no-cleanup", - dest="cleanup", - action="store_false", - help="Do not clean up temporary build files.", - ) - parser.add_argument( - "--lib-paths", - nargs=1, - default="", - help="Add semicolon-delimited library directories for delvewheel to include in the module wheel", - ) - parser.add_argument( - "--exclude-libs", - nargs=1, - default="", - help='Add semicolon-delimited library names that must not be included in the module wheel, e.g. "nvcuda.dll"', - ) - parser.add_argument( - "cmake_options", - nargs="*", - help="Extra options to pass to CMake, e.g. -DBUILD_SHARED_LIBS:BOOL=OFF", - ) - args = parser.parse_args() - - build_wheels( - cleanup=args.cleanup, py_envs=args.py_envs, cmake_options=args.cmake_options - ) - fixup_wheels(args.py_envs, ";".join(args.lib_paths), ";".join(args.exclude_libs)) diff --git a/scripts/windows_build_python_instance.py b/scripts/windows_build_python_instance.py new file mode 100644 index 00000000..0f966db1 --- /dev/null +++ b/scripts/windows_build_python_instance.py @@ -0,0 +1,256 @@ +import re +from pathlib import Path + +from build_python_instance_base import BuildPythonInstanceBase + + +class WindowsBuildPythonInstance(BuildPythonInstanceBase): + """Windows-specific wheel builder. + + Handles Windows path conventions, pixi-based Python environment + discovery, and ``delvewheel`` for wheel repair. + """ + + def prepare_build_env(self) -> None: + """Set up the Windows build environment, TBB paths, and venv info.""" + # ############################################# + # ### Setup build tools + self.package_env_config["USE_TBB"] = "ON" + self.package_env_config["TBB_DIR"] = str( + self.build_dir_root / "build" / "oneTBB-prefix" / "lib" / "cmake" / "TBB" + ) + # The interpreter is provided; ensure basic tools are available + self.venv_paths() + self.update_venv_itk_build_configurations() + + target_arch = self.package_env_config["ARCH"] + itk_binary_build_name: Path = ( + self.build_dir_root + / "build" + / f"ITK-{self.platform_env}-{self.get_pixi_environment_name()}_{target_arch}" + ) + + self.cmake_itk_source_build_configurations.set( + "ITK_BINARY_DIR:PATH", str(itk_binary_build_name) + ) + + # Keep values consistent with prior quoting behavior + # self.cmake_compiler_configurations.set("CMAKE_CXX_FLAGS:STRING", "-O3 -DNDEBUG") + # self.cmake_compiler_configurations.set("CMAKE_C_FLAGS:STRING", "-O3 -DNDEBUG") + + def post_build_fixup(self) -> None: + """Repair wheels with ``delvewheel``, including oneTBB library paths.""" + # append the oneTBB-prefix\\bin directory for fixing wheels built with local oneTBB + search_lib_paths = ( + [s for s in str(self.windows_extra_lib_paths[0]).rstrip(";") if s] + if self.windows_extra_lib_paths + else [] + ) + search_lib_paths.append(str(self.build_dir_root / "oneTBB-prefix" / "bin")) + search_lib_paths_str: str = ";".join(map(str, search_lib_paths)) + self.fixup_wheels(search_lib_paths_str) + + def fixup_wheel( + self, filepath, lib_paths: str = "", remote_module_wheel: bool = False + ) -> None: + """Repair a wheel using ``delvewheel`` with the given library paths. + + Parameters + ---------- + filepath : str + Path to the ``.whl`` file to repair. + lib_paths : str, optional + Semicolon-delimited directories to add to ``delvewheel --add-path``. + remote_module_wheel : bool, optional + Unused on Windows (kept for interface compatibility). + """ + # Windows fixup_wheel + lib_paths = lib_paths.strip() + lib_paths = lib_paths + ";" if lib_paths else "" + print(f"Library paths for fixup: {lib_paths}") + + delve_wheel = "delvewheel.exe" + cmd = [ + str(delve_wheel), + "repair", + "--no-mangle-all", + "--add-path", + lib_paths.strip(";"), + "--ignore-in-wheel", + "-w", + str(self.build_dir_root / "dist"), + str(filepath), + ] + self.echo_check_call(cmd) + + def build_tarball(self): + """Create an archive of the ITK Python package build tree (Windows). + + Mirrors scripts/windows-build-tarball.ps1 behavior: + - Remove contents of IPP/dist + - Use 7-Zip, when present, to archive the full IPP tree into + ITKPythonBuilds-windows.zip at the parent directory of IPP (e.g., C:\P) + - Fallback to Python's zip archive creation if 7-Zip is unavailable + """ + + # out_zip = self.build_dir_root / "build" / "ITKPythonBuilds-windows.zip" + out_zip = self.build_dir_root / "ITKPythonBuilds-windows.zip" + + # 1) Clean IPP/dist contents (do not remove the directory itself) + dist_dir = self.build_dir_root / "dist" + if dist_dir.exists(): + for p in dist_dir.glob("*"): + try: + if p.is_dir(): + # shutil.rmtree alternative without importing here + for sub in p.rglob("*"): + # best-effort clean + try: + if sub.is_file() or sub.is_symlink(): + sub.unlink(missing_ok=True) + except Exception: + pass + try: + p.rmdir() + except Exception: + pass + else: + p.unlink(missing_ok=True) + except Exception: + # best-effort cleanup; ignore errors to continue packaging + pass + + # 2) Try to use 7-Zip if available + seven_zip_candidates = [ + Path(r"C:\\7-Zip\\7z.exe"), + Path(r"C:\\Program Files\\7-Zip\\7z.exe"), + Path(r"C:\\Program Files (x86)\\7-Zip\\7z.exe"), + ] + + seven_zip = None + for cand in seven_zip_candidates: + if cand.exists(): + seven_zip = cand + break + + if seven_zip is None: + # Try PATH lookup using where/which behavior from shutil + import shutil as _shutil + + found = _shutil.which("7z.exe") or _shutil.which("7z") + if found: + seven_zip = Path(found) + + if seven_zip is not None: + cmd = [ + str(seven_zip), + "a", + "-t7z", + "-r", + str(out_zip), + str(self.build_dir_root / "ITK"), + str(self.build_dir_root / "build"), + str(self.ipp_dir), + "-xr!*.o", + "-xr!*.obj", # Windows equivalent of .o + "-xr!wheelbuilds", # Do not include the wheelbuild support directory + "-xr!__pycache__", # Do not include __pycache__ + "-xr!install_manifest_*.txt", # Do not include install manifest files + "-xr!.git", # Exclude git directory + "-xr!.idea", # Exclude IDE directory + "-xr!.pixi", # Exclude pixi environment + "-xr!castxml_inputs", + "-xr!Wrapping\Modules", + "-xr!*.pdb", # Exclude debug symbols + ] + return_status: int = self.echo_check_call(cmd) + if return_status == 0: + return + + # 3) Fallback: create a .zip using Python's shutil + # This will create a zip archive named ITKPythonBuilds-windows.zip + import shutil as _shutil + + if out_zip.exists(): + try: + out_zip.unlink() + except Exception: + pass + # make_archive requires base name without extension + base_name = str(out_zip.with_suffix("").with_suffix("")) + # shutil.make_archive will append .zip + _shutil.make_archive( + base_name, + "zip", + root_dir=str(self.build_dir_root), + base_dir=str(self.build_dir_root.name), + ) + + def venv_paths(self) -> None: + """Populate ``venv_info_dict`` from the pixi-managed Python environment on Windows.""" + + def get_python_version(platform_env: str) -> None | tuple[int, int]: + pattern = re.compile(r"py3(?P\d+)") + m = pattern.search(platform_env) + if not m: + return None + return 3, int(m.group("minor")) + + # Get the python executable path + python_exe = Path(self.package_env_config["PYTHON_EXECUTABLE"]) + + # For the pixi environment structure: + # python.exe is at: /python.exe + # Headers are at: /include/ + # Libraries are at: /libs/ + env_root = python_exe.parent # C:/BDR/IPP/.pixi/envs/windows-py311 + + venv_bin_path = env_root # Where python.exe is + venv_base_dir = env_root + + # Python development files are directly under env root + python_include_dir = env_root / "include" + + python_major, python_minor = get_python_version(self.platform_env) + # Version-specific library (e.g., python311.lib) - required for + # CMake's FindPython3 to extract version info for Development.Module + xy_lib_ver = f"{python_major}{python_minor}" + python_library = env_root / "libs" / f"python{xy_lib_ver}.lib" + + # Stable ABI library (python3.lib) - for Development.SABIModule + if python_minor >= 11: + python_sabi_library = env_root / "libs" / f"python{python_major}.lib" + else: + python_sabi_library = python_library + + self.venv_info_dict = { + "python_include_dir": python_include_dir, # .../windows-py311/include + "python_library": python_library, # .../windows-py311/libs/python311.lib + "python_sabi_library": python_sabi_library, # .../windows-py311/libs/python3.lib + "venv_bin_path": venv_bin_path, # .../windows-py311 + "venv_base_dir": venv_base_dir, # .../windows-py311 + "python_root_dir": env_root, # .../windows-py311 + } + + def discover_python_venvs( + self, platform_os_name: str, platform_architecture: str + ) -> list[str]: + """Return default Windows Python environment names. + + Parameters + ---------- + platform_os_name : str + Operating system identifier (unused, kept for interface). + platform_architecture : str + Architecture suffix appended to each environment name. + + Returns + ------- + list[str] + Environment names like ``['39-x64', '310-x64', '311-x64']``. + """ + default_platform_envs = [ + f"310-{platform_architecture}", + f"311-{platform_architecture}", + ] + return default_platform_envs diff --git a/scripts/windows_build_wheels.py b/scripts/windows_build_wheels.py deleted file mode 100644 index 4c1404bd..00000000 --- a/scripts/windows_build_wheels.py +++ /dev/null @@ -1,411 +0,0 @@ -#!/usr/bin/env python - -import argparse -import glob -import json -import os -import shutil -import sys -import tempfile -import textwrap - -from subprocess import check_call, check_output - - -SCRIPT_DIR = os.path.dirname(__file__) -ROOT_DIR = os.path.abspath(os.path.join(SCRIPT_DIR, "..")) -ITK_SOURCE = os.path.join(ROOT_DIR, "ITK-source") - -print("SCRIPT_DIR: %s" % SCRIPT_DIR) -print("ROOT_DIR: %s" % ROOT_DIR) -print("ITK_SOURCE: %s" % ITK_SOURCE) - -sys.path.insert(0, os.path.join(SCRIPT_DIR, "internal")) -from wheel_builder_utils import push_dir, push_env -from windows_build_common import DEFAULT_PY_ENVS, venv_paths - - -def pip_install(python_dir, package, upgrade=True): - pip = os.path.join(python_dir, "Scripts", "pip.exe") - print("Installing %s using %s" % (package, pip)) - args = [pip, "install"] - if upgrade: - args.append("--upgrade") - args.append(package) - check_call(args) - - -def prepare_build_env(python_version): - python_dir = "C:/Python%s" % python_version - if not os.path.exists(python_dir): - raise FileNotFoundError( - "Aborting. python_dir [%s] does not exist." % python_dir - ) - - venv = os.path.join(python_dir, "Scripts", "virtualenv.exe") - venv_dir = os.path.join(ROOT_DIR, "venv-%s" % python_version) - print("Creating python virtual environment: %s" % venv_dir) - if not os.path.exists(venv_dir): - check_call([venv, venv_dir]) - pip_install(venv_dir, "scikit-build-core") - pip_install(venv_dir, "ninja") - pip_install(venv_dir, "delvewheel") - - -def build_wrapped_itk( - ninja_executable, - build_type, - source_path, - build_path, - python_executable, - python_include_dir, - python_library, - python_sabi_library, -): - tbb_dir = os.path.join(ROOT_DIR, "oneTBB-prefix", "lib", "cmake", "TBB") - - # Build ITK python - with push_dir(directory=build_path, make_directory=True): - check_call( - [ - "cmake", - "-DCMAKE_MAKE_PROGRAM:FILEPATH=%s" % ninja_executable, - "-DCMAKE_BUILD_TYPE:STRING=%s" % build_type, - "-DITK_SOURCE_DIR:PATH=%s" % source_path, - "-DITK_BINARY_DIR:PATH=%s" % build_path, - "-DBUILD_TESTING:BOOL=OFF", - "-DSKBUILD:BOOL=ON", - "-DPython3_EXECUTABLE:FILEPATH=%s" % python_executable, - "-DITK_WRAP_unsigned_short:BOOL=ON", - "-DITK_WRAP_double:BOOL=ON", - "-DITK_WRAP_complex_double:BOOL=ON", - "-DITK_WRAP_IMAGE_DIMS:STRING=2;3;4", - "-DPython3_INCLUDE_DIR:PATH=%s" % python_include_dir, - "-DPython3_INCLUDE_DIRS:PATH=%s" % python_include_dir, - "-DPython3_LIBRARY:FILEPATH=%s" % python_library, - "-DPython3_SABI_LIBRARY:FILEPATH=%s" % python_sabi_library, - "-DWRAP_ITK_INSTALL_COMPONENT_IDENTIFIER:STRING=PythonWheel", - "-DWRAP_ITK_INSTALL_COMPONENT_PER_MODULE:BOOL=ON", - "-DPY_SITE_PACKAGES_PATH:PATH=.", - "-DITK_LEGACY_SILENT:BOOL=ON", - "-DITK_WRAP_PYTHON:BOOL=ON", - "-DITK_WRAP_DOC:BOOL=ON", - "-DDOXYGEN_EXECUTABLE:FILEPATH=C:/P/doxygen/doxygen.exe", - "-DModule_ITKTBB:BOOL=ON", - "-DTBB_DIR:PATH=%s" % tbb_dir, - "-G", - "Ninja", - source_path, - ] - ) - check_call([ninja_executable]) - - -def build_wheel( - python_version, - build_type="Release", - single_wheel=False, - cleanup=True, - wheel_names=None, - cmake_options=[], -): - ( - python_executable, - python_include_dir, - python_library, - python_sabi_library, - pip, - ninja_executable, - path, - ) = venv_paths(python_version) - - with push_env(PATH="%s%s%s" % (path, os.pathsep, os.environ["PATH"])): - # Install dependencies - check_call( - [ - pip, - "install", - "--upgrade", - "-r", - os.path.join(ROOT_DIR, "requirements-dev.txt"), - ] - ) - - source_path = "%s/ITK" % ITK_SOURCE - build_path = "%s/ITK-win_%s" % (ROOT_DIR, python_version) - pyproject_configure = os.path.join(SCRIPT_DIR, "pyproject_configure.py") - - # Clean up previous invocations - if cleanup and os.path.exists(build_path): - shutil.rmtree(build_path) - - if single_wheel: - print("#") - print("# Build single ITK wheel") - print("#") - - # Configure pyproject.toml - check_call([python_executable, pyproject_configure, "itk"]) - - # Generate wheel - check_call( - [ - python_executable, - "-m", - "build", - "--verbose", - "--wheel", - "--outdir", - "dist", - "--no-isolation", - "--skip-dependency-check", - "--config-setting=cmake.build-type=%s" % build_type, - "--config-setting=cmake.define.ITK_SOURCE_DIR:PATH=%s" - % source_path, - "--config-setting=cmake.define.ITK_BINARY_DIR:PATH=%s" % build_path, - "--config-setting=cmake.define.Python3_EXECUTABLE:FILEPATH=%s" - % python_executable, - "--config-setting=cmake.define.Python3_INCLUDE_DIR:PATH=%s" - % python_include_dir, - "--config-setting=cmake.define.Python3_INCLUDE_DIRS:PATH=%s" - % python_include_dir, - "--config-setting=cmake.define.Python3_LIBRARY:FILEPATH=%s" - % python_library, - "--config-setting=cmake.define.Python3_SABI_LIBRARY:FILEPATH=%s" - % python_sabi_library, - "--config-setting=cmake.define.DOXYGEN_EXECUTABLE:FILEPATH=C:/P/doxygen/doxygen.exe", - ] - + [ - o.replace("-D", "--config-setting=cmake.define.") - for o in cmake_options - ] - + [ - ".", - ] - ) - - else: - print("#") - print("# Build multiple ITK wheels") - print("#") - - build_wrapped_itk( - ninja_executable, - build_type, - source_path, - build_path, - python_executable, - python_include_dir, - python_library, - python_sabi_library, - ) - - # Build wheels - if wheel_names is None: - with open(os.path.join(SCRIPT_DIR, "WHEEL_NAMES.txt"), "r") as content: - wheel_names = [ - wheel_name.strip() for wheel_name in content.readlines() - ] - - for wheel_name in wheel_names: - # Configure pyproject.toml - check_call([python_executable, pyproject_configure, wheel_name]) - - # Generate wheel - check_call( - [ - python_executable, - "-m", - "build", - "--verbose", - "--wheel", - "--outdir", - "dist", - "--no-isolation", - "--skip-dependency-check", - "--config-setting=cmake.build-type=%s" % build_type, - "--config-setting=cmake.define.ITK_SOURCE_DIR:PATH=%s" - % source_path, - "--config-setting=cmake.define.ITK_BINARY_DIR:PATH=%s" - % build_path, - "--config-setting=cmake.define.ITKPythonPackage_ITK_BINARY_REUSE:BOOL=ON", - "--config-setting=cmake.define.ITKPythonPackage_WHEEL_NAME:STRING=%s" - % wheel_name, - "--config-setting=cmake.define.Python3_EXECUTABLE:FILEPATH=%s" - % python_executable, - "--config-setting=cmake.define.Python3_INCLUDE_DIR:PATH=%s" - % python_include_dir, - "--config-setting=cmake.define.Python3_INCLUDE_DIRS:PATH=%s" - % python_include_dir, - "--config-setting=cmake.define.Python3_LIBRARY:FILEPATH=%s" - % python_library, - "--config-setting=cmake.define.Python3_SABI_LIBRARY:FILEPATH=%s" - % python_sabi_library, - ] - + [ - o.replace("-D", "--config-setting=cmake.define.") - for o in cmake_options - ] - + [ - ".", - ] - ) - - # Remove unnecessary files for building against ITK - if cleanup: - for root, _, file_list in os.walk(build_path): - for filename in file_list: - extension = os.path.splitext(filename)[1] - if extension in [".cpp", ".xml", ".obj", ".o"]: - os.remove(os.path.join(root, filename)) - shutil.rmtree(os.path.join(build_path, "Wrapping", "Generators", "CastXML")) - - -def fixup_wheel(py_envs, filepath, lib_paths: str = ""): - lib_paths = lib_paths.strip() if lib_paths.isspace() else lib_paths.strip() + ";" - lib_paths += "C:/P/IPP/oneTBB-prefix/bin" - print(f"Library paths for fixup: {lib_paths}") - - py_env = py_envs[0] - - delve_wheel = os.path.join(ROOT_DIR, "venv-" + py_env, "Scripts", "delvewheel.exe") - check_call( - [ - delve_wheel, - "repair", - "--no-mangle-all", - "--add-path", - lib_paths, - "--ignore-in-wheel", - "-w", - os.path.join(ROOT_DIR, "dist"), - filepath, - ] - ) - - -def fixup_wheels(single_wheel, py_envs, lib_paths: str = ""): - # TBB library fix-up - tbb_wheel = "itk_core" - if single_wheel: - tbb_wheel = "itk" - for wheel in glob.glob(os.path.join(ROOT_DIR, "dist", tbb_wheel + "*.whl")): - fixup_wheel(py_envs, wheel, lib_paths) - - -def test_wheels(python_env): - ( - python_executable, - python_include_dir, - python_library, - python_sabi_library, - pip, - ninja_executable, - path, - ) = venv_paths(python_env) - check_call([pip, "install", "numpy"]) - check_call([pip, "install", "itk", "--no-cache-dir", "--no-index", "-f", "dist"]) - print("Wheel successfully installed.") - check_call([python_executable, os.path.join(ROOT_DIR, "docs/code/test.py")]) - print("Documentation tests passed.") - - -def build_wheels( - py_envs=DEFAULT_PY_ENVS, - single_wheel=False, - cleanup=False, - wheel_names=None, - cmake_options=[], -): - for py_env in py_envs: - prepare_build_env(py_env) - - build_type = "Release" - - with push_dir(directory=ITK_SOURCE, make_directory=True): - cmake_executable = "cmake.exe" - tools_venv = os.path.join(ROOT_DIR, "venv-" + py_envs[0]) - ninja_executable = shutil.which("ninja.exe") - if ninja_executable is None: - pip_install(tools_venv, "ninja") - ninja_executable = os.path.join(tools_venv, "Scripts", "ninja.exe") - - # Build standalone project and populate archive cache - check_call( - [ - cmake_executable, - "-DCMAKE_BUILD_TYPE:STRING=%s" % build_type, - "-DITKPythonPackage_BUILD_PYTHON:PATH=0", - "-G", - "Ninja", - "-DCMAKE_MAKE_PROGRAM:FILEPATH=%s" % ninja_executable, - ROOT_DIR, - ] - ) - - check_call([ninja_executable]) - - # Compile wheels re-using standalone project and archive cache - for py_env in py_envs: - tools_venv = os.path.join(ROOT_DIR, "venv-" + py_env) - ninja_executable = shutil.which("ninja.exe") - if ninja_executable is None: - pip_install(tools_venv, "ninja") - build_wheel( - py_env, - build_type, - single_wheel=single_wheel, - cleanup=cleanup, - wheel_names=wheel_names, - cmake_options=cmake_options, - ) - - -def main(wheel_names=None): - parser = argparse.ArgumentParser( - description="Driver script to build ITK Python wheels." - ) - parser.add_argument( - "--single-wheel", - action="store_true", - help="Build a single wheel as opposed to one wheel per ITK module group.", - ) - parser.add_argument( - "--py-envs", - nargs="+", - default=DEFAULT_PY_ENVS, - help='Target Python environment versions, e.g. "310-x64".', - ) - parser.add_argument( - "--no-cleanup", - dest="cleanup", - action="store_false", - help="Do not clean up temporary build files.", - ) - parser.add_argument( - "--lib-paths", - nargs=1, - default="", - help="Add semicolon-delimited library directories for delvewheel to include in the module wheel", - ) - parser.add_argument( - "cmake_options", - nargs="*", - help="Extra options to pass to CMake, e.g. -DBUILD_SHARED_LIBS:BOOL=OFF", - ) - args = parser.parse_args() - - build_wheels( - single_wheel=args.single_wheel, - cleanup=args.cleanup, - py_envs=args.py_envs, - wheel_names=wheel_names, - cmake_options=args.cmake_options, - ) - fixup_wheels(args.single_wheel, args.py_envs, ";".join(args.lib_paths)) - for py_env in args.py_envs: - test_wheels(py_env) - - -if __name__ == "__main__": - main() From 7d682b0d5ecb46ffb371691f13239db6a8fb4d9f Mon Sep 17 00:00:00 2001 From: Cavan Riley Date: Tue, 17 Mar 2026 15:34:55 -0500 Subject: [PATCH 04/27] ENH: Add tarball creation and ITK build cache management Adds make_tarballs.sh and integrates tarball generation logic into build_python_instance_base.py. Supports creating, downloading, and reusing ITK build caches across Linux, macOS, and Windows, including manylinux tarball support, arch-specific naming, and a --build-itk-tarball-cache CLI option. Adds make_windows_zip.ps1 for streamlined Windows wheel packaging and zip creation. --- scripts/dockcross-manylinux-build-tarball.sh | 44 ------ scripts/macpython-build-tarball.sh | 29 ---- scripts/make_tarballs.sh | 120 ++++++++++++++ scripts/make_windows_zip.ps1 | 157 +++++++++++++++++++ scripts/windows-build-tarball.ps1 | 8 - 5 files changed, 277 insertions(+), 81 deletions(-) delete mode 100755 scripts/dockcross-manylinux-build-tarball.sh delete mode 100755 scripts/macpython-build-tarball.sh create mode 100755 scripts/make_tarballs.sh create mode 100644 scripts/make_windows_zip.ps1 delete mode 100644 scripts/windows-build-tarball.ps1 diff --git a/scripts/dockcross-manylinux-build-tarball.sh b/scripts/dockcross-manylinux-build-tarball.sh deleted file mode 100755 index ca29e75c..00000000 --- a/scripts/dockcross-manylinux-build-tarball.sh +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/env bash - -# This script creates a tarball of the ITK Python package build tree. It is -# downloaded by the external module build scripts and used to build their -# Python package on GitHub CI services. - -# ----------------------------------------------------------------------- - -zstd_exe=`(which zstd)` - -# Find an appropriately versioned zstd. -# -# "--long" is introduced in zstd==v1.3.2 -# https://github.com/facebook/zstd/releases/tag/v1.3.2 -# -# Sample --version output: -# *** zstd command line interface 64-bits v1.4.4, by Yann Collet *** # -ZSTD_MIN_VERSION="1.3.2" - -if [[ -n `(which dpkg)` && `(${zstd_exe} --version)` =~ v([0-9]+.[0-9]+.[0-9]+) ]]; then - if $(dpkg --compare-versions ${BASH_REMATCH[1]} "ge" ${ZSTD_MIN_VERSION} ); then - echo "Found zstd v${BASH_REMATCH[1]} at ${zstd_exe}" - else - echo "Expected zstd v${ZSTD_MIN_VERSION} or higher but found v${BASH_REMATCH[1]} at ${zstd_exe}" - exit 255 - fi -else - # dpkg not available for version comparison so simply print version - ${zstd_exe} --version -fi - -# ----------------------------------------------------------------------- - -tar -cf ITKPythonBuilds-linux.tar \ - ITKPythonPackage/ITK-* \ - ITKPythonPackage/oneTBB* \ - ITKPythonPackage/requirements-dev.txt \ - ITKPythonPackage/scripts -$zstd_exe -f \ - -10 \ - -T6 \ - --long=31 \ - ./ITKPythonBuilds-linux.tar \ - -o ./ITKPythonBuilds-linux.tar.zst diff --git a/scripts/macpython-build-tarball.sh b/scripts/macpython-build-tarball.sh deleted file mode 100755 index c4a727b4..00000000 --- a/scripts/macpython-build-tarball.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env bash - -# This script creates a tarball of the ITK Python package build tree. It is -# downloaded by the external module build scripts and used to build their -# Python package on GitHub CI services. - -#tbb_contents="ITKPythonPackage/oneTBB*" -tbb_contents="" -arch_postfix="" -if test $(arch) == "arm64"; then - arch_postfix="-arm64" - tbb_contents="" -fi - -pushd /Users/svc-dashboard/D/P > /dev/null -dot_clean ITKPythonPackage -tar -cf ITKPythonBuilds-macosx${arch_postfix}.tar \ - ITKPythonPackage/ITK-* \ - ${tbb_contents} \ - ITKPythonPackage/venvs \ - ITKPythonPackageRequiredExtractionDir.txt \ - ITKPythonPackage/scripts -zstd -f \ - -10 \ - -T6 \ - --long=31 \ - ./ITKPythonBuilds-macosx${arch_postfix}.tar \ - -o ./ITKPythonBuilds-macosx${arch_postfix}.tar.zst -popd > /dev/null diff --git a/scripts/make_tarballs.sh b/scripts/make_tarballs.sh new file mode 100755 index 00000000..cdd93d6e --- /dev/null +++ b/scripts/make_tarballs.sh @@ -0,0 +1,120 @@ +#!/usr/bin/env bash +# NOTES: Building tarballs requires specific pathing for supporting github CI +# workflows + +script_dir=$( + cd "$(dirname "$0")" || exit 1 + pwd +) +_ipp_dir=$(dirname "${script_dir}") + +# If args are given, use them. Otherwise use default python environments +pyenvs=("${@:-py310 py311}") + +# Otherwise process mac and linux based on uname + +# Need to explicitly request to --build-itk-tarball-cache +BUILD_WHEELS_EXTRA_FLAGS=("--build-itk-tarball-cache") +if [ -z "${ITK_GIT_TAG}" ]; then + DEFAULT_ITK_GIT_TAG=v6.0b02 + echo "=============================================================================" + echo "=============================================================================" + for _ in x x x x x x x x x x x x x x x x x x x x x x x x x x x x x; do + echo "===== WARNING: ITK_GIT_TAG not set, so defaulting to ${DEFAULT_ITK_GIT_TAG}" + done + echo "=============================================================================" + echo "=============================================================================" +fi +ITK_GIT_TAG=${ITK_GIT_TAG:=${DEFAULT_ITK_GIT_TAG}} + +## -- +# -- +# -- +# -- +# Short circuit builds to use dockcross if MANYLINUX_VERSION is requested +if [ -n "${MANYLINUX_VERSION}" ]; then + BUILD_WHEELS_EXTRA_FLAGS="${BUILD_WHEELS_EXTRA_FLAGS[*]}" \ + ITK_GIT_TAG=${ITK_GIT_TAG} \ + MANYLINUX_VERSION=${MANYLINUX_VERSION} \ + bash "${_ipp_dir}/scripts/dockcross-manylinux-build-wheels.sh" \ + "${pyenvs[@]}" + exit $? +fi + +## -- +# -- +# -- +# -- +case "$(uname -s)" in +Darwin) + PLATFORM_PREFIX="macosx" + DASHBOARD_BUILD_DIRECTORY=${DASHBOARD_BUILD_DIRECTORY:=/Users/svc-dashboard/D/P} + ;; +Linux) + PLATFORM_PREFIX="linux" + DASHBOARD_BUILD_DIRECTORY=${DASHBOARD_BUILD_DIRECTORY:=/work} + ;; + # POSIX build env NOT SUPPORTED for windows, Needs to be done in a .ps1 shell + # MINGW*|MSYS*|CYGWIN*) + # PLATFORM_PREFIX="windows" + # DASHBOARD_BUILD_DIRECTORY="C:\P" + # ;; +*) + echo "Unsupported platform: $(uname -s)" + exit 1 + ;; +esac + +# Required environment variables +required_vars=( + ITK_GIT_TAG + PLATFORM_PREFIX + DASHBOARD_BUILD_DIRECTORY + +) + +# Sanity Validation loop +_missing_required=0 +for v in "${required_vars[@]}"; do + if [ -z "${!v:-}" ]; then + _missing_required=1 + echo "ERROR: Required environment variable '$v' is not set or empty." + fi +done +if [ "${_missing_required}" -ne 0 ]; then + exit 1 +fi +unset _missing_required + +if [ ! -d "${DASHBOARD_BUILD_DIRECTORY}" ]; then + # This is the expected directory for the cache, It may require creation with administrator credentials + mkdir -p "${DASHBOARD_BUILD_DIRECTORY}" +fi +if [ "${script_dir}" != "${DASHBOARD_BUILD_DIRECTORY}/ITKPythonPackage/scripts" ]; then + echo "ERROR: Github CI requires rigid directory structure, you may substitute the ITKPythonPackage organization if testing" + echo " RUN: cd ${DASHBOARD_BUILD_DIRECTORY}" + echo " RUN: git clone git@github.com:${ITKPYTHONPACKAGE_ORG}/ITKPythonPackage.git ${DASHBOARD_BUILD_DIRECTORY}/ITKPythonPackage" + echo " FOR DEVELOPMENT RUN: git checkout python_based_build_scripts" + echo " RUN: ${DASHBOARD_BUILD_DIRECTORY}/ITKPythonPackage/scripts/make_tarballs.sh" + exit 1 +fi + +export PIXI_HOME=${DASHBOARD_BUILD_DIRECTORY}/.pixi +if [ ! -f "${PIXI_HOME}/bin/pixi" ]; then + #PIXI INSTALL + if [ ! -f "${PIXI_HOME}/bin/pixi" ]; then + curl -fsSL https://pixi.sh/install.sh | sh + export PATH="${PIXI_HOME}/bin:$PATH" + fi +fi + +for pyenv in "${pyenvs[@]}"; do + cd "${DASHBOARD_BUILD_DIRECTORY}/ITKPythonPackage" || exit + "${PIXI_HOME}/bin/pixi" run -e "${PLATFORM_PREFIX}-${pyenv}" \ + python3 "${DASHBOARD_BUILD_DIRECTORY}/ITKPythonPackage/scripts/build_wheels.py" \ + --platform-env "${PLATFORM_PREFIX}-${pyenv}" \ + --build-dir-root "${DASHBOARD_BUILD_DIRECTORY}/ITKPythonPackage-build" \ + --itk-source-dir "${DASHBOARD_BUILD_DIRECTORY}/ITKPythonPackage-build/ITK" \ + --itk-git-tag "${ITK_GIT_TAG}" \ + "${BUILD_WHEELS_EXTRA_FLAGS[@]}" +done diff --git a/scripts/make_windows_zip.ps1 b/scripts/make_windows_zip.ps1 new file mode 100644 index 00000000..fe69477a --- /dev/null +++ b/scripts/make_windows_zip.ps1 @@ -0,0 +1,157 @@ +######################################################################## +# Build ITK Python wheel tarballs (build cache) on Windows. +# +# This is the Windows PowerShell equivalent of make_tarballs.sh. +# POSIX shell is not supported for this workflow on Windows. +# +# This script builds the ITK core cache only — it has no knowledge of +# external modules. Module-specific flags (--module-source-dir, +# --module-dependencies-root-dir, --itk-module-deps, --lib-paths) are +# intentionally absent; they belong only in the module wheel build script. +# +# Directory names are intentionally kept short to avoid Windows MAX_PATH +# issues during deep CMake/compiler builds. Everything lives under one +# root directory (C:\BDR) so no build artifacts are scattered at C:\: +# ITKPythonPackage -> C:\BDR\IPP (scripts clone) +# ITK source -> C:\BDR\ITK (ITK git checkout) +# build root -> C:\BDR (build_wheels.py root; cached build lands at C:\BDR\build\ITK-windows-...) +# +# This script MUST be run from the canonical location: +# C:\BDR\IPP\scripts\make_tarballs.ps1 +# +# Typical usage: +# > $env:ITK_GIT_TAG = "v6.0b02" +# > .\make_tarballs.ps1 +# +# Restrict to specific python versions by passing them as arguments: +# > .\make_tarballs.ps1 py311 +# +# ----------------------------------------------------------------------- +# Environment variables: +# +# `$env:ITK_GIT_TAG` +# ITK git tag to build from. Falls back to v6.0b02 with loud warnings +# if unset, matching the bash script behaviour. +# +######################################################################## +param ( + [Parameter(ValueFromRemainingArguments)] + [string[]]$pyenvs +) + +Set-StrictMode -Version Latest +$ErrorActionPreference = "Stop" + +# Resolve python environments +if (-not $pyenvs -or $pyenvs.Count -eq 0) { + $pyenvs = @("py310", "py311") +} +echo "Building for python environments: $($pyenvs -join ', ')" + +# Resolve ITK_GIT_TAG — loud warning if unset, matching bash behaviour +$DEFAULT_ITK_GIT_TAG = "v6.0b02" +if (-not $env:ITK_GIT_TAG) { + $warningLine = "===== WARNING: ITK_GIT_TAG not set, so defaulting to $DEFAULT_ITK_GIT_TAG" + echo "=============================================================================" + 1..29 | ForEach-Object { echo $warningLine } + echo "=============================================================================" + $env:ITK_GIT_TAG = $DEFAULT_ITK_GIT_TAG +} +$ITK_GIT_TAG = $env:ITK_GIT_TAG +echo "ITK_GIT_TAG : $ITK_GIT_TAG" + +# Compute paths from this script's location. +# Everything is contained under C:\BDR to keep all build artifacts in one +# place and avoid spreading directories across the drive root. +# +# C:\BDR\ <- $BDR (single root for all build content) +# C:\BDR\IPP\scripts\ <- $ScriptsDir (this file) +# C:\BDR\IPP\ <- $IPPDir (ITKPythonPackage clone) +# C:\BDR\ITK\ <- $ItkSourceDir (ITK git checkout) +# C:\BDR\ <- $BuildDirRoot (build root; cached build lands at C:\BDR\build\ITK-windows-...) +# C:\BDR\.pixi\ <- pixi home +$BDR = "C:\BDR" +$ScriptsDir = Split-Path -Parent $MyInvocation.MyCommand.Path +$IPPDir = Split-Path -Parent $ScriptsDir +$BuildScript = Join-Path $ScriptsDir "build_wheels.py" +$ItkSourceDir = Join-Path $BDR "ITK" +$BuildDirRoot = $BDR + +echo "BDR : $BDR" +echo "IPPDir : $IPPDir" +echo "ScriptsDir : $ScriptsDir" +echo "ItkSourceDir : $ItkSourceDir" +echo "BuildDirRoot : $BuildDirRoot" + +# Validate script is running from the expected canonical location +$ExpectedScriptsDir = Join-Path $BDR "IPP\scripts" +if ($ScriptsDir -ne $ExpectedScriptsDir) { + Write-Error @" +ERROR: GitHub CI requires a rigid directory structure. +Script found at : $ScriptsDir +Expected location: $ExpectedScriptsDir + + RUN: cd $BDR + RUN: git clone git@github.com:/ITKPythonPackage.git $BDR\IPP + FOR DEVELOPMENT: git checkout python_based_build_scripts + RUN: $ExpectedScriptsDir\make_windows_zip.ps1 +"@ + exit 1 +} + +if (-not (Test-Path -LiteralPath $BuildScript)) { + throw "build_wheels.py not found at: $BuildScript" +} + +# Create BDR if it doesn't exist +# (may require administrator credentials on a fresh machine) +if (-not (Test-Path -LiteralPath $BDR)) { + echo "Creating directory: $BDR" + New-Item -ItemType Directory -Path $BDR -Force | Out-Null +} + +# Install pixi if not already present. +# Python, Doxygen, and all build tools are provided by the pixi environment. +$env:PIXI_HOME = "$BDR\.pixi" +if (-not (Test-Path "$env:PIXI_HOME\bin\pixi.exe")) { + echo "Installing pixi..." + Invoke-WebRequest -Uri "https://pixi.sh/install.ps1" -OutFile "install-pixi.ps1" + powershell -ExecutionPolicy Bypass -File "install-pixi.ps1" +} +$env:Path = "$env:PIXI_HOME\bin;$env:Path" + +# Build each requested python environment. +# Push-Location/finally ensures we always restore the caller's directory. +Push-Location $IPPDir +try { + foreach ($pyenv in $pyenvs) { + # Normalise any of: py311 / py3.11 / cp311 / 3.11 -> py311 + $pySquashed = $pyenv -replace 'py|cp|\.', '' + $pyenv = "py$pySquashed" + $platformEnv = "windows-$pyenv" + + echo "" + echo "========================================================" + echo "Building cache for platform env: $platformEnv" + echo "========================================================" + + pixi run -e $platformEnv python $BuildScript ` + --platform-env $platformEnv ` + --build-itk-tarball-cache ` + --build-dir-root $BuildDirRoot ` + --itk-source-dir $ItkSourceDir ` + --itk-git-tag $ITK_GIT_TAG ` + --no-use-sudo ` + --no-use-ccache + + if ($LASTEXITCODE -ne 0) { + throw "build_wheels.py failed for $platformEnv (exit code $LASTEXITCODE)" + } + } +} +finally { + Pop-Location +} + +echo "" +echo "All tarball builds completed successfully." diff --git a/scripts/windows-build-tarball.ps1 b/scripts/windows-build-tarball.ps1 deleted file mode 100644 index dab4f09f..00000000 --- a/scripts/windows-build-tarball.ps1 +++ /dev/null @@ -1,8 +0,0 @@ -# This script creates a tarball of the ITK Python package build tree. It is -# downloaded by the external module build scripts and used to build their -# Python package on GitHub CI services. - -cd C:\P\ -Remove-Item IPP\dist\* -C:\7-Zip\7z.exe a -t7z -r 'C:\P\ITKPythonBuilds-windows.zip' -w 'C:\P\IPP' -# C:\7-Zip\7z.exe a -t7z -mx=9 -mfb=273 -ms -md=31 -myx=9 -mtm=- -mmt -mmtf -md=1536m -mmf=bt3 -mmc=10000 -mpb=0 -mlc=0 -r 'C:\P\ITKPythonBuilds-windows.zip' -w 'C:\P\IPP' From 2b289dad11d62867a725f3183dc979530496a103 Mon Sep 17 00:00:00 2001 From: Cavan Riley Date: Tue, 17 Mar 2026 15:35:57 -0500 Subject: [PATCH 05/27] ENH: Remove legacy shell scripts, add pre-commit hooks, drop Python 3.9 Removes unused and outdated shell scripts and legacy build utilities superseded by the new Python build system. Adds pre-commit hooks with linting applied across the codebase. Drops Python 3.9 support as it is EOL. Includes README and documentation updates for the new build workflow. --- .gitattributes | 2 + .github/ISSUE_TEMPLATE/bug_report.md | 37 + .github/ISSUE_TEMPLATE/config.yml | 8 + .github/ISSUE_TEMPLATE/feature_request.md | 23 + .github/pull_request_template.md | 30 + .github/workflows/pre-commit.yaml | 16 + .gitignore | 5 +- .pre-commit-config.yaml | 69 ++ .travis.yml | 15 - README.md | 302 ++++++-- docs/Build_ITK_Python_packages.rst | 288 ++++++-- docs/Prerequisites.rst | 2 + docs/Quick_start_guide.rst | 247 ------- pixi.lock | 846 ++++++++++++++++++++++ pixi.toml | 7 + scripts/lint-shell-scripts.sh | 20 - 16 files changed, 1536 insertions(+), 381 deletions(-) create mode 100644 .gitattributes create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md create mode 100644 .github/pull_request_template.md create mode 100644 .github/workflows/pre-commit.yaml delete mode 100644 .travis.yml delete mode 100644 docs/Quick_start_guide.rst delete mode 100755 scripts/lint-shell-scripts.sh diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..887a2c18 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# SCM syntax highlighting & preventing 3-way merges +pixi.lock merge=binary linguist-language=YAML linguist-generated=true diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 00000000..042fd93e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,37 @@ +--- +name: Bug report +about: Something is broken in the build or packaging pipeline +title: "fix: " +labels: bug +assignees: "" +--- + +## Environment + +- **OS / Platform**: +- **Python version**: +- **ITK version / branch**: +- **Script / entry point used**: + +## Steps to Reproduce + + +## Expected Behavior + + + +## Actual Behavior + + + +
+Log output + +``` +``` + +
+ +## Additional Context + + diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 00000000..07191d51 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: true +contact_links: + - name: ITK Discourse (questions & support) + url: https://discourse.itk.org + about: For build questions or general ITK support, please use the ITK Discourse forum. + - name: ITK Documentation + url: https://itkpythonpackage.readthedocs.io + about: Check the docs before filing an issue. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 00000000..f54cb07a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,23 @@ +--- +name: Feature request +about: Suggest a new capability or improvement to the build/packaging pipeline +title: "feat: " +labels: enhancement +assignees: "" +--- + +## Problem / Motivation + + + +## Proposed Solution + + + +## Alternatives Considered + + + +## Additional Context + + diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 00000000..fa1ada99 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,30 @@ +## Summary + + + +## Type of Change + +- [ ] Bug fix +- [ ] New feature / enhancement +- [ ] Refactor / cleanup +- [ ] Docs / CI only + +## Checklist + +- [ ] Pre-commit hooks pass locally (`pre-commit run --all-files`) +- [ ] Tested wheel build on affected platform(s) (Linux / macOS / Windows) +- [ ] Docs updated if behavior changed (`docs/`) +- [ ] Commit messages follow Conventional Commits (`feat:`, `fix:`, `chore:`, etc.) + +## Platform(s) Tested + + +- [ ] Linux x86_64 (manylinux) +- [ ] Linux aarch64 (manylinux) +- [ ] macOS x86_64 +- [ ] macOS arm64 +- [ ] Windows x86_64 + +## Related Issues + + diff --git a/.github/workflows/pre-commit.yaml b/.github/workflows/pre-commit.yaml new file mode 100644 index 00000000..f1356482 --- /dev/null +++ b/.github/workflows/pre-commit.yaml @@ -0,0 +1,16 @@ +name: pre-commit + +on: + pull_request: + push: + branches: [main] + +jobs: + pre-commit: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: "3.11" + - uses: pre-commit/action@v3.0.1 diff --git a/.gitignore b/.gitignore index cffba1ed..ae101831 100644 --- a/.gitignore +++ b/.gitignore @@ -43,7 +43,6 @@ lib lib64 MANIFEST oneTBB-prefix/ -pyproject.toml # Installer logs pip-log.txt @@ -73,3 +72,7 @@ docs/_build # IDE junk .idea/* *.swp +/itkVersion.py +# pixi environments +.pixi/* +!.pixi/config.toml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b15a4760..8e3166d1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,4 +1,73 @@ +# Pre-commit configuration for ITKPythonPackage +# Run `pre-commit install` to install git hooks locally +# Run `pre-commit run --all-files` to check all files +# Run `pre-commit autoupdate` to update hook versions + +# Exclude generated/vendored directories from all hooks +exclude: ^(\.pixi|build|pixi.lock|docs)/ + repos: + # General file hygiene + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v5.0.0 + hooks: + - id: trailing-whitespace + stages: [pre-commit] + - id: end-of-file-fixer + stages: [pre-commit] + - id: check-yaml + stages: [pre-commit] + - id: check-toml + stages: [pre-commit] + - id: check-merge-conflict + stages: [pre-commit] + - id: check-added-large-files + args: [--maxkb=500] + stages: [pre-commit] + # Enforce LF line endings everywhere except Windows PowerShell scripts + - id: mixed-line-ending + args: [--fix=lf] + exclude: \.ps1$ + stages: [pre-commit] + + # Python: formatting + - repo: https://github.com/psf/black + rev: 24.10.0 + hooks: + - id: black + stages: [pre-commit] + + # Python: linting + import sorting + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.8.6 + hooks: + - id: ruff + args: [--fix] + stages: [pre-commit] + + # Shell: linting + - repo: https://github.com/shellcheck-py/shellcheck-py + rev: v0.10.0.1 + hooks: + - id: shellcheck + stages: [pre-commit] + + # Shell: formatting + - repo: https://github.com/scop/pre-commit-shfmt + rev: v3.12.0-2 + hooks: + - id: shfmt + args: [-i, "2", -w] + stages: [pre-commit] + + # TOML: formatting + - repo: https://github.com/ComPWA/taplo-pre-commit + rev: v0.9.3 + hooks: + - id: taplo-format + stages: [pre-commit] + + # ITK commit message hooks (matching ITK/Utilities/Hooks/) - repo: local hooks: - id: local-prepare-commit-msg diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index e00ff622..00000000 --- a/.travis.yml +++ /dev/null @@ -1,15 +0,0 @@ -sudo: required - -services: - - docker - -cache: - directories: - - $HOME/docker - -before_install: - - sudo pip install -U scikit-ci-addons - - ci_addons docker load-pull-save r.j3ss.co/shellcheck - -script: - - scripts/lint-shell-scripts.sh diff --git a/README.md b/README.md index 052a849a..25e41f22 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ This project configures pyproject.toml files and manages environmental variables needed to build ITK Python binary wheels on MacOS, Linux, and Windows platforms. -Scripts are available for both [ITK infrastructure](https://github.com/insightSoftwareConsortium/ITK) and +Scripts are available for both [ITK infrastructure](https://github.com/insightSoftwareConsortium/ITK) and ITK external module Python packages. The Insight Toolkit (ITK) is an open-source, cross-platform system that provides developers @@ -12,86 +12,292 @@ or at the [ITK GitHub homepage](https://github.com/insightSoftwareConsortium/ITK ## Table of Contents -- [Using ITK Python Packages](#using-itk-python-packages) -- [Building with ITKPythonPackage](#building-with-itkpythonpackage) +- [Building Remote Modules with ITKPythonPackage](#building-remote-modules-with-itkpythonpackage) +- [Building ITK Python Wheels](#building-itk-python-wheels) - [Frequently Asked Questions](#frequently-asked-questions) - [Additional Information](#additional-information) -## Using ITK Python Packages (pre-built, or locally built) +## Building Remote Modules with ITKPythonPackage -ITKPythonPackage scripts can be used to produce [Python](https://www.python.org/) packages -for ITK and ITK external modules. The resulting packages can be -hosted on the [Python Package Index (PyPI)](https://pypi.org/) -for easy distribution. +ITK reusable workflows are available to build and package Python wheels as +part of Continuous Integration (CI) via Github Actions runners. +Those workflows can handle the overhead of fetching, configuring, and +running ITKPythonPackage build scripts for most ITK external modules. +See [ITKRemoteModuleBuildTestPackageAction](https://github.com/InsightSoftwareConsortium/ITKRemoteModuleBuildTestPackageAction) +for more information. + +> [!NOTE] +> When using`ITKRemoteModuleBuildTestPackageAction` in your remote module, you can specify the `itk-python-package-org` and `itk-python-package-tag` to build with. + +For special cases where ITK reusable workflows are not a good fit, +ITKPythonPackage scripts can be directly used to build Python wheels +to target Windows, Linux, and MacOS platforms. See +below or the [ITKPythonPackage ReadTheDocs](https://itkpythonpackage.readthedocs.io/en/latest/Build_ITK_Module_Python_packages.html) +documentation for more information on building wheels by hand. -### Installation of pre-built packages +## Building ITK Python Wheels -To install baseline ITK Python packages: +### Do You Actually Need to Build ITK? + +Most users do not need to build ITK from source. + +Pre-built ITK binaries are available as downloadable tarballs and the provided download-and-build shell scripts will fetch them automatically. + +You may only need to build ITK yourself if you: +- Have a local ITK with custom patches or bug fixes not yet in a release +- Need to build against a specific unreleased commit +- Are developing ITK core itself + +If none of the above apply to you, you may download an existing build of ITK from ITK's repository for [ITK Python Builds](https://github.com/InsightSoftwareConsortium/ITKPythonBuilds/releases). **Or**, use the download-and-build script seen in the [Building Remote Module Wheels](#building-remote-module-wheels) section below. + +For more control over your builds, skip to [The Build Process](#the-build-process) + +--- + +### Prerequisites + +- Python 3.10 or later +- Git +- Docker (for manylinux builds) +- [Pixi](https://pixi.sh) package manager + +**Install Pixi:** +```bash +# Linux or Mac +curl -fsSL https://pixi.sh/install.sh | bash + +# Windows +powershell -ExecutionPolicy Bypass -c "irm -useb https://pixi.sh/install.ps1 | iex" +``` -```sh -> pip install itk +**Clone the repo:** +```bash +git clone https://github.com/InsightSoftwareConsortium/ITKPythonPackage.git +cd ITKPythonPackage ``` -To install ITK external module packages: +--- -```sh -> pip install itk- +### Building Remote Module Wheels + +#### The Build Process + +The build process calls `build_wheels.py`, which runs up to 7 steps: + +1. Build SuperBuild support components +2. Build ITK C++ with Python wrapping +3. Build wheels for ITK C++ +4. Fix up wheels if needed +5. Import test +6. *(optional)* Build a remote module against the ITK build +7. *(optional)* Build an ITK tarball cache + +> [!NOTE] +> When using the download-and-build scripts, steps 2–3 are skipped because the pre-built cache covers them. + +You can invoke the `build_wheels.py` script directly for more control shown below + +Available pixi platform build environments: + +| Platform | Architectures | Python Versions | +|----------|---------------|-----------------| +| `linux` | x86_64, aarch64 | py310, py311 | +| `manylinux228` | x86_64, aarch64 | py310, py311 | +| `macosx` | x86_64, arm64 | py310, py311 | +| `windows` | x86_64 | py310, py311 | + + +```bash +# Building ITK Python Wheels on macOS for ITK v6.0b01 +pixi run python3 scripts/build_wheels.py \ + --platform-env macosx-py310 \ + --itk-git-tag v6.0b01 \ + --no-build-itk-tarball-cache ``` -### Using ITK in Python scripts +Key options: + +| Option | Description | Example | +|----------------------------------|----------------------------------------------|-------------------------------| +| `--platform-env` | Target platform and Python version | `macosx-py310` | +| `--build-dir-root` | Location for build artifacts | `/tmp/ITKPythonPackage-build` | +| `--itk-git-tag` | ITK version/branch/commit to use | `0ffcaed`, `main`, `v6.0b01` | +| `--itk-package-version` | PEP440 version string for wheels | `v6.0b01` | +| `--manylinux-version` | Manylinux standard version | `_2_28` | +| `--module-source-dir` | Path to remote module to build | `/path/to/module` | +| `--itk-module-deps` | Remote module dependencies | `Mod1@tag:Mod2@tag` | +| `--module-dependencies-root-dir` | Root directory for module dependencies | `./dependencies` | +| `--itk-source-dir` | Path to ITK source (use local development) | `/path/to/ITK` | +| `--cleanup` | Leave temporary build files after completion | (flag) | +| `--no-build-itk-tarball-cache` | Skip tarball generation (default) | (flag) | +| `--no-skip-itk-build` | Don't skip ITK build step (default | (flag) | +| `--no-skip-itk-wheel-build` | Don't skip the ITK wheel build step (default) | (flag) | + -```python - import itk - import sys +Run `pixi run python3 scripts/build_wheels.py --help` for the full option list. - input_filename = sys.argv[1] - output_filename = sys.argv[2] +> [!NOTE] +> Building ITK from source can take 1-2 hours on typical hardware. Once complete, use `--build-itk-tarball-cache` to save the result and avoid rebuilding. - image = itk.imread(input_filename) +To use the scripts that take care of the build for you, see this section: - median = itk.median_image_filter(image, radius=2) +
+Download-and-Build Remote Module Builds - itk.imwrite(median, output_filename) +This is the same process as used in the GitHub Actions CI/CD + +```bash +cd ITKRemoteModule ``` -### Other Resources for Using ITK in Python +#### Linux (manylinux) -See also the [ITK Python Quick Start -Guide](https://itkpythonpackage.readthedocs.io/en/master/Quick_start_guide.html). -There are also many [downloadable examples on the ITK examples website](https://examples.itk.org/search.html?q=Python). +Use `dockcross-manylinux-download-cache-and-build-module-wheels.sh`. This script: +1. Downloads the pre-built ITK binary tarball for your platform +2. Extracts it to a local build directory +3. Calls `dockcross-manylinux-build-module-wheels.sh` to build the module wheels inside a manylinux Docker container -For more information on ITK's Python wrapping, [an introduction is -provided in the ITK Software -Guide](https://itk.org/ITKSoftwareGuide/html/Book1/ITKSoftwareGuide-Book1ch3.html#x32-420003.7). +Run from your ITK external module root: +```bash +bash dockcross-manylinux-download-cache-and-build-module-wheels.sh cp310 +``` -## Building with ITKPythonPackage +> [!NOTE] +> Omit the Python version argument (e.g. `cp310`) to build for all default versions (cp310 and cp311). -ITK reusable workflows are available to build and package Python wheels as -part of Continuous Integration (CI) via Github Actions runners. -Those workflows can handle the overhead of fetching, configuring, and -running ITKPythonPackage build scripts for most ITK external modules. -See [ITKRemoteModuleBuildTestPackageAction](https://github.com/InsightSoftwareConsortium/ITKRemoteModuleBuildTestPackageAction) -for more information. +#### macOS -For special cases where ITK reusable workflows are not a good fit, -ITKPythonPackage scripts can be directly used to build Python wheels -to target Windows, Linux, and MacOS platforms. See -[ITKPythonPackage ReadTheDocs](https://itkpythonpackage.readthedocs.io/en/master/Build_ITK_Module_Python_packages.html) -documentation for more information on building wheels by hand. +Use `macpython-download-cache-and-build-module-wheels.sh`. This script: +1. Installs required tools (aria2, zstd, gnu-tar) via Pixi if not present +2. Downloads and extracts the macOS ITK binary tarball +3. Builds your module wheels for each requested Python version + +Run from your module root: +```bash +bash macpython-download-cache-and-build-module-wheels.sh 3.10 +``` + +#### Windows + +Use `windows-download-cache-and-build-module-wheels.ps1`. This script: +1. Installs required tools (git, aria2) via Pixi if not present +2. Downloads and extracts the Windows ITK binary zip file +3. Builds your module wheels for each requested Python version + +Run from your module root: +```powershell +.\windows-download-cache-and-build-module-wheels.ps1 3.11 +``` + + +#### Output + +Finished wheels are placed in `/dist/`. + +
+ + +To see how to build wheels for your version of ITK see this section: + +
+Building ITK from Source + +If you have a local ITK with custom patches, a bug fix not yet released, or you're developing ITK core itself. Build as follows + +Pass `--itk-source-dir` pointing to your local ITK clone. `build_wheels.py` will build ITK from that source instead of re-cloning. + +#### manylinux — building ITK from source + +Use `dockcross-manylinux-build-wheels.sh` directly (skips the download step): + +```bash +ITK_SOURCE_DIR=/path/to/your/ITK \ +bash scripts/dockcross-manylinux-build-wheels.sh cp310 +``` + +Key environment variables: + +| Variable | Default | Description | +|----------|-----------------------------------------|-------------| +| `ITK_GIT_TAG` | `main` | ITK branch/tag/commit to build | +| `ITK_SOURCE_DIR` | `/ITKPythonPackage-build/ITK` | Path to local ITK source (skips git clone) | +| `MANYLINUX_VERSION` | `_2_28` | Manylinux standard to target | +| `IMAGE_TAG` | `20250913-6ea98ba` | Dockcross image tag | +#### Linux/macOS/Windows — building ITK from source + +Use `build_wheels.py` directly with `--itk-source-dir`: + +```bash +# Building on macOS with a specific git tag +pixi run python3 scripts/build_wheels.py \ + --platform-env macosx-py310 \ + --itk-source-dir /path/to/your/ITK \ + --itk-git-tag my-bugfix-branch \ + --no-build-itk-tarball-cache \ + --build-dir-root /tmp/itk-build +``` + +Add `--build-itk-tarball-cache` if you want to save the result as a reusable tarball. + +
+ +To see how to build ITK Python Build Caches, see this section: + +
+Building ITK Python Caches + +#### GitHub Compatible Caches + +To build the caches compatible with GitHub Actions CI and the ITKPythonBuilds repository. You can run: + +On Linux and macOS systems +```bash +bash scripts/make_tarballs.sh # py310 (optionally add specific version of Python) +``` + +On Windows systems +```powershell +.\scripts\make_windows_zip.ps1 # py310 (optionally add specific version of Python) +``` + +> [!IMPORTANT] +> Build caches embed absolute paths. If you extract a tarball to a different path than it was built with, CMake will fail. Standard build paths for CI/CD are: +> - manylinux (Docker): `/work/ITKPythonPackage-build` +> - macOS: `/Users/svc-dashboard/D/P/ITKPythonPackage-build` +> - Windows: `C:\BDR` +> +> This script ensures you are building with the correct conventions + +#### Local Caches + +To build caches for local use, you can run the `build_wheels.py` script with the `--build-itk-tarball-cache` + +
+ + +--- ## Frequently Asked Questions ### What target platforms and architectures are supported? ITKPythonPackage currently supports building wheels for the following platforms and architectures: - - Windows 10 x86_64 platforms - - Windows 11 x86_64 platforms - - MacOS 15.0+ arm64 platforms - - Linux glibc 2.17+ (E.g. Ubuntu 18.04+) x86_64 platforms - - Linux glibc 2.28+ (E.g. Ubuntu 20.04+) aarch64 (ARMv8) platforms + +- Windows 10/11 x86_64 platforms +- macOS arm64 (Apple Silicon) +- macOS x86_64 (Intel) +- Linux glibc 2.17+ (e.g. Ubuntu 20.04+) x86_64 +- Linux glibc 2.28+ (e.g. Ubuntu 20.04+) aarch64 (ARMv8) Python 3.10+ is required. +[ITKRemoteModuleBuildTestPackageAction](https://github.com/InsightSoftwareConsortium/ITKRemoteModuleBuildTestPackageAction) +CI workflows support Python 3.10–3.11 on GitHub-hosted runners for: +- Ubuntu x86_64 +- Ubuntu aarch64 (ARM) +- macOS arm64 (Apple Silicon) +- Windows x86_64 + ### What should I do if my target platform/architecture does not appear on the list above? Please open an issue in the [ITKPythonPackage issue tracker](https://github.com/InsightSoftwareConsortium/ITKPythonPackage/issues) diff --git a/docs/Build_ITK_Python_packages.rst b/docs/Build_ITK_Python_packages.rst index bb0d647c..f3856317 100644 --- a/docs/Build_ITK_Python_packages.rst +++ b/docs/Build_ITK_Python_packages.rst @@ -18,49 +18,121 @@ Automated platform scripts Steps required to build wheels on Linux, macOS and Windows have been automated. The following sections outline how to use the associated scripts. + +Setup Instructions +================== + +1. Clone the ITKPythonPackage repository:: + + $ git clone https://github.com/InsightSoftwareConsortium/ITKPythonPackage.git + $ cd ITKPythonPackage + +.. note:: + You can replace ``InsightSoftwareConsortium`` with a different organization if using a fork. + +2. Configure the build environment (optional) + +The following environment variables can be set to customize the build: + +**MODULE_SRC_DIRECTORY** + Directory where the ITK remote module is located. Default: Current Directory + +**DASHBOARD_BUILD_DIRECTORY** + Directory where build artifacts will be created. Default: /Users/svc-dashboard/D/P + +**ITK_GIT_TAG** + ITK version to build (branch name or commit hash). Default: ``main`` + +**ITK_PACKAGE_VERSION** + ITK version tag to build against. Essentially the same as ITK_GIT_TAG for backwards compatability + +**TARGET_ARCH** + Target architecture. Default: ``x64`` (Linux), auto-detected (macOS) + +**ITKPYTHONPACKAGE_ORG** + GitHub organization hosting ITKPythonPackage. Default: ``InsightSoftwareConsortium`` + +**ITKPYTHONPACKAGE_TAG** + Optional: specific tag/branch of build scripts to use. Default: ``main`` + +**MANYLINUX_VERSION** (manylinux only) + Manylinux standard version. Default: ``_2_28`` + +**IMAGE_TAG** (Linux only) + Docker image tag for manylinux builds. Default: ``20250913-6ea98ba`` + + +For example:: + + $ export ITK_GIT_TAG=v5.4.0 + $ export MANYLINUX_VERSION=_2_28 + + +Building Wheels +=============== + +All build processes download pre-built ITK artifacts and builds wheels +using from the `ITKPythonBuilds repository `_ distributions. + Linux ----- -On any linux distribution with docker and bash installed, running the script dockcross-manylinux-build-wheels.sh will create 64-bit wheels for python 3.9+ in the dist directory. +You can download the Python builds for your specific system and architecture using the following script:: -For example:: + $ ./scripts/dockcross-manylinux-download-cache.sh + +On any linux distribution with docker and bash installed, running the script `dockcross-manylinux-build-wheels.sh` will create 64-bit wheels for python 3.9+ in the dist directory.:: + + $ ./scripts/dockcross-manylinux-build-wheels.sh + +Build for specific Python version(s):: + + $ ./scripts/dockcross-manylinux-build-wheels.sh cp310 + $ ./scripts/dockcross-manylinux-build-wheels.sh cp39 cp310 cp311 - $ git clone https://github.com/InsightSoftwareConsortium/ITKPythonPackage.git - [...] +.. note:: + Python versions can be specified as ``cp39``, ``cp310``, ``cp311``, or + ``py39``, ``py310``, ``py311`` - both formats are supported. - $ ./scripts/dockcross-manylinux-build-wheels.sh - [...] +After the build completes, wheels will be located in the `DASHBOARD_BUILD_DIRECTORY` directory, for example:: - $ ls -1 dist/ - itk-4.11.0.dev20170218-cp27-cp27m-manylinux2014_x86_64.whl - itk-4.11.0.dev20170218-cp27-cp27mu-manylinux2014_x86_64.whl - itk-4.11.0.dev20170218-cp34-cp34m-manylinux2014_x86_64.whl - itk-4.11.0.dev20170218-cp35-cp35m-manylinux2014_x86_64.whl - itk-4.11.0.dev20170218-cp36-cp36m-manylinux2014_x86_64.whl + $ ls -1 ${DASHBOARD_BUILD_DIRECTORY}/ITKPythonPackage-build/dist/ + itk-6.0.0-cp39-cp39-manylinux_2_28_x86_64.whl + itk-6.0.0-cp310-cp310-manylinux_2_28_x86_64.whl + itk-6.0.0-cp311-cp311-manylinux_2_28_x86_64.whl macOS ----- -First, install the Python.org macOS Python distributions. This step requires sudo:: +Build all default Python versions:: - ./scripts/macpython-install-python.sh + $ ./scripts/macpython-download-cache-and-build-module-wheels.sh +Build for specific Python version(s):: -Then, build the wheels:: + $ ./scripts/macpython-download-cache-and-build-module-wheels.sh py310 + $ ./scripts/macpython-download-cache-and-build-module-wheels.sh py39 py310 py311 - $ ./scripts/macpython-build-wheels.sh - [...] - $ ls -1 dist/ - itk-4.11.0.dev20170213-cp27-cp27m-macosx_10_6_x86_64.whl - itk-4.11.0.dev20170213-cp34-cp34m-macosx_10_6_x86_64.whl - itk-4.11.0.dev20170213-cp35-cp35m-macosx_10_6_x86_64.whl - itk-4.11.0.dev20170213-cp36-cp36m-macosx_10_6_x86_64.whl +After the build completes, similarly, builds can be found in:: + + $ ls -1 ${DASHBOARD_BUILD_DIRECTORY}/ITKPythonPackage-build/dist/ + itk-6.0.0-cp39-cp39-macosx_10_9_x86_64.whl + itk-6.0.0-cp310-cp310-macosx_10_9_x86_64.whl + itk-6.0.0-cp311-cp311-macosx_10_9_x86_64.whl Windows ------- -First, install Microsoft Visual Studio 2015, Git, and CMake, which should be added to the system PATH environmental variable. +.. important:: + We need to work in a short directory to avoid path length limitations on + Windows. The examples below use ``C:\IPP`` for this reason. + +.. important:: + Disable antivirus checking on the build directory (e.g., ``C:\IPP``). + The build system creates and deletes many files quickly, which can conflict + with antivirus software and result in "Access Denied" errors. Windows + Defender should be configured to exclude this directory. Open a PowerShell terminal as Administrator, and install Python:: @@ -68,31 +140,147 @@ Open a PowerShell terminal as Administrator, and install Python:: PS C:\> $pythonArch = "64" PS C:\> iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/scikit-build/scikit-ci-addons/master/windows/install-python.ps1')) -In a PowerShell prompt:: +In a PowerShell prompt, clone into a short path:: + + PS C:\> cd C:\ + PS C:\> git clone https://github.com/InsightSoftwareConsortium/ITKPythonPackage.git IPP + PS C:\> cd IPP + +After the build completes:: + + PS C:\IPP> ls dist + Directory: C:\IPP\dist + + Mode LastWriteTime Length Name + ---- ------------- ------ ---- + -a---- 1/1/2026 11:14 PM 63274441 itk-6.0.0-cp39-cp39-win_amd64.whl + -a---- 1/1/2026 11:45 PM 63257220 itk-6.0.0-cp310-cp310-win_amd64.whl + + +Testing and Deployment +====================== + +Testing Wheels Locally +---------------------- + +Install and test a built wheel:: + + $ pip install dist/itk-6.0.0-cp310-cp310-macosx_10_9_x86_64.whl + $ python -c "import itk; print(dir(itk))" + +Publishing Wheels +----------------- + +Once you've built and tested the wheels, you can: + +* Upload to PyPI using ``twine``:: + + $ pip install twine + $ twine upload dist/*.whl + +* Upload to a private package index +* Distribute directly to users + + +Troubleshooting +=============== + +Path Length Issues (Windows) +----------------------------- + +If you encounter path length errors: + +* Use a shorter build directory (e.g., ``C:\IPP`` instead of ``C:\Users\YourName\Documents\Projects\ITKPythonPackage``) +* Enable long path support in Windows 10/11:: + + PS C:\> New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem" -Name "LongPathsEnabled" -Value 1 -PropertyType DWORD -Force + +Antivirus Conflicts (Windows) +------------------------------ + +Configure Windows Defender to exclude the build directory: + +1. Open Windows Security +2. Go to "Virus & threat protection" +3. Under "Virus & threat protection settings", click "Manage settings" +4. Scroll to "Exclusions" and click "Add or remove exclusions" +5. Add the build directory (e.g., ``C:\IPP``) + +.. Linux +.. ----- + +.. On any linux distribution with docker and bash installed, running the script dockcross-manylinux-build-wheels.sh will create 64-bit wheels for python 3.9+ in the dist directory. + +.. For example:: + +.. $ git clone https://github.com/InsightSoftwareConsortium/ITKPythonPackage.git +.. [...] +.. +.. $ ./scripts/dockcross-manylinux-build-wheels.sh +.. [...] + +.. $ ls -1 dist/ +.. itk-6.0.1.dev20251126-cp39-cp39m-manylinux2014_x86_64.whl +.. itk-6.0.1.dev20251126-cp39-cp39mu-manylinux2014_x86_64.whl +.. itk-6.0.1.dev20251126-cp39-cp39m-manylinux2014_x86_64.whl +.. itk-6.0.1.dev20251126-cp39-cp39m-manylinux2014_x86_64.whl +.. itk-6.0.1.dev20251126-cp39-cp39m-manylinux2014_x86_64.whl + +.. macOS +.. ----- + +.. First, install the Python.org macOS Python distributions. This step requires sudo:: + +.. ./scripts/macpython-install-python.sh + + +.. Then, build the wheels:: + +.. $ ./scripts/macpython-build-wheels.sh +.. [...] +.. +.. $ ls -1 dist/ +.. itk-6.0.1.dev20251126-cp39-cp39m-macosx_10_6_x86_64.whl +.. itk-6.0.1.dev20251126-cp39-cp39m-macosx_10_6_x86_64.whl +.. itk-6.0.1.dev20251126-cp39-cp39m-macosx_10_6_x86_64.whl +.. itk-6.0.1.dev20251126-cp39-cp39m-macosx_10_6_x86_64.whl + +.. Windows +.. ------- + +.. First, install Microsoft Visual Studio 2015, Git, and CMake, which should be added to the system PATH environmental variable. + +.. Open a PowerShell terminal as Administrator, and install Python:: + +.. PS C:\> Set-ExecutionPolicy Unrestricted +.. PS C:\> $pythonArch = "64" +.. PS C:\> iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/scikit-build/scikit-ci-addons/master/windows/install-python.ps1')) + +.. In a PowerShell prompt:: - PS C:\Windows> cd C:\ - PS C:\> git clone https://github.com/InsightSoftwareConsortium/ITKPythonPackage.git IPP - PS C:\> cd IPP - PS C:\IPP> .\scripts\windows-build-wheels.ps1 - [...] +.. PS C:\Windows> cd C:\ +.. PS C:\> git clone https://github.com/InsightSoftwareConsortium/ITKPythonPackage.git IPP +.. PS C:\> cd IPP +.. PS C:\IPP> .\scripts\windows-build-wheels.ps1 +.. [...] - PS C:\IPP> ls dist - Directory: C:\IPP\dist +.. PS C:\IPP> ls dist +.. Directory: C:\IPP\dist - Mode LastWriteTime Length Name - ---- ------------- ------ ---- - -a---- 4/9/2017 11:14 PM 63274441 itk-4.11.0.dev20170407-cp35-cp35m-win_amd64.whl - -a---- 4/10/2017 2:08 AM 63257220 itk-4.11.0.dev20170407-cp36-cp36m-win_amd64.whl +.. Mode LastWriteTime Length Name +.. ---- ------------- ------ ---- +.. -a---- 4/9/2017 11:14 PM 63274441 itk-6.0.1.dev20251126-cp39-cp39m-win_amd64.whl +.. -a---- 4/10/2017 2:08 AM 63257220 itk-6.0.1.dev20251126-cp39-cp39m-win_amd64.whl -We need to work in a short directory to avoid path length limitations on -Windows, so the repository is cloned into C:\IPP. +.. We need to work in a short directory to avoid path length limitations on +.. Windows, so the repository is cloned into C:\IPP. -Also, it is very important to disable antivirus checking on the C:\IPP -directory. Otherwise, the build system conflicts with the antivirus when many -files are created and deleted quickly, which can result in Access Denied -errors. Windows 10 ships with an antivirus application, Windows Defender, that -is enabled by default. +.. Also, it is very important to disable antivirus checking on the C:\IPP +.. directory. Otherwise, the build system conflicts with the antivirus when many +.. files are created and deleted quickly, which can result in Access Denied +.. errors. Windows 10 ships with an antivirus application, Windows Defender, that +.. is enabled by default. .. The below instructions are outdated and need to be re-written .. sdist @@ -100,15 +288,15 @@ is enabled by default. .. .. To create source distributions, sdist's, that will be used by pip to compile a wheel for installation if a binary wheel is not available for the current Python version or platform:: .. -.. $ python setup.py sdist --formats=gztar,zip +.. $ python -m build --sdist .. [...] .. .. $ ls -1 dist/ -.. itk-4.11.0.dev20170216.tar.gz -.. itk-4.11.0.dev20170216.zip +.. itk-6.0.1.dev20251126.tar.gz +.. itk-6.0.1.dev20251126.zip .. -.. Manual builds -.. ============= +.. Manual builds (not recommended) +.. =============================== .. .. Building ITK Python wheels .. -------------------------- @@ -117,8 +305,8 @@ is enabled by default. .. .. python3 -m venv build-itk .. ./build-itk/bin/pip install --upgrade pip -.. ./build-itk/bin/pip install -r requirements-dev.txt numpy -.. ./build-itk/bin/python setup.py bdist_wheel +.. ./build-itk/bin/pip install -r requirements-dev.txt +.. ./build-itk/bin/python -m build .. .. Build a wheel for a custom version of ITK .. ----------------------------------------- @@ -126,7 +314,7 @@ is enabled by default. .. To build a wheel for a custom version of ITK, point to your ITK git repository .. with the `ITK_SOURCE_DIR` CMake variable:: .. -.. ./build-itk/bin/python setup.py bdist_wheel -- \ +.. ./build-itk/bin/python -m build --wheel -- \ .. -DITK_SOURCE_DIR:PATH=/path/to/ITKPythonPackage-core-build/ITK .. .. Other CMake variables can also be passed with `-D` after the double dash. diff --git a/docs/Prerequisites.rst b/docs/Prerequisites.rst index 83b0f1a7..34d367d8 100644 --- a/docs/Prerequisites.rst +++ b/docs/Prerequisites.rst @@ -4,6 +4,8 @@ Prerequisites Building wheels requires: - CMake +- zstd - Git - C++ Compiler - Platform specific requirements are summarized in scikit-build documentation. - Python +- Docker diff --git a/docs/Quick_start_guide.rst b/docs/Quick_start_guide.rst deleted file mode 100644 index f1ae8205..00000000 --- a/docs/Quick_start_guide.rst +++ /dev/null @@ -1,247 +0,0 @@ -=========================== -Quick start guide -=========================== - -.. _quick-start: - -Installation ------------- - -To install the ITK Python package:: - - $ pip install itk - - -Usage ------ - -Basic example -.............. - -Here is a simple python script that reads an image, applies a median image filter (radius of 2 pixels), and writes the resulting image in a file. - -.. literalinclude:: code/ReadMedianWrite.py - -ITK and NumPy -............. - -A common use case for using ITK in Python is to mingle NumPy and ITK operations on raster data. ITK provides a large number of I/O image formats and several sophisticated image processing algorithms not available in any other packages. The ability to intersperse that with the SciPy ecosystem provides a great tool for rapid prototyping. - -The following script shows how to integrate NumPy and `itk.Image`: - -.. literalinclude:: code/MixingITKAndNumPy.py - :lines: 16-59 - -NumPy and `itk.Mesh`: - -.. literalinclude:: code/MixingITKAndNumPy.py - :lines: 62-76 - -NumPy and `itk.Transform`: - -.. literalinclude:: code/MixingITKAndNumPy.py - :lines: 96-115 - -NumPy and `itk.Matrix`, VNL vectors, and VNL matrices: - -.. literalinclude:: code/MixingITKAndNumPy.py - :lines: 118- - -ITK and Xarray -.............. - -An `itk.Image` can be converted to and from an `xarray.DataArray -`_ while -preserving metadata:: - - da = itk.xarray_from_image(image) - - image = itk.image_from_xarray(da) - -ITK and VTK -............ - -An `itk.Image` can be converted to and from a `vtk.vtkImageData -`_ while -preserving metadata:: - - vtk_image = itk.vtk_image_from_image(image) - - image = itk.image_from_vtk_image(vtk_image) - -ITK and napari -.............. - -An `itk.Image` can be converted to and from a `napari.layers.Image -`_ while -preserving metadata with the `itk-napari-conversion package -`_. - -ITK Python types -................ - -+---------------------+--------------------+--------------------+ -| C++ type | Python type | NumPy dtype | -+=====================+====================+====================+ -| float | itk.F | np.float32 | -+---------------------+--------------------+--------------------+ -| double | itk.D | np.float64 | -+---------------------+--------------------+--------------------+ -| unsigned char | itk.UC | np.uint8 | -+---------------------+--------------------+--------------------+ -| std::complex | itk.complex[itk.F] | np.complex64 | -+---------------------+--------------------+--------------------+ - -This list is not exhaustive and is only presented to illustrate the type names. The complete list of types can be found in the `ITK Software Guide `_. - -Types can also be obtained from their name in the C programming language: - -.. literalinclude:: code/CompareITKTypes.py - :lines: 5 - -To cast the pixel type of an image, use `.astype`: - -.. literalinclude:: code/Cast.py - :lines: 10-18 - -Metadata dictionary -................... - -An `itk.Image` has a metadata dict of `key: value` pairs. - - -The metadata dictionary can be retrieved with:: - - meta_dict = dict(image) - -For example:: - - In [3]: dict(image) - Out[3]: - {'0008|0005': 'ISO IR 100', - '0008|0008': 'ORIGINAL\\PRIMARY\\AXIAL', - '0008|0016': '1.2.840.10008.5.1.4.1.1.2', - '0008|0018': '1.3.12.2.1107.5.8.99.484849.834848.79844848.2001082217554549', - '0008|0020': '20010822', - -Individual dictionary items can be accessed or assigned:: - - print(image['0008|0008']) - - image['origin'] = [4.0, 2.0, 2.0] - -In the Python dictionary interface to image metadata, keys for the spatial -metadata, the *'origin'*, *'spacing'*, and *'direction'*, are reversed in -order from `image.GetOrigin()`, `image.GetSpacing()`, `image.GetDirection()` -to be consistent with the `NumPy array index order -`_ -resulting from pixel buffer array views on the image. - -Access pixel data with NumPy indexing -..................................... - -Array views of an `itk.Image` provide a way to set and get pixel values with NumPy indexing syntax, e.g.:: - - In [6]: image[0,:2,4] = [5,5] - - In [7]: image[0,:4,4:6] - Out[7]: - NDArrayITKBase([[ 5, -997], - [ 5, -1003], - [ -993, -999], - [ -996, -994]], dtype=int16) - -Input/Output (IO) -................. - -Convenient functions are provided read and write from ITK's many supported -file formats:: - - image = itk.imread('image.tif') - - # Read in with a specific pixel type. - image = itk.imread('image.tif', itk.F) - - # Read in an image series. - # Pass a sorted list of files. - image = itk.imread(['image1.png', 'image2.png', 'image3.png']) - - # Read in a volume from a DICOM series. - # Pass a directory. - # Only a single series, sorted spatially, will be returned. - image = itk.imread('/a/dicom/directory/') - - # Write an image. - itk.imwrite(image, 'image.tif') - - - # Read a mesh. - mesh = itk.meshread('mesh.vtk') - - # Write a mesh. - itk.meshwrite(mesh, 'mesh.vtk') - - - # Read a spatial transform. - transform = itk.transformread('transform.h5') - - # Write a spatial transform. - itk.transformwrite(transform, 'transform.h5') - -Image filters and Image-like inputs and outputs -............................................... - -All `itk` functional image filters operate on an `itk.Image` but also: - -- `xarray.DataArray `_ * -- `numpy.ndarray `_ -- `dask.array.Array `_ - -\* Preserves image metadata - -Filter parameters -................. - -ITK filter parameters can be specified in the following ways: - -.. literalinclude:: code/FilterParameters.py - :lines: 10- - -Filter types -............ - -In `itk`, filters are optimized at compile time for each image pixel type and -image dimension. There are two ways to instantiate these filters with the `itk` -Python wrapping: - -- *Implicit (recommended)*: Type information is automatically detected from the data. Typed filter objects and images are implicitly created. - -.. literalinclude:: code/ImplicitInstantiation.py - :lines: 8- - -- *Explicit*: This can be useful if an appropriate type cannot be determined implicitly or when a different filter type than the default is desired. - -To specify the type of the filter, use the `ttype` keyword argument. Explicit instantiation of a median image filter: - -.. literalinclude:: code/ExplicitInstantiation.py - :lines: 8- - -Instantiate an ITK object -......................... - -There are two types of ITK objects. Most ITK objects, such as images, filters, or adapters, are instantiated the following way: - -.. literalinclude:: code/InstantiateITKObjects.py - :lines: 6-8 - -Some objects, like a Matrix, Vector, or RGBPixel, do not require the attribute `.New()` to be added to instantiate them: - -.. literalinclude:: code/InstantiateITKObjects.py - :lines: 11 - -In case of doubt, look at the attributes of the object you are trying to instantiate. - -Examples --------- - -Examples can be found in the `ITKSphinxExamples project `_. diff --git a/pixi.lock b/pixi.lock index 94039c9e..995d524a 100644 --- a/pixi.lock +++ b/pixi.lock @@ -17,20 +17,25 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.2.25-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-2.0.0-py314h4a8dc5f_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cfgv-3.5.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.5-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/conda-26.1.1-py314hdafbbf9_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/conda-libmamba-solver-25.11.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-handling-2.4.0-pyh7900ff3_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-streaming-0.12.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/cpp-expected-1.3.1-h171cf75_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/distro-1.9.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.25.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/fmt-12.1.0-hff5e90c_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/frozendict-2.4.7-py314h5bd0f2a_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.2-h33c6efd_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/identify-2.6.18-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpatch-1.33-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpointer-3.0.0-pyhcf101f3_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda @@ -66,17 +71,21 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/msgpack-python-1.1.2-py314h9891dd4_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nlohmann_json-abi-3.12.0-h0f90c79_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nodeenv-1.10.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.1-h35e630c_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pixi-pycharm-0.0.10-unix_hf108a03_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.4-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pre-commit-4.5.1-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pybind11-abi-11-hc364b38_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pycosat-0.6.6-py314h5bd0f2a_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.14.3-h32b2ec7_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-discovery-1.2.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py314h67df5f8_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/reproc-14.2.5.post0-hb9d3cd8_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/reproc-cpp-14.2.5.post0-h5888daf_0.conda @@ -90,9 +99,14 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/truststore-0.10.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ukkonen-1.1.0-py314h9891dd4_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-21.2.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h280c20c_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-cpp-0.8.0-h3f2d84a_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zstandard-0.25.0-py314h0f05182_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda linux-aarch64: @@ -106,20 +120,25 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.2.25-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cffi-2.0.0-py314h0bd77cf_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cfgv-3.5.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.5-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/conda-26.1.1-py314h28a4750_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/conda-libmamba-solver-25.11.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-handling-2.4.0-pyh7900ff3_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-streaming-0.12.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cpp-expected-1.3.1-hdc560ac_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/distro-1.9.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.25.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/fmt-12.1.0-h20c602a_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/frozendict-2.4.7-py314h51f160d_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/icu-78.2-hcab7f73_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/identify-2.6.18-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpatch-1.33-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpointer-3.0.0-pyhcf101f3_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/keyutils-1.6.3-h86ecc28_0.conda @@ -155,17 +174,21 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/msgpack-python-1.1.2-py314hd7d8586_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.5-ha32ae93_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nlohmann_json-abi-3.12.0-h0f90c79_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nodeenv-1.10.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.6.1-h546c87b_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pixi-pycharm-0.0.10-unix_hf108a03_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.4-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pre-commit-4.5.1-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pybind11-abi-11-hc364b38_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pycosat-0.6.6-py314h51f160d_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.14.3-hb06a95a_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-discovery-1.2.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pyyaml-6.0.3-py314h807365f_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/readline-8.3-hb682ff5_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/reproc-14.2.5.post0-h86ecc28_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/reproc-cpp-14.2.5.post0-h5ad3122_0.conda @@ -179,9 +202,14 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tk-8.6.13-noxft_h0dc03b3_103.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/truststore-0.10.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ukkonen-1.1.0-py314hd7d8586_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-21.2.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/yaml-0.2.5-h80f16a2_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/yaml-cpp-0.8.0-h5ad3122_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstandard-0.25.0-py314h2e8dab5_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.7-h85ac4a6_6.conda osx-64: @@ -194,20 +222,25 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.2.25-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/cffi-2.0.0-py314h8ca4d5a_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cfgv-3.5.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.5-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/conda-26.1.1-py314hee6578b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/conda-libmamba-solver-25.11.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-handling-2.4.0-pyh7900ff3_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-streaming-0.12.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/cpp-expected-1.3.1-h0ba0a54_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/distro-1.9.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.25.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/fmt-12.1.0-hda137b5_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/frozendict-2.4.7-py314h6482030_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/icu-78.2-h14c5de8_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/identify-2.6.18-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpatch-1.33-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpointer-3.0.0-pyhcf101f3_3.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/krb5-1.22.2-h207b36a_0.conda @@ -237,17 +270,21 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/msgpack-python-1.1.2-py314h00ed6fe_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.5-h0622a9a_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nlohmann_json-abi-3.12.0-h0f90c79_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nodeenv-1.10.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/openssl-3.6.1-hb6871ef_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pixi-pycharm-0.0.10-unix_hf108a03_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.4-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pre-commit-4.5.1-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pybind11-abi-11-hc364b38_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/pycosat-0.6.6-py314h03d016b_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.14.3-h4f44bb5_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-discovery-1.2.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/pyyaml-6.0.3-py314h10d0514_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/readline-8.3-h68b038d_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/reproc-14.2.5.post0-h6e16a3a_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/reproc-cpp-14.2.5.post0-h240833e_0.conda @@ -261,9 +298,14 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-h7142dee_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/truststore-0.10.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ukkonen-1.1.0-py314h473ef84_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-21.2.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/yaml-0.2.5-h4132b18_3.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/yaml-cpp-0.8.0-h92383a6_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/zstandard-0.25.0-py314hd1e8ddb_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.7-h3eecb57_6.conda osx-arm64: @@ -276,20 +318,25 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.2.25-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cffi-2.0.0-py314h44086f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cfgv-3.5.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.5-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/conda-26.1.1-py314h4dc9dd8_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/conda-libmamba-solver-25.11.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-handling-2.4.0-pyh7900ff3_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-streaming-0.12.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cpp-expected-1.3.1-h4f10f1e_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/distro-1.9.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.25.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/fmt-12.1.0-h403dcb5_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/frozendict-2.4.7-py314h0612a62_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.2-hef89b57_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/identify-2.6.18-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpatch-1.33-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpointer-3.0.0-pyhcf101f3_3.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.22.2-h385eeb1_0.conda @@ -319,17 +366,21 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/msgpack-python-1.1.2-py314h784bc60_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.5-h5e97a16_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nlohmann_json-abi-3.12.0-h0f90c79_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nodeenv-1.10.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.1-hd24854e_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pixi-pycharm-0.0.10-unix_hf108a03_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.4-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pre-commit-4.5.1-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pybind11-abi-11-hc364b38_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pycosat-0.6.6-py314hb84d1df_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.14.3-h4c637c5_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-discovery-1.2.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyyaml-6.0.3-py314h6e9b3f0_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/reproc-14.2.5.post0-h5505292_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/reproc-cpp-14.2.5.post0-h286801f_0.conda @@ -343,9 +394,14 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h010d191_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/truststore-0.10.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ukkonen-1.1.0-py314h6cfcd04_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-21.2.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/yaml-0.2.5-h925e9cb_3.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/yaml-cpp-0.8.0-ha1acc90_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstandard-0.25.0-py314h9d33bd4_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda win-64: @@ -357,6 +413,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-h4c7d964_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.2.25-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/cffi-2.0.0-py314h5a2d7ad_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cfgv-3.5.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.5-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/conda-26.1.1-py314h86ab7b2_0.conda @@ -364,13 +421,17 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-handling-2.4.0-pyh7900ff3_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-streaming-0.12.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/cpp-expected-1.3.1-h477610d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/distro-1.9.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.25.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/fmt-12.1.0-h7f4e812_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/frozendict-2.4.7-py314h5a2d7ad_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/identify-2.6.18-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpatch-1.33-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpointer-3.0.0-pyhcf101f3_3.conda - conda: https://conda.anaconda.org/conda-forge/win-64/krb5-1.22.2-h0ea6238_0.conda @@ -395,17 +456,21 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/menuinst-2.4.2-py314h13fbf68_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/msgpack-python-1.1.2-py314h909e829_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nlohmann_json-abi-3.12.0-h0f90c79_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nodeenv-1.10.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.6.1-hf411b9b_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pixi-pycharm-0.0.10-win_hba80fca_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.4-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pre-commit-4.5.1-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pybind11-abi-11-hc364b38_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/pycosat-0.6.6-py314h5a2d7ad_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyh09c184e_7.conda - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.14.3-h4b44e0e_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-discovery-1.2.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pyyaml-6.0.3-py314h2359020_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/reproc-14.2.5.post0-h2466b09_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/reproc-cpp-14.2.5.post0-he0c23c2_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.32.5-pyhcf101f3_1.conda @@ -418,14 +483,19 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h6ed50ae_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyha7b4d00_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/truststore-0.10.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ukkonen-1.1.0-py314h909e829_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.3-h41ae7f8_34.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.44.35208-h818238b_34.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vcomp14-14.44.35208-h818238b_34.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-21.2.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/win_inet_pton-1.1.0-pyh7428d3b_8.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/yaml-0.2.5-h6a83c73_3.conda - conda: https://conda.anaconda.org/conda-forge/win-64/yaml-cpp-0.8.0-he0c23c2_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/zstandard-0.25.0-py314hc5dbbe4_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.7-h534d264_6.conda linux-py310: @@ -452,6 +522,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.2.25-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-2.0.0-py310he7384ee_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cfgv-3.5.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.5-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/cmake-3.31.8-hc85cc9f_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/conda-26.1.1-py310hff52083_0.conda @@ -461,9 +532,11 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-streaming-0.12.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/cpp-expected-1.3.1-h171cf75_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/cxx-compiler-1.11.0-hfcd1e18_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/distro-1.9.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/doxygen-1.13.2-h8e693c7_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.25.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/fmt-12.1.0-hff5e90c_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/frozendict-2.4.7-py310h7c4b9e2_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc-14.3.0-h0dff253_18.conda @@ -476,6 +549,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.2-h33c6efd_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/identify-2.6.18-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-resources-6.5.2-pyhd8ed1ab_0.conda @@ -530,6 +604,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ninja-1.13.2-h171cf75_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nlohmann_json-abi-3.12.0-h0f90c79_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nodeenv-1.10.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.2.6-py310hefbff90_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.1-h35e630c_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-25.0-pyh29332c3_1.conda @@ -540,6 +615,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/pkginfo-1.12.1.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.4-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pre-commit-4.5.1-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pybind11-abi-11-hc364b38_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pycosat-0.6.6-py310h7c4b9e2_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda @@ -547,7 +623,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/pyproject-metadata-0.11.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.10.20-h3c07f61_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-discovery-1.2.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.10-8_cp310.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py310h3406613_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/reproc-14.2.5.post0-hb9d3cd8_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/reproc-cpp-14.2.5.post0-h5888daf_0.conda @@ -570,8 +648,11 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ukkonen-1.1.0-py310h03d9f68_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-21.2.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.46.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h280c20c_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-cpp-0.8.0-h3f2d84a_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zstandard-0.25.0-py310h139afa4_1.conda @@ -594,6 +675,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.2.25-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cffi-2.0.0-py310h0826a50_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cfgv-3.5.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.6-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cmake-3.31.8-hc9d863e_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/conda-26.1.1-py310h4c7bcd0_0.conda @@ -603,9 +685,11 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-streaming-0.12.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cpp-expected-1.3.1-hdc560ac_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cxx-compiler-1.11.0-h7b35c40_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/distro-1.9.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/doxygen-1.13.2-h5e0f5ae_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.25.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/fmt-12.1.0-h20c602a_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/frozendict-2.4.7-py310h5b55623_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gcc-14.3.0-h2e72a27_18.conda @@ -618,6 +702,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/icu-78.3-hcab7f73_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/identify-2.6.18-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-resources-6.5.2-pyhd8ed1ab_0.conda @@ -672,6 +757,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.5-ha32ae93_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ninja-1.13.2-hdc560ac_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nlohmann_json-abi-3.12.0-h0f90c79_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nodeenv-1.10.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/numpy-2.2.6-py310h6e5608f_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.6.1-h546c87b_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-25.0-pyh29332c3_1.conda @@ -682,6 +768,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/pkginfo-1.12.1.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.4-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pre-commit-4.5.1-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pybind11-abi-11-hc364b38_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pycosat-0.6.6-py310h5b55623_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda @@ -689,7 +776,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/pyproject-metadata-0.11.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.10.20-h28be5d3_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-discovery-1.2.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.10-8_cp310.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pyyaml-6.0.3-py310h2d8da20_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/readline-8.3-hb682ff5_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/reproc-14.2.5.post0-h86ecc28_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/reproc-cpp-14.2.5.post0-h5ad3122_0.conda @@ -712,8 +801,11 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ukkonen-1.1.0-py310h0992a49_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-21.2.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.46.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/yaml-0.2.5-h80f16a2_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/yaml-cpp-0.8.0-h5ad3122_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstandard-0.25.0-py310hef25091_1.conda @@ -744,6 +836,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.2.25-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-2.0.0-py311h03d9500_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cfgv-3.5.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.5-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/cmake-3.31.8-hc85cc9f_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/conda-26.1.1-py311h38be061_0.conda @@ -753,9 +846,11 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-streaming-0.12.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/cpp-expected-1.3.1-h171cf75_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/cxx-compiler-1.11.0-hfcd1e18_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/distro-1.9.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/doxygen-1.13.2-h8e693c7_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.25.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/fmt-12.1.0-hff5e90c_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/frozendict-2.4.7-py311h49ec1c0_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc-14.3.0-h0dff253_18.conda @@ -768,6 +863,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.2-h33c6efd_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/identify-2.6.18-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-resources-6.5.2-pyhd8ed1ab_0.conda @@ -822,6 +918,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ninja-1.13.2-h171cf75_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nlohmann_json-abi-3.12.0-h0f90c79_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nodeenv-1.10.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.4.2-py311h2e04523_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.1-h35e630c_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-25.0-pyh29332c3_1.conda @@ -832,6 +929,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/pkginfo-1.12.1.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.4-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pre-commit-4.5.1-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pybind11-abi-11-hc364b38_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pycosat-0.6.6-py311h49ec1c0_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda @@ -839,7 +937,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/pyproject-metadata-0.11.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.11.15-hd63d673_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-discovery-1.2.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.11-8_cp311.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py311h3778330_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/reproc-14.2.5.post0-hb9d3cd8_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/reproc-cpp-14.2.5.post0-h5888daf_0.conda @@ -862,8 +962,11 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ukkonen-1.1.0-py311hdf67eae_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-21.2.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.46.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h280c20c_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-cpp-0.8.0-h3f2d84a_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zstandard-0.25.0-py311haee01d2_1.conda @@ -886,6 +989,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.2.25-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cffi-2.0.0-py311h460c349_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cfgv-3.5.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.6-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cmake-3.31.8-hc9d863e_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/conda-26.1.1-py311hec3470c_0.conda @@ -895,9 +999,11 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-streaming-0.12.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cpp-expected-1.3.1-hdc560ac_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cxx-compiler-1.11.0-h7b35c40_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/distro-1.9.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/doxygen-1.13.2-h5e0f5ae_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.25.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/fmt-12.1.0-h20c602a_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/frozendict-2.4.7-py311h19352d5_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gcc-14.3.0-h2e72a27_18.conda @@ -910,6 +1016,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/icu-78.3-hcab7f73_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/identify-2.6.18-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-resources-6.5.2-pyhd8ed1ab_0.conda @@ -964,6 +1071,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.5-ha32ae93_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ninja-1.13.2-hdc560ac_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nlohmann_json-abi-3.12.0-h0f90c79_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nodeenv-1.10.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/numpy-2.4.3-py311h669026d_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.6.1-h546c87b_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-25.0-pyh29332c3_1.conda @@ -974,6 +1082,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/pkginfo-1.12.1.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.4-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pre-commit-4.5.1-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pybind11-abi-11-hc364b38_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pycosat-0.6.6-py311h19352d5_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda @@ -981,7 +1090,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/pyproject-metadata-0.11.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.11.15-h91f4b29_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-discovery-1.2.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.11-8_cp311.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pyyaml-6.0.3-py311h164a683_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/readline-8.3-hb682ff5_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/reproc-14.2.5.post0-h86ecc28_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/reproc-cpp-14.2.5.post0-h5ad3122_0.conda @@ -1004,8 +1115,11 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ukkonen-1.1.0-py311hfca10b7_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-21.2.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.46.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/yaml-0.2.5-h80f16a2_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/yaml-cpp-0.8.0-h5ad3122_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstandard-0.25.0-py311h51cfe5d_1.conda @@ -1033,6 +1147,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/cctools_osx-64-986-h58a35ae_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.2.25-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/cffi-1.16.0-py310hdca579f_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cfgv-3.5.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.5-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-18-18.1.3-default_h7151d67_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-18.1.3-default_h7151d67_0.conda @@ -1049,12 +1164,15 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-streaming-0.12.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/cryptography-41.0.7-py310h527a09d_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/cxx-compiler-1.10.0-h20888b2_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/doxygen-1.10.0-h5ff76d1_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.25.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/icu-73.2-hf5e326d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/identify-2.6.18-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-resources-6.5.2-pyhd8ed1ab_0.conda @@ -1090,6 +1208,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-tools-18.1.3-hbcf5fad_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.5-h5846eda_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/ninja-1.12.0-h7728843_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nodeenv-1.10.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/numpy-1.26.4-py310h4bfa8fc_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/openssl-3.3.0-hd75f5a5_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-25.0-pyh29332c3_1.conda @@ -1097,14 +1216,18 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/pip-26.0.1-pyh8b19718_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pixi-pycharm-0.0.10-unix_hf108a03_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pkginfo-1.12.1.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.4-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pre-commit-4.5.1-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/pycosat-0.6.6-py310h6729b98_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pyopenssl-25.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pyproject-metadata-0.11.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.10.14-h00d2728_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-discovery-1.2.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.10-8_cp310.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/pyyaml-6.0.1-py310h6729b98_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/readline-8.2-h7cca4af_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.32.5-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/rhash-1.4.4-h0dc2134_0.conda @@ -1124,9 +1247,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ukkonen-1.0.1-py310h88cfcbd_4.conda - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.5.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-21.2.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.46.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/xz-5.2.6-h775f41a_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/yaml-0.2.5-h0d85af4_2.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/zstandard-0.22.0-py310hd88f66e_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.5-h829000d_0.conda @@ -1148,6 +1274,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cctools_osx-arm64-986-hd11630f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.2.25-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cffi-1.16.0-py310hdcd7c05_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cfgv-3.5.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.5-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-18-18.1.3-default_he012953_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-18.1.3-default_h4cf2255_0.conda @@ -1164,12 +1291,15 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-streaming-0.12.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cryptography-41.0.7-py310h4c55245_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cxx-compiler-1.10.0-hba80287_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/doxygen-1.10.0-h8fbad5d_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.25.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-73.2-hc8870d7_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/identify-2.6.18-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-resources-6.5.2-pyhd8ed1ab_0.conda @@ -1205,6 +1335,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-tools-18.1.3-h30cc82d_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.5-hb89a1cb_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ninja-1.12.0-h2ffa867_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nodeenv-1.10.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-1.26.4-py310hd45542a_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.3.0-h0d3ecfb_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-25.0-pyh29332c3_1.conda @@ -1212,14 +1343,18 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/pip-26.0.1-pyh8b19718_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pixi-pycharm-0.0.10-unix_hf108a03_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pkginfo-1.12.1.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.4-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pre-commit-4.5.1-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pycosat-0.6.6-py310h2aa6e3c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pyopenssl-25.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pyproject-metadata-0.11.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.10.14-h2469fbe_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-discovery-1.2.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.10-8_cp310.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyyaml-6.0.1-py310h2aa6e3c_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.2-h1d1bf99_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.32.5-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rhash-1.4.4-hb547adb_0.conda @@ -1239,9 +1374,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ukkonen-1.0.1-py310h38f39d4_4.conda - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.5.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-21.2.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.46.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/xz-5.2.6-h57fd34a_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/yaml-0.2.5-h3422bc3_2.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstandard-0.22.0-py310h6289e41_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.5-h4f39d0f_0.conda @@ -1271,6 +1409,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/cctools_osx-64-986-h58a35ae_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.2.25-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/cffi-1.16.0-py311hc0b63fd_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cfgv-3.5.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.5-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-18-18.1.3-default_h7151d67_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-18.1.3-default_h7151d67_0.conda @@ -1287,12 +1426,15 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-streaming-0.12.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/cryptography-41.0.7-py311h48c7838_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/cxx-compiler-1.10.0-h20888b2_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/doxygen-1.10.0-h5ff76d1_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.25.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/icu-73.2-hf5e326d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/identify-2.6.18-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-resources-6.5.2-pyhd8ed1ab_0.conda @@ -1328,6 +1470,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-tools-18.1.3-hbcf5fad_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.5-h5846eda_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/ninja-1.12.0-h7728843_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nodeenv-1.10.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/numpy-1.26.4-py311hc43a94b_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/openssl-3.3.0-hd75f5a5_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-25.0-pyh29332c3_1.conda @@ -1335,14 +1478,18 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/pip-26.0.1-pyh8b19718_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pixi-pycharm-0.0.10-unix_hf108a03_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pkginfo-1.12.1.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.4-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pre-commit-4.5.1-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/pycosat-0.6.6-py311h2725bcf_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pyopenssl-25.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pyproject-metadata-0.11.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.11.8-h9f0c242_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-discovery-1.2.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.11-8_cp311.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/pyyaml-6.0.1-py311h2725bcf_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/readline-8.2-h7cca4af_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.32.5-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/rhash-1.4.4-h0dc2134_0.conda @@ -1362,9 +1509,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ukkonen-1.0.1-py311h5fe6e05_4.conda - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.5.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-21.2.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.46.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/xz-5.2.6-h775f41a_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/yaml-0.2.5-h0d85af4_2.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/zstandard-0.22.0-py311hed14148_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.5-h829000d_0.conda @@ -1386,6 +1536,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cctools_osx-arm64-986-hd11630f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.2.25-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cffi-1.16.0-py311h4a08483_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cfgv-3.5.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.5-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-18-18.1.3-default_he012953_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-18.1.3-default_h4cf2255_0.conda @@ -1402,12 +1553,15 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-streaming-0.12.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cryptography-41.0.7-py311h08c85a6_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cxx-compiler-1.10.0-hba80287_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/doxygen-1.10.0-h8fbad5d_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.25.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-73.2-hc8870d7_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/identify-2.6.18-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-resources-6.5.2-pyhd8ed1ab_0.conda @@ -1443,6 +1597,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-tools-18.1.3-h30cc82d_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.5-hb89a1cb_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ninja-1.12.0-h2ffa867_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nodeenv-1.10.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-1.26.4-py311h7125741_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.3.0-h0d3ecfb_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-25.0-pyh29332c3_1.conda @@ -1450,14 +1605,18 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/pip-26.0.1-pyh8b19718_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pixi-pycharm-0.0.10-unix_hf108a03_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pkginfo-1.12.1.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.4-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pre-commit-4.5.1-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pycosat-0.6.6-py311heffc1b2_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pyopenssl-25.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pyproject-metadata-0.11.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.11.8-hdf0ec26_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-discovery-1.2.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.11-8_cp311.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyyaml-6.0.1-py311heffc1b2_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.2-h1d1bf99_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.32.5-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rhash-1.4.4-hb547adb_0.conda @@ -1477,9 +1636,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ukkonen-1.0.1-py311he4fd1f5_4.conda - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.5.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-21.2.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.46.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/xz-5.2.6-h57fd34a_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/yaml-0.2.5-h3422bc3_2.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstandard-0.22.0-py311h67b91a1_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.5-h4f39d0f_0.conda @@ -1508,6 +1670,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.2.25-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-2.0.0-py310he7384ee_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cfgv-3.5.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.5-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/cmake-3.31.8-hc85cc9f_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/conda-26.1.1-py310hff52083_0.conda @@ -1515,15 +1678,18 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-handling-2.4.0-pyh7900ff3_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-streaming-0.12.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/cpp-expected-1.3.1-h171cf75_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/distro-1.9.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/doxygen-1.13.2-h8e693c7_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.25.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/fmt-12.1.0-hff5e90c_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/frozendict-2.4.7-py310h7c4b9e2_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.2-h33c6efd_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/identify-2.6.18-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-resources-6.5.2-pyhd8ed1ab_0.conda @@ -1573,6 +1739,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ninja-1.13.2-h171cf75_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nlohmann_json-abi-3.12.0-h0f90c79_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nodeenv-1.10.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.2.6-py310hefbff90_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.1-h35e630c_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-25.0-pyh29332c3_1.conda @@ -1583,6 +1750,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/pkginfo-1.12.1.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.4-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pre-commit-4.5.1-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pybind11-abi-11-hc364b38_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pycosat-0.6.6-py310h7c4b9e2_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda @@ -1590,7 +1758,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/pyproject-metadata-0.11.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.10.20-h3c07f61_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-discovery-1.2.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.10-8_cp310.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py310h3406613_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/reproc-14.2.5.post0-hb9d3cd8_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/reproc-cpp-14.2.5.post0-h5888daf_0.conda @@ -1612,8 +1782,11 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ukkonen-1.1.0-py310h03d9f68_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-21.2.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.46.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h280c20c_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-cpp-0.8.0-h3f2d84a_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zstandard-0.25.0-py310h139afa4_1.conda @@ -1632,6 +1805,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.2.25-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cffi-2.0.0-py310h0826a50_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cfgv-3.5.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.5-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cmake-3.31.8-hc9d863e_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/conda-26.1.1-py310h4c7bcd0_0.conda @@ -1639,15 +1813,18 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-handling-2.4.0-pyh7900ff3_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-streaming-0.12.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cpp-expected-1.3.1-hdc560ac_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/distro-1.9.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/doxygen-1.13.2-h5e0f5ae_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.25.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/fmt-12.1.0-h20c602a_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/frozendict-2.4.7-py310h5b55623_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/icu-78.2-hcab7f73_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/identify-2.6.18-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-resources-6.5.2-pyhd8ed1ab_0.conda @@ -1697,6 +1874,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.5-ha32ae93_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ninja-1.13.2-hdc560ac_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nlohmann_json-abi-3.12.0-h0f90c79_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nodeenv-1.10.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/numpy-2.2.6-py310h6e5608f_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.6.1-h546c87b_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-25.0-pyh29332c3_1.conda @@ -1707,6 +1885,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/pkginfo-1.12.1.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.4-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pre-commit-4.5.1-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pybind11-abi-11-hc364b38_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pycosat-0.6.6-py310h5b55623_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda @@ -1714,7 +1893,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/pyproject-metadata-0.11.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.10.20-h28be5d3_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-discovery-1.2.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.10-8_cp310.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pyyaml-6.0.3-py310h2d8da20_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/readline-8.3-hb682ff5_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/reproc-14.2.5.post0-h86ecc28_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/reproc-cpp-14.2.5.post0-h5ad3122_0.conda @@ -1736,8 +1917,11 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ukkonen-1.1.0-py310h0992a49_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-21.2.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.46.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/yaml-0.2.5-h80f16a2_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/yaml-cpp-0.8.0-h5ad3122_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstandard-0.25.0-py310hef25091_1.conda @@ -1764,6 +1948,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.2.25-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-2.0.0-py311h03d9500_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cfgv-3.5.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.5-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/cmake-3.31.8-hc85cc9f_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/conda-26.1.1-py311h38be061_0.conda @@ -1771,15 +1956,18 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-handling-2.4.0-pyh7900ff3_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-streaming-0.12.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/cpp-expected-1.3.1-h171cf75_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/distro-1.9.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/doxygen-1.13.2-h8e693c7_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.25.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/fmt-12.1.0-hff5e90c_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/frozendict-2.4.7-py311h49ec1c0_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.2-h33c6efd_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/identify-2.6.18-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-resources-6.5.2-pyhd8ed1ab_0.conda @@ -1829,6 +2017,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ninja-1.13.2-h171cf75_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nlohmann_json-abi-3.12.0-h0f90c79_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nodeenv-1.10.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.4.2-py311h2e04523_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.1-h35e630c_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-25.0-pyh29332c3_1.conda @@ -1839,6 +2028,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/pkginfo-1.12.1.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.4-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pre-commit-4.5.1-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pybind11-abi-11-hc364b38_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pycosat-0.6.6-py311h49ec1c0_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda @@ -1846,7 +2036,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/pyproject-metadata-0.11.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.11.15-hd63d673_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-discovery-1.2.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.11-8_cp311.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py311h3778330_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/reproc-14.2.5.post0-hb9d3cd8_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/reproc-cpp-14.2.5.post0-h5888daf_0.conda @@ -1868,8 +2060,11 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ukkonen-1.1.0-py311hdf67eae_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-21.2.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.46.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h280c20c_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-cpp-0.8.0-h3f2d84a_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zstandard-0.25.0-py311haee01d2_1.conda @@ -1888,6 +2083,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.2.25-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cffi-2.0.0-py311h460c349_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cfgv-3.5.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.5-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cmake-3.31.8-hc9d863e_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/conda-26.1.1-py311hec3470c_0.conda @@ -1895,15 +2091,18 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-handling-2.4.0-pyh7900ff3_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-streaming-0.12.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cpp-expected-1.3.1-hdc560ac_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/distro-1.9.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/doxygen-1.13.2-h5e0f5ae_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.25.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/fmt-12.1.0-h20c602a_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/frozendict-2.4.7-py311h19352d5_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/icu-78.2-hcab7f73_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/identify-2.6.18-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-resources-6.5.2-pyhd8ed1ab_0.conda @@ -1953,6 +2152,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.5-ha32ae93_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ninja-1.13.2-hdc560ac_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nlohmann_json-abi-3.12.0-h0f90c79_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nodeenv-1.10.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/numpy-2.4.2-py311h669026d_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.6.1-h546c87b_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-25.0-pyh29332c3_1.conda @@ -1963,6 +2163,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/pkginfo-1.12.1.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.4-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pre-commit-4.5.1-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pybind11-abi-11-hc364b38_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pycosat-0.6.6-py311h19352d5_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda @@ -1970,7 +2171,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/pyproject-metadata-0.11.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.11.15-h91f4b29_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-discovery-1.2.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.11-8_cp311.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pyyaml-6.0.3-py311h164a683_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/readline-8.3-hb682ff5_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/reproc-14.2.5.post0-h86ecc28_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/reproc-cpp-14.2.5.post0-h5ad3122_0.conda @@ -1992,8 +2195,11 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ukkonen-1.1.0-py311hfca10b7_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-21.2.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.46.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/yaml-0.2.5-h80f16a2_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/yaml-cpp-0.8.0-h5ad3122_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstandard-0.25.0-py311h51cfe5d_1.conda @@ -2018,6 +2224,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-h4c7d964_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.2.25-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/cffi-2.0.0-py310h29418f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cfgv-3.5.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.5-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/cmake-3.31.8-hdcbee5b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda @@ -2027,15 +2234,18 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-streaming-0.12.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/cpp-expected-1.3.1-h477610d_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/cxx-compiler-1.11.0-h1c1089f_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/distro-1.9.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/doxygen-1.13.2-hbf3f430_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.25.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/fmt-12.1.0-h7f4e812_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/frozendict-2.4.7-py310h29418f3_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/git-2.53.0-h57928b3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/identify-2.6.18-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-resources-6.5.2-pyhd8ed1ab_0.conda @@ -2072,6 +2282,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/msgpack-python-1.1.2-py310he9f1925_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/ninja-1.13.2-h477610d_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nlohmann_json-abi-3.12.0-h0f90c79_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nodeenv-1.10.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/numpy-2.2.6-py310h4987827_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.6.1-hf411b9b_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-25.0-pyh29332c3_1.conda @@ -2081,13 +2292,16 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/pkginfo-1.12.1.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.4-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pre-commit-4.5.1-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pybind11-abi-11-hc364b38_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/pycosat-0.6.6-py310h29418f3_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pyproject-metadata-0.11.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyh09c184e_7.conda - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.10.20-hc20f281_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-discovery-1.2.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.10-8_cp310.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pyyaml-6.0.3-py310hdb0e946_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/reproc-14.2.5.post0-h2466b09_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/reproc-cpp-14.2.5.post0-he0c23c2_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.32.5-pyhcf101f3_1.conda @@ -2109,14 +2323,17 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ukkonen-1.1.0-py310he9f1925_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.3-h41ae7f8_34.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.44.35208-h818238b_34.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vcomp14-14.44.35208-h818238b_34.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-21.2.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vs2022_win-64-19.44.35207-ha74f236_34.conda - conda: https://conda.anaconda.org/conda-forge/noarch/vswhere-3.1.7-h40126e0_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.46.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/win_inet_pton-1.1.0-pyh7428d3b_8.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/yaml-0.2.5-h6a83c73_3.conda - conda: https://conda.anaconda.org/conda-forge/win-64/yaml-cpp-0.8.0-he0c23c2_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/zstandard-0.25.0-py310h1637853_1.conda @@ -2143,6 +2360,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-h4c7d964_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.2.25-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/cffi-2.0.0-py311h3485c13_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cfgv-3.5.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.5-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/cmake-3.31.8-hdcbee5b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda @@ -2152,15 +2370,18 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-streaming-0.12.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/cpp-expected-1.3.1-h477610d_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/cxx-compiler-1.11.0-h1c1089f_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/distro-1.9.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/doxygen-1.13.2-hbf3f430_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.25.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/fmt-12.1.0-h7f4e812_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/frozendict-2.4.7-py311h3485c13_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/git-2.53.0-h57928b3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/identify-2.6.18-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-resources-6.5.2-pyhd8ed1ab_0.conda @@ -2197,6 +2418,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/msgpack-python-1.1.2-py311h3fd045d_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/ninja-1.13.2-h477610d_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nlohmann_json-abi-3.12.0-h0f90c79_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nodeenv-1.10.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/numpy-2.4.2-py311h80b3fa1_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.6.1-hf411b9b_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-25.0-pyh29332c3_1.conda @@ -2206,13 +2428,16 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/pkginfo-1.12.1.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.4-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pre-commit-4.5.1-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pybind11-abi-11-hc364b38_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/pycosat-0.6.6-py311h3485c13_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pyproject-metadata-0.11.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyh09c184e_7.conda - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.11.15-h0159041_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-discovery-1.2.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.11-8_cp311.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pyyaml-6.0.3-py311h3f79411_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/reproc-14.2.5.post0-h2466b09_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/reproc-cpp-14.2.5.post0-he0c23c2_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.32.5-pyhcf101f3_1.conda @@ -2234,14 +2459,17 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ukkonen-1.1.0-py311h3fd045d_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.3-h41ae7f8_34.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.44.35208-h818238b_34.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vcomp14-14.44.35208-h818238b_34.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-21.2.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vs2022_win-64-19.44.35207-ha74f236_34.conda - conda: https://conda.anaconda.org/conda-forge/noarch/vswhere-3.1.7-h40126e0_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.46.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/win_inet_pton-1.1.0-pyh7428d3b_8.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/yaml-0.2.5-h6a83c73_3.conda - conda: https://conda.anaconda.org/conda-forge/win-64/yaml-cpp-0.8.0-he0c23c2_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/zstandard-0.25.0-py311hf893f09_1.conda @@ -3255,6 +3483,17 @@ packages: license_family: MIT size: 294731 timestamp: 1761203441365 +- conda: https://conda.anaconda.org/conda-forge/noarch/cfgv-3.5.0-pyhd8ed1ab_0.conda + sha256: aa589352e61bb221351a79e5946d56916e3c595783994884accdb3b97fe9d449 + md5: 381bd45fb7aa032691f3063aff47e3a1 + depends: + - python >=3.10 + license: MIT + license_family: MIT + purls: + - pkg:pypi/cfgv?source=hash-mapping + size: 13589 + timestamp: 1763607964133 - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.5-pyhd8ed1ab_0.conda sha256: 05ea76a016c77839b64f9f8ec581775f6c8a259044bd5b45a177e46ab4e7feac md5: beb628209b2b354b98203066f90b3287 @@ -4353,6 +4592,17 @@ packages: requires_dist: - pefile>=2024.8.26 requires_python: '>=3.9' +- conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.4.0-pyhd8ed1ab_0.conda + sha256: 6d977f0b2fc24fee21a9554389ab83070db341af6d6f09285360b2e09ef8b26e + md5: 003b8ba0a94e2f1e117d0bd46aebc901 + depends: + - python >=3.9 + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/distlib?source=hash-mapping + size: 275642 + timestamp: 1752823081585 - conda: https://conda.anaconda.org/conda-forge/noarch/distro-1.9.0-pyhd8ed1ab_1.conda sha256: 5603c7d0321963bb9b4030eadabc3fd7ca6103a38475b4e0ed13ed6d97c86f4e md5: 0a2014fd9860f8b1eaa0b1f3d3771a08 @@ -4435,6 +4685,16 @@ packages: - pkg:pypi/exceptiongroup?source=hash-mapping size: 21333 timestamp: 1763918099466 +- conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.25.2-pyhd8ed1ab_0.conda + sha256: dddea9ec53d5e179de82c24569d41198f98db93314f0adae6b15195085d5567f + md5: f58064cec97b12a7136ebb8a6f8a129b + depends: + - python >=3.10 + license: Unlicense + purls: + - pkg:pypi/filelock?source=compressed-mapping + size: 25845 + timestamp: 1773314012590 - conda: https://conda.anaconda.org/conda-forge/linux-64/fmt-12.1.0-hff5e90c_0.conda sha256: d4e92ba7a7b4965341dc0fca57ec72d01d111b53c12d11396473115585a9ead6 md5: f7d7a4104082b39e3b3473fbd4a38229 @@ -4900,6 +5160,18 @@ packages: license_family: MIT size: 12389400 timestamp: 1772209104304 +- conda: https://conda.anaconda.org/conda-forge/noarch/identify-2.6.18-pyhd8ed1ab_0.conda + sha256: 3bae1b612ccc71e49c5795a369a82c4707ae6fd4e63360e8ecc129f9539f779b + md5: 635d1a924e1c55416fce044ed96144a2 + depends: + - python >=3.10 + - ukkonen + license: MIT + license_family: MIT + purls: + - pkg:pypi/identify?source=hash-mapping + size: 79749 + timestamp: 1774239544252 - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda sha256: ae89d0299ada2a3162c2614a9d26557a92aa6a77120ce142f8e0109bbf0342b0 md5: 53abe63df7e10a6ba605dc5f9f961d36 @@ -4924,6 +5196,17 @@ packages: - pkg:pypi/importlib-metadata?source=hash-mapping size: 34641 timestamp: 1747934053147 +- conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda + sha256: 82ab2a0d91ca1e7e63ab6a4939356667ef683905dea631bc2121aa534d347b16 + md5: 080594bf4493e6bae2607e65390c520a + depends: + - python >=3.10 + - zipp >=3.20 + - python + license: Apache-2.0 + license_family: APACHE + size: 34387 + timestamp: 1773931568510 - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-resources-6.5.2-pyhd8ed1ab_0.conda sha256: a99a3dafdfff2bb648d2b10637c704400295cb2ba6dc929e2d814870cf9f6ae5 md5: e376ea42e9ae40f3278b0f79c9bf9826 @@ -8351,6 +8634,18 @@ packages: purls: [] size: 4335 timestamp: 1758194464430 +- conda: https://conda.anaconda.org/conda-forge/noarch/nodeenv-1.10.0-pyhd8ed1ab_0.conda + sha256: 4fa40e3e13fc6ea0a93f67dfc76c96190afd7ea4ffc1bac2612d954b42cdc3ee + md5: eb52d14a901e23c39e9e7b4a1a5c015f + depends: + - python >=3.10 + - setuptools + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/nodeenv?source=hash-mapping + size: 40866 + timestamp: 1766261270149 - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.2.6-py310hefbff90_0.conda sha256: 0ba94a61f91d67413e60fa8daa85627a8f299b5054b0eff8f93d26da83ec755e md5: b0cea2c364bf65cd19e023040eeab05d @@ -8794,6 +9089,22 @@ packages: - pkg:pypi/pluggy?source=compressed-mapping size: 25877 timestamp: 1764896838868 +- conda: https://conda.anaconda.org/conda-forge/noarch/pre-commit-4.5.1-pyha770c72_0.conda + sha256: 5b81b7516d4baf43d0c185896b245fa7384b25dc5615e7baa504b7fa4e07b706 + md5: 7f3ac694319c7eaf81a0325d6405e974 + depends: + - cfgv >=2.0.0 + - identify >=1.0.0 + - nodeenv >=0.11.1 + - python >=3.10 + - pyyaml >=5.1 + - virtualenv >=20.10.0 + license: MIT + license_family: MIT + purls: + - pkg:pypi/pre-commit?source=compressed-mapping + size: 200827 + timestamp: 1765937577534 - conda: https://conda.anaconda.org/conda-forge/noarch/pybind11-abi-11-hc364b38_1.conda sha256: 9e7fe12f727acd2787fb5816b2049cef4604b7a00ad3e408c5e709c298ce8bf1 md5: f0599959a2447c1e544e216bddf393fa @@ -9434,6 +9745,19 @@ packages: size: 18273230 timestamp: 1770675442998 python_site_packages_path: Lib/site-packages +- conda: https://conda.anaconda.org/conda-forge/noarch/python-discovery-1.2.1-pyhcf101f3_0.conda + sha256: 5a70a9cbcf48be522c2b82df8c7a57988eed776f159142b0d30099b61f31a35e + md5: f2e88fc463b249bc1f40d9ca969d9b5e + depends: + - python >=3.10 + - filelock >=3.15.4 + - platformdirs <5,>=4.3.6 + - python + license: MIT + purls: + - pkg:pypi/python-discovery?source=compressed-mapping + size: 34137 + timestamp: 1774605818480 - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.10-8_cp310.conda build_number: 8 sha256: 7ad76fa396e4bde336872350124c0819032a9e8a0a40590744ff9527b54351c1 @@ -9466,6 +9790,217 @@ packages: license_family: BSD size: 6989 timestamp: 1752805904792 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py310h3406613_1.conda + sha256: f23de6cc72541c6081d3d27482dbc9fc5dd03be93126d9155f06d0cf15d6e90e + md5: 2160894f57a40d2d629a34ee8497795f + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - python >=3.10,<3.11.0a0 + - python_abi 3.10.* *_cp310 + - yaml >=0.2.5,<0.3.0a0 + license: MIT + license_family: MIT + purls: + - pkg:pypi/pyyaml?source=hash-mapping + size: 176522 + timestamp: 1770223379599 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py311h3778330_1.conda + sha256: c9a6cd2c290d7c3d2b30ea34a0ccda30f770e8ddb2937871f2c404faf60d0050 + md5: a24add9a3bababee946f3bc1c829acfe + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + - yaml >=0.2.5,<0.3.0a0 + license: MIT + license_family: MIT + purls: + - pkg:pypi/pyyaml?source=compressed-mapping + size: 206190 + timestamp: 1770223702917 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py314h67df5f8_1.conda + sha256: b318fb070c7a1f89980ef124b80a0b5ccf3928143708a85e0053cde0169c699d + md5: 2035f68f96be30dc60a5dfd7452c7941 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + - yaml >=0.2.5,<0.3.0a0 + license: MIT + license_family: MIT + size: 202391 + timestamp: 1770223462836 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pyyaml-6.0.3-py310h2d8da20_1.conda + sha256: 8acefeb5cc4bcf835f33e45b5cc8b350e738b4954f68c3d8051426e851ca2806 + md5: 7e1a74e779e08e3504230f8216be618b + depends: + - libgcc >=14 + - python >=3.10,<3.11.0a0 + - python >=3.10,<3.11.0a0 *_cpython + - python_abi 3.10.* *_cp310 + - yaml >=0.2.5,<0.3.0a0 + license: MIT + license_family: MIT + purls: + - pkg:pypi/pyyaml?source=hash-mapping + size: 171618 + timestamp: 1770223419125 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pyyaml-6.0.3-py311h164a683_1.conda + sha256: e3175f507827cd575b5a7b7b50058cd253977f8286079cb3a6bf0aeaa878071b + md5: 7e1888f50cc191b7817848dbf6f90590 + depends: + - libgcc >=14 + - python >=3.11,<3.12.0a0 + - python >=3.11,<3.12.0a0 *_cpython + - python_abi 3.11.* *_cp311 + - yaml >=0.2.5,<0.3.0a0 + license: MIT + license_family: MIT + purls: + - pkg:pypi/pyyaml?source=hash-mapping + size: 201473 + timestamp: 1770223445971 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pyyaml-6.0.3-py314h807365f_1.conda + sha256: 496b5e65dfdd0aaaaa5de0dcaaf3bceea00fcb4398acf152f89e567c82ec1046 + md5: 9ae2c92975118058bd720e9ba2bb7c58 + depends: + - libgcc >=14 + - python >=3.14,<3.15.0a0 + - python >=3.14,<3.15.0a0 *_cp314 + - python_abi 3.14.* *_cp314 + - yaml >=0.2.5,<0.3.0a0 + license: MIT + license_family: MIT + size: 195678 + timestamp: 1770223441816 +- conda: https://conda.anaconda.org/conda-forge/osx-64/pyyaml-6.0.1-py310h6729b98_1.conda + sha256: 00567f2cb2d1c8fede8fe7727f7bbd1c38cbca886814d612e162d5c936d8db1b + md5: d964cec3e7972e44bc4a328134b9eaf1 + depends: + - python >=3.10,<3.11.0a0 + - python_abi 3.10.* *_cp310 + - yaml >=0.2.5,<0.3.0a0 + license: MIT + license_family: MIT + purls: + - pkg:pypi/pyyaml?source=hash-mapping + size: 160097 + timestamp: 1695373947773 +- conda: https://conda.anaconda.org/conda-forge/osx-64/pyyaml-6.0.1-py311h2725bcf_1.conda + sha256: 8ce2ba443414170a2570514d0ce6d03625a847e91af9763d48dc58c338e6f7f3 + md5: 9283f991b5e5856a99f8aabba9927df5 + depends: + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + - yaml >=0.2.5,<0.3.0a0 + license: MIT + license_family: MIT + purls: + - pkg:pypi/pyyaml?source=hash-mapping + size: 188606 + timestamp: 1695373840022 +- conda: https://conda.anaconda.org/conda-forge/osx-64/pyyaml-6.0.3-py314h10d0514_1.conda + sha256: aef010899d642b24de6ccda3bc49ef008f8fddf7bad15ebce9bdebeae19a4599 + md5: ebd224b733573c50d2bfbeacb5449417 + depends: + - __osx >=10.13 + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + - yaml >=0.2.5,<0.3.0a0 + license: MIT + license_family: MIT + size: 191947 + timestamp: 1770226344240 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyyaml-6.0.1-py310h2aa6e3c_1.conda + sha256: 7b8668cd86d2421c62ec241f840d84a600b854afc91383a509bbb60ba907aeec + md5: 0e7ccdd121ce7b486f1de7917178387c + depends: + - python >=3.10,<3.11.0a0 + - python >=3.10,<3.11.0a0 *_cpython + - python_abi 3.10.* *_cp310 + - yaml >=0.2.5,<0.3.0a0 + license: MIT + license_family: MIT + purls: + - pkg:pypi/pyyaml?source=hash-mapping + size: 158641 + timestamp: 1695373859696 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyyaml-6.0.1-py311heffc1b2_1.conda + sha256: b155f5c27f0e2951256774628c4b91fdeee3267018eef29897a74e3d1316c8b0 + md5: d310bfbb8230b9175c0cbc10189ad804 + depends: + - python >=3.11,<3.12.0a0 + - python >=3.11,<3.12.0a0 *_cpython + - python_abi 3.11.* *_cp311 + - yaml >=0.2.5,<0.3.0a0 + license: MIT + license_family: MIT + purls: + - pkg:pypi/pyyaml?source=hash-mapping + size: 187795 + timestamp: 1695373829282 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyyaml-6.0.3-py314h6e9b3f0_1.conda + sha256: 95f385f9606e30137cf0b5295f63855fd22223a4cf024d306cf9098ea1c4a252 + md5: dcf51e564317816cb8d546891019b3ab + depends: + - __osx >=11.0 + - python >=3.14,<3.15.0a0 + - python >=3.14,<3.15.0a0 *_cp314 + - python_abi 3.14.* *_cp314 + - yaml >=0.2.5,<0.3.0a0 + license: MIT + license_family: MIT + size: 189475 + timestamp: 1770223788648 +- conda: https://conda.anaconda.org/conda-forge/win-64/pyyaml-6.0.3-py310hdb0e946_1.conda + sha256: 3b643534d7b029073fd0ec1548a032854bb45391bc51dfdf9fec8d327e9f688d + md5: 463566b14434383e34e366143808b4b7 + depends: + - python >=3.10,<3.11.0a0 + - python_abi 3.10.* *_cp310 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - yaml >=0.2.5,<0.3.0a0 + license: MIT + license_family: MIT + purls: + - pkg:pypi/pyyaml?source=hash-mapping + size: 157282 + timestamp: 1770223476842 +- conda: https://conda.anaconda.org/conda-forge/win-64/pyyaml-6.0.3-py311h3f79411_1.conda + sha256: 301c3ba100d25cd5ae37895988ee3ab986210d4d972aa58efed948fbe857773d + md5: a0153c033dc55203e11d1cac8f6a9cf2 + depends: + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - yaml >=0.2.5,<0.3.0a0 + license: MIT + license_family: MIT + purls: + - pkg:pypi/pyyaml?source=hash-mapping + size: 187108 + timestamp: 1770223467913 +- conda: https://conda.anaconda.org/conda-forge/win-64/pyyaml-6.0.3-py314h2359020_1.conda + sha256: a2aff34027aa810ff36a190b75002d2ff6f9fbef71ec66e567616ac3a679d997 + md5: 0cd9b88826d0f8db142071eb830bce56 + depends: + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - yaml >=0.2.5,<0.3.0a0 + license: MIT + license_family: MIT + size: 181257 + timestamp: 1770223460931 - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda sha256: 12ffde5a6f958e285aa22c191ca01bbd3d6e710aa852e00618fa6ddc59149002 md5: d7d95fc8287ea7bf33e0e7116d2b95ec @@ -10665,6 +11200,229 @@ packages: purls: [] size: 694692 timestamp: 1756385147981 +- conda: https://conda.anaconda.org/conda-forge/linux-64/ukkonen-1.1.0-py310h03d9f68_0.conda + sha256: 24a1140fa1dcaf2d2b7da1014eba5801eae8c4c025bb17845a3b1b6c487cf8f7 + md5: c3b1f5bc28ae6282ba95156d18fde825 + depends: + - __glibc >=2.17,<3.0.a0 + - cffi + - libgcc >=14 + - libstdcxx >=14 + - python >=3.10,<3.11.0a0 + - python_abi 3.10.* *_cp310 + license: MIT + license_family: MIT + purls: + - pkg:pypi/ukkonen?source=hash-mapping + size: 14822 + timestamp: 1769438718477 +- conda: https://conda.anaconda.org/conda-forge/linux-64/ukkonen-1.1.0-py311hdf67eae_0.conda + sha256: 31ad759e2d7668f1615021bca0ae2358a284939e3ca3fcb971b3f7aa83c2a6d6 + md5: 5a715cf5e3dc6cd68717c50e47dd7b6b + depends: + - __glibc >=2.17,<3.0.a0 + - cffi + - libgcc >=14 + - libstdcxx >=14 + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + license: MIT + license_family: MIT + purls: + - pkg:pypi/ukkonen?source=compressed-mapping + size: 14898 + timestamp: 1769438724694 +- conda: https://conda.anaconda.org/conda-forge/linux-64/ukkonen-1.1.0-py314h9891dd4_0.conda + sha256: c84034056dc938c853e4f61e72e5bd37e2ec91927a661fb9762f678cbea52d43 + md5: 5d3c008e54c7f49592fca9c32896a76f + depends: + - __glibc >=2.17,<3.0.a0 + - cffi + - libgcc >=14 + - libstdcxx >=14 + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + size: 15004 + timestamp: 1769438727085 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ukkonen-1.1.0-py310h0992a49_0.conda + sha256: 9547520cb3504f6acf364f4fa2447d19901360adae69701d7a3906458a7e3538 + md5: bac9c59669edb94e345b97412af6d283 + depends: + - cffi + - libgcc >=14 + - libstdcxx >=14 + - python >=3.10,<3.11.0a0 + - python >=3.10,<3.11.0a0 *_cpython + - python_abi 3.10.* *_cp310 + license: MIT + license_family: MIT + purls: + - pkg:pypi/ukkonen?source=hash-mapping + size: 15584 + timestamp: 1769438771691 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ukkonen-1.1.0-py311hfca10b7_0.conda + sha256: 8870876bc36f47d7aea163843e01399c37153c7f448335f629d37f276bfa5010 + md5: 07e977e2a642a2348385860eb6fa84e9 + depends: + - cffi + - libgcc >=14 + - libstdcxx >=14 + - python >=3.11,<3.12.0a0 + - python >=3.11,<3.12.0a0 *_cpython + - python_abi 3.11.* *_cp311 + license: MIT + license_family: MIT + purls: + - pkg:pypi/ukkonen?source=hash-mapping + size: 15709 + timestamp: 1769438766154 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ukkonen-1.1.0-py314hd7d8586_0.conda + sha256: 0a7efe469d7e2a34a1d017bc51cf6fb9a51436730256983694c5ad74a33bd4e0 + md5: f3a967efabf9cf450b7741487318ea6e + depends: + - cffi + - libgcc >=14 + - libstdcxx >=14 + - python >=3.14,<3.15.0a0 + - python >=3.14,<3.15.0a0 *_cp314 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + size: 15756 + timestamp: 1769438772414 +- conda: https://conda.anaconda.org/conda-forge/osx-64/ukkonen-1.0.1-py310h88cfcbd_4.conda + sha256: 662d357d36210e7cad2072e5e071b98fc18985ec36293f43139812efc29c6b4b + md5: 9b1aa3d9f02b72f2544ee531bb7ccea9 + depends: + - cffi + - libcxx >=15.0.7 + - python >=3.10,<3.11.0a0 + - python_abi 3.10.* *_cp310 + license: MIT + license_family: MIT + purls: + - pkg:pypi/ukkonen?source=hash-mapping + size: 13071 + timestamp: 1695549876888 +- conda: https://conda.anaconda.org/conda-forge/osx-64/ukkonen-1.0.1-py311h5fe6e05_4.conda + sha256: b273782a1277042a54e12411beebd378d2a2a69e503bcf147766e98628e91c91 + md5: 8f750b84128d48dc8376572c5eace61e + depends: + - cffi + - libcxx >=15.0.7 + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + license: MIT + license_family: MIT + purls: + - pkg:pypi/ukkonen?source=hash-mapping + size: 13193 + timestamp: 1695549883822 +- conda: https://conda.anaconda.org/conda-forge/osx-64/ukkonen-1.1.0-py314h473ef84_0.conda + sha256: a77214fabb930c5332dece5407973c0c1c711298bf687976a0b6a9207b758e12 + md5: 08a26dd1ba8fc9681d6b5256b2895f8e + depends: + - __osx >=10.13 + - cffi + - libcxx >=19 + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + size: 14286 + timestamp: 1769439103231 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/ukkonen-1.0.1-py310h38f39d4_4.conda + sha256: 3d668d21ba00d5e8c90c64cfaffc5bccd8b3349f584f1e96c7423f372289227a + md5: d44fc7ee5098e2cf4db125eda63878c6 + depends: + - cffi + - libcxx >=15.0.7 + - python >=3.10,<3.11.0a0 + - python >=3.10,<3.11.0a0 *_cpython + - python_abi 3.10.* *_cp310 + license: MIT + license_family: MIT + purls: + - pkg:pypi/ukkonen?source=hash-mapping + size: 13807 + timestamp: 1695549789224 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/ukkonen-1.0.1-py311he4fd1f5_4.conda + sha256: 384fc81a34e248019d43a115386f77859ab63e0e6f12dade486d76359703743f + md5: 5d5ab5c5af32931e03608034f4a5fd75 + depends: + - cffi + - libcxx >=15.0.7 + - python >=3.11,<3.12.0a0 + - python >=3.11,<3.12.0a0 *_cpython + - python_abi 3.11.* *_cp311 + license: MIT + license_family: MIT + purls: + - pkg:pypi/ukkonen?source=hash-mapping + size: 13958 + timestamp: 1695549884615 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/ukkonen-1.1.0-py314h6cfcd04_0.conda + sha256: 033dbf9859fe58fb85350cf6395be6b1346792e1766d2d5acab538a6eb3659fb + md5: e229f444fbdb28d8c4f40e247154d993 + depends: + - __osx >=11.0 + - cffi + - libcxx >=19 + - python >=3.14,<3.15.0a0 + - python >=3.14,<3.15.0a0 *_cp314 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + size: 14884 + timestamp: 1769439056290 +- conda: https://conda.anaconda.org/conda-forge/win-64/ukkonen-1.1.0-py310he9f1925_0.conda + sha256: f66932dc9e68950dae39a6ccd5ef00503e433414e25267185ff8416cb3be1282 + md5: f63f6904311dc01152f624c828ee24b5 + depends: + - cffi + - python >=3.10,<3.11.0a0 + - python_abi 3.10.* *_cp310 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: MIT + license_family: MIT + purls: + - pkg:pypi/ukkonen?source=hash-mapping + size: 18319 + timestamp: 1769438862573 +- conda: https://conda.anaconda.org/conda-forge/win-64/ukkonen-1.1.0-py311h3fd045d_0.conda + sha256: f30fdd8cdc5aa9800d6f05ed772d8e5b6427202c4bf2c86513ac62070215f19d + md5: fb1cf06b4259739eaa61d94bc219c0e8 + depends: + - cffi + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: MIT + license_family: MIT + purls: + - pkg:pypi/ukkonen?source=hash-mapping + size: 18452 + timestamp: 1769438859987 +- conda: https://conda.anaconda.org/conda-forge/win-64/ukkonen-1.1.0-py314h909e829_0.conda + sha256: 96990a5948e0c30788360836d94bf6145fdac0c187695ed9b3c2d61d9e11d267 + md5: 54e012b629ac5a40c9b3fa32738375dc + depends: + - cffi + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: MIT + license_family: MIT + size: 18504 + timestamp: 1769438844417 - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.5.0-pyhd8ed1ab_0.conda sha256: 4fb9789154bd666ca74e428d973df81087a697dbb987775bc3198d2215f240f8 md5: 436c165519e140cb08d246a4472a9d6a @@ -10732,6 +11490,24 @@ packages: purls: [] size: 115235 timestamp: 1767320173250 +- conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-21.2.0-pyhcf101f3_0.conda + sha256: b83246d145ba0e6814d2ed0b616293e56924e6c7d6649101f5a4f97f9e757ed1 + md5: 704c22301912f7e37d0a92b2e7d5942d + depends: + - python >=3.10 + - distlib >=0.3.7,<1 + - filelock <4,>=3.24.2 + - importlib-metadata >=6.6 + - platformdirs >=3.9.1,<5 + - python-discovery >=1 + - typing_extensions >=4.13.2 + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/virtualenv?source=compressed-mapping + size: 4647775 + timestamp: 1773133660203 - conda: https://conda.anaconda.org/conda-forge/win-64/vs2022_win-64-19.44.35207-ha74f236_34.conda sha256: 05bc657625b58159bcea039a35cc89d1f8baf54bf4060019c2b559a03ba4a45e md5: 1d699ffd41c140b98e199ddd9787e1e1 @@ -10793,6 +11569,76 @@ packages: purls: [] size: 235693 timestamp: 1660346961024 +- conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h280c20c_3.conda + sha256: 6d9ea2f731e284e9316d95fa61869fe7bbba33df7929f82693c121022810f4ad + md5: a77f85f77be52ff59391544bfe73390a + depends: + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + license: MIT + license_family: MIT + purls: [] + size: 85189 + timestamp: 1753484064210 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/yaml-0.2.5-h80f16a2_3.conda + sha256: 66265e943f32ce02396ad214e27cb35f5b0490b3bd4f064446390f9d67fa5d88 + md5: 032d8030e4a24fe1f72c74423a46fb88 + depends: + - libgcc >=14 + license: MIT + license_family: MIT + purls: [] + size: 88088 + timestamp: 1753484092643 +- conda: https://conda.anaconda.org/conda-forge/osx-64/yaml-0.2.5-h0d85af4_2.tar.bz2 + sha256: 5301417e2c8dea45b401ffee8df3957d2447d4ce80c83c5ff151fc6bfe1c4148 + md5: d7e08fcf8259d742156188e8762b4d20 + license: MIT + license_family: MIT + purls: [] + size: 84237 + timestamp: 1641347062780 +- conda: https://conda.anaconda.org/conda-forge/osx-64/yaml-0.2.5-h4132b18_3.conda + sha256: a335161bfa57b64e6794c3c354e7d49449b28b8d8a7c4ed02bf04c3f009953f9 + md5: a645bb90997d3fc2aea0adf6517059bd + depends: + - __osx >=10.13 + license: MIT + license_family: MIT + size: 79419 + timestamp: 1753484072608 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/yaml-0.2.5-h3422bc3_2.tar.bz2 + sha256: 93181a04ba8cfecfdfb162fc958436d868cc37db504c58078eab4c1a3e57fbb7 + md5: 4bb3f014845110883a3c5ee811fd84b4 + license: MIT + license_family: MIT + purls: [] + size: 88016 + timestamp: 1641347076660 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/yaml-0.2.5-h925e9cb_3.conda + sha256: b03433b13d89f5567e828ea9f1a7d5c5d697bf374c28a4168d71e9464f5dafac + md5: 78a0fe9e9c50d2c381e8ee47e3ea437d + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + size: 83386 + timestamp: 1753484079473 +- conda: https://conda.anaconda.org/conda-forge/win-64/yaml-0.2.5-h6a83c73_3.conda + sha256: 80ee68c1e7683a35295232ea79bcc87279d31ffeda04a1665efdb43cbd50a309 + md5: 433699cba6602098ae8957a323da2664 + depends: + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + license: MIT + license_family: MIT + purls: [] + size: 63944 + timestamp: 1753484092156 - conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-cpp-0.8.0-h3f2d84a_0.conda sha256: 4b0b713a4308864a59d5f0b66ac61b7960151c8022511cdc914c0c0458375eca md5: 92b90f5f7a322e74468bb4909c7354b5 diff --git a/pixi.toml b/pixi.toml index d9e5c991..d69ee48d 100644 --- a/pixi.toml +++ b/pixi.toml @@ -175,9 +175,16 @@ windows-py311 = ["py311", "build-dev-tools", "python-dev-pkgs", "windows-build"] pixi-pycharm = ">=0.0.10,<0.0.11" conda = "*" taplo = ">=0.8.1,<0.11" +pre-commit = "*" [tasks] taplo = "fmt pixi.toml" [tasks.build-itk-wheels] cmd = ["python", "scripts/build_wheels.py"] + +[tasks.pre-commit-install] +cmd = "pre-commit install -f -t pre-commit -t prepare-commit-msg -t commit-msg --hook-type commit-msg --install-hooks" + +[tasks.pre-commit-run] +cmd = "pre-commit run --all-files" diff --git a/scripts/lint-shell-scripts.sh b/scripts/lint-shell-scripts.sh deleted file mode 100755 index 47e10c9a..00000000 --- a/scripts/lint-shell-scripts.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/bash - -set -e -set -o pipefail - -SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" - -pushd $SCRIPT_DIR > /dev/null - -docker run --rm -it \ - --name df-shellcheck \ - -v $(pwd):/usr/src:ro \ - --workdir /usr/src \ - r.j3ss.co/shellcheck ./internal/shellcheck-run.sh - -exit_code=$? - -popd > /dev/null - -exit $exit_code From e3a9da83c591ad522048d089140b64b808b928fb Mon Sep 17 00:00:00 2001 From: Cavan Riley Date: Wed, 18 Mar 2026 12:11:28 -0500 Subject: [PATCH 06/27] DOC: Update online docs and infrastructure for docs generation --- .readthedocs.yml | 13 + docs/Build_ITK_Module_Python_packages.rst | 410 ++++++++++------- docs/Build_ITK_Python_packages.rst | 533 ++++++++++++---------- docs/Miscellaneous.rst | 2 +- docs/Prerequisites.rst | 57 ++- docs/_static/custom.css | 29 ++ docs/conf.py | 94 ++-- docs/index.rst | 62 ++- docs/requirements-docs.txt | 4 +- 9 files changed, 711 insertions(+), 493 deletions(-) create mode 100644 .readthedocs.yml create mode 100644 docs/_static/custom.css diff --git a/.readthedocs.yml b/.readthedocs.yml new file mode 100644 index 00000000..72aeff6c --- /dev/null +++ b/.readthedocs.yml @@ -0,0 +1,13 @@ +version: 2 + +build: + os: ubuntu-22.04 + tools: + python: "3.11" + +sphinx: + configuration: docs/conf.py + +python: + install: + - requirements: docs/requirements-docs.txt diff --git a/docs/Build_ITK_Module_Python_packages.rst b/docs/Build_ITK_Module_Python_packages.rst index dd88d7b9..88e0152f 100644 --- a/docs/Build_ITK_Module_Python_packages.rst +++ b/docs/Build_ITK_Module_Python_packages.rst @@ -1,238 +1,322 @@ ===================================== -Build ITK Module Python packages -====================================== - -ITK is organized into *modules*. Modules for ITK can be developed outside the -ITK source tree as *remote modules*. The *remote module* can be made -available in ITK's `CMake `_ configuration by -`contributing it -`_ -as a *remote module*. Python packages can also be generated for remote -modules and uploaded to the `Python Package Index (PyPI) `_ +Build ITK Module Python Packages +===================================== -This section describes how to create, build, and upload ITK remote -module Python packages to PyPI. +ITK is organized into *modules*. Community members can extend ITK by developing +an ITK *external module* in a separate repository. When a module meets community +standards for documentation and maintenance it may be included in the ITK build +as a *remote module*. +This section describes how to create, build, and publish Python packages for +ITK remote and external modules to PyPI. -.. include:: Prerequisites.rst +Create a Module +=============== -Create the module -================= - -To create an ITK module with Python wrapping, first run cookiecutter:: +To scaffold a new ITK module with Python wrapping, use the official template:: python -m pip install cookiecutter python -m cookiecutter gh:InsightSoftwareConsortium/ITKModuleTemplate # Fill in the information requested at the prompts +Fill in the prompts, then add your C++ filter classes. See +`Chapter 9 of the ITK Software Guide +`_ +for guidance on populating the module and writing ``.wrap`` files for SWIG. -Then, add your classes. Reference documentation on `how to populate the module -`_ -can be found in the `ITK Software Guide -`_. +GitHub Actions Workflows +============================== -GitHub automated CI package builds -================================== +For most ITK external modules, the recommended and easiest path to building, testing, and +publishing Python wheels is the +`ITKRemoteModuleBuildTestPackageAction +`_ +reusable workflow. It handles fetching, configuring, and running +ITKPythonPackage build scripts automatically. -Freely available GitHub Actions continous integration (CI) build and test -services for open source repositories are provided by -`GitHub `_. These services will build and test the C++ -code for your module and also generate Linux, macOS, and Windows Python -packages for your module. +Every pull request and push triggers a build that: -For every pull request and push to the GitHub repository, a GitHub Action will -run that builds and runs the repository's C++ tests and reports the results to -the `ITK CDash Dashboard `_. -Python packages are also generated for every commit. Packages for a commit's -build can be downloaded from the GitHub Action result page in the *Artifacts* -Section. +- Compiles and runs your module's C++ tests +- Generates Linux, macOS, and Windows Python wheels + +Wheel artifacts are downloadable from the **Artifacts** section of the +GitHub Actions run page. .. figure:: images/GitHubActionArtifacts.png - :alt: GitHub Action Artifacts + :alt: GitHub Action Artifacts + +To pin the specific ITKPythonPackage version used by the workflow (defaults are shown below): -Reusable workflows available in -[ITKRemoteModuleBuildTestPackageAction](https://github.com/InsightSoftwareConsortium/ITKRemoteModuleBuildTestPackageAction) -can be used to handle the build-test-package process -for a majority of ITK external modules with minimal extra development. +.. code-block:: yaml -Upload the packages to PyPI ----------------------------- + uses: InsightSoftwareConsortium/ITKRemoteModuleBuildTestPackageAction/.github/workflows/build-test-package.yml@v5.4.5 + with: + itk-python-package-org: InsightSoftwareConsortium + itk-python-package-tag: main + +.. include:: Prerequisites.rst -First, `register for an account on PyPI `_. +Manual Builds +============= -Next, create a `~/.pypirc` file with your login credentials:: +For cases where the reusable workflow is not a good fit, the +download-and-build scripts can be run locally. Each script: - [distutils] - index-servers = - pypi - pypitest +1. Downloads and installs the necessary build packages +2. Downloads the pre-built ITK binary tarball for the target platform from + `ITKPythonBuilds `_ +3. Extracts it to a local build directory +4. Builds your module wheels against the pre-built ITK - [pypi] - username= - password= +.. important:: + Place and run the script from your module's root directory. Or specify exact paths using the environment variables below - [pypitest] - repository=https://test.pypi.org/legacy/ - username= - password= +Set the ITK PEP 440 compliant version before running any script:: -where `` and `` correspond to your PyPI account. + export ITK_PACKAGE_VERSION=v6.0b01 # Linux / macOS + $env:ITK_PACKAGE_VERSION = "v6.0b01" # Windows PowerShell -Then, upload wheels to the testing server. The wheels of dist/* are those that -you have built locally or have downloaded from a recent build listed at -`https://github.com/InsightSoftwareConsortium//actions`. -:: +Linux (manylinux) +----------------- - python -m pip install twine - python -m twine upload -r pypitest dist/* +Requires Docker. Produces ``manylinux_2_28`` portable wheels. -Check out the packages on ``_ the testing server. +.. code-block:: bash -Finally, upload the wheel packages to the production PyPI server:: + cd ~/ITKMyModule + # First build — downloads ITK cache, then builds module wheels + export MODULE_SRC_DIRECTORY=/path/to/module + bash ITKPythonPackage/scripts/dockcross-manylinux-download-cache-and-build-module-wheels.sh cp310 - python -m twine upload dist/* + # Subsequent builds — reuses the downloaded cache + bash ITKPythonPackage/scripts/dockcross-manylinux-build-module-wheels.sh cp310 -Congratulations! Your packages can be installed with the commands:: +Omit the Python version argument to build all supported versions (cp310 and cp311): - python -m pip install --upgrade pip - python -m pip install itk- +.. code-block:: bash -where `itk-` is the short name for your module that is -specified in the configured `pyproject.toml` file. + export MODULE_SRC_DIRECTORY=/path/to/module + bash ITKPythonPackage/scripts/dockcross-manylinux-download-cache-and-build-module-wheels.sh -Automate PyPI Package Uploads ------------------------------ +macOS +----- -Automated uploads of Python packages to the Python package index, `PyPI -`_ will occur after adding a PyPI upload token to GitHub and -creating a Git tag. Create a PyPI API token by logging in to -``_. Generally, for the token name -use:: +.. code-block:: bash - itk--github-action + cd ~/ITKMyModule + export MODULE_SRC_DIRECTORY=/path/to/module + bash ITKPythonPackage/scripts/macpython-download-cache-and-build-module-wheels.sh 3.10 3.11 -and for the scope use:: +Windows +------- - itk- +Open a PowerShell terminal: + +.. code-block:: powershell + + cd C:\ITKMyModule + $env:ITK_PACKAGE_VERSION = "v6.0b01" + $env:MODULE_SRC_DIRECTORY = /path/to/module + .\ITKPythonPackage\scripts\windows-download-cache-and-build-module-wheels.ps1 -python_version_minor 10 + +Build multiple Python versions: + +.. code-block:: powershell + + foreach ($v in @(10, 11)) { + .\ITKPythonPackage\scripts\windows-download-cache-and-build-module-wheels.ps1 -python_version_minor $v + } + +.. important:: + Use a short build path (e.g. ``C:\BDR``) to avoid Windows 260-character + path length limits. See the Troubleshooting section in + :doc:`Build_ITK_Python_packages` for details. -where `` is the short name for your module that is -specified in your configured `pyproject.toml` file. That scope will be available if you have -already uploaded a first set of wheels via twine as described above; and that -is the recommended approach. Otherwise, if you are creating the project at -this time, choose an unlimited scope, but be careful with the created token. +Key environment variables: + +.. list-table:: + :header-rows: 1 + :widths: 30 20 50 + + * - Variable + - Default + - Description + * - ``ITK_PACKAGE_VERSION`` + - ``v6.0b01`` + - PEP 440 ITK release to build against + * - ``TARGET_ARCH`` + - ``x64`` + - ``x64`` or ``aarch64`` + * - ``IMAGE_TAG`` + - ``20250913-6ea98ba`` + - Dockcross Docker image tag + * - ``MODULE_SRC_DIRECTORY`` + - script directory + - Path to your module source + * - ``MODULE_DEPS_DIR`` + - platform dependant + - Root directory for module dependency checkouts + * - ``DASHBOARD_BUILD_DIRECTORY`` + - platform dependant + - Root directory for build artifacts + * - ``MANYLINUX_VERSION`` + - ``_2_28`` + - Manylinux compatibility standard + * - ``CMAKE_OPTIONS`` + - *(empty)* + - Extra CMake ``-D`` definitions + * - ``ITKPYTHONPACKAGE_TAG`` + - ``main`` + - ITKPythonPackage branch/tag to fetch + * - ``ITKPYTHONPACKAGE_ORG`` + - ``InsightSoftwareConsortium`` + - ITKPythonPackage organization to fetch + * - ``NO_SUDO`` + - *(unset)* + - Set to skip ``sudo`` for Docker commands + * - ``DYLD_LIBRARY_PATH`` + - *(unset)* + - Extra library paths to bundle into wheels -.. figure:: images/PyPIToken.png - :alt: PyPI Token -Then, add the API token to the GitHub repository -`https://github.com/InsightSoftwareConsortium/`. Choose -the *Settings -> Secrets* page and add a key called *pypi_password*, setting -the password to be the token string that begins with `pypi-`. Note that this -will be a *token* instead of a password. Limit the scope of the token to the -individual package as a best practice. +Use the Build Script Directly +==================================== -.. figure:: images/GitHubPyPISecret.png - :alt: GitHub PyPI token secret +For more control over build option, call ``build_wheels.py`` directly with +``--module-source-dir``. This approach will create a local ITK build by default: -To push packages to PyPI, first, make sure to update the `version` for your -package in the *pyproject.toml* file. The initial version might be `0.1.0` or -`1.0.0`. Subsequent versions should follow -`semantic versioning `_. +.. code-block:: bash -Then, create a Git tag corresponding to the version. A Git tag can be created -in the GitHub user interface via *Releases -> Draft a new release*. + pixi run python3 scripts/build_wheels.py \ + --platform-env macosx-py310 \ + --itk-git-tag v6.0b01 \ + --module-source-dir /path/to/ITKMyModule \ + --no-skip-itk-build \ + --no-skip-itk-wheel-build \ + --no-build-itk-tarball-cache -.. figure:: images/GitHubReleaseTag.png - :alt: GitHub Release Tag +Module Dependencies +=================== -Automated platform scripts -========================== +If your module depends on other ITK external modules, list them with +``--itk-module-deps`` (or the ``ITK_MODULE_PREQ`` environment variable for the +shell scripts): -Automated scripts are available in this repository to build Python packages -that are binary compatible with the Python distributions provided by -Python.org, Anaconda, and package managers like apt or Homebrew. -The following sections outline how to use the associated scripts for Linux, -macOS, and Windows. +.. code-block:: bash -Once the builds are complete, Python packages will be available in the `dist` -directory. + pixi run python3 scripts/build_wheels.py \ + --platform-env macosx-py310 \ + --itk-git-tag v6.0b01 \ + --module-source-dir /path/to/ITKMyModule \ + --itk-module-deps "InsightSoftwareConsortium/ITKMeshToPolyData@v1.0.0" \ + --no-build-itk-tarball-cache -Linux ------ +For multiple dependencies, separate them with colons in **dependency order** +(each module listed before the modules that depend on it): -To build portable Python packages on Linux, first `install Docker -`_. +.. code-block:: bash -For the first local build, clone the `ITKPythonPackage` repository inside your -and download the required ITK binary builds:: + --itk-module-deps "org/ITKModA@v1.0:org/ITKModB@v2.1:org/ITKModC@main" - cd ~/ITKMyModule - git clone https://github.com/InsightSoftwareConsortium/ITKPythonPackage - ./ITKPythonPackage/scripts/dockcross-manylinux-download-cache-and-build-module-wheels.sh +The format for each entry is ``/@``. -For subsequent builds, just call the build script:: +For the download-and-build shell scripts, set ``ITK_MODULE_PREQ`` instead: - ./ITKPythonPackage/scripts/dockcross-manylinux-build-module-wheels.sh +.. code-block:: bash -macOS ------ + export ITK_MODULE_PREQ="org/ITKModA@v1.0:org/ITKModB@v2.1" + bash ITKPythonPackage/scripts/dockcross-manylinux-download-cache-and-build-module-wheels.sh cp310 -First, install the Python.org macOS Python distributions. This step requires sudo:: +Dependencies are cloned to ``/`` before the +main module build begins. - cd ~/ITKMyModule - git clone https://github.com/InsightSoftwareConsortium/ITKPythonPackage - ./ITKPythonPackage/scripts/macpython-install-python.sh -Then, build the wheels:: +Third-Party Libraries +===================== - ./ITKPythonPackage/scripts/macpython-build-wheels.sh +If your module links against a third-party library that is not part of ITK, +the wheel repair tools (``auditwheel``, ``delocate``, ``delvewheel``) need +to be able to find it to bundle it into the wheel. -Windows -------- +**Linux**: add the library's directory to ``LD_LIBRARY_PATH`` before running +the build script:: + + export LD_LIBRARY_PATH=/path/to/mylib/lib:$LD_LIBRARY_PATH + +**macOS**: add the directory to ``DYLD_LIBRARY_PATH``:: + + export DYLD_LIBRARY_PATH=/path/to/mylib/lib:$DYLD_LIBRARY_PATH + +**Windows**: pass the library directory via ``--lib-paths`` (or the +``-setup_options`` parameter of the PowerShell script): + +.. code-block:: powershell + + .\windows-download-cache-and-build-module-wheels.ps1 ` + -python_version_minor 10 ` + -setup_options "--exclude-libs nvcuda.dll" + + +Output +====== + +Finished wheels are placed in ``dist/`` inside your module directory +(or ``/dist/`` when running ``build_wheels.py`` directly). + +Example output:: + + dist/ + itk-mymodule-1.0.0-cp310-cp310-manylinux_2_28_x86_64.whl + itk-mymodule-1.0.0-cp310-cp310-macosx_13_0_arm64.whl + itk-mymodule-1.0.0-cp310-cp310-win_amd64.whl + + +Uploading to PyPI +================= + +Manual Upload +------------- + +Test on TestPyPI first:: + + pip install twine + twine upload -r testpypi dist/*.whl -First, install Microsoft Visual Studio 2022, Git, and CMake, which should be added to the system PATH environmental variable. +Then upload to production PyPI:: -Open a PowerShell terminal as Administrator, and install Python:: + twine upload dist/*.whl - PS C:\> Set-ExecutionPolicy Unrestricted - PS C:\> $pythonArch = "64" - PS C:\> iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/scikit-build/scikit-ci-addons/master/windows/install-python.ps1')) +Your package can then be installed with:: -In a PowerShell prompt, run the `windows-build-wheels.ps1` script:: + pip install itk- - PS C:\Windows> cd C:\ITKMyModule - PS C:\ITKMyModule> git clone https://github.com/InsightSoftwareConsortium/ITKPythonPackage.git IPP - PS C:\ITKMyModule> .\ITKPythonPackage\scripts\windows-download-cache-and-build-module-wheels.ps1 +Automated Upload via GitHub Actions +------------------------------------- -Other Notes ------------ +To automate publishing on every tagged release: -ITK modules sometimes depend on third-party libraries. To include third-party libraries -in development wheels for distribution, first add the library path to `LD_LIBRARY_PATH` -on Linux, `DYLD_LIBRARY_PATH` on MacOS, or `PATH` on Windows. Then, run the platform -build script. +1. Create a PyPI API token at ``_. + Name it ``itk--github-action`` and scope it to your + package (scope becomes available after the first manual upload). -ITK modules sometimes depend on other ITK modules. For instance, to build -[ITKBSplineGradient](https://github.com/InsightSoftwareConsortium/ITKBSplineGradient) -the user must first build ITK and then [ITKMeshToPolyData](https://github.com/InsightSoftwareConsortium/ITKmeshtopolydata). -ITKPythonPackage scripts support iterative prerequisite ITK module dependencies with the `ITK_MODULE_PREQ` -environment variable. + .. figure:: images/PyPIToken.png + :alt: PyPI Token -For Python build scripts, the ordered list of ITK module dependencies must be formatted as follows: +2. In your GitHub repository, go to **Settings → Secrets → Actions** and + add a secret named ``pypi_password`` with the token value (starts with + ``pypi-``). -``` -ITK_MODULE_PREQ=/@:/@:... -``` + .. figure:: images/GitHubPyPISecret.png + :alt: GitHub PyPI token secret -Where -- `module_org` is the name of a Github organization to use to fetch the module, i.e. "InsightSoftwareConsortium"; -- `module_name` is the name of the module, i.e. "ITKMeshToPolyData"; -- `module_tag` is the git tag or commit hash to use to fetch the module, i.e. "v1.0.0" +3. Create a GitHub Release (via **Releases → Draft a new release**). + The tag name should match the version in your ``pyproject.toml``. -Module names must be provided in order of dependencies for the build to succeed. + .. figure:: images/GitHubReleaseTag.png + :alt: GitHub Release Tag -For more information see the -[build scripts directory](https://github.com/InsightSoftwareConsortium/ITKPythonPackage/tree/master/scripts). +The ``ITKRemoteModuleBuildTestPackageAction`` workflow will detect the tag +and upload wheels automatically. diff --git a/docs/Build_ITK_Python_packages.rst b/docs/Build_ITK_Python_packages.rst index f3856317..8ecd535c 100644 --- a/docs/Build_ITK_Python_packages.rst +++ b/docs/Build_ITK_Python_packages.rst @@ -1,14 +1,13 @@ -====================================== -Build ITK Python packages -====================================== +============================== +Build ITK Python Packages +============================== -This section describes how to builds ITK's Python packages. In most cases, the -:ref:`pre-built ITK binary wheels can be used `. - -ITK Python packages are built nightly on Kitware build systems and uploaded to -the `ITKPythonPackage GitHub releases page -`_. +This section describes how to build ITK's core Python wheels +(``itk-core``, ``itk-numerics``, ``itk-io``, ``itk-filtering``, +``itk-registration``, ``itk-segmentation``, and ``itk-meta``). In most cases, the pre-built ITK binary wheels can be used. +You may only need to build ITK from source if you need a custom patch, a specific unreleased +commit, or are developing ITK core itself. .. include:: Prerequisites.rst @@ -19,167 +18,329 @@ Steps required to build wheels on Linux, macOS and Windows have been automated. The following sections outline how to use the associated scripts. -Setup Instructions -================== +Overview +======== -1. Clone the ITKPythonPackage repository:: +The build is driven by ``scripts/build_wheels.py``, which orchestrates up to +seven sequential steps: - $ git clone https://github.com/InsightSoftwareConsortium/ITKPythonPackage.git - $ cd ITKPythonPackage +1. Build SuperBuild support components (oneTBB and other ITK dependencies) +2. Build ITK C++ with Python wrapping +3. Build Python wheels for each ITK subpackage +4. Fix up wheels if platform requires (``auditwheel`` / ``delocate`` / ``delvewheel``) +5. Import test +6. *(optional)* Build a remote module against the ITK build +7. *(optional)* Create a reusable ITK build tarball cache -.. note:: - You can replace ``InsightSoftwareConsortium`` with a different organization if using a fork. +Step state is persisted to ``/dist/build_report-.json`` so that a +build interrupted part-way through can be resumed by re-running the same command. -2. Configure the build environment (optional) -The following environment variables can be set to customize the build: +Setup +===== -**MODULE_SRC_DIRECTORY** - Directory where the ITK remote module is located. Default: Current Directory +Clone the repository:: -**DASHBOARD_BUILD_DIRECTORY** - Directory where build artifacts will be created. Default: /Users/svc-dashboard/D/P + git clone https://github.com/InsightSoftwareConsortium/ITKPythonPackage.git + cd ITKPythonPackage -**ITK_GIT_TAG** - ITK version to build (branch name or commit hash). Default: ``main`` -**ITK_PACKAGE_VERSION** - ITK version tag to build against. Essentially the same as ITK_GIT_TAG for backwards compatability +Platform Environments +===================== -**TARGET_ARCH** - Target architecture. Default: ``x64`` (Linux), auto-detected (macOS) +Each Pixi environment targets a specific OS and Python version. Pass the +environment name to ``--platform-env``: -**ITKPYTHONPACKAGE_ORG** - GitHub organization hosting ITKPythonPackage. Default: ``InsightSoftwareConsortium`` +.. list-table:: + :header-rows: 1 + :widths: 30 70 -**ITKPYTHONPACKAGE_TAG** - Optional: specific tag/branch of build scripts to use. Default: ``main`` + * - ``--platform-env`` + - Notes + * - ``linux-py310`` + - Native Linux (GCC, glibc of host) + * - ``linux-py311`` + - Native Linux (GCC, glibc of host) + * - ``manylinux228-py310`` + - Portable Linux ≥ glibc 2.28 (x86_64 or aarch64 via Docker) + * - ``manylinux228-py311`` + - Portable Linux ≥ glibc 2.28 (x86_64 or aarch64 via Docker) + * - ``macosx-py310`` + - macOS (x86_64 and arm64) + * - ``macosx-py311`` + - macOS (x86_64 and arm64) + * - ``windows-py310`` + - Windows x86_64 (MSVC 2022) + * - ``windows-py311`` + - Windows x86_64 (MSVC 2022) -**MANYLINUX_VERSION** (manylinux only) - Manylinux standard version. Default: ``_2_28`` +If ``--platform-env`` is omitted, the platform is auto-detected from the +host OS and defaults to Python 3.10. -**IMAGE_TAG** (Linux only) - Docker image tag for manylinux builds. Default: ``20250913-6ea98ba`` +Building Wheels +=============== -For example:: +manylinux +--------- - $ export ITK_GIT_TAG=v5.4.0 - $ export MANYLINUX_VERSION=_2_28 +On any linux distribution with docker and bash installed, running the script dockcross-manylinux-build-wheels.sh will create 64-bit wheels for python 3.10+ in the dist directory. +.. code-block:: bash -Building Wheels -=============== + ./scripts/dockcross-manylinux-build-wheels.sh # py310 optionally specify python version -All build processes download pre-built ITK artifacts and builds wheels -using from the `ITKPythonBuilds repository `_ distributions. +Or you can build using a specific platform environment using: Linux ----- -You can download the Python builds for your specific system and architecture using the following script:: - - $ ./scripts/dockcross-manylinux-download-cache.sh +.. code-block:: bash -On any linux distribution with docker and bash installed, running the script `dockcross-manylinux-build-wheels.sh` will create 64-bit wheels for python 3.9+ in the dist directory.:: + pixi run python3 scripts/build_wheels.py \ + --platform-env linux-py310 \ + --itk-git-tag v6.0b01 \ + --no-build-itk-tarball-cache - $ ./scripts/dockcross-manylinux-build-wheels.sh +macOS +----- -Build for specific Python version(s):: +.. code-block:: bash - $ ./scripts/dockcross-manylinux-build-wheels.sh cp310 - $ ./scripts/dockcross-manylinux-build-wheels.sh cp39 cp310 cp311 + pixi run python3 scripts/build_wheels.py \ + --platform-env macosx-py310 \ + --itk-git-tag v6.0b01 \ + --no-build-itk-tarball-cache -.. note:: - Python versions can be specified as ``cp39``, ``cp310``, ``cp311``, or - ``py39``, ``py310``, ``py311`` - both formats are supported. +Windows +------- -After the build completes, wheels will be located in the `DASHBOARD_BUILD_DIRECTORY` directory, for example:: +Similarly, on windows - $ ls -1 ${DASHBOARD_BUILD_DIRECTORY}/ITKPythonPackage-build/dist/ - itk-6.0.0-cp39-cp39-manylinux_2_28_x86_64.whl - itk-6.0.0-cp310-cp310-manylinux_2_28_x86_64.whl - itk-6.0.0-cp311-cp311-manylinux_2_28_x86_64.whl +.. code-block:: powershell -macOS ------ + pixi run python3 scripts/build_wheels.py ` + --platform-env windows-py310 ` + --itk-git-tag v6.0b01 ` + --no-build-itk-tarball-cache -Build all default Python versions:: - $ ./scripts/macpython-download-cache-and-build-module-wheels.sh +Finished wheels are placed in ``/dist/``. -Build for specific Python version(s):: +.. note:: + Building ITK from source takes 1–2 hours on typical hardware. Pass + ``--build-itk-tarball-cache`` to save the result as a reusable tarball + and avoid rebuilding on subsequent runs. + + +Key Options +=========== + +.. list-table:: + :header-rows: 1 + :widths: 35 15 50 + + * - Option + - Default + - Description + * - ``--platform-env`` + - auto-detected + - Target platform and Python version (see table above) + * - ``--itk-git-tag`` + - ``main`` + - ITK version, branch, or commit to build + * - ``--itk-package-version`` + - auto (git describe) + - PEP 440 version string embedded in the wheels + * - ``--build-dir-root`` + - ``../ITKPythonPackage-build`` + - Root directory for all build artifacts + * - ``--manylinux-version`` + - ``_2_28`` + - Manylinux compatibility standard (e.g. ``_2_28``, ``_2_34``) + * - ``--itk-source-dir`` + - cloned automatically + - Path to a local ITK checkout (skips git clone) + * - ``--module-source-dir`` + - *(none)* + - Path to an ITK external module to build against the ITK build + * - ``--itk-module-deps`` + - *(none)* + - Colon-delimited prerequisite modules (``org/repo@tag:org/repo@tag``) + * - ``--build-itk-tarball-cache`` + - off + - Package the ITK build as a reusable ``.tar.zst`` / ``.zip`` + * - ``--no-build-itk-tarball-cache`` + - *(default)* + - Skip tarball generation + * - ``--skip-itk-build`` / ``--no-skip-itk-build`` + - off + - Skip step 2 (ITK C++ build) when a build already exists + * - ``--skip-itk-wheel-build`` / ``--no-skip-itk-wheel-build`` + - off + - Skip step 3 (wheel build) when wheels already exist + * - ``--cleanup`` + - off + - Remove intermediate build files after completion + * - ``--use-ccache`` + - off + - Enable ccache to speed up recompilation + * - ``--macosx-deployment-target`` + - ``10.7`` + - Minimum macOS version for compiled binaries + * - ``--use-sudo`` / ``--no-use-sudo`` + - off + - Pass ``sudo`` to Docker commands (manylinux only) + +Any remaining positional arguments are forwarded to CMake as ``-D`` definitions, +for example:: + + pixi run python3 scripts/build_wheels.py \ + --platform-env macosx-py310 \ + --itk-git-tag v6.0b01 \ + -DBUILD_SHARED_LIBS:BOOL=OFF + + +Environment Variable Equivalents +--------------------------------- + +All ``--`` options can alternatively be set as environment variables, which is +useful in CI pipelines: + +.. list-table:: + :header-rows: 1 + :widths: 35 65 + + * - Environment Variable + - Equivalent Option + * - ``ITK_GIT_TAG`` + - ``--itk-git-tag`` + * - ``ITK_PACKAGE_VERSION`` + - ``--itk-package-version`` + * - ``ITK_SOURCE_DIR`` + - ``--itk-source-dir`` + * - ``MANYLINUX_VERSION`` + - ``--manylinux-version`` + * - ``TARGET_ARCH`` + - target architecture (``x64`` or ``aarch64``) + * - ``IMAGE_TAG`` + - Docker image tag for manylinux builds + * - ``NO_SUDO`` + - ``--no-use-sudo`` + * - ``USE_CCACHE`` + - ``--use-ccache`` + * - ``CMAKE_OPTIONS`` + - extra CMake ``-D`` definitions + * - ``MACOSX_DEPLOYMENT_TARGET`` + - ``--macosx-deployment-target`` + + +Building from a Local ITK Source +================================= + +If you have a local ITK checkout with custom patches or an unreleased fix, pass +``--itk-source-dir`` to use it instead of cloning from GitHub: + +.. code-block:: bash + + pixi run python3 scripts/build_wheels.py \ + --platform-env macosx-py310 \ + --itk-source-dir /path/to/your/ITK \ + --itk-git-tag my-bugfix-branch \ + --no-build-itk-tarball-cache + +For manylinux, use the shell wrapper which handles Docker volume mounting: + +.. code-block:: bash + + ITK_SOURCE_DIR=/path/to/your/ITK \ + bash scripts/dockcross-manylinux-build-wheels.sh cp310 + + +Building ITK Tarball Caches +============================ + +Tarball caches package the entire ITK build output (headers, libraries, wrapper +artifacts) so that external module builds can skip the costly ITK compilation step. +These are the same caches distributed via `ITKPythonBuilds +`_ releases. + +By default these scripts build for python version 3.10 and 3.11 but you can optionally add a specific version to build for + +Linux / macOS: + +.. code-block:: bash + + ITK_GIT_TAG=v6.0b01 + bash scripts/make_tarballs.sh py310 - $ ./scripts/macpython-download-cache-and-build-module-wheels.sh py310 - $ ./scripts/macpython-download-cache-and-build-module-wheels.sh py39 py310 py311 +Windows (PowerShell): +.. code-block:: powershell -After the build completes, similarly, builds can be found in:: + $env:ITK_GIT_TAG = "v6.0b01" + .\scripts\make_windows_zip.ps1 py310 - $ ls -1 ${DASHBOARD_BUILD_DIRECTORY}/ITKPythonPackage-build/dist/ - itk-6.0.0-cp39-cp39-macosx_10_9_x86_64.whl - itk-6.0.0-cp310-cp310-macosx_10_9_x86_64.whl - itk-6.0.0-cp311-cp311-macosx_10_9_x86_64.whl +Or via ``build_wheels.py`` directly: -Windows -------- +.. code-block:: bash -.. important:: - We need to work in a short directory to avoid path length limitations on - Windows. The examples below use ``C:\IPP`` for this reason. + pixi run python3 scripts/build_wheels.py \ + --platform-env macosx-py310 \ + --itk-git-tag v6.0b01 \ + --build-itk-tarball-cache .. important:: - Disable antivirus checking on the build directory (e.g., ``C:\IPP``). - The build system creates and deletes many files quickly, which can conflict - with antivirus software and result in "Access Denied" errors. Windows - Defender should be configured to exclude this directory. - -Open a PowerShell terminal as Administrator, and install Python:: - - PS C:\> Set-ExecutionPolicy Unrestricted - PS C:\> $pythonArch = "64" - PS C:\> iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/scikit-build/scikit-ci-addons/master/windows/install-python.ps1')) + Build caches embed absolute paths. They must be extracted to the same path + they were built from or CMake will fail to locate required files. The + standard CI/CD paths are: -In a PowerShell prompt, clone into a short path:: + - **manylinux (Docker)**: ``/work/ITKPythonPackage-build`` + - **macOS**: ``/Users/svc-dashboard/D/P/ITKPythonPackage-build`` + - **Windows**: ``C:\BDR`` - PS C:\> cd C:\ - PS C:\> git clone https://github.com/InsightSoftwareConsortium/ITKPythonPackage.git IPP - PS C:\> cd IPP + The ``make_tarballs.sh`` and ``make_windows_zip.ps1`` scripts enforce these + paths automatically. -After the build completes:: - PS C:\IPP> ls dist - Directory: C:\IPP\dist +Output Artifacts +================ - Mode LastWriteTime Length Name - ---- ------------- ------ ---- - -a---- 1/1/2026 11:14 PM 63274441 itk-6.0.0-cp39-cp39-win_amd64.whl - -a---- 1/1/2026 11:45 PM 63257220 itk-6.0.0-cp310-cp310-win_amd64.whl +.. list-table:: + :header-rows: 1 + :widths: 30 70 + * - Artifact + - Location + * - Built wheels + - ``/dist/*.whl`` + * - Effective command line + - ``/effective_cmdline_.sh`` + * - manylinux tarball caches + - ``/ITKPythonBuilds-manylinux_2_28-*.tar.zst`` + * - Linux tarball caches + - ``/ITKPythonBuilds-linux-*.tar.zst`` + * - macOS tarball caches + - ``/ITKPythonBuilds-macosx-*.tar.zst`` + * - Windows ZIP cache + - ``/ITKPythonBuilds-windows.zip`` -Testing and Deployment -====================== +Example wheel names:: -Testing Wheels Locally ----------------------- + itk-6.0.0-cp310-cp310-manylinux_2_28_x86_64.whl + itk-6.0.0-cp310-cp310-macosx_13_0_arm64.whl + itk-6.0.0-cp310-cp310-win_amd64.whl -Install and test a built wheel:: - $ pip install dist/itk-6.0.0-cp310-cp310-macosx_10_9_x86_64.whl - $ python -c "import itk; print(dir(itk))" +Testing Built Wheels +==================== -Publishing Wheels ------------------ +Install and smoke-test a wheel directly from the ``dist/`` directory: -Once you've built and tested the wheels, you can: +.. code-block:: bash -* Upload to PyPI using ``twine``:: - - $ pip install twine - $ twine upload dist/*.whl - -* Upload to a private package index -* Distribute directly to users + pip install dist/itk-6.0.0-cp310-cp310-macosx_13_0_arm64.whl + python -c "import itk; print(itk.__version__)" Troubleshooting @@ -190,131 +351,31 @@ Path Length Issues (Windows) If you encounter path length errors: -* Use a shorter build directory (e.g., ``C:\IPP`` instead of ``C:\Users\YourName\Documents\Projects\ITKPythonPackage``) -* Enable long path support in Windows 10/11:: +Windows has a 260-character path limit by default. Use a short build directory +(e.g. ``C:\BDR``) and optionally enable long path support: + +.. code-block:: powershell - PS C:\> New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem" -Name "LongPathsEnabled" -Value 1 -PropertyType DWORD -Force + New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem" ` + -Name "LongPathsEnabled" -Value 1 -PropertyType DWORD -Force Antivirus Conflicts (Windows) ------------------------------ -Configure Windows Defender to exclude the build directory: +The build creates and deletes large numbers of files rapidly, which can trigger +Windows Defender and produce "Access Denied" errors. Add the build directory to +Windows Defender exclusions: + +1. Open **Windows Security → Virus & threat protection → Manage settings** +2. Scroll to **Exclusions → Add or remove exclusions** +3. Add the build root (e.g. ``C:\BDR``) + +Docker Permissions (Linux) +--------------------------- + +If Docker requires ``sudo``, pass ``--use-sudo`` to ``build_wheels.py`` or set +``NO_SUDO=`` (empty string) before running the manylinux shell script. To add +your user to the ``docker`` group instead:: -1. Open Windows Security -2. Go to "Virus & threat protection" -3. Under "Virus & threat protection settings", click "Manage settings" -4. Scroll to "Exclusions" and click "Add or remove exclusions" -5. Add the build directory (e.g., ``C:\IPP``) - -.. Linux -.. ----- - -.. On any linux distribution with docker and bash installed, running the script dockcross-manylinux-build-wheels.sh will create 64-bit wheels for python 3.9+ in the dist directory. - -.. For example:: - -.. $ git clone https://github.com/InsightSoftwareConsortium/ITKPythonPackage.git -.. [...] -.. -.. $ ./scripts/dockcross-manylinux-build-wheels.sh -.. [...] - -.. $ ls -1 dist/ -.. itk-6.0.1.dev20251126-cp39-cp39m-manylinux2014_x86_64.whl -.. itk-6.0.1.dev20251126-cp39-cp39mu-manylinux2014_x86_64.whl -.. itk-6.0.1.dev20251126-cp39-cp39m-manylinux2014_x86_64.whl -.. itk-6.0.1.dev20251126-cp39-cp39m-manylinux2014_x86_64.whl -.. itk-6.0.1.dev20251126-cp39-cp39m-manylinux2014_x86_64.whl - -.. macOS -.. ----- - -.. First, install the Python.org macOS Python distributions. This step requires sudo:: - -.. ./scripts/macpython-install-python.sh - - -.. Then, build the wheels:: - -.. $ ./scripts/macpython-build-wheels.sh -.. [...] -.. -.. $ ls -1 dist/ -.. itk-6.0.1.dev20251126-cp39-cp39m-macosx_10_6_x86_64.whl -.. itk-6.0.1.dev20251126-cp39-cp39m-macosx_10_6_x86_64.whl -.. itk-6.0.1.dev20251126-cp39-cp39m-macosx_10_6_x86_64.whl -.. itk-6.0.1.dev20251126-cp39-cp39m-macosx_10_6_x86_64.whl - -.. Windows -.. ------- - -.. First, install Microsoft Visual Studio 2015, Git, and CMake, which should be added to the system PATH environmental variable. - -.. Open a PowerShell terminal as Administrator, and install Python:: - -.. PS C:\> Set-ExecutionPolicy Unrestricted -.. PS C:\> $pythonArch = "64" -.. PS C:\> iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/scikit-build/scikit-ci-addons/master/windows/install-python.ps1')) - -.. In a PowerShell prompt:: - -.. PS C:\Windows> cd C:\ -.. PS C:\> git clone https://github.com/InsightSoftwareConsortium/ITKPythonPackage.git IPP -.. PS C:\> cd IPP -.. PS C:\IPP> .\scripts\windows-build-wheels.ps1 -.. [...] - -.. PS C:\IPP> ls dist -.. Directory: C:\IPP\dist - - -.. Mode LastWriteTime Length Name -.. ---- ------------- ------ ---- -.. -a---- 4/9/2017 11:14 PM 63274441 itk-6.0.1.dev20251126-cp39-cp39m-win_amd64.whl -.. -a---- 4/10/2017 2:08 AM 63257220 itk-6.0.1.dev20251126-cp39-cp39m-win_amd64.whl - -.. We need to work in a short directory to avoid path length limitations on -.. Windows, so the repository is cloned into C:\IPP. - -.. Also, it is very important to disable antivirus checking on the C:\IPP -.. directory. Otherwise, the build system conflicts with the antivirus when many -.. files are created and deleted quickly, which can result in Access Denied -.. errors. Windows 10 ships with an antivirus application, Windows Defender, that -.. is enabled by default. - -.. The below instructions are outdated and need to be re-written -.. sdist -.. ----- -.. -.. To create source distributions, sdist's, that will be used by pip to compile a wheel for installation if a binary wheel is not available for the current Python version or platform:: -.. -.. $ python -m build --sdist -.. [...] -.. -.. $ ls -1 dist/ -.. itk-6.0.1.dev20251126.tar.gz -.. itk-6.0.1.dev20251126.zip -.. -.. Manual builds (not recommended) -.. =============================== -.. -.. Building ITK Python wheels -.. -------------------------- -.. -.. Build the ITK Python wheel with the following command:: -.. -.. python3 -m venv build-itk -.. ./build-itk/bin/pip install --upgrade pip -.. ./build-itk/bin/pip install -r requirements-dev.txt -.. ./build-itk/bin/python -m build -.. -.. Build a wheel for a custom version of ITK -.. ----------------------------------------- -.. -.. To build a wheel for a custom version of ITK, point to your ITK git repository -.. with the `ITK_SOURCE_DIR` CMake variable:: -.. -.. ./build-itk/bin/python -m build --wheel -- \ -.. -DITK_SOURCE_DIR:PATH=/path/to/ITKPythonPackage-core-build/ITK -.. -.. Other CMake variables can also be passed with `-D` after the double dash. + sudo usermod -aG docker $USER + # Then log out and back in diff --git a/docs/Miscellaneous.rst b/docs/Miscellaneous.rst index d7ae223f..acf64221 100644 --- a/docs/Miscellaneous.rst +++ b/docs/Miscellaneous.rst @@ -2,7 +2,7 @@ Miscellaneous ============= -Written by Jean-Christophe Fillion-Robin and Matt McCormick from Kitware Inc. +Written by Jean-Christophe Fillion-Robin and Matt McCormick from Kitware Inc and Cavan Riley from the University of Iowa. It is covered by the Apache License, Version 2.0: diff --git a/docs/Prerequisites.rst b/docs/Prerequisites.rst index 34d367d8..73b22012 100644 --- a/docs/Prerequisites.rst +++ b/docs/Prerequisites.rst @@ -1,11 +1,52 @@ Prerequisites ============= -Building wheels requires: - -- CMake -- zstd -- Git -- C++ Compiler - Platform specific requirements are summarized in scikit-build documentation. -- Python -- Docker +The following tools are required to build ITK Python wheels locally. + +All Platforms +------------- + +`Pixi `_ is the primary build environment manager. It automatically +provisions the correct Python version, compiler toolchain, CMake, Ninja, and all +other build dependencies for each target platform. Manual installation of compilers +or CMake is not required when using Pixi. + +Install Pixi: + +.. code-block:: bash + + # Linux or macOS + curl -fsSL https://pixi.sh/install.sh | bash + + # Windows (PowerShell) + powershell -ExecutionPolicy Bypass -c "irm -useb https://pixi.sh/install.ps1 | iex" + +You will also need `Git `_ 2.x or later. + +Linux +----- + +Portable manylinux builds require Docker (or an OCI-compatible runtime such as +Podman or nerdctl) to run the manylinux container environment. + +Install Docker by following the official `Docker Engine installation guide +`_. + +macOS +----- + +No additional tools are required beyond Pixi. The Pixi ``macosx-build`` +environment provides the Clang 1.10.0 compiler toolchain and the +`delocate `_ wheel repair utility. + +Windows +------- + +`Microsoft Visual Studio 2022 `_ +(or the Build Tools for Visual Studio 2022) with the +**Desktop development with C++** workload is required. + +.. note:: + Pixi environments provision Python, CMake, Ninja, and build helpers + (``auditwheel`` on Linux, ``delocate`` on macOS, ``delvewheel`` on Windows) + automatically. Only Docker (Linux) and MSVC (Windows) require separate installation. diff --git a/docs/_static/custom.css b/docs/_static/custom.css new file mode 100644 index 00000000..7b5c8b9d --- /dev/null +++ b/docs/_static/custom.css @@ -0,0 +1,29 @@ +/* -- ITKPythonPackage custom styles (pydata-sphinx-theme) -- */ + +/* Sidebar brand text */ +.navbar-brand p { + font-weight: 700; + font-size: 1.15rem; +} + +/* Better code block styling */ +.highlight pre { + border-radius: 6px; + font-size: 0.85rem; +} + +/* Admonition tweaks */ +.admonition { + border-radius: 6px; + font-size: 0.92rem; +} + +/* Quick-links card grid on index */ +.sd-card { + border-radius: 8px; + transition: box-shadow 0.2s ease; +} + +.sd-card:hover { + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12); +} diff --git a/docs/conf.py b/docs/conf.py index b642ec55..8be81c96 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,28 +1,5 @@ import os -# -*- coding: utf-8 -*- -# -# ITKPythonPackage documentation build configuration file, created by -# sphinx-quickstart on Mon May 29 15:53:20 2017. -# -# This file is execfile()d with the current directory set to its -# containing dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -# -# import os -# import sys -# sys.path.insert(0, os.path.abspath('.')) - - # -- General configuration ------------------------------------------------ # If your documentation needs a minimal Sphinx version, state it here. @@ -32,8 +9,10 @@ # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. -extensions = [] - +extensions = [ + "sphinx_copybutton", + "sphinx_design", +] # Add any paths that contain templates here, relative to this directory. templates_path = ["_templates"] @@ -51,21 +30,10 @@ copyright = "2017, Jean-Christophe Fillion-Robin and Matt McCormick" author = "Jean-Christophe Fillion-Robin and Matt McCormick" -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# -# The short X.Y version. -version = "" -# The full version, including alpha/beta/rc tags. -release = "" +version = os.environ.get("READTHEDOCS_VERSION", "") +release = version -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -# -# This is also used if you do content translation via gettext catalogs. -# Usually you set "language" from the command line for these cases. -language = None +language = "en" # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. @@ -81,21 +49,27 @@ # -- Options for HTML output ---------------------------------------------- -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -# -html_theme = "default" - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -# -# html_theme_options = {} - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". +html_theme = "furo" html_static_path = ["_static"] +html_css_files = ["custom.css"] +html_title = "ITKPythonPackage" + +html_theme_options = { + "source_repository": "https://github.com/InsightSoftwareConsortium/ITKPythonPackage", + "source_branch": "main", + "source_directory": "docs/", + "sidebar_hide_name": False, + "navigation_with_keys": True, + "top_of_page_buttons": ["view", "edit"], + "light_css_variables": { + "color-brand-primary": "#2962FF", + "color-brand-content": "#2962FF", + }, + "dark_css_variables": { + "color-brand-primary": "#82B1FF", + "color-brand-content": "#82B1FF", + }, +} # -- Options for HTMLHelp output ------------------------------------------ @@ -156,19 +130,7 @@ "ITKPythonPackage Documentation", author, "ITKPythonPackage", - "One line description of project.", + "Scripts and configuration for building ITK Python binary wheels.", "Miscellaneous", ), ] - - -# -- Read The Docs ----------------------------------------------------- - -# on_rtd is whether we are on readthedocs.io -on_rtd = os.environ.get("READTHEDOCS", None) == "True" - -if not on_rtd: # only import and set the theme if we're building docs locally - import sphinx_rtd_theme - - html_theme = "sphinx_rtd_theme" - html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] diff --git a/docs/index.rst b/docs/index.rst index 32fc2fbc..00db0e9f 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,36 +1,62 @@ -Welcome to ITKPythonPackage's documentation! -============================================ +ITKPythonPackage +================ -This project provides a script to generate `pyproject.toml` files used to build -ITK Python wheels and infrastructure to build ITK external module Python +Build infrastructure for ITK Python wheels and ITK external module Python wheels. `ITK `_ is an open-source, cross-platform system that provides developers with an extensive suite of software tools for image analysis. -To install the pre-built stable ITK Python package:: +.. code-block:: bash - $ pip install itk + pip install itk For more information on ITK's Python wrapping, see `an introduction in the Book 1, Chapter 3 of the ITK Software Guide `_. There are also many `downloadable examples documented in Sphinx `_. +---- -.. toctree:: - :maxdepth: 2 - :caption: Contents +Quick Links +----------- + +.. grid:: 2 + :gutter: 3 + + .. grid-item-card:: Prerequisites + :link: Prerequisites + :link-type: doc + + Platform requirements and tooling setup for building ITK wheels. + + .. grid-item-card:: Build ITK Python Packages + :link: Build_ITK_Python_packages + :link-type: doc + + Build core ITK wheels (``itk-core``, ``itk-numerics``, ``itk-io``, etc.) + from source. - Quick_start_guide.rst - Build_ITK_Module_Python_packages.rst - Build_ITK_Python_packages.rst - Miscellaneous.rst + .. grid-item-card:: Build ITK Module Packages + :link: Build_ITK_Module_Python_packages + :link-type: doc -Indices and tables -================== + Create, build, and publish Python packages for ITK remote and external + modules. + + .. grid-item-card:: Miscellaneous + :link: Miscellaneous + :link-type: doc + + License, authors, and additional resources. + +---- + +.. toctree:: + :maxdepth: 3 -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` + Prerequisites + Build_ITK_Python_packages + Build_ITK_Module_Python_packages + Miscellaneous diff --git a/docs/requirements-docs.txt b/docs/requirements-docs.txt index 82133027..7d464dc3 100644 --- a/docs/requirements-docs.txt +++ b/docs/requirements-docs.txt @@ -1,2 +1,4 @@ sphinx -sphinx_rtd_theme +furo +sphinx-copybutton +sphinx-design From 892ef20b8d31dcc9f7891bda911fa23eea830938 Mon Sep 17 00:00:00 2001 From: Cavan Riley Date: Wed, 18 Mar 2026 12:19:28 -0500 Subject: [PATCH 07/27] ENH: Add GitHub Action to generate documentation artifacts --- .github/workflows/docs.yaml | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 .github/workflows/docs.yaml diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml new file mode 100644 index 00000000..133a0df4 --- /dev/null +++ b/.github/workflows/docs.yaml @@ -0,0 +1,31 @@ +name: docs + +on: + pull_request: + paths: + - "docs/**" + - ".readthedocs.yml" + push: + branches: [main] + paths: + - "docs/**" + - ".readthedocs.yml" + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: "3.11" + - name: Install dependencies + run: pip install -r docs/requirements-docs.txt + - name: Build docs + run: sphinx-build -W --keep-going -b html docs docs/_build/html + - uses: actions/upload-artifact@v4 + if: always() + with: + name: docs-html + path: docs/_build/html + retention-days: 7 From b9859c48300c81c4e9045d1d1724d78566eb89c7 Mon Sep 17 00:00:00 2001 From: Cavan Riley Date: Sat, 28 Mar 2026 14:30:00 -0500 Subject: [PATCH 08/27] DOC: Add CONTRIBUTING.md file --- CONTRIBUTING.md | 73 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..719705d1 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,73 @@ +# Contributing to ITKPythonPackage + +## Getting Started + +Clone the repository and install the pre-commit hooks: + +```bash +git clone https://github.com/InsightSoftwareConsortium/ITKPythonPackage.git +cd ITKPythonPackage +```` + +Install [Pixi](https://pixi.sh) for managing the build environment: + +```bash +curl -fsSL https://pixi.sh/install.sh | bash +pixi install +``` + +Install pre-commit hooks + +```bash +pixi run pre-commit-install +# optionally run pre-commit hooks +pixi run pre-commit-run +``` + + +## Development Workflow + +### Code Style + +Pre-commit hooks enforce all formatting and linting automatically on commit: + +- **Python**: Black (formatting), Ruff (linting + import sorting) +- **Shell**: ShellCheck (linting), shfmt (formatting) +- **TOML**: Taplo (formatting) + +Run against all files manually: + +```bash +pre-commit run --all-files +``` + +### Commit Messages + +This project uses [Conventional Commits](https://www.conventionalcommits.org), enforced by Commitizen: + +``` +feat: add support for Python 3.12 wheels +fix: correct cmake args not propagating to module builds +chore: update pre-commit hook versions +docs: clarify aarch64 build requirements +``` + +Commitizen will reject commits that don't follow this format. + +### Building Docs + +```bash +pip install -r docs/requirements-docs.txt +sphinx-build -W -b html docs docs/_build/html +``` + +## Submitting a Pull Request + +1. Create a branch from `main` +2. Make your changes and ensure `pre-commit run --all-files` passes +3. Open a PR, fill out the template, including which platforms you tested on +4. CI will run pre-commit checks automatically + +## Questions + +For build questions or general ITK support, use the [ITK Discourse forum](https://discourse.itk.org). From 1728684c40e44c59f6b2ab466be22a88bf55555a Mon Sep 17 00:00:00 2001 From: Cavan Riley Date: Sun, 29 Mar 2026 16:51:36 -0500 Subject: [PATCH 09/27] ENH: Add scripts to publish wheels and cached builds --- .gitignore | 3 + .pypirc.example | 23 + README.md | 41 +- docs/Build_ITK_Module_Python_packages.rst | 26 + docs/Build_ITK_Python_packages.rst | 97 ++ pixi.lock | 1626 +++++++++++++++++++-- pixi.toml | 21 + scripts/publish_tarball_cache.py | 126 ++ scripts/publish_wheels.py | 93 ++ 9 files changed, 1922 insertions(+), 134 deletions(-) create mode 100644 .pypirc.example create mode 100644 scripts/publish_tarball_cache.py create mode 100644 scripts/publish_wheels.py diff --git a/.gitignore b/.gitignore index ae101831..c49bb1de 100644 --- a/.gitignore +++ b/.gitignore @@ -73,6 +73,9 @@ docs/_build .idea/* *.swp /itkVersion.py +# PyPI credentials +.pypirc + # pixi environments .pixi/* !.pixi/config.toml diff --git a/.pypirc.example b/.pypirc.example new file mode 100644 index 00000000..05b64161 --- /dev/null +++ b/.pypirc.example @@ -0,0 +1,23 @@ +# .pypirc.example -- DO NOT commit real credentials +# Copy to ~/.pypirc and fill in your token. +# +# Generate a token at: https://pypi.org/manage/account/token/ +# For TestPyPI: https://test.pypi.org/manage/account/token/ +# +# Alternatively, set environment variables: +# TWINE_USERNAME=__token__ +# TWINE_PASSWORD=pypi- + +[distutils] +index-servers = + pypi + testpypi + +[pypi] +username = __token__ +password = pypi-YOUR-TOKEN-HERE + +[testpypi] +repository = https://test.pypi.org/legacy/ +username = __token__ +password = pypi-YOUR-TOKEN-HERE diff --git a/README.md b/README.md index 25e41f22..3b42c7de 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # ITK Python Package This project configures pyproject.toml files and manages environmental -variables needed to build ITK Python binary wheels on MacOS, Linux, and Windows platforms. +variables needed to build ITK Python binary wheels on macOS, Linux, and Windows platforms. Scripts are available for both [ITK infrastructure](https://github.com/insightSoftwareConsortium/ITK) and ITK external module Python packages. @@ -20,7 +20,7 @@ or at the [ITK GitHub homepage](https://github.com/insightSoftwareConsortium/ITK ## Building Remote Modules with ITKPythonPackage ITK reusable workflows are available to build and package Python wheels as -part of Continuous Integration (CI) via Github Actions runners. +part of Continuous Integration (CI) via GitHub Actions runners. Those workflows can handle the overhead of fetching, configuring, and running ITKPythonPackage build scripts for most ITK external modules. See [ITKRemoteModuleBuildTestPackageAction](https://github.com/InsightSoftwareConsortium/ITKRemoteModuleBuildTestPackageAction) @@ -31,7 +31,7 @@ for more information. For special cases where ITK reusable workflows are not a good fit, ITKPythonPackage scripts can be directly used to build Python wheels -to target Windows, Linux, and MacOS platforms. See +to target Windows, Linux, and macOS platforms. See below or the [ITKPythonPackage ReadTheDocs](https://itkpythonpackage.readthedocs.io/en/latest/Build_ITK_Module_Python_packages.html) documentation for more information on building wheels by hand. @@ -273,8 +273,43 @@ On Windows systems To build caches for local use, you can run the `build_wheels.py` script with the `--build-itk-tarball-cache` +#### Publish Tarball Caches + +To publish the tarball caches to a GitHub Release, you can run: + +> [!NOTE] +> This requires the `GH_TOKEN` environment variable to be set or `gh auth login` to have been run beforehand. +> Tarballs are expected in the parent directory of `--build-dir-root` (POSIX `.tar.zst`) or inside it (Windows `.zip`). + +```bash +pixi run -e publish publish-tarball-cache --itk-package-version v6.0b02 --build-dir-root /path/to/build/root +``` + +Users can also specify the GitHub repository to publish to using `--repo` (defaults to ITKPythonBuilds) and +`--create-release` to create the release if it does not already exist. + +To see how to publish wheels see this section: + +
+Publishing Wheels +This repository contains a script for publishing wheels to PyPI and TestPyPI. + +The script can be run with the pixi environment as such: + +> [!NOTE] +> This script assumes you have the `TWINE_USERNAME` and `TWINE_PASSWORD` environment variables set or the +> `.pypirc` file configured on your machine. An example `.pypirc` can be seen in the root of this repository + +```bash +pixi run -e publish publish-wheels --dist-directory /path/to/dist/ +``` + +You can also optionally pass in `--test` to publish to TestPyPI for validation before uploading to production, +`--repository-url` to specify a custom package index, or `--skip-existing` to skip already-uploaded wheels. + +
--- ## Frequently Asked Questions diff --git a/docs/Build_ITK_Module_Python_packages.rst b/docs/Build_ITK_Module_Python_packages.rst index 88e0152f..ad134af5 100644 --- a/docs/Build_ITK_Module_Python_packages.rst +++ b/docs/Build_ITK_Module_Python_packages.rst @@ -277,9 +277,35 @@ Example output:: Uploading to PyPI ================= +Using the Publish Environment +----------------------------- + +ITKPythonPackage provides a ``publish`` Pixi environment with ``twine`` +pre-configured. Set your PyPI credentials (see ``.pypirc.example`` in the +repository root) and run: + +.. code-block:: bash + + export TWINE_USERNAME=__token__ + export TWINE_PASSWORD=pypi- + + # Test on TestPyPI first + pixi run -e publish publish-wheels \ + --dist-directory /path/to/module/dist \ + --test + + # Then upload to production PyPI + pixi run -e publish publish-wheels \ + --dist-directory /path/to/module/dist + +Pass ``--skip-existing`` to skip already-uploaded wheels when re-running after +a partial upload failure. + Manual Upload ------------- +Alternatively, install and use ``twine`` directly. + Test on TestPyPI first:: pip install twine diff --git a/docs/Build_ITK_Python_packages.rst b/docs/Build_ITK_Python_packages.rst index 8ecd535c..f4172e3a 100644 --- a/docs/Build_ITK_Python_packages.rst +++ b/docs/Build_ITK_Python_packages.rst @@ -343,6 +343,103 @@ Install and smoke-test a wheel directly from the ``dist/`` directory: python -c "import itk; print(itk.__version__)" +Publishing +========== + +ITKPythonPackage provides a lightweight ``publish`` Pixi environment with +`twine `_ for uploading wheels to PyPI and the +`GitHub CLI `_ for uploading tarball caches to GitHub +Releases. Install it with:: + + pixi install -e publish + + +Publishing Wheels to PyPI +------------------------- + +The ``publish-wheels`` task validates wheel metadata with ``twine check`` and +then uploads all ``.whl`` files from a ``dist/`` directory. + +**Authentication** — set environment variables or configure ``~/.pypirc`` +(see ``.pypirc.example`` in the repository root): + +.. code-block:: bash + + export TWINE_USERNAME=__token__ + export TWINE_PASSWORD=pypi- + +Upload to **TestPyPI** first for validation: + +.. code-block:: bash + + pixi run -e publish publish-wheels \ + --dist-directory /path/to/dist \ + --test + +Then upload to **production PyPI**: + +.. code-block:: bash + + pixi run -e publish publish-wheels \ + --dist-directory /path/to/dist + +Additional options: + +.. list-table:: + :header-rows: 1 + :widths: 30 70 + + * - Option + - Description + * - ``--test`` + - Upload to TestPyPI (``https://test.pypi.org/legacy/``) + * - ``--repository-url`` + - Custom package index URL (overrides ``--test``) + * - ``--skip-existing`` + - Skip already-uploaded wheels instead of failing + + +Publishing Tarball Caches to GitHub Releases +-------------------------------------------- + +The ``publish-tarball-cache`` task uploads ``.tar.zst`` (POSIX) and ``.zip`` +(Windows) build caches to a GitHub Release on the +`ITKPythonBuilds `_ +repository. + +**Authentication** — set the ``GH_TOKEN`` environment variable or run +``gh auth login`` beforehand. + +.. code-block:: bash + + pixi run -e publish publish-tarball-cache \ + --itk-package-version v6.0b02 \ + --build-dir-root /path/to/build \ + --create-release + +Additional options: + +.. list-table:: + :header-rows: 1 + :widths: 30 70 + + * - Option + - Description + * - ``--itk-package-version`` + - **(required)** Release tag name (e.g. ``v6.0b02``) + * - ``--build-dir-root`` + - Root of the build directory; tarballs are found in its parent + (POSIX ``.tar.zst``) or inside it (Windows ``.zip``) + * - ``--repo`` + - Target GitHub repository (default: ``InsightSoftwareConsortium/ITKPythonBuilds``) + * - ``--create-release`` + - Create the GitHub Release if it does not already exist + +.. note:: + The ``--clobber`` flag is used internally so re-uploading a tarball for the + same platform replaces the existing asset without manual cleanup. + + Troubleshooting =============== diff --git a/pixi.lock b/pixi.lock index 995d524a..e1622f65 100644 --- a/pixi.lock +++ b/pixi.lock @@ -2206,6 +2206,598 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.7-h85ac4a6_6.conda - pypi: https://files.pythonhosted.org/packages/c5/0d/84a4380f930db0010168e0aa7b7a8fed9ba1835a8fbb1472bc6d0201d529/build-1.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl + publish: + channels: + - url: https://conda.anaconda.org/conda-forge/ + indexes: + - https://pypi.org/simple + options: + pypi-prerelease-mode: if-necessary-or-explicit + packages: + linux-64: + - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/archspec-0.2.5-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.3.0-py314h680f03e_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/boltons-25.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.2.0-py314h3de4e8d_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_9.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.34.6-hb03c661_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.2.25-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-2.0.0-py314h4a8dc5f_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cfgv-3.5.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.6-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/conda-26.1.1-py314hdafbbf9_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-libmamba-solver-25.11.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-handling-2.4.0-pyh7900ff3_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-streaming-0.12.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cpp-expected-1.3.1-h171cf75_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.4.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/distro-1.9.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.25.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/fmt-12.1.0-hff5e90c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/frozendict-2.4.7-py314h5bd0f2a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gh-2.88.1-h76a2195_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-h33c6efd_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/identify-2.6.18-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpatch-1.33-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpointer-3.1.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.22.2-ha1258a1_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_102.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libarchive-3.8.6-gpl_hc2c16d8_100.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcurl-8.19.0-hcf29cc6_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libev-4.33-hd590300_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.5-hecca717_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.18-h3b78370_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.2-hb03c661_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libmamba-2.5.0-hd28c85e_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libmamba-spdlog-2.5.0-h12fcf84_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libmambapy-2.5.0-py314hcbd71af_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb03c661_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.68.1-h877daf1_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsolv-0.7.36-h9463b59_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.52.0-hf4e2dac_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libssh2-1.11.1-hcf80075_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42-h5347b49_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-16-2.15.2-hca6bf5a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.15.2-he237659_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/lz4-c-1.10.0-h5888daf_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/lzo-2.10-h280c20c_1002.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/menuinst-2.4.2-py314hdafbbf9_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/msgpack-python-1.1.2-py314h9891dd4_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nlohmann_json-abi-3.12.0-h0f90c79_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nodeenv-1.10.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.1-h35e630c_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pixi-pycharm-0.0.10-unix_hf108a03_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pre-commit-4.5.1-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pybind11-abi-11-hc364b38_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pycosat-0.6.6-py314h5bd0f2a_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.14.3-h32b2ec7_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-discovery-1.2.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py314h67df5f8_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/reproc-14.2.5.post0-hb9d3cd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/reproc-cpp-14.2.5.post0-h5888daf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.33.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ruamel.yaml-0.18.17-py314h0f05182_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ruamel.yaml.clib-0.2.15-py314h0f05182_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/simdjson-4.2.4-hb700be7_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/spdlog-1.17.0-hab81395_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/taplo-0.10.0-h2d22210_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/truststore-0.10.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ukkonen-1.1.0-py314h9891dd4_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-21.2.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h280c20c_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-cpp-0.8.0-h3f2d84a_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstandard-0.25.0-py314h0f05182_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda + - pypi: https://files.pythonhosted.org/packages/34/71/1ea5a7352ae516d5512d17babe7e1b87d9db5150b21f794b1377eac1edc0/cryptography-46.0.6-cp311-abi3-manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/02/10/5da547df7a391dcde17f59520a231527b8571e6f46fc8efb02ccb370ab12/docutils-0.22.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/42/77/de194443bf38daed9452139e960c632b0ef9f9a5dd9ce605fdf18ca9f1b1/id-1.6.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7f/66/b15ce62552d84bbfcec9a4873ab79d993a1dd4edb922cbfccae192bd5b5f/jaraco.classes-3.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f2/58/bc8954bda5fcda97bd7c19be11b85f91973d67a706ed4a3aec33e7de22db/jaraco_context-6.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fd/c4/813bb09f0985cb21e959f21f2464169eca882656849adf727ac7bb7e1767/jaraco_functools-4.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b2/a3/e137168c9c44d18eff0376253da9f1e9234d0239e0ee230d2fee6cea8e55/jeepney-0.9.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/81/db/e655086b7f3a705df045bf0933bdd9c2f79bb3c97bfef1384598bb79a217/keyring-25.7.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a4/8e/469e5a4a2f5855992e425f3cb33804cc07bf18d48f2db061aec61ce50270/more_itertools-10.8.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d6/b7/ec1cbc6b297a808c513f59f501656389623fc09ad6a58c640851289c7854/nh3-0.3.4-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e1/67/921ec3024056483db83953ae8e48079ad62b92db7880013ca77632921dd0/readme_renderer-44.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3f/51/d4db610ef29373b879047326cbf6fa98b6c1969d6f6dc423279de2b1be2c/requests_toolbelt-1.0.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ff/9a/9afaade874b2fa6c752c36f1548f718b5b83af81ed9b76628329dab81c1b/rfc3986-2.0.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/14/25/b208c5683343959b670dc001595f2f3737e051da617f66c31f7c4fa93abc/rich-14.3.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b7/46/f5af3402b579fd5e11573ce652019a67074317e18c1935cc0b4ba9b35552/secretstorage-3.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3a/7a/882d99539b19b1490cac5d77c67338d126e4122c8276bf640e411650c830/twine-6.2.0-py3-none-any.whl + linux-aarch64: + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-20_gnu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/archspec-0.2.5-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.3.0-py314h680f03e_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/boltons-25.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/brotli-python-1.2.0-py314h352cb57_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/bzip2-1.0.8-h4777abc_9.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/c-ares-1.34.6-he30d5cf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.2.25-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cffi-2.0.0-py314h0bd77cf_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cfgv-3.5.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.6-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/conda-26.1.1-py314h28a4750_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-libmamba-solver-25.11.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-handling-2.4.0-pyh7900ff3_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-streaming-0.12.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cpp-expected-1.3.1-hdc560ac_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.4.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/distro-1.9.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.25.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/fmt-12.1.0-h20c602a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/frozendict-2.4.7-py314h51f160d_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gh-2.88.1-h94b2740_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/icu-78.3-hcab7f73_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/identify-2.6.18-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpatch-1.33-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpointer-3.1.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/keyutils-1.6.3-h86ecc28_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/krb5-1.22.2-hfd895c2_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.45.1-default_h1979696_102.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libarchive-3.8.6-gpl_hbe7d12b_100.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcurl-8.19.0-hc57f145_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libedit-3.1.20250104-pl5321h976ea20_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libev-4.33-h31becfc_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.7.5-hfae3067_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libffi-3.5.2-h376a255_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-15.2.0-h8acb6b2_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-ng-15.2.0-he9431aa_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-15.2.0-h8acb6b2_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libiconv-1.18-h90929bb_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblzma-5.8.2-he30d5cf_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libmamba-2.5.0-hc712cdd_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libmamba-spdlog-2.5.0-h3ad78e7_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libmambapy-2.5.0-py314h709e558_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libmpdec-4.0.0-he30d5cf_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libnghttp2-1.68.1-hd3077d7_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsolv-0.7.36-hdda61c4_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.52.0-h10b116e_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libssh2-1.11.1-h18c354c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-15.2.0-hef695bb_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.42-h1022ec0_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxml2-16-2.15.2-h79dcc73_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxml2-2.15.2-h825857f_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.3.2-hdc9db2a_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lz4-c-1.10.0-h5ad3122_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lzo-2.10-h80f16a2_1002.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/menuinst-2.4.2-py314h28a4750_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/msgpack-python-1.1.2-py314hd7d8586_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.5-ha32ae93_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nlohmann_json-abi-3.12.0-h0f90c79_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nodeenv-1.10.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.6.1-h546c87b_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pixi-pycharm-0.0.10-unix_hf108a03_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pre-commit-4.5.1-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pybind11-abi-11-hc364b38_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pycosat-0.6.6-py314h51f160d_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.14.3-hb06a95a_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-discovery-1.2.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pyyaml-6.0.3-py314h807365f_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/readline-8.3-hb682ff5_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/reproc-14.2.5.post0-h86ecc28_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/reproc-cpp-14.2.5.post0-h5ad3122_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.33.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ruamel.yaml-0.18.17-py314h2e8dab5_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ruamel.yaml.clib-0.2.15-py314h2e8dab5_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/simdjson-4.2.4-hfefdfc9_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/spdlog-1.17.0-h9f97df7_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/taplo-0.10.0-h3618846_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tk-8.6.13-noxft_h0dc03b3_103.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/truststore-0.10.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ukkonen-1.1.0-py314hd7d8586_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-21.2.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/yaml-0.2.5-h80f16a2_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/yaml-cpp-0.8.0-h5ad3122_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstandard-0.25.0-py314h2e8dab5_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.7-h85ac4a6_6.conda + - pypi: https://files.pythonhosted.org/packages/d4/12/123be7292674abf76b21ac1fc0e1af50661f0e5b8f0ec8285faac18eb99e/cryptography-46.0.6-cp311-abi3-manylinux_2_28_aarch64.whl + - pypi: https://files.pythonhosted.org/packages/02/10/5da547df7a391dcde17f59520a231527b8571e6f46fc8efb02ccb370ab12/docutils-0.22.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/42/77/de194443bf38daed9452139e960c632b0ef9f9a5dd9ce605fdf18ca9f1b1/id-1.6.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7f/66/b15ce62552d84bbfcec9a4873ab79d993a1dd4edb922cbfccae192bd5b5f/jaraco.classes-3.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f2/58/bc8954bda5fcda97bd7c19be11b85f91973d67a706ed4a3aec33e7de22db/jaraco_context-6.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fd/c4/813bb09f0985cb21e959f21f2464169eca882656849adf727ac7bb7e1767/jaraco_functools-4.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b2/a3/e137168c9c44d18eff0376253da9f1e9234d0239e0ee230d2fee6cea8e55/jeepney-0.9.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/81/db/e655086b7f3a705df045bf0933bdd9c2f79bb3c97bfef1384598bb79a217/keyring-25.7.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a4/8e/469e5a4a2f5855992e425f3cb33804cc07bf18d48f2db061aec61ce50270/more_itertools-10.8.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2b/60/c9a33361da8cde7c7760f091cd10467bc470634e4eea31c8bb70935b00a4/nh3-0.3.4-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + - pypi: https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e1/67/921ec3024056483db83953ae8e48079ad62b92db7880013ca77632921dd0/readme_renderer-44.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3f/51/d4db610ef29373b879047326cbf6fa98b6c1969d6f6dc423279de2b1be2c/requests_toolbelt-1.0.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ff/9a/9afaade874b2fa6c752c36f1548f718b5b83af81ed9b76628329dab81c1b/rfc3986-2.0.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/14/25/b208c5683343959b670dc001595f2f3737e051da617f66c31f7c4fa93abc/rich-14.3.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b7/46/f5af3402b579fd5e11573ce652019a67074317e18c1935cc0b4ba9b35552/secretstorage-3.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3a/7a/882d99539b19b1490cac5d77c67338d126e4122c8276bf640e411650c830/twine-6.2.0-py3-none-any.whl + osx-64: + - conda: https://conda.anaconda.org/conda-forge/noarch/archspec-0.2.5-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.3.0-py314h680f03e_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/boltons-25.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/brotli-python-1.2.0-py314h3262eb8_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/bzip2-1.0.8-h500dc9f_9.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/c-ares-1.34.6-hb5e19a0_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.2.25-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/cffi-2.0.0-py314h8ca4d5a_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cfgv-3.5.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.6-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/conda-26.1.1-py314hee6578b_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-libmamba-solver-25.11.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-handling-2.4.0-pyh7900ff3_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-streaming-0.12.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/cpp-expected-1.3.1-h0ba0a54_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.4.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/distro-1.9.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.25.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/fmt-12.1.0-hda137b5_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/frozendict-2.4.7-py314h6482030_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/gh-2.88.1-hdaada87_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/icu-78.3-h25d91c4_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/identify-2.6.18-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpatch-1.33-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpointer-3.1.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/krb5-1.22.2-h207b36a_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libarchive-3.8.6-gpl_h2bf6321_100.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcurl-8.19.0-h8f0b9e4_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcxx-22.1.2-h19cb2f5_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libedit-3.1.20250104-pl5321ha958ccf_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libev-4.33-h10d778d_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libexpat-2.7.5-hcc62823_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libffi-3.5.2-hd1f9c09_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libiconv-1.18-h57a12c2_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/liblzma-5.8.2-h11316ed_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libmamba-2.5.0-h7fe6c55_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libmamba-spdlog-2.5.0-hb923e0c_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libmambapy-2.5.0-py314haca2e77_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libmpdec-4.0.0-hf3981d6_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libnghttp2-1.68.1-h70048d4_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libsolv-0.7.36-hf97c9bc_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.52.0-h77d7759_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libssh2-1.11.1-hed3591d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libxml2-16-2.15.2-h7a90416_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libxml2-2.15.2-hd552753_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.3.2-hbb4bfdb_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/lz4-c-1.10.0-h240833e_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/lzo-2.10-h4132b18_1002.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/menuinst-2.4.2-py314hee6578b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/msgpack-python-1.1.2-py314h00ed6fe_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.5-h0622a9a_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nlohmann_json-abi-3.12.0-h0f90c79_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nodeenv-1.10.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/openssl-3.6.1-hb6871ef_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pixi-pycharm-0.0.10-unix_hf108a03_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pre-commit-4.5.1-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pybind11-abi-11-hc364b38_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/pycosat-0.6.6-py314h03d016b_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.14.3-h4f44bb5_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-discovery-1.2.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/pyyaml-6.0.3-py314h10d0514_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/readline-8.3-h68b038d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/reproc-14.2.5.post0-h6e16a3a_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/reproc-cpp-14.2.5.post0-h240833e_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.33.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ruamel.yaml-0.18.17-py314hd330473_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ruamel.yaml.clib-0.2.15-py314hd330473_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/simdjson-4.2.4-hcb651aa_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/spdlog-1.17.0-h30f01e4_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/taplo-0.10.0-hffa81eb_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-h7142dee_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/truststore-0.10.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ukkonen-1.1.0-py314h473ef84_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-21.2.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/yaml-0.2.5-h4132b18_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/yaml-cpp-0.8.0-h92383a6_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/zstandard-0.25.0-py314hd1e8ddb_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.7-h3eecb57_6.conda + - pypi: https://files.pythonhosted.org/packages/02/10/5da547df7a391dcde17f59520a231527b8571e6f46fc8efb02ccb370ab12/docutils-0.22.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/42/77/de194443bf38daed9452139e960c632b0ef9f9a5dd9ce605fdf18ca9f1b1/id-1.6.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7f/66/b15ce62552d84bbfcec9a4873ab79d993a1dd4edb922cbfccae192bd5b5f/jaraco.classes-3.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f2/58/bc8954bda5fcda97bd7c19be11b85f91973d67a706ed4a3aec33e7de22db/jaraco_context-6.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fd/c4/813bb09f0985cb21e959f21f2464169eca882656849adf727ac7bb7e1767/jaraco_functools-4.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/81/db/e655086b7f3a705df045bf0933bdd9c2f79bb3c97bfef1384598bb79a217/keyring-25.7.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a4/8e/469e5a4a2f5855992e425f3cb33804cc07bf18d48f2db061aec61ce50270/more_itertools-10.8.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/4a/57/a97955bc95960cfb1f0517043d60a121f4ba93fde252d4d9ffd3c2a9eead/nh3-0.3.4-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl + - pypi: https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e1/67/921ec3024056483db83953ae8e48079ad62b92db7880013ca77632921dd0/readme_renderer-44.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3f/51/d4db610ef29373b879047326cbf6fa98b6c1969d6f6dc423279de2b1be2c/requests_toolbelt-1.0.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ff/9a/9afaade874b2fa6c752c36f1548f718b5b83af81ed9b76628329dab81c1b/rfc3986-2.0.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/14/25/b208c5683343959b670dc001595f2f3737e051da617f66c31f7c4fa93abc/rich-14.3.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3a/7a/882d99539b19b1490cac5d77c67338d126e4122c8276bf640e411650c830/twine-6.2.0-py3-none-any.whl + osx-arm64: + - conda: https://conda.anaconda.org/conda-forge/noarch/archspec-0.2.5-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.3.0-py314h680f03e_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/boltons-25.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-python-1.2.0-py314h3daef5d_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-hd037594_9.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-ares-1.34.6-hc919400_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.2.25-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cffi-2.0.0-py314h44086f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cfgv-3.5.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.6-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/conda-26.1.1-py314h4dc9dd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-libmamba-solver-25.11.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-handling-2.4.0-pyh7900ff3_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-streaming-0.12.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cpp-expected-1.3.1-h4f10f1e_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.4.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/distro-1.9.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.25.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/fmt-12.1.0-h403dcb5_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/frozendict-2.4.7-py314h0612a62_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/gh-2.88.1-h01237fd_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.3-hef89b57_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/identify-2.6.18-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpatch-1.33-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpointer-3.1.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.22.2-h385eeb1_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarchive-3.8.6-gpl_h6fbacd7_100.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcurl-8.19.0-hd5a2499_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-22.1.2-h55c6f16_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libedit-3.1.20250104-pl5321hafb1f1b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libev-4.33-h93a5062_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.7.5-hf6b4638_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-hcf2aa1b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libiconv-1.18-h23cfdf5_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.2-h8088a28_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmamba-2.5.0-h7950639_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmamba-spdlog-2.5.0-h85b9800_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmambapy-2.5.0-py314hf8f60b7_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmpdec-4.0.0-h84a0fba_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libnghttp2-1.68.1-h8f3e76b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsolv-0.7.36-h7d962ec_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.52.0-h1ae2325_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libssh2-1.11.1-h1590b86_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-16-2.15.2-h5ef1a60_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-2.15.2-h8d039ee_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.2-h8088a28_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/lz4-c-1.10.0-h286801f_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/lzo-2.10-h925e9cb_1002.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/menuinst-2.4.2-py314h4dc9dd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/msgpack-python-1.1.2-py314h784bc60_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.5-h5e97a16_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nlohmann_json-abi-3.12.0-h0f90c79_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nodeenv-1.10.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.1-hd24854e_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pixi-pycharm-0.0.10-unix_hf108a03_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pre-commit-4.5.1-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pybind11-abi-11-hc364b38_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pycosat-0.6.6-py314hb84d1df_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.14.3-h4c637c5_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-discovery-1.2.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyyaml-6.0.3-py314h6e9b3f0_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/reproc-14.2.5.post0-h5505292_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/reproc-cpp-14.2.5.post0-h286801f_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.33.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ruamel.yaml-0.18.17-py314ha14b1ff_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ruamel.yaml.clib-0.2.15-py314ha14b1ff_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/simdjson-4.2.4-ha7d2532_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/spdlog-1.17.0-ha0f8610_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/taplo-0.10.0-h2b2570c_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h010d191_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/truststore-0.10.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ukkonen-1.1.0-py314h6cfcd04_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-21.2.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/yaml-0.2.5-h925e9cb_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/yaml-cpp-0.8.0-ha1acc90_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstandard-0.25.0-py314h9d33bd4_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda + - pypi: https://files.pythonhosted.org/packages/02/10/5da547df7a391dcde17f59520a231527b8571e6f46fc8efb02ccb370ab12/docutils-0.22.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/42/77/de194443bf38daed9452139e960c632b0ef9f9a5dd9ce605fdf18ca9f1b1/id-1.6.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7f/66/b15ce62552d84bbfcec9a4873ab79d993a1dd4edb922cbfccae192bd5b5f/jaraco.classes-3.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f2/58/bc8954bda5fcda97bd7c19be11b85f91973d67a706ed4a3aec33e7de22db/jaraco_context-6.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fd/c4/813bb09f0985cb21e959f21f2464169eca882656849adf727ac7bb7e1767/jaraco_functools-4.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/81/db/e655086b7f3a705df045bf0933bdd9c2f79bb3c97bfef1384598bb79a217/keyring-25.7.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a4/8e/469e5a4a2f5855992e425f3cb33804cc07bf18d48f2db061aec61ce50270/more_itertools-10.8.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/4a/57/a97955bc95960cfb1f0517043d60a121f4ba93fde252d4d9ffd3c2a9eead/nh3-0.3.4-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl + - pypi: https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e1/67/921ec3024056483db83953ae8e48079ad62b92db7880013ca77632921dd0/readme_renderer-44.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3f/51/d4db610ef29373b879047326cbf6fa98b6c1969d6f6dc423279de2b1be2c/requests_toolbelt-1.0.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ff/9a/9afaade874b2fa6c752c36f1548f718b5b83af81ed9b76628329dab81c1b/rfc3986-2.0.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/14/25/b208c5683343959b670dc001595f2f3737e051da617f66c31f7c4fa93abc/rich-14.3.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3a/7a/882d99539b19b1490cac5d77c67338d126e4122c8276bf640e411650c830/twine-6.2.0-py3-none-any.whl + win-64: + - conda: https://conda.anaconda.org/conda-forge/noarch/archspec-0.2.5-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.3.0-py314h680f03e_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/boltons-25.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/brotli-python-1.2.0-py314he701e3d_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-h0ad9c76_9.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-h4c7d964_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.2.25-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cffi-2.0.0-py314h5a2d7ad_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cfgv-3.5.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.6-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/conda-26.1.1-py314h86ab7b2_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-libmamba-solver-25.11.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-handling-2.4.0-pyh7900ff3_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-streaming-0.12.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cpp-expected-1.3.1-h477610d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.4.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/distro-1.9.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.25.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/fmt-12.1.0-h7f4e812_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/frozendict-2.4.7-py314h5a2d7ad_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/gh-2.88.1-h36e2d1d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/identify-2.6.18-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpatch-1.33-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpointer-3.1.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/krb5-1.22.2-h0ea6238_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libarchive-3.8.6-gpl_he24518a_100.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libcurl-8.19.0-h8206538_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.7.5-hac47afa_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libffi-3.5.2-h3d046cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libiconv-1.18-hc1393d2_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/liblzma-5.8.2-hfd05255_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libmamba-2.5.0-h06825f5_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libmamba-spdlog-2.5.0-h9ae1bf1_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libmambapy-2.5.0-py314h532c739_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libmpdec-4.0.0-hfd05255_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libsolv-0.7.36-h8883371_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.52.0-hf5d6505_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libssh2-1.11.1-h9aa295b_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-16-2.15.2-h692994f_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-2.15.2-h5d26750_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.3.2-hfd05255_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/lz4-c-1.10.0-h2466b09_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/lzo-2.10-h6a83c73_1002.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/menuinst-2.4.2-py314h13fbf68_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/msgpack-python-1.1.2-py314h909e829_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nlohmann_json-abi-3.12.0-h0f90c79_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nodeenv-1.10.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.6.1-hf411b9b_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pixi-pycharm-0.0.10-win_hba80fca_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pre-commit-4.5.1-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pybind11-abi-11-hc364b38_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pycosat-0.6.6-py314h5a2d7ad_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyh09c184e_7.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.14.3-h4b44e0e_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-discovery-1.2.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pyyaml-6.0.3-py314h2359020_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/reproc-14.2.5.post0-h2466b09_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/reproc-cpp-14.2.5.post0-he0c23c2_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.33.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ruamel.yaml-0.18.17-py314hc5dbbe4_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ruamel.yaml.clib-0.2.15-py314hc5dbbe4_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/simdjson-4.2.4-h49e36cd_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/spdlog-1.17.0-h9f585f1_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/taplo-0.10.0-h63977a8_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h6ed50ae_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyha7b4d00_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/truststore-0.10.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ukkonen-1.1.0-py314h909e829_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.3-h41ae7f8_34.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.44.35208-h818238b_34.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vcomp14-14.44.35208-h818238b_34.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-21.2.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/win_inet_pton-1.1.0-pyh7428d3b_8.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/yaml-0.2.5-h6a83c73_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/yaml-cpp-0.8.0-he0c23c2_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/zstandard-0.25.0-py314hc5dbbe4_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.7-h534d264_6.conda + - pypi: https://files.pythonhosted.org/packages/02/10/5da547df7a391dcde17f59520a231527b8571e6f46fc8efb02ccb370ab12/docutils-0.22.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/42/77/de194443bf38daed9452139e960c632b0ef9f9a5dd9ce605fdf18ca9f1b1/id-1.6.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7f/66/b15ce62552d84bbfcec9a4873ab79d993a1dd4edb922cbfccae192bd5b5f/jaraco.classes-3.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f2/58/bc8954bda5fcda97bd7c19be11b85f91973d67a706ed4a3aec33e7de22db/jaraco_context-6.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fd/c4/813bb09f0985cb21e959f21f2464169eca882656849adf727ac7bb7e1767/jaraco_functools-4.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/81/db/e655086b7f3a705df045bf0933bdd9c2f79bb3c97bfef1384598bb79a217/keyring-25.7.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a4/8e/469e5a4a2f5855992e425f3cb33804cc07bf18d48f2db061aec61ce50270/more_itertools-10.8.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/73/4f/af8e9071d7464575a7316831938237ffc9d92d27f163dbdd964b1309cd9b/nh3-0.3.4-cp38-abi3-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/de/3d/8161f7711c017e01ac9f008dfddd9410dff3674334c233bde66e7ba65bbf/pywin32_ctypes-0.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e1/67/921ec3024056483db83953ae8e48079ad62b92db7880013ca77632921dd0/readme_renderer-44.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3f/51/d4db610ef29373b879047326cbf6fa98b6c1969d6f6dc423279de2b1be2c/requests_toolbelt-1.0.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ff/9a/9afaade874b2fa6c752c36f1548f718b5b83af81ed9b76628329dab81c1b/rfc3986-2.0.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/14/25/b208c5683343959b670dc001595f2f3737e051da617f66c31f7c4fa93abc/rich-14.3.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3a/7a/882d99539b19b1490cac5d77c67338d126e4122c8276bf640e411650c830/twine-6.2.0-py3-none-any.whl windows-py310: channels: - url: https://conda.anaconda.org/conda-forge/ @@ -2618,6 +3210,7 @@ packages: depends: - python >=3.14 license: BSD-3-Clause AND MIT AND EPL-2.0 + purls: [] size: 7514 timestamp: 1767044983590 - conda: https://conda.anaconda.org/conda-forge/win-64/backports.zstd-1.3.0-py310h458dff3_0.conda @@ -2772,6 +3365,8 @@ packages: - libbrotlicommon 1.2.0 hb03c661_1 license: MIT license_family: MIT + purls: + - pkg:pypi/brotli?source=hash-mapping size: 367376 timestamp: 1764017265553 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/brotli-python-1.2.0-py310hbe54bbb_1.conda @@ -2821,6 +3416,8 @@ packages: - libbrotlicommon 1.2.0 he30d5cf_1 license: MIT license_family: MIT + purls: + - pkg:pypi/brotli?source=hash-mapping size: 373193 timestamp: 1764017486851 - conda: https://conda.anaconda.org/conda-forge/osx-64/brotli-python-1.1.0-py310h9e9d8ca_1.conda @@ -2865,6 +3462,8 @@ packages: - libbrotlicommon 1.2.0 h8616949_1 license: MIT license_family: MIT + purls: + - pkg:pypi/brotli?source=hash-mapping size: 390153 timestamp: 1764017784596 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-python-1.1.0-py310h1253130_1.conda @@ -2912,6 +3511,8 @@ packages: - libbrotlicommon 1.2.0 hc919400_1 license: MIT license_family: MIT + purls: + - pkg:pypi/brotli?source=hash-mapping size: 359854 timestamp: 1764018178608 - conda: https://conda.anaconda.org/conda-forge/win-64/brotli-python-1.2.0-py310hfff998d_1.conda @@ -2961,6 +3562,8 @@ packages: - libbrotlicommon 1.2.0 hfd05255_1 license: MIT license_family: MIT + purls: + - pkg:pypi/brotli?source=hash-mapping size: 335782 timestamp: 1764018443683 - pypi: https://files.pythonhosted.org/packages/c5/0d/84a4380f930db0010168e0aa7b7a8fed9ba1835a8fbb1472bc6d0201d529/build-1.4.0-py3-none-any.whl @@ -2978,21 +3581,6 @@ packages: - virtualenv>=20.17 ; python_full_version >= '3.10' and python_full_version < '3.14' and extra == 'virtualenv' - virtualenv>=20.31 ; python_full_version >= '3.14' and extra == 'virtualenv' requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/4a/57/3b7d4dd193ade4641c865bc2b93aeeb71162e81fc348b8dad020215601ed/build-1.4.2-py3-none-any.whl - name: build - version: 1.4.2 - sha256: 7a4d8651ea877cb2a89458b1b198f2e69f536c95e89129dbf5d448045d60db88 - requires_dist: - - packaging>=24.0 - - pyproject-hooks - - colorama ; os_name == 'nt' - - importlib-metadata>=4.6 ; python_full_version < '3.10.2' - - tomli>=1.1.0 ; python_full_version < '3.11' - - uv>=0.1.18 ; extra == 'uv' - - virtualenv>=20.11 ; python_full_version < '3.10' and extra == 'virtualenv' - - virtualenv>=20.17 ; python_full_version >= '3.10' and python_full_version < '3.14' and extra == 'virtualenv' - - virtualenv>=20.31 ; python_full_version >= '3.14' and extra == 'virtualenv' - requires_python: '>=3.9' - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_9.conda sha256: 0b75d45f0bba3e95dc693336fa51f40ea28c980131fec438afb7ce6118ed05f6 md5: d2ffd7602c02f2b316fd921d39876885 @@ -3029,6 +3617,7 @@ packages: - __osx >=10.13 license: bzip2-1.0.6 license_family: BSD + purls: [] size: 133427 timestamp: 1771350680709 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-h93a5062_5.conda @@ -3046,6 +3635,7 @@ packages: - __osx >=11.0 license: bzip2-1.0.6 license_family: BSD + purls: [] size: 124834 timestamp: 1771350416561 - conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-h0ad9c76_9.conda @@ -3096,6 +3686,7 @@ packages: - __osx >=10.13 license: MIT license_family: MIT + purls: [] size: 186122 timestamp: 1765215100384 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-ares-1.28.1-h93a5062_0.conda @@ -3113,6 +3704,7 @@ packages: - __osx >=11.0 license: MIT license_family: MIT + purls: [] size: 180327 timestamp: 1765215064054 - conda: https://conda.anaconda.org/conda-forge/linux-64/c-compiler-1.11.0-h4d9bdce_0.conda @@ -3307,6 +3899,8 @@ packages: - python_abi 3.14.* *_cp314 license: MIT license_family: MIT + purls: + - pkg:pypi/cffi?source=hash-mapping size: 300271 timestamp: 1761203085220 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cffi-2.0.0-py310h0826a50_1.conda @@ -3350,6 +3944,8 @@ packages: - python_abi 3.14.* *_cp314 license: MIT license_family: MIT + purls: + - pkg:pypi/cffi?source=hash-mapping size: 318357 timestamp: 1761203973223 - conda: https://conda.anaconda.org/conda-forge/osx-64/cffi-1.16.0-py310hdca579f_0.conda @@ -3391,6 +3987,8 @@ packages: - python_abi 3.14.* *_cp314 license: MIT license_family: MIT + purls: + - pkg:pypi/cffi?source=hash-mapping size: 293633 timestamp: 1761203106369 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cffi-1.16.0-py310hdcd7c05_0.conda @@ -3435,6 +4033,8 @@ packages: - python_abi 3.14.* *_cp314 license: MIT license_family: MIT + purls: + - pkg:pypi/cffi?source=hash-mapping size: 292983 timestamp: 1761203354051 - conda: https://conda.anaconda.org/conda-forge/win-64/cffi-2.0.0-py310h29418f3_1.conda @@ -3481,6 +4081,8 @@ packages: - vc14_runtime >=14.44.35208 license: MIT license_family: MIT + purls: + - pkg:pypi/cffi?source=hash-mapping size: 294731 timestamp: 1761203441365 - conda: https://conda.anaconda.org/conda-forge/noarch/cfgv-3.5.0-pyhd8ed1ab_0.conda @@ -3945,6 +4547,8 @@ packages: - conda-content-trust >=0.1.1 license: BSD-3-Clause license_family: BSD + purls: + - pkg:pypi/conda?source=hash-mapping size: 1307275 timestamp: 1772191378974 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/conda-26.1.1-py310h4c7bcd0_0.conda @@ -4051,6 +4655,8 @@ packages: - conda-env >=2.6 license: BSD-3-Clause license_family: BSD + purls: + - pkg:pypi/conda?source=hash-mapping size: 1311034 timestamp: 1772191450615 - conda: https://conda.anaconda.org/conda-forge/osx-64/conda-23.9.0-py310h2ec42d9_2.conda @@ -4144,6 +4750,8 @@ packages: - conda-env >=2.6 license: BSD-3-Clause license_family: BSD + purls: + - pkg:pypi/conda?source=hash-mapping size: 1310551 timestamp: 1772191748761 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/conda-23.9.0-py310hbe9552e_2.conda @@ -4240,6 +4848,8 @@ packages: - conda-env >=2.6 license: BSD-3-Clause license_family: BSD + purls: + - pkg:pypi/conda?source=hash-mapping size: 1310581 timestamp: 1772191962239 - conda: https://conda.anaconda.org/conda-forge/win-64/conda-26.1.1-py310h5588dad_0.conda @@ -4343,6 +4953,8 @@ packages: - conda-build >=25.9 license: BSD-3-Clause license_family: BSD + purls: + - pkg:pypi/conda?source=hash-mapping size: 1309098 timestamp: 1772191684896 - conda: https://conda.anaconda.org/conda-forge/linux-64/conda-gcc-specs-14.3.0-he8ccf15_18.conda @@ -4437,6 +5049,7 @@ packages: - __osx >=10.13 - libcxx >=19 license: CC0-1.0 + purls: [] size: 24618 timestamp: 1756734941438 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cpp-expected-1.3.1-h4f10f1e_0.conda @@ -4446,6 +5059,7 @@ packages: - __osx >=11.0 - libcxx >=19 license: CC0-1.0 + purls: [] size: 24960 timestamp: 1756734870487 - conda: https://conda.anaconda.org/conda-forge/win-64/cpp-expected-1.3.1-h477610d_0.conda @@ -4462,6 +5076,66 @@ packages: purls: [] size: 21733 timestamp: 1756734797622 +- pypi: https://files.pythonhosted.org/packages/34/71/1ea5a7352ae516d5512d17babe7e1b87d9db5150b21f794b1377eac1edc0/cryptography-46.0.6-cp311-abi3-manylinux_2_28_x86_64.whl + name: cryptography + version: 46.0.6 + sha256: 22259338084d6ae497a19bae5d4c66b7ca1387d3264d1c2c0e72d9e9b6a77b97 + requires_dist: + - cffi>=1.14 ; python_full_version == '3.8.*' and platform_python_implementation != 'PyPy' + - cffi>=2.0.0 ; python_full_version >= '3.9' and platform_python_implementation != 'PyPy' + - typing-extensions>=4.13.2 ; python_full_version < '3.11' + - bcrypt>=3.1.5 ; extra == 'ssh' + - nox[uv]>=2024.4.15 ; extra == 'nox' + - cryptography-vectors==46.0.6 ; extra == 'test' + - pytest>=7.4.0 ; extra == 'test' + - pytest-benchmark>=4.0 ; extra == 'test' + - pytest-cov>=2.10.1 ; extra == 'test' + - pytest-xdist>=3.5.0 ; extra == 'test' + - pretend>=0.7 ; extra == 'test' + - certifi>=2024 ; extra == 'test' + - pytest-randomly ; extra == 'test-randomorder' + - sphinx>=5.3.0 ; extra == 'docs' + - sphinx-rtd-theme>=3.0.0 ; extra == 'docs' + - sphinx-inline-tabs ; extra == 'docs' + - pyenchant>=3 ; extra == 'docstest' + - readme-renderer>=30.0 ; extra == 'docstest' + - sphinxcontrib-spelling>=7.3.1 ; extra == 'docstest' + - build>=1.0.0 ; extra == 'sdist' + - ruff>=0.11.11 ; extra == 'pep8test' + - mypy>=1.14 ; extra == 'pep8test' + - check-sdist ; extra == 'pep8test' + - click>=8.0.1 ; extra == 'pep8test' + requires_python: '>=3.8,!=3.9.0,!=3.9.1' +- pypi: https://files.pythonhosted.org/packages/d4/12/123be7292674abf76b21ac1fc0e1af50661f0e5b8f0ec8285faac18eb99e/cryptography-46.0.6-cp311-abi3-manylinux_2_28_aarch64.whl + name: cryptography + version: 46.0.6 + sha256: 67177e8a9f421aa2d3a170c3e56eca4e0128883cf52a071a7cbf53297f18b175 + requires_dist: + - cffi>=1.14 ; python_full_version == '3.8.*' and platform_python_implementation != 'PyPy' + - cffi>=2.0.0 ; python_full_version >= '3.9' and platform_python_implementation != 'PyPy' + - typing-extensions>=4.13.2 ; python_full_version < '3.11' + - bcrypt>=3.1.5 ; extra == 'ssh' + - nox[uv]>=2024.4.15 ; extra == 'nox' + - cryptography-vectors==46.0.6 ; extra == 'test' + - pytest>=7.4.0 ; extra == 'test' + - pytest-benchmark>=4.0 ; extra == 'test' + - pytest-cov>=2.10.1 ; extra == 'test' + - pytest-xdist>=3.5.0 ; extra == 'test' + - pretend>=0.7 ; extra == 'test' + - certifi>=2024 ; extra == 'test' + - pytest-randomly ; extra == 'test-randomorder' + - sphinx>=5.3.0 ; extra == 'docs' + - sphinx-rtd-theme>=3.0.0 ; extra == 'docs' + - sphinx-inline-tabs ; extra == 'docs' + - pyenchant>=3 ; extra == 'docstest' + - readme-renderer>=30.0 ; extra == 'docstest' + - sphinxcontrib-spelling>=7.3.1 ; extra == 'docstest' + - build>=1.0.0 ; extra == 'sdist' + - ruff>=0.11.11 ; extra == 'pep8test' + - mypy>=1.14 ; extra == 'pep8test' + - check-sdist ; extra == 'pep8test' + - click>=8.0.1 ; extra == 'pep8test' + requires_python: '>=3.8,!=3.9.0,!=3.9.1' - conda: https://conda.anaconda.org/conda-forge/osx-64/cryptography-41.0.7-py310h527a09d_1.conda sha256: cb43f44af3ff4ec8ffb1517234075d39e64442ec75ce995f1e9bd8b032a8aef0 md5: e5291aa101f6590559177df876cd0955 @@ -4614,6 +5288,11 @@ packages: - pkg:pypi/distro?source=hash-mapping size: 41773 timestamp: 1734729953882 +- pypi: https://files.pythonhosted.org/packages/02/10/5da547df7a391dcde17f59520a231527b8571e6f46fc8efb02ccb370ab12/docutils-0.22.4-py3-none-any.whl + name: docutils + version: 0.22.4 + sha256: d0013f540772d1420576855455d050a2180186c91c15779301ac2ccb3eeb68de + requires_python: '>=3.9' - conda: https://conda.anaconda.org/conda-forge/linux-64/doxygen-1.13.2-h8e693c7_0.conda sha256: 349c4c872357b4a533e127b2ade8533796e8e062abc2cd685756a1a063ae1e35 md5: 0869f41ea5c64643dd2f5b47f32709ca @@ -4726,6 +5405,7 @@ packages: - libcxx >=19 license: MIT license_family: MIT + purls: [] size: 188352 timestamp: 1767681462452 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/fmt-12.1.0-h403dcb5_0.conda @@ -4736,6 +5416,7 @@ packages: - libcxx >=19 license: MIT license_family: MIT + purls: [] size: 180970 timestamp: 1767681372955 - conda: https://conda.anaconda.org/conda-forge/win-64/fmt-12.1.0-h7f4e812_0.conda @@ -4788,6 +5469,8 @@ packages: - python_abi 3.14.* *_cp314 license: LGPL-3.0-only license_family: LGPL + purls: + - pkg:pypi/frozendict?source=hash-mapping size: 31627 timestamp: 1763082886391 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/frozendict-2.4.7-py310h5b55623_0.conda @@ -4828,6 +5511,8 @@ packages: - python_abi 3.14.* *_cp314 license: LGPL-3.0-only license_family: LGPL + purls: + - pkg:pypi/frozendict?source=hash-mapping size: 31504 timestamp: 1763082941890 - conda: https://conda.anaconda.org/conda-forge/osx-64/frozendict-2.4.7-py314h6482030_0.conda @@ -4839,6 +5524,8 @@ packages: - python_abi 3.14.* *_cp314 license: LGPL-3.0-only license_family: LGPL + purls: + - pkg:pypi/frozendict?source=hash-mapping size: 31842 timestamp: 1763083176058 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/frozendict-2.4.7-py314h0612a62_0.conda @@ -4851,6 +5538,8 @@ packages: - python_abi 3.14.* *_cp314 license: LGPL-3.0-only license_family: LGPL + purls: + - pkg:pypi/frozendict?source=hash-mapping size: 32182 timestamp: 1763083208667 - conda: https://conda.anaconda.org/conda-forge/win-64/frozendict-2.4.7-py310h29418f3_0.conda @@ -4894,6 +5583,8 @@ packages: - vc14_runtime >=14.44.35208 license: LGPL-3.0-only license_family: LGPL + purls: + - pkg:pypi/frozendict?source=hash-mapping size: 32072 timestamp: 1763082973024 - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc-14.3.0-h0dff253_18.conda @@ -4976,6 +5667,58 @@ packages: purls: [] size: 28666 timestamp: 1770908257439 +- conda: https://conda.anaconda.org/conda-forge/linux-64/gh-2.88.1-h76a2195_0.conda + sha256: 78f9fbbf18272e92e62bc1672d34178760ced73edc1e818ebd5fd00296b5df88 + md5: 0290cdefa20d98adb936c465ccb76ad6 + depends: + - __glibc >=2.17,<3.0.a0 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 22875681 + timestamp: 1773332470542 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gh-2.88.1-h94b2740_0.conda + sha256: bfa267b3a68c629b8d5a3bbb06dc828ba724f68a1e10aa5cc62667cca690d16a + md5: e1f7ec5f227660d3e0ce658e9acb3827 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 20986983 + timestamp: 1773335353762 +- conda: https://conda.anaconda.org/conda-forge/osx-64/gh-2.88.1-hdaada87_0.conda + sha256: c587e956e14f06b8517923864410e612c7882bac57cc7f1b5b11398f907362f9 + md5: af030582e521e76176f9765bd0d623a8 + depends: + - __osx >=11.0 + constrains: + - __osx>=10.12 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 23106117 + timestamp: 1773333114711 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/gh-2.88.1-h01237fd_0.conda + sha256: ed5ac50ece778e035d7739dc7547023c0391b44d20b98d7ef473b06cbdb5d040 + md5: 1bb23382c23eae0e52a48bfd4c3cd5e6 + depends: + - __osx >=11.0 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 21742200 + timestamp: 1773332985739 +- conda: https://conda.anaconda.org/conda-forge/win-64/gh-2.88.1-h36e2d1d_0.conda + sha256: b286e07b5aa44db0e4969789da8b27ec62974108efd45900a444b72f32941859 + md5: 70ee65f0ce705a07b4848aec9ce97014 + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 22357323 + timestamp: 1773332611831 - conda: https://conda.anaconda.org/conda-forge/win-64/git-2.53.0-h57928b3_0.conda sha256: 6bc7eb1202395c044ff24f175f9f6d594bdc4c620e0cfa9e03ed46ef34c265ba md5: b63e3ad61f7507fc72479ab0dde1a6be @@ -5105,6 +5848,18 @@ packages: purls: [] size: 12728445 timestamp: 1767969922681 +- conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-h33c6efd_0.conda + sha256: fbf86c4a59c2ed05bbffb2ba25c7ed94f6185ec30ecb691615d42342baa1a16a + md5: c80d8a3b84358cb967fa81e7075fbc8a + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libstdcxx >=14 + license: MIT + license_family: MIT + purls: [] + size: 12723451 + timestamp: 1773822285671 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/icu-78.2-hcab7f73_0.conda sha256: dcbaa3042084ac58685e3ef4547e4c4be9d37dc52b92ea18581288af95e48b52 md5: 998ee7d53e32f7ab57fc35707285527e @@ -5123,6 +5878,7 @@ packages: - libgcc >=14 - libstdcxx >=14 license: MIT + license_family: MIT purls: [] size: 12837286 timestamp: 1773822650615 @@ -5143,6 +5899,16 @@ packages: license_family: MIT size: 12263724 timestamp: 1767970604977 +- conda: https://conda.anaconda.org/conda-forge/osx-64/icu-78.3-h25d91c4_0.conda + sha256: 1294117122d55246bb83ad5b589e2a031aacdf2d0b1f99fd338aa4394f881735 + md5: 627eca44e62e2b665eeec57a984a7f00 + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + purls: [] + size: 12273764 + timestamp: 1773822733780 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-73.2-hc8870d7_0.conda sha256: ff9cd0c6cd1349954c801fb443c94192b637e1b414514539f3c49c56a39f51b1 md5: 8521bd47c0e11c5902535bb1a17c565f @@ -5160,6 +5926,34 @@ packages: license_family: MIT size: 12389400 timestamp: 1772209104304 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.3-hef89b57_0.conda + sha256: 3a7907a17e9937d3a46dfd41cffaf815abad59a569440d1e25177c15fd0684e5 + md5: f1182c91c0de31a7abd40cedf6a5ebef + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + purls: [] + size: 12361647 + timestamp: 1773822915649 +- pypi: https://files.pythonhosted.org/packages/42/77/de194443bf38daed9452139e960c632b0ef9f9a5dd9ce605fdf18ca9f1b1/id-1.6.1-py3-none-any.whl + name: id + version: 1.6.1 + sha256: f5ec41ed2629a508f5d0988eda142e190c9c6da971100612c4de9ad9f9b237ca + requires_dist: + - urllib3>=2,<3 + - build ; extra == 'dev' + - bump>=1.3.2 ; extra == 'dev' + - id[test,lint] ; extra == 'dev' + - bandit ; extra == 'lint' + - interrogate ; extra == 'lint' + - mypy ; extra == 'lint' + - ruff<0.14.15 ; extra == 'lint' + - pytest ; extra == 'test' + - pytest-cov ; extra == 'test' + - pretend ; extra == 'test' + - coverage[toml] ; extra == 'test' + requires_python: '>=3.9' - conda: https://conda.anaconda.org/conda-forge/noarch/identify-2.6.18-pyhd8ed1ab_0.conda sha256: 3bae1b612ccc71e49c5795a369a82c4707ae6fd4e63360e8ecc129f9539f779b md5: 635d1a924e1c55416fce044ed96144a2 @@ -5205,6 +5999,8 @@ packages: - python license: Apache-2.0 license_family: APACHE + purls: + - pkg:pypi/importlib-metadata?source=compressed-mapping size: 34387 timestamp: 1773931568510 - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-resources-6.5.2-pyhd8ed1ab_0.conda @@ -5232,6 +6028,80 @@ packages: - pkg:pypi/importlib-resources?source=hash-mapping size: 33781 timestamp: 1736252433366 +- pypi: https://files.pythonhosted.org/packages/7f/66/b15ce62552d84bbfcec9a4873ab79d993a1dd4edb922cbfccae192bd5b5f/jaraco.classes-3.4.0-py3-none-any.whl + name: jaraco-classes + version: 3.4.0 + sha256: f662826b6bed8cace05e7ff873ce0f9283b5c924470fe664fff1c2f00f581790 + requires_dist: + - more-itertools + - sphinx>=3.5 ; extra == 'docs' + - jaraco-packaging>=9.3 ; extra == 'docs' + - rst-linker>=1.9 ; extra == 'docs' + - furo ; extra == 'docs' + - sphinx-lint ; extra == 'docs' + - jaraco-tidelift>=1.4 ; extra == 'docs' + - pytest>=6 ; extra == 'testing' + - pytest-checkdocs>=2.4 ; extra == 'testing' + - pytest-cov ; extra == 'testing' + - pytest-mypy ; extra == 'testing' + - pytest-enabler>=2.2 ; extra == 'testing' + - pytest-ruff>=0.2.1 ; extra == 'testing' + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/f2/58/bc8954bda5fcda97bd7c19be11b85f91973d67a706ed4a3aec33e7de22db/jaraco_context-6.1.2-py3-none-any.whl + name: jaraco-context + version: 6.1.2 + sha256: bf8150b79a2d5d91ae48629d8b427a8f7ba0e1097dd6202a9059f29a36379535 + requires_dist: + - backports-tarfile ; python_full_version < '3.12' + - pytest>=6,!=8.1.* ; extra == 'test' + - jaraco-test>=5.6.0 ; extra == 'test' + - portend ; extra == 'test' + - sphinx>=3.5 ; extra == 'doc' + - jaraco-packaging>=9.3 ; extra == 'doc' + - rst-linker>=1.9 ; extra == 'doc' + - furo ; extra == 'doc' + - sphinx-lint ; extra == 'doc' + - jaraco-tidelift>=1.4 ; extra == 'doc' + - pytest-checkdocs>=2.14 ; extra == 'check' + - pytest-ruff>=0.2.1 ; sys_platform != 'cygwin' and extra == 'check' + - pytest-cov ; extra == 'cover' + - pytest-enabler>=3.4 ; extra == 'enabler' + - pytest-mypy>=1.0.1 ; platform_python_implementation != 'PyPy' and extra == 'type' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/fd/c4/813bb09f0985cb21e959f21f2464169eca882656849adf727ac7bb7e1767/jaraco_functools-4.4.0-py3-none-any.whl + name: jaraco-functools + version: 4.4.0 + sha256: 9eec1e36f45c818d9bf307c8948eb03b2b56cd44087b3cdc989abca1f20b9176 + requires_dist: + - more-itertools + - pytest>=6,!=8.1.* ; extra == 'test' + - jaraco-classes ; extra == 'test' + - sphinx>=3.5 ; extra == 'doc' + - jaraco-packaging>=9.3 ; extra == 'doc' + - rst-linker>=1.9 ; extra == 'doc' + - furo ; extra == 'doc' + - sphinx-lint ; extra == 'doc' + - jaraco-tidelift>=1.4 ; extra == 'doc' + - pytest-checkdocs>=2.4 ; extra == 'check' + - pytest-ruff>=0.2.1 ; sys_platform != 'cygwin' and extra == 'check' + - pytest-cov ; extra == 'cover' + - pytest-enabler>=3.4 ; extra == 'enabler' + - pytest-mypy>=1.0.1 ; extra == 'type' + - mypy<1.19 ; platform_python_implementation == 'PyPy' and extra == 'type' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/b2/a3/e137168c9c44d18eff0376253da9f1e9234d0239e0ee230d2fee6cea8e55/jeepney-0.9.0-py3-none-any.whl + name: jeepney + version: 0.9.0 + sha256: 97e5714520c16fc0a45695e5365a2e11b81ea79bba796e26f9f1d178cb182683 + requires_dist: + - pytest ; extra == 'test' + - pytest-trio ; extra == 'test' + - pytest-asyncio>=0.17 ; extra == 'test' + - testpath ; extra == 'test' + - trio ; extra == 'test' + - async-timeout ; python_full_version < '3.11' and extra == 'test' + - trio ; extra == 'trio' + requires_python: '>=3.7' - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpatch-1.33-pyhd8ed1ab_1.conda sha256: 304955757d1fedbe344af43b12b5467cca072f83cce6109361ba942e186b3993 md5: cb60ae9cf02b9fcb8004dec4089e5691 @@ -5256,6 +6126,18 @@ packages: - pkg:pypi/jsonpointer?source=hash-mapping size: 13967 timestamp: 1765026384757 +- conda: https://conda.anaconda.org/conda-forge/noarch/jsonpointer-3.1.1-pyhcf101f3_0.conda + sha256: a3d10301b6ff399ba1f3d39e443664804a3d28315a4fb81e745b6817845f70ae + md5: 89bf346df77603055d3c8fe5811691e6 + depends: + - python >=3.10 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/jsonpointer?source=compressed-mapping + size: 14190 + timestamp: 1774311356147 - conda: https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-64-4.18.0-he073ed8_9.conda sha256: 41557eeadf641de6aeae49486cef30d02a6912d8da98585d687894afd65b356a md5: 86d9cba083cd041bfbf242a01a7a1999 @@ -5276,6 +6158,36 @@ packages: purls: [] size: 1248134 timestamp: 1765578613607 +- pypi: https://files.pythonhosted.org/packages/81/db/e655086b7f3a705df045bf0933bdd9c2f79bb3c97bfef1384598bb79a217/keyring-25.7.0-py3-none-any.whl + name: keyring + version: 25.7.0 + sha256: be4a0b195f149690c166e850609a477c532ddbfbaed96a404d4e43f8d5e2689f + requires_dist: + - pywin32-ctypes>=0.2.0 ; sys_platform == 'win32' + - secretstorage>=3.2 ; sys_platform == 'linux' + - jeepney>=0.4.2 ; sys_platform == 'linux' + - importlib-metadata>=4.11.4 ; python_full_version < '3.12' + - jaraco-classes + - jaraco-functools + - jaraco-context + - pytest>=6,!=8.1.* ; extra == 'test' + - pyfakefs ; extra == 'test' + - sphinx>=3.5 ; extra == 'doc' + - jaraco-packaging>=9.3 ; extra == 'doc' + - rst-linker>=1.9 ; extra == 'doc' + - furo ; extra == 'doc' + - sphinx-lint ; extra == 'doc' + - jaraco-tidelift>=1.4 ; extra == 'doc' + - pytest-checkdocs>=2.4 ; extra == 'check' + - pytest-ruff>=0.2.1 ; sys_platform != 'cygwin' and extra == 'check' + - pytest-cov ; extra == 'cover' + - pytest-enabler>=3.4 ; extra == 'enabler' + - pytest-mypy>=1.0.1 ; extra == 'type' + - pygobject-stubs ; extra == 'type' + - shtab ; extra == 'type' + - types-pywin32 ; extra == 'type' + - shtab>=1.1.0 ; extra == 'completion' + requires_python: '>=3.9' - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda sha256: 0960d06048a7185d3542d850986d807c6e37ca2e644342dd0c72feefcf26c2a4 md5: b38117a3c920364aff79f870c984b4a3 @@ -5350,6 +6262,7 @@ packages: - openssl >=3.5.5,<4.0a0 license: MIT license_family: MIT + purls: [] size: 1193620 timestamp: 1769770267475 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.21.2-h92f50d5_0.conda @@ -5376,6 +6289,7 @@ packages: - openssl >=3.5.5,<4.0a0 license: MIT license_family: MIT + purls: [] size: 1160828 timestamp: 1769770119811 - conda: https://conda.anaconda.org/conda-forge/win-64/krb5-1.22.2-h0ea6238_0.conda @@ -5468,6 +6382,19 @@ packages: purls: [] size: 725507 timestamp: 1770267139900 +- conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_102.conda + sha256: 3d584956604909ff5df353767f3a2a2f60e07d070b328d109f30ac40cd62df6c + md5: 18335a698559cdbcd86150a48bf54ba6 + depends: + - __glibc >=2.17,<3.0.a0 + - zstd >=1.5.7,<1.6.0a0 + constrains: + - binutils_impl_linux-64 2.45.1 + license: GPL-3.0-only + license_family: GPL + purls: [] + size: 728002 + timestamp: 1774197446916 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.45.1-default_h1979696_101.conda sha256: 44527364aa333be631913451c32eb0cae1e09343827e9ce3ccabd8d962584226 md5: 35b2ae7fadf364b8e5fb8185aaeb80e5 @@ -5480,6 +6407,18 @@ packages: purls: [] size: 875924 timestamp: 1770267209884 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.45.1-default_h1979696_102.conda + sha256: 7abd913d81a9bf00abb699e8987966baa2065f5132e37e815f92d90fc6bba530 + md5: a21644fc4a83da26452a718dc9468d5f + depends: + - zstd >=1.5.7,<1.6.0a0 + constrains: + - binutils_impl_linux-aarch64 2.45.1 + license: GPL-3.0-only + license_family: GPL + purls: [] + size: 875596 + timestamp: 1774197520746 - conda: https://conda.anaconda.org/conda-forge/linux-64/libarchive-3.8.6-gpl_hc2c16d8_100.conda sha256: 69ea8da58658ad26cb64fb0bfccd8a3250339811f0b57c6b8a742e5e51bacf70 md5: 981d372c31a23e1aa9965d4e74d085d5 @@ -5536,6 +6475,7 @@ packages: - zstd >=1.5.7,<1.6.0a0 license: BSD-2-Clause license_family: BSD + purls: [] size: 761501 timestamp: 1773243700449 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarchive-3.8.6-gpl_h6fbacd7_100.conda @@ -5555,6 +6495,7 @@ packages: - zstd >=1.5.7,<1.6.0a0 license: BSD-2-Clause license_family: BSD + purls: [] size: 791560 timestamp: 1773243648871 - conda: https://conda.anaconda.org/conda-forge/win-64/libarchive-3.8.6-gpl_he24518a_100.conda @@ -5596,24 +6537,6 @@ packages: purls: [] size: 18213 timestamp: 1765818813880 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-6_h4a7cf45_openblas.conda - build_number: 6 - sha256: 7bfe936dbb5db04820cf300a9cc1f5ee8d5302fc896c2d66e30f1ee2f20fbfd6 - md5: 6d6d225559bfa6e2f3c90ee9c03d4e2e - depends: - - libopenblas >=0.3.32,<0.3.33.0a0 - - libopenblas >=0.3.32,<1.0a0 - constrains: - - blas 2.306 openblas - - liblapack 3.11.0 6*_openblas - - liblapacke 3.11.0 6*_openblas - - libcblas 3.11.0 6*_openblas - - mkl <2026 - license: BSD-3-Clause - license_family: BSD - purls: [] - size: 18621 - timestamp: 1774503034895 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libblas-3.11.0-5_haddc8a3_openblas.conda build_number: 5 sha256: 700f3c03d0fba8e687a345404a45fbabe781c1cf92242382f62cef2948745ec4 @@ -5697,21 +6620,6 @@ packages: purls: [] size: 18194 timestamp: 1765818837135 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-6_h0358290_openblas.conda - build_number: 6 - sha256: 57edafa7796f6fa3ebbd5367692dd4c7f552be42109c2dd1a7c89b55089bf374 - md5: 36ae340a916635b97ac8a0655ace2a35 - depends: - - libblas 3.11.0 6_h4a7cf45_openblas - constrains: - - blas 2.306 openblas - - liblapack 3.11.0 6*_openblas - - liblapacke 3.11.0 6*_openblas - license: BSD-3-Clause - license_family: BSD - purls: [] - size: 18622 - timestamp: 1774503050205 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcblas-3.11.0-5_hd72aa62_openblas.conda build_number: 5 sha256: 3fad5c9de161dccb4e42c8b1ae8eccb33f4ed56bccbcced9cbb0956ae7869e61 @@ -5840,6 +6748,7 @@ packages: - zstd >=1.5.7,<1.6.0a0 license: curl license_family: MIT + purls: [] size: 419039 timestamp: 1773219507657 - conda: https://conda.anaconda.org/conda-forge/osx-64/libcurl-8.4.0-h726d00d_0.conda @@ -5870,6 +6779,7 @@ packages: - zstd >=1.5.7,<1.6.0a0 license: curl license_family: MIT + purls: [] size: 399616 timestamp: 1773219210246 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcurl-8.4.0-h2d989ff_0.conda @@ -5919,6 +6829,16 @@ packages: license_family: Apache size: 564942 timestamp: 1773203656390 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libcxx-22.1.2-h19cb2f5_0.conda + sha256: 46561199545890e050a8a90edcfce984e5f881da86b09388926e3a6c6b759dec + md5: ed6f7b7a35f942a0301e581d72616f7d + depends: + - __osx >=11.0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + purls: [] + size: 564908 + timestamp: 1774439353713 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-16.0.6-h4653b0c_0.conda sha256: 11d3fb51c14832d9e4f6d84080a375dec21ea8a3a381a1910e67ff9cedc20355 md5: 9d7d724faf0413bf1dbc5a85935700c8 @@ -5936,6 +6856,16 @@ packages: license_family: Apache size: 570281 timestamp: 1773203613980 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-22.1.2-h55c6f16_0.conda + sha256: d1402087c8792461bfc081629e8aa97e6e577a31ae0b84e6b9cc144a18f48067 + md5: 4280e0a7fd613b271e022e60dea0138c + depends: + - __osx >=11.0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + purls: [] + size: 568094 + timestamp: 1774439202359 - conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.conda sha256: d789471216e7aba3c184cd054ed61ce3f6dac6f87a50ec69291b9297f8c18724 md5: c277e0a4d549b03ac1e9d6cbbe3d017b @@ -5980,6 +6910,7 @@ packages: - ncurses >=6.5,<7.0a0 license: BSD-2-Clause license_family: BSD + purls: [] size: 115563 timestamp: 1738479554273 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libedit-3.1.20191231-hc8eb9b7_2.tar.bz2 @@ -6001,6 +6932,7 @@ packages: - ncurses >=6.5,<7.0a0 license: BSD-2-Clause license_family: BSD + purls: [] size: 107691 timestamp: 1738479560845 - conda: https://conda.anaconda.org/conda-forge/linux-64/libev-4.33-hd590300_2.conda @@ -6052,6 +6984,19 @@ packages: purls: [] size: 76798 timestamp: 1771259418166 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.5-hecca717_0.conda + sha256: e8c2b57f6aacabdf2f1b0924bd4831ce5071ba080baa4a9e8c0d720588b6794c + md5: 49f570f3bc4c874a06ea69b7225753af + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + constrains: + - expat 2.7.5.* + license: MIT + license_family: MIT + purls: [] + size: 76624 + timestamp: 1774719175983 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.7.4-hfae3067_0.conda sha256: 995ce3ad96d0f4b5ed6296b051a0d7b6377718f325bc0e792fbb96b0e369dad7 md5: 57f3b3da02a50a1be2a6fe847515417d @@ -6064,6 +7009,18 @@ packages: purls: [] size: 76564 timestamp: 1771259530958 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.7.5-hfae3067_0.conda + sha256: 6d438fc0bfdb263c24654fe49c09b31f06ec78eb709eb386392d2499af105f85 + md5: 05d1e0b30acd816a192c03dc6e164f4d + depends: + - libgcc >=14 + constrains: + - expat 2.7.5.* + license: MIT + license_family: MIT + purls: [] + size: 76523 + timestamp: 1774719129371 - conda: https://conda.anaconda.org/conda-forge/osx-64/libexpat-2.6.2-h73e2aa4_0.conda sha256: a188a77b275d61159a32ab547f7d17892226e7dac4518d2c6ac3ac8fc8dfde92 md5: 3d1d51c8f716d97c864d12f7af329526 @@ -6085,6 +7042,18 @@ packages: license_family: MIT size: 74578 timestamp: 1771260142624 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libexpat-2.7.5-hcc62823_0.conda + sha256: 341d8a457a8342c396a8ac788da2639cbc8b62568f6ba2a3d322d1ace5aa9e16 + md5: 1d6e71b8c73711e28ffe207acdc4e2f8 + depends: + - __osx >=11.0 + constrains: + - expat 2.7.5.* + license: MIT + license_family: MIT + purls: [] + size: 74797 + timestamp: 1774719557730 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.6.2-hebf3989_0.conda sha256: ba7173ac30064ea901a4c9fb5a51846dcc25512ceb565759be7d18cbf3e5415e md5: e3cde7cfa87f82f7cb13d482d5e0ad09 @@ -6106,6 +7075,18 @@ packages: license_family: MIT size: 68199 timestamp: 1771260020767 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.7.5-hf6b4638_0.conda + sha256: 06780dec91dd25770c8cf01e158e1062fbf7c576b1406427475ce69a8af75b7e + md5: a32123f93e168eaa4080d87b0fb5da8a + depends: + - __osx >=11.0 + constrains: + - expat 2.7.5.* + license: MIT + license_family: MIT + purls: [] + size: 68192 + timestamp: 1774719211725 - conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.7.4-hac47afa_0.conda sha256: b31f6fb629c4e17885aaf2082fb30384156d16b48b264e454de4a06a313b533d md5: 1c1ced969021592407f16ada4573586d @@ -6120,6 +7101,20 @@ packages: purls: [] size: 70323 timestamp: 1771259521393 +- conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.7.5-hac47afa_0.conda + sha256: 6850c3a4d5dc215b86f58518cfb8752998533d6569b08da8df1da72e7c68e571 + md5: bfb43f52f13b7c56e7677aa7a8efdf0c + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + constrains: + - expat 2.7.5.* + license: MIT + license_family: MIT + purls: [] + size: 70609 + timestamp: 1774719377850 - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda sha256: 31f19b6a88ce40ebc0d5a992c131f57d919f73c0b92cd1617a5bec83f6e961e6 md5: a360c33a5abe61c07959e449fa1453eb @@ -6156,6 +7151,7 @@ packages: - __osx >=10.13 license: MIT license_family: MIT + purls: [] size: 53583 timestamp: 1769456300951 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.4.2-h3422bc3_5.tar.bz2 @@ -6173,6 +7169,7 @@ packages: - __osx >=11.0 license: MIT license_family: MIT + purls: [] size: 40979 timestamp: 1769456747661 - conda: https://conda.anaconda.org/conda-forge/win-64/libffi-3.5.2-h3d046cb_0.conda @@ -6469,6 +7466,7 @@ packages: depends: - __osx >=10.13 license: LGPL-2.1-only + purls: [] size: 737846 timestamp: 1754908900138 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libiconv-1.17-h0d3ecfb_2.conda @@ -6484,6 +7482,7 @@ packages: depends: - __osx >=11.0 license: LGPL-2.1-only + purls: [] size: 750379 timestamp: 1754909073836 - conda: https://conda.anaconda.org/conda-forge/win-64/libiconv-1.18-hc1393d2_2.conda @@ -6512,21 +7511,6 @@ packages: purls: [] size: 18200 timestamp: 1765818857876 -- conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.11.0-6_h47877c9_openblas.conda - build_number: 6 - sha256: 371f517eb7010b21c6cc882c7606daccebb943307cb9a3bf2c70456a5c024f7d - md5: 881d801569b201c2e753f03c84b85e15 - depends: - - libblas 3.11.0 6_h4a7cf45_openblas - constrains: - - blas 2.306 openblas - - liblapacke 3.11.0 6*_openblas - - libcblas 3.11.0 6*_openblas - license: BSD-3-Clause - license_family: BSD - purls: [] - size: 18624 - timestamp: 1774503065378 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblapack-3.11.0-5_h88aeb00_openblas.conda build_number: 5 sha256: 692222d186d3ffbc99eaf04b5b20181fd26aee1edec1106435a0a755c57cce86 @@ -6644,6 +7628,7 @@ packages: constrains: - xz 5.8.2.* license: 0BSD + purls: [] size: 105482 timestamp: 1768753411348 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.2-h8088a28_0.conda @@ -6654,6 +7639,7 @@ packages: constrains: - xz 5.8.2.* license: 0BSD + purls: [] size: 92242 timestamp: 1768752982486 - conda: https://conda.anaconda.org/conda-forge/win-64/liblzma-5.8.2-hfd05255_0.conda @@ -6739,6 +7725,7 @@ packages: - libsolv >=0.7.35,<0.8.0a0 license: BSD-3-Clause license_family: BSD + purls: [] size: 1785898 timestamp: 1767884200743 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmamba-2.5.0-h7950639_0.conda @@ -6762,6 +7749,7 @@ packages: - reproc-cpp >=14.2,<15.0a0 license: BSD-3-Clause license_family: BSD + purls: [] size: 1653523 timestamp: 1767884201469 - conda: https://conda.anaconda.org/conda-forge/win-64/libmamba-2.5.0-h06825f5_0.conda @@ -6823,6 +7811,7 @@ packages: - libmamba >=2.5.0,<2.6.0a0 license: BSD-3-Clause license_family: BSD + purls: [] size: 20784 timestamp: 1767884200753 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmamba-spdlog-2.5.0-h85b9800_0.conda @@ -6834,6 +7823,7 @@ packages: - libmamba >=2.5.0,<2.6.0a0 license: BSD-3-Clause license_family: BSD + purls: [] size: 23068 timestamp: 1767884201476 - conda: https://conda.anaconda.org/conda-forge/win-64/libmamba-spdlog-2.5.0-h9ae1bf1_0.conda @@ -6920,6 +7910,8 @@ packages: - libmamba >=2.5.0,<2.6.0a0 license: BSD-3-Clause license_family: BSD + purls: + - pkg:pypi/libmambapy?source=hash-mapping size: 948138 timestamp: 1767884157875 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libmambapy-2.5.0-py310hdf79504_0.conda @@ -6993,6 +7985,8 @@ packages: - nlohmann_json-abi ==3.12.0 license: BSD-3-Clause license_family: BSD + purls: + - pkg:pypi/libmambapy?source=hash-mapping size: 834849 timestamp: 1767884182402 - conda: https://conda.anaconda.org/conda-forge/osx-64/libmambapy-2.5.0-py314haca2e77_0.conda @@ -7015,6 +8009,8 @@ packages: - openssl >=3.5.4,<4.0a0 license: BSD-3-Clause license_family: BSD + purls: + - pkg:pypi/libmambapy?source=hash-mapping size: 815795 timestamp: 1767884200763 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmambapy-2.5.0-py314hf8f60b7_0.conda @@ -7038,6 +8034,8 @@ packages: - pybind11-abi ==11 license: BSD-3-Clause license_family: BSD + purls: + - pkg:pypi/libmambapy?source=hash-mapping size: 769644 timestamp: 1767884201481 - conda: https://conda.anaconda.org/conda-forge/win-64/libmambapy-2.5.0-py310h1916185_0.conda @@ -7111,6 +8109,8 @@ packages: - openssl >=3.5.4,<4.0a0 license: BSD-3-Clause license_family: BSD + purls: + - pkg:pypi/libmambapy?source=hash-mapping size: 587744 timestamp: 1767884194858 - conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb03c661_1.conda @@ -7121,6 +8121,7 @@ packages: - libgcc >=14 license: BSD-2-Clause license_family: BSD + purls: [] size: 92400 timestamp: 1769482286018 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libmpdec-4.0.0-he30d5cf_1.conda @@ -7130,6 +8131,7 @@ packages: - libgcc >=14 license: BSD-2-Clause license_family: BSD + purls: [] size: 114056 timestamp: 1769482343003 - conda: https://conda.anaconda.org/conda-forge/osx-64/libmpdec-4.0.0-hf3981d6_1.conda @@ -7139,6 +8141,7 @@ packages: - __osx >=10.13 license: BSD-2-Clause license_family: BSD + purls: [] size: 79899 timestamp: 1769482558610 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmpdec-4.0.0-h84a0fba_1.conda @@ -7148,6 +8151,7 @@ packages: - __osx >=11.0 license: BSD-2-Clause license_family: BSD + purls: [] size: 73690 timestamp: 1769482560514 - conda: https://conda.anaconda.org/conda-forge/win-64/libmpdec-4.0.0-hfd05255_1.conda @@ -7159,6 +8163,7 @@ packages: - vc14_runtime >=14.44.35208 license: BSD-2-Clause license_family: BSD + purls: [] size: 89411 timestamp: 1769482314283 - conda: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.67.0-had1ee68_0.conda @@ -7178,6 +8183,23 @@ packages: purls: [] size: 666600 timestamp: 1756834976695 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.68.1-h877daf1_0.conda + sha256: 663444d77a42f2265f54fb8b48c5450bfff4388d9c0f8253dd7855f0d993153f + md5: 2a45e7f8af083626f009645a6481f12d + depends: + - __glibc >=2.17,<3.0.a0 + - c-ares >=1.34.6,<2.0a0 + - libev >=4.33,<4.34.0a0 + - libev >=4.33,<5.0a0 + - libgcc >=14 + - libstdcxx >=14 + - libzlib >=1.3.1,<2.0a0 + - openssl >=3.5.5,<4.0a0 + license: MIT + license_family: MIT + purls: [] + size: 663344 + timestamp: 1773854035739 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libnghttp2-1.67.0-ha888d0e_0.conda sha256: b03f406fd5c3f865a5e08c89b625245a9c4e026438fd1a445e45e6a0d69c2749 md5: 981082c1cc262f514a5a2cf37cab9b81 @@ -7239,6 +8261,22 @@ packages: license_family: MIT size: 605680 timestamp: 1756835898134 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libnghttp2-1.68.1-h70048d4_0.conda + sha256: 899551e16aac9dfb85bfc2fd98b655f4d1b7fea45720ec04ccb93d95b4d24798 + md5: dba4c95e2fe24adcae4b77ebf33559ae + depends: + - __osx >=11.0 + - c-ares >=1.34.6,<2.0a0 + - libcxx >=19 + - libev >=4.33,<4.34.0a0 + - libev >=4.33,<5.0a0 + - libzlib >=1.3.1,<2.0a0 + - openssl >=3.5.5,<4.0a0 + license: MIT + license_family: MIT + purls: [] + size: 606749 + timestamp: 1773854765508 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libnghttp2-1.52.0-hae82a92_0.conda sha256: 1a3944d6295dcbecdf6489ce8a05fe416ad401727c901ec390e9200a351bdb10 md5: 1d319e95a0216f801293626a00337712 @@ -7263,11 +8301,27 @@ packages: - libev >=4.33,<4.34.0a0 - libev >=4.33,<5.0a0 - libzlib >=1.3.1,<2.0a0 - - openssl >=3.5.2,<4.0a0 + - openssl >=3.5.2,<4.0a0 + license: MIT + license_family: MIT + size: 575454 + timestamp: 1756835746393 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libnghttp2-1.68.1-h8f3e76b_0.conda + sha256: 2bc7bc3978066f2c274ebcbf711850cc9ab92e023e433b9631958a098d11e10a + md5: 6ea18834adbc3b33df9bd9fb45eaf95b + depends: + - __osx >=11.0 + - c-ares >=1.34.6,<2.0a0 + - libcxx >=19 + - libev >=4.33,<4.34.0a0 + - libev >=4.33,<5.0a0 + - libzlib >=1.3.1,<2.0a0 + - openssl >=3.5.5,<4.0a0 license: MIT license_family: MIT - size: 575454 - timestamp: 1756835746393 + purls: [] + size: 576526 + timestamp: 1773854624224 - conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hb9d3cd8_1.conda sha256: 927fe72b054277cde6cb82597d0fcf6baf127dcbce2e0a9d8925a68f1265eef5 md5: d864d34357c3b65a4b731f78c0801dc4 @@ -7304,21 +8358,6 @@ packages: purls: [] size: 5927939 timestamp: 1763114673331 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.32-pthreads_h94d23a6_0.conda - sha256: 6dc30b28f32737a1c52dada10c8f3a41bc9e021854215efca04a7f00487d09d9 - md5: 89d61bc91d3f39fda0ca10fcd3c68594 - depends: - - __glibc >=2.17,<3.0.a0 - - libgcc >=14 - - libgfortran - - libgfortran5 >=14.3.0 - constrains: - - openblas >=0.3.32,<0.3.33.0a0 - license: BSD-3-Clause - license_family: BSD - purls: [] - size: 5928890 - timestamp: 1774471724897 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libopenblas-0.3.30-pthreads_h9d3fd7e_4.conda sha256: 794a7270ea049ec931537874cd8d2de0ef4b3cef71c055cfd8b4be6d2f4228b0 md5: 11d7d57b7bdd01da745bbf2b67020b2e @@ -7397,6 +8436,19 @@ packages: purls: [] size: 518374 timestamp: 1754325691186 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libsolv-0.7.36-h9463b59_0.conda + sha256: 2a336d83e25e67b69548ee233188fa612cbce6809b3e2d45dd0b6520d75b3870 + md5: e6e2535fc6b69b08cdbaeab01aa1c277 + depends: + - libstdcxx >=14 + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + - libzlib >=1.3.1,<2.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 519098 + timestamp: 1773328331358 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsolv-0.7.35-hdda61c4_0.conda sha256: f68dde30e903721825214310a98ff2444857d168b12ef657c064aad22a620f06 md5: 3e817cbcc10f018c547a1b4885094b15 @@ -7431,6 +8483,18 @@ packages: license_family: BSD size: 457297 timestamp: 1754325699071 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libsolv-0.7.36-hf97c9bc_0.conda + sha256: 622bc7d0799ba7f9825ca82fcee3d4d60bef3acdb1ad1136bfa618e479c6d338 + md5: 06871f2bcba5d0026d6698f363c36a87 + depends: + - __osx >=11.0 + - libcxx >=19 + - libzlib >=1.3.1,<2.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 459988 + timestamp: 1773328382913 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsolv-0.7.35-h5f525b2_0.conda sha256: 6da97a1c572659c2be3c3f2f39d9238dac5af2b1fd546adf2b735b0fda2ed8ec md5: b7ffc6dc926929b9b35af5084a761f26 @@ -7442,6 +8506,18 @@ packages: license_family: BSD size: 428408 timestamp: 1754325703193 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsolv-0.7.36-h7d962ec_0.conda + sha256: d7eeef792c8b12804c99b6a2c66e635e4f7d7a3d34713af070c2aa6c41c9b750 + md5: 038c047500a1db74206cf56811e80e08 + depends: + - __osx >=11.0 + - libcxx >=19 + - libzlib >=1.3.1,<2.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 428233 + timestamp: 1773328439105 - conda: https://conda.anaconda.org/conda-forge/win-64/libsolv-0.7.35-h8883371_0.conda sha256: 80ccb7857fa2b60679a5209ca04334c86c46a441e8f4f2859308b69f8e1e928a md5: 987be7025314bcfe936de3f0e91082b5 @@ -7458,6 +8534,19 @@ packages: purls: [] size: 466924 timestamp: 1754325716718 +- conda: https://conda.anaconda.org/conda-forge/win-64/libsolv-0.7.36-h8883371_0.conda + sha256: a5abc59cd2644b964a303cc62ef8c2e08adad05d14941196130cd718d00e6eea + md5: 3ab153559588783712f13ab285a0a506 + depends: + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - libzlib >=1.3.1,<2.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 468194 + timestamp: 1773328370793 - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.52.0-hf4e2dac_0.conda sha256: d716847b7deca293d2e49ed1c8ab9e4b9e04b9d780aea49a97c26925b28a7993 md5: fd893f6a3002a635b5e50ceb9dd2c0f4 @@ -7497,6 +8586,7 @@ packages: - __osx >=11.0 - libzlib >=1.3.1,<2.0a0 license: blessing + purls: [] size: 996526 timestamp: 1772819669038 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.45.3-h091b4b1_0.conda @@ -7516,6 +8606,7 @@ packages: - icu >=78.2,<79.0a0 - libzlib >=1.3.1,<2.0a0 license: blessing + purls: [] size: 918420 timestamp: 1772819478684 - conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.52.0-hf5d6505_0.conda @@ -7574,6 +8665,7 @@ packages: - openssl >=3.5.0,<4.0a0 license: BSD-3-Clause license_family: BSD + purls: [] size: 284216 timestamp: 1745608575796 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libssh2-1.11.0-h7a5bd25_0.conda @@ -7595,6 +8687,7 @@ packages: - openssl >=3.5.0,<4.0a0 license: BSD-3-Clause license_family: BSD + purls: [] size: 279193 timestamp: 1745608793272 - conda: https://conda.anaconda.org/conda-forge/win-64/libssh2-1.11.1-h9aa295b_0.conda @@ -7687,6 +8780,17 @@ packages: purls: [] size: 40311 timestamp: 1766271528534 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42-h5347b49_0.conda + sha256: bc1b08c92626c91500fd9f26f2c797f3eb153b627d53e9c13cd167f1e12b2829 + md5: 38ffe67b78c9d4de527be8315e5ada2c + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 40297 + timestamp: 1775052476770 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.41.3-h1022ec0_0.conda sha256: c37a8e89b700646f3252608f8368e7eb8e2a44886b92776e57ad7601fc402a11 md5: cf2861212053d05f27ec49c3784ff8bb @@ -7697,6 +8801,16 @@ packages: purls: [] size: 43453 timestamp: 1766271546875 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.42-h1022ec0_0.conda + sha256: 7d427edf58c702c337bf62bc90f355b7fc374a65fd9f70ea7a490f13bb76b1b9 + md5: a0b5de740d01c390bdbb46d7503c9fab + depends: + - libgcc >=14 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 43567 + timestamp: 1775052485727 - conda: https://conda.anaconda.org/conda-forge/linux-64/libuv-1.51.0-hb03c661_1.conda sha256: c180f4124a889ac343fc59d15558e93667d894a966ec6fdb61da1604481be26b md5: 0f03292cc56bf91a077a134ea8747118 @@ -7832,6 +8946,7 @@ packages: - libzlib >=1.3.1,<2.0a0 license: MIT license_family: MIT + purls: [] size: 41106 timestamp: 1772705465931 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-2.12.6-h35eab27_2.conda @@ -7859,6 +8974,7 @@ packages: - libzlib >=1.3.1,<2.0a0 license: MIT license_family: MIT + purls: [] size: 41206 timestamp: 1772704982288 - conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-2.15.2-h5d26750_0.conda @@ -7925,6 +9041,7 @@ packages: - libxml2 2.15.2 license: MIT license_family: MIT + purls: [] size: 495922 timestamp: 1772705426323 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-16-2.15.2-h5ef1a60_0.conda @@ -7940,6 +9057,7 @@ packages: - libxml2 2.15.2 license: MIT license_family: MIT + purls: [] size: 466220 timestamp: 1772704950232 - conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-16-2.15.2-h692994f_0.conda @@ -7973,6 +9091,18 @@ packages: purls: [] size: 60963 timestamp: 1727963148474 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_2.conda + sha256: 55044c403570f0dc26e6364de4dc5368e5f3fc7ff103e867c487e2b5ab2bcda9 + md5: d87ff7921124eccd67248aa483c23fec + depends: + - __glibc >=2.17,<3.0.a0 + constrains: + - zlib 1.3.2 *_2 + license: Zlib + license_family: Other + purls: [] + size: 63629 + timestamp: 1774072609062 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.3.1-h86ecc28_2.conda sha256: 5a2c1eeef69342e88a98d1d95bff1603727ab1ff4ee0e421522acd8813439b84 md5: 08aad7cbe9f5a6b460d0976076b6ae64 @@ -7985,6 +9115,16 @@ packages: purls: [] size: 66657 timestamp: 1727963199518 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.3.2-hdc9db2a_2.conda + sha256: eb111e32e5a7313a5bf799c7fb2419051fa2fe7eff74769fac8d5a448b309f7f + md5: 502006882cf5461adced436e410046d1 + constrains: + - zlib 1.3.2 *_2 + license: Zlib + license_family: Other + purls: [] + size: 69833 + timestamp: 1774072605429 - conda: https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.3.1-hd23fc13_2.conda sha256: 8412f96504fc5993a63edf1e211d042a1fd5b1d51dedec755d2058948fcced09 md5: 003a54a4e32b02f7355b50a837e699da @@ -8006,6 +9146,18 @@ packages: purls: [] size: 57480 timestamp: 1709241092733 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.3.2-hbb4bfdb_2.conda + sha256: 4c6da089952b2d70150c74234679d6f7ac04f4a98f9432dec724968f912691e7 + md5: 30439ff30578e504ee5e0b390afc8c65 + depends: + - __osx >=11.0 + constrains: + - zlib 1.3.2 *_2 + license: Zlib + license_family: Other + purls: [] + size: 59000 + timestamp: 1774073052242 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.1-h0d3ecfb_0.conda sha256: 9c59bd3f3e3e1900620e3a85c04d3a3699cb93c714333d06cb8afdd7addaae9d md5: 2a2463424cc5e961a6d04bbbfb5838cf @@ -8027,6 +9179,18 @@ packages: license_family: Other size: 46438 timestamp: 1727963202283 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.2-h8088a28_2.conda + sha256: 361415a698514b19a852f5d1123c5da746d4642139904156ddfca7c922d23a05 + md5: bc5a5721b6439f2f62a84f2548136082 + depends: + - __osx >=11.0 + constrains: + - zlib 1.3.2 *_2 + license: Zlib + license_family: Other + purls: [] + size: 47759 + timestamp: 1774072956767 - conda: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.3.1-h2466b09_2.conda sha256: ba945c6493449bed0e6e29883c4943817f7c79cbff52b83360f7b341277c6402 md5: 41fbfac52c601159df6c01f875de31b9 @@ -8041,6 +9205,20 @@ packages: purls: [] size: 55476 timestamp: 1727963768015 +- conda: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.3.2-hfd05255_2.conda + sha256: 88609816e0cc7452bac637aaf65783e5edf4fee8a9f8e22bdc3a75882c536061 + md5: dbabbd6234dea34040e631f87676292f + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + constrains: + - zlib 1.3.2 *_2 + license: Zlib + license_family: Other + purls: [] + size: 58347 + timestamp: 1774072851498 - conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-openmp-18.1.3-hb6ac08f_0.conda sha256: 997e4169ea474a7bc137fed3b5f4d94b1175162b3318e8cb3943003e460fe458 md5: 506f270f4f00980d27cc1fc127e0ed37 @@ -8143,6 +9321,7 @@ packages: - libcxx >=18 license: BSD-2-Clause license_family: BSD + purls: [] size: 159500 timestamp: 1733741074747 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/lz4-c-1.10.0-h286801f_1.conda @@ -8153,6 +9332,7 @@ packages: - libcxx >=18 license: BSD-2-Clause license_family: BSD + purls: [] size: 148824 timestamp: 1733741047892 - conda: https://conda.anaconda.org/conda-forge/win-64/lz4-c-1.10.0-h2466b09_1.conda @@ -8195,6 +9375,7 @@ packages: - __osx >=10.13 license: GPL-2.0-or-later license_family: GPL + purls: [] size: 174634 timestamp: 1753889269889 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/lzo-2.10-h925e9cb_1002.conda @@ -8204,6 +9385,7 @@ packages: - __osx >=11.0 license: GPL-2.0-or-later license_family: GPL + purls: [] size: 152755 timestamp: 1753889267953 - conda: https://conda.anaconda.org/conda-forge/win-64/lzo-2.10-h6a83c73_1002.conda @@ -8227,6 +9409,44 @@ packages: sha256: da1a3fa8266e30f0ce7e97c6a54eefaae8edd1e5f86f3eb8b95457cae90265ea requires_dist: - altgraph>=0.17 +- pypi: https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl + name: markdown-it-py + version: 4.0.0 + sha256: 87327c59b172c5011896038353a81343b6754500a08cd7a4973bb48c6d578147 + requires_dist: + - mdurl~=0.1 + - psutil ; extra == 'benchmarking' + - pytest ; extra == 'benchmarking' + - pytest-benchmark ; extra == 'benchmarking' + - commonmark~=0.9 ; extra == 'compare' + - markdown~=3.4 ; extra == 'compare' + - mistletoe~=1.0 ; extra == 'compare' + - mistune~=3.0 ; extra == 'compare' + - panflute~=2.3 ; extra == 'compare' + - markdown-it-pyrs ; extra == 'compare' + - linkify-it-py>=1,<3 ; extra == 'linkify' + - mdit-py-plugins>=0.5.0 ; extra == 'plugins' + - gprof2dot ; extra == 'profiling' + - mdit-py-plugins>=0.5.0 ; extra == 'rtd' + - myst-parser ; extra == 'rtd' + - pyyaml ; extra == 'rtd' + - sphinx ; extra == 'rtd' + - sphinx-copybutton ; extra == 'rtd' + - sphinx-design ; extra == 'rtd' + - sphinx-book-theme~=1.0 ; extra == 'rtd' + - jupyter-sphinx ; extra == 'rtd' + - ipykernel ; extra == 'rtd' + - coverage ; extra == 'testing' + - pytest ; extra == 'testing' + - pytest-cov ; extra == 'testing' + - pytest-regressions ; extra == 'testing' + - requests ; extra == 'testing' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl + name: mdurl + version: 0.1.2 + sha256: 84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8 + requires_python: '>=3.7' - conda: https://conda.anaconda.org/conda-forge/linux-64/menuinst-2.4.2-py310hff52083_0.conda sha256: ec100872ca86c8dc6a08b16d0046661dd85ebb6b6910c57dfcafecbdc622a1ba md5: 937b4f62485b63f71ee8d50ae021cc33 @@ -8256,6 +9476,8 @@ packages: - python >=3.14,<3.15.0a0 - python_abi 3.14.* *_cp314 license: BSD-3-Clause AND MIT + purls: + - pkg:pypi/menuinst?source=hash-mapping size: 188752 timestamp: 1765733220513 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/menuinst-2.4.2-py310h4c7bcd0_0.conda @@ -8290,6 +9512,8 @@ packages: - python >=3.14,<3.15.0a0 *_cp314 - python_abi 3.14.* *_cp314 license: BSD-3-Clause AND MIT + purls: + - pkg:pypi/menuinst?source=hash-mapping size: 188584 timestamp: 1765733234092 - conda: https://conda.anaconda.org/conda-forge/osx-64/menuinst-2.4.2-py314hee6578b_0.conda @@ -8299,6 +9523,8 @@ packages: - python >=3.14,<3.15.0a0 - python_abi 3.14.* *_cp314 license: BSD-3-Clause AND MIT + purls: + - pkg:pypi/menuinst?source=hash-mapping size: 187629 timestamp: 1765733352246 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/menuinst-2.4.2-py314h4dc9dd8_0.conda @@ -8309,6 +9535,8 @@ packages: - python >=3.14,<3.15.0a0 *_cp314 - python_abi 3.14.* *_cp314 license: BSD-3-Clause AND MIT + purls: + - pkg:pypi/menuinst?source=hash-mapping size: 188284 timestamp: 1765733422732 - conda: https://conda.anaconda.org/conda-forge/win-64/menuinst-2.4.2-py310h73ae2b4_0.conda @@ -8349,6 +9577,8 @@ packages: - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: BSD-3-Clause AND MIT + purls: + - pkg:pypi/menuinst?source=hash-mapping size: 179510 timestamp: 1765733497067 - conda: https://conda.anaconda.org/conda-forge/win-64/mkl-2025.3.0-hac47afa_455.conda @@ -8365,6 +9595,11 @@ packages: purls: [] size: 100224829 timestamp: 1767634557029 +- pypi: https://files.pythonhosted.org/packages/a4/8e/469e5a4a2f5855992e425f3cb33804cc07bf18d48f2db061aec61ce50270/more_itertools-10.8.0-py3-none-any.whl + name: more-itertools + version: 10.8.0 + sha256: 52d4362373dcf7c52546bc4af9a86ee7c4579df9a8dc268be0a2f949d376cc9b + requires_python: '>=3.9' - conda: https://conda.anaconda.org/conda-forge/linux-64/msgpack-python-1.1.2-py310h03d9f68_1.conda sha256: 61cf3572d6afa3fa711c5f970a832783d2c281facb7b3b946a6b71a0bac2c592 md5: 5eea9d8f8fcf49751dab7927cb0dfc3f @@ -8406,6 +9641,8 @@ packages: - python_abi 3.14.* *_cp314 license: Apache-2.0 license_family: Apache + purls: + - pkg:pypi/msgpack?source=hash-mapping size: 103380 timestamp: 1762504077009 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/msgpack-python-1.1.2-py310h0992a49_1.conda @@ -8449,6 +9686,8 @@ packages: - python_abi 3.14.* *_cp314 license: Apache-2.0 license_family: Apache + purls: + - pkg:pypi/msgpack?source=hash-mapping size: 100176 timestamp: 1762504193305 - conda: https://conda.anaconda.org/conda-forge/osx-64/msgpack-python-1.1.2-py314h00ed6fe_1.conda @@ -8461,6 +9700,8 @@ packages: - python_abi 3.14.* *_cp314 license: Apache-2.0 license_family: Apache + purls: + - pkg:pypi/msgpack?source=hash-mapping size: 92312 timestamp: 1762504434513 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/msgpack-python-1.1.2-py314h784bc60_1.conda @@ -8474,6 +9715,8 @@ packages: - python_abi 3.14.* *_cp314 license: Apache-2.0 license_family: Apache + purls: + - pkg:pypi/msgpack?source=hash-mapping size: 92381 timestamp: 1762504601981 - conda: https://conda.anaconda.org/conda-forge/win-64/msgpack-python-1.1.2-py310he9f1925_1.conda @@ -8517,6 +9760,8 @@ packages: - vc14_runtime >=14.44.35208 license: Apache-2.0 license_family: Apache + purls: + - pkg:pypi/msgpack?source=hash-mapping size: 88657 timestamp: 1762504357246 - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda @@ -8544,6 +9789,7 @@ packages: depends: - __osx >=10.13 license: X11 AND BSD-3-Clause + purls: [] size: 822259 timestamp: 1738196181298 - conda: https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.5-h5846eda_0.conda @@ -8559,6 +9805,7 @@ packages: depends: - __osx >=11.0 license: X11 AND BSD-3-Clause + purls: [] size: 797030 timestamp: 1738196177597 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.5-hb89a1cb_0.conda @@ -8568,6 +9815,26 @@ packages: purls: [] size: 795131 timestamp: 1715194898402 +- pypi: https://files.pythonhosted.org/packages/2b/60/c9a33361da8cde7c7760f091cd10467bc470634e4eea31c8bb70935b00a4/nh3-0.3.4-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + name: nh3 + version: 0.3.4 + sha256: 0d825722a1e8cbc87d7ca1e47ffb1d2a6cf343ad4c1b8465becf7cadcabcdfd0 + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/4a/57/a97955bc95960cfb1f0517043d60a121f4ba93fde252d4d9ffd3c2a9eead/nh3-0.3.4-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl + name: nh3 + version: 0.3.4 + sha256: d8bebcb20ab4b91858385cd98fe58046ec4a624275b45ef9b976475604f45b49 + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/73/4f/af8e9071d7464575a7316831938237ffc9d92d27f163dbdd964b1309cd9b/nh3-0.3.4-cp38-abi3-win_amd64.whl + name: nh3 + version: 0.3.4 + sha256: c10b1f0c741e257a5cb2978d6bac86e7c784ab20572724b20c6402c2e24bce75 + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/d6/b7/ec1cbc6b297a808c513f59f501656389623fc09ad6a58c640851289c7854/nh3-0.3.4-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + name: nh3 + version: 0.3.4 + sha256: 0961a27dc2057c38d0364cb05880e1997ae1c80220cbc847db63213720b8f304 + requires_python: '>=3.8' - conda: https://conda.anaconda.org/conda-forge/linux-64/ninja-1.13.2-h171cf75_0.conda sha256: 6f7d59dbec0a7b00bf5d103a4306e8886678b796ff2151b62452d4582b2a53fb md5: b518e9e92493721281a60fa975bddc65 @@ -8686,26 +9953,6 @@ packages: - pkg:pypi/numpy?source=compressed-mapping size: 9385101 timestamp: 1770098496391 -- conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.4.3-py311h2e04523_0.conda - sha256: ea4e92bb68b58ce92c0d4152c308eecfee94f131d5ef247395fbe70b7697074d - md5: cfc8f864dea571677095ebae8e6f0c07 - depends: - - python - - libgcc >=14 - - __glibc >=2.17,<3.0.a0 - - libstdcxx >=14 - - libcblas >=3.9.0,<4.0a0 - - liblapack >=3.9.0,<4.0a0 - - python_abi 3.11.* *_cp311 - - libblas >=3.9.0,<4.0a0 - constrains: - - numpy-base <0a0 - license: BSD-3-Clause - license_family: BSD - purls: - - pkg:pypi/numpy?source=compressed-mapping - size: 9384747 - timestamp: 1773839224422 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/numpy-2.2.6-py310h6e5608f_0.conda sha256: d7234b9c45e4863c7d4c5221c1e91d69b0e0009464bf361c3fea47e64dc4adc2 md5: 9e9f1f279eb02c41bda162a42861adc0 @@ -8922,6 +10169,7 @@ packages: - ca-certificates license: Apache-2.0 license_family: Apache + purls: [] size: 2777136 timestamp: 1769557662405 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.3.0-h0d3ecfb_0.conda @@ -8944,6 +10192,7 @@ packages: - ca-certificates license: Apache-2.0 license_family: Apache + purls: [] size: 3104268 timestamp: 1769556384749 - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.6.1-hf411b9b_1.conda @@ -8979,6 +10228,8 @@ packages: - python license: Apache-2.0 license_family: APACHE + purls: + - pkg:pypi/packaging?source=compressed-mapping size: 72010 timestamp: 1769093650580 - conda: https://conda.anaconda.org/conda-forge/linux-64/patchelf-0.17.2-h58526e2_0.conda @@ -9151,6 +10402,8 @@ packages: - python_abi 3.14.* *_cp314 license: MIT license_family: MIT + purls: + - pkg:pypi/pycosat?source=hash-mapping size: 88644 timestamp: 1757744868118 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pycosat-0.6.6-py310h5b55623_3.conda @@ -9191,6 +10444,8 @@ packages: - python_abi 3.14.* *_cp314 license: MIT license_family: MIT + purls: + - pkg:pypi/pycosat?source=hash-mapping size: 89501 timestamp: 1757744787708 - conda: https://conda.anaconda.org/conda-forge/osx-64/pycosat-0.6.6-py310h6729b98_0.conda @@ -9226,6 +10481,8 @@ packages: - python_abi 3.14.* *_cp314 license: MIT license_family: MIT + purls: + - pkg:pypi/pycosat?source=hash-mapping size: 96705 timestamp: 1757744863538 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pycosat-0.6.6-py310h2aa6e3c_0.conda @@ -9264,6 +10521,8 @@ packages: - python_abi 3.14.* *_cp314 license: MIT license_family: MIT + purls: + - pkg:pypi/pycosat?source=hash-mapping size: 92986 timestamp: 1757744788529 - conda: https://conda.anaconda.org/conda-forge/win-64/pycosat-0.6.6-py310h29418f3_3.conda @@ -9307,6 +10566,8 @@ packages: - vc14_runtime >=14.44.35208 license: MIT license_family: MIT + purls: + - pkg:pypi/pycosat?source=hash-mapping size: 79551 timestamp: 1757744726713 - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda @@ -9332,6 +10593,13 @@ packages: - pkg:pypi/pyelftools?source=hash-mapping size: 149336 timestamp: 1744148364068 +- pypi: https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl + name: pygments + version: 2.20.0 + sha256: 81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176 + requires_dist: + - colorama>=0.4.6 ; extra == 'windows-terminal' + requires_python: '>=3.9' - conda: https://conda.anaconda.org/conda-forge/noarch/pyopenssl-25.1.0-pyhd8ed1ab_0.conda sha256: 0d7a8ebdfff0f579a64a95a94cf280ec2889d6c52829a9dbbd3ea9eef02c2f6f md5: 63d6393b45f33dc0782d73f6d8ae36a0 @@ -9466,6 +10734,7 @@ packages: - tzdata - zstd >=1.5.7,<1.6.0a0 license: Python-2.0 + purls: [] size: 36702440 timestamp: 1770675584356 python_site_packages_path: lib/python3.14/site-packages @@ -9544,6 +10813,7 @@ packages: - tzdata - zstd >=1.5.7,<1.6.0a0 license: Python-2.0 + purls: [] size: 37305578 timestamp: 1770674395875 python_site_packages_path: lib/python3.14/site-packages @@ -9609,6 +10879,7 @@ packages: - tzdata - zstd >=1.5.7,<1.6.0a0 license: Python-2.0 + purls: [] size: 14387288 timestamp: 1770676578632 python_site_packages_path: lib/python3.14/site-packages @@ -9674,6 +10945,7 @@ packages: - tzdata - zstd >=1.5.7,<1.6.0a0 license: Python-2.0 + purls: [] size: 13522698 timestamp: 1770675365241 python_site_packages_path: lib/python3.14/site-packages @@ -9742,6 +11014,7 @@ packages: - vc14_runtime >=14.44.35208 - zstd >=1.5.7,<1.6.0a0 license: Python-2.0 + purls: [] size: 18273230 timestamp: 1770675442998 python_site_packages_path: Lib/site-packages @@ -9788,8 +11061,14 @@ packages: - python 3.14.* *_cp314 license: BSD-3-Clause license_family: BSD + purls: [] size: 6989 timestamp: 1752805904792 +- pypi: https://files.pythonhosted.org/packages/de/3d/8161f7711c017e01ac9f008dfddd9410dff3674334c233bde66e7ba65bbf/pywin32_ctypes-0.2.3-py3-none-any.whl + name: pywin32-ctypes + version: 0.2.3 + sha256: 8a1513379d709975552d202d942d9837758905c8d01eb82b8bcc30918929e7b8 + requires_python: '>=3.6' - conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py310h3406613_1.conda sha256: f23de6cc72541c6081d3d27482dbc9fc5dd03be93126d9155f06d0cf15d6e90e md5: 2160894f57a40d2d629a34ee8497795f @@ -9831,6 +11110,8 @@ packages: - yaml >=0.2.5,<0.3.0a0 license: MIT license_family: MIT + purls: + - pkg:pypi/pyyaml?source=compressed-mapping size: 202391 timestamp: 1770223462836 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pyyaml-6.0.3-py310h2d8da20_1.conda @@ -9874,6 +11155,8 @@ packages: - yaml >=0.2.5,<0.3.0a0 license: MIT license_family: MIT + purls: + - pkg:pypi/pyyaml?source=hash-mapping size: 195678 timestamp: 1770223441816 - conda: https://conda.anaconda.org/conda-forge/osx-64/pyyaml-6.0.1-py310h6729b98_1.conda @@ -9912,6 +11195,8 @@ packages: - yaml >=0.2.5,<0.3.0a0 license: MIT license_family: MIT + purls: + - pkg:pypi/pyyaml?source=hash-mapping size: 191947 timestamp: 1770226344240 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyyaml-6.0.1-py310h2aa6e3c_1.conda @@ -9953,6 +11238,8 @@ packages: - yaml >=0.2.5,<0.3.0a0 license: MIT license_family: MIT + purls: + - pkg:pypi/pyyaml?source=hash-mapping size: 189475 timestamp: 1770223788648 - conda: https://conda.anaconda.org/conda-forge/win-64/pyyaml-6.0.3-py310hdb0e946_1.conda @@ -9999,6 +11286,8 @@ packages: - yaml >=0.2.5,<0.3.0a0 license: MIT license_family: MIT + purls: + - pkg:pypi/pyyaml?source=compressed-mapping size: 181257 timestamp: 1770223460931 - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda @@ -10042,6 +11331,7 @@ packages: - ncurses >=6.5,<7.0a0 license: GPL-3.0-only license_family: GPL + purls: [] size: 317819 timestamp: 1765813692798 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.2-h1d1bf99_2.conda @@ -10062,8 +11352,19 @@ packages: - ncurses >=6.5,<7.0a0 license: GPL-3.0-only license_family: GPL + purls: [] size: 313930 timestamp: 1765813902568 +- pypi: https://files.pythonhosted.org/packages/e1/67/921ec3024056483db83953ae8e48079ad62b92db7880013ca77632921dd0/readme_renderer-44.0-py3-none-any.whl + name: readme-renderer + version: '44.0' + sha256: 2fbca89b81a08526aadf1357a8c2ae889ec05fb03f5da67f9769c9a592166151 + requires_dist: + - nh3>=0.2.14 + - docutils>=0.21.2 + - pygments>=2.5.1 + - cmarkgfm>=0.8.0 ; extra == 'md' + requires_python: '>=3.9' - conda: https://conda.anaconda.org/conda-forge/linux-64/reproc-14.2.5.post0-hb9d3cd8_0.conda sha256: a1973f41a6b956f1305f9aaefdf14b2f35a8c9615cfe5f143f1784ed9aa6bf47 md5: 69fbc0a9e42eb5fe6733d2d60d818822 @@ -10092,6 +11393,7 @@ packages: - __osx >=10.13 license: MIT license_family: MIT + purls: [] size: 31749 timestamp: 1731926270954 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/reproc-14.2.5.post0-h5505292_0.conda @@ -10101,6 +11403,7 @@ packages: - __osx >=11.0 license: MIT license_family: MIT + purls: [] size: 32023 timestamp: 1731926255834 - conda: https://conda.anaconda.org/conda-forge/win-64/reproc-14.2.5.post0-h2466b09_0.conda @@ -10149,6 +11452,7 @@ packages: - reproc 14.2.5.post0 h6e16a3a_0 license: MIT license_family: MIT + purls: [] size: 24394 timestamp: 1731926392643 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/reproc-cpp-14.2.5.post0-h286801f_0.conda @@ -10160,6 +11464,7 @@ packages: - reproc 14.2.5.post0 h5505292_0 license: MIT license_family: MIT + purls: [] size: 24834 timestamp: 1731926355120 - conda: https://conda.anaconda.org/conda-forge/win-64/reproc-cpp-14.2.5.post0-he0c23c2_0.conda @@ -10193,24 +11498,6 @@ packages: - pkg:pypi/requests?source=compressed-mapping size: 63602 timestamp: 1766926974520 -- conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.33.0-pyhcf101f3_0.conda - sha256: fbc7183778e1f9976ae7d812986c227f9d43f841326ac03b5f43f1ac93fa8f3b - md5: bee5ed456361bfe8af502beaf5db82e2 - depends: - - python >=3.10 - - certifi >=2023.5.7 - - charset-normalizer >=2,<4 - - idna >=2.5,<4 - - urllib3 >=1.26,<3 - - python - constrains: - - chardet >=3.0.2,<6 - license: Apache-2.0 - license_family: APACHE - purls: - - pkg:pypi/requests?source=compressed-mapping - size: 63788 - timestamp: 1774462091279 - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.33.1-pyhcf101f3_0.conda sha256: c0249bc4bf4c0e8e06d0e7b4d117a5d593cc4ab2144d5006d6d47c83cb0af18e md5: 10afbb4dbf06ff959ad25a92ccee6e59 @@ -10224,6 +11511,7 @@ packages: constrains: - chardet >=3.0.2,<6 license: Apache-2.0 + license_family: APACHE purls: - pkg:pypi/requests?source=compressed-mapping size: 63712 @@ -10279,6 +11567,15 @@ packages: purls: [] size: 177491 timestamp: 1693456037505 +- pypi: https://files.pythonhosted.org/packages/14/25/b208c5683343959b670dc001595f2f3737e051da617f66c31f7c4fa93abc/rich-14.3.3-py3-none-any.whl + name: rich + version: 14.3.3 + sha256: 793431c1f8619afa7d3b52b2cdec859562b950ea0d4b6b505397612db8d5362d + requires_dist: + - ipywidgets>=7.5.1,<9 ; extra == 'jupyter' + - markdown-it-py>=2.2.0 + - pygments>=2.13.0,<3.0.0 + requires_python: '>=3.8.0' - conda: https://conda.anaconda.org/conda-forge/linux-64/ruamel.yaml-0.18.17-py310h139afa4_2.conda sha256: 0741675606a288ca70a68282d9b8b67b61cc6e991dcec38bae9ec1e38237524c md5: 26ad912afb7835e474284d61f482905d @@ -10320,6 +11617,8 @@ packages: - python_abi 3.14.* *_cp314 license: MIT license_family: MIT + purls: + - pkg:pypi/ruamel-yaml?source=hash-mapping size: 308487 timestamp: 1766175778417 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ruamel.yaml-0.18.17-py310hef25091_2.conda @@ -10363,6 +11662,8 @@ packages: - python_abi 3.14.* *_cp314 license: MIT license_family: MIT + purls: + - pkg:pypi/ruamel-yaml?source=hash-mapping size: 311783 timestamp: 1766175823921 - conda: https://conda.anaconda.org/conda-forge/osx-64/ruamel.yaml-0.17.40-py310hb372a2b_0.conda @@ -10403,6 +11704,8 @@ packages: - python_abi 3.14.* *_cp314 license: MIT license_family: MIT + purls: + - pkg:pypi/ruamel-yaml?source=hash-mapping size: 308947 timestamp: 1766175829662 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ruamel.yaml-0.17.40-py310hd125d64_0.conda @@ -10446,6 +11749,8 @@ packages: - python_abi 3.14.* *_cp314 license: MIT license_family: MIT + purls: + - pkg:pypi/ruamel-yaml?source=hash-mapping size: 311922 timestamp: 1766175797575 - conda: https://conda.anaconda.org/conda-forge/win-64/ruamel.yaml-0.18.17-py310h1637853_2.conda @@ -10492,6 +11797,8 @@ packages: - python_abi 3.14.* *_cp314 license: MIT license_family: MIT + purls: + - pkg:pypi/ruamel-yaml?source=hash-mapping size: 306951 timestamp: 1766175833786 - conda: https://conda.anaconda.org/conda-forge/linux-64/ruamel.yaml.clib-0.2.15-py310h139afa4_1.conda @@ -10532,6 +11839,8 @@ packages: - python_abi 3.14.* *_cp314 license: MIT license_family: MIT + purls: + - pkg:pypi/ruamel-yaml-clib?source=hash-mapping size: 150041 timestamp: 1766159514023 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ruamel.yaml.clib-0.2.15-py310hef25091_1.conda @@ -10572,6 +11881,8 @@ packages: - python_abi 3.14.* *_cp314 license: MIT license_family: MIT + purls: + - pkg:pypi/ruamel-yaml-clib?source=hash-mapping size: 148495 timestamp: 1766159541094 - conda: https://conda.anaconda.org/conda-forge/osx-64/ruamel.yaml.clib-0.2.15-py314hd330473_1.conda @@ -10583,6 +11894,8 @@ packages: - python_abi 3.14.* *_cp314 license: MIT license_family: MIT + purls: + - pkg:pypi/ruamel-yaml-clib?source=hash-mapping size: 136902 timestamp: 1766159517466 - conda: https://conda.anaconda.org/conda-forge/osx-64/ruamel.yaml.clib-0.2.8-py310hb372a2b_0.conda @@ -10619,6 +11932,8 @@ packages: - python_abi 3.14.* *_cp314 license: MIT license_family: MIT + purls: + - pkg:pypi/ruamel-yaml-clib?source=hash-mapping size: 133016 timestamp: 1766159585543 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ruamel.yaml.clib-0.2.8-py310hd125d64_0.conda @@ -10688,6 +12003,8 @@ packages: - python_abi 3.14.* *_cp314 license: MIT license_family: MIT + purls: + - pkg:pypi/ruamel-yaml-clib?source=hash-mapping size: 105668 timestamp: 1766159584330 - conda: https://conda.anaconda.org/conda-forge/noarch/scikit-build-core-0.11.6-pyh7e86bf3_1.conda @@ -10710,6 +12027,14 @@ packages: - pkg:pypi/scikit-build-core?source=hash-mapping size: 213181 timestamp: 1755919500167 +- pypi: https://files.pythonhosted.org/packages/b7/46/f5af3402b579fd5e11573ce652019a67074317e18c1935cc0b4ba9b35552/secretstorage-3.5.0-py3-none-any.whl + name: secretstorage + version: 3.5.0 + sha256: 0ce65888c0725fcb2c5bc0fdb8e5438eece02c523557ea40ce0703c266248137 + requires_dist: + - cryptography>=2.0 + - jeepney>=0.6 + requires_python: '>=3.10' - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda sha256: 82088a6e4daa33329a30bc26dc19a98c7c1d3f05c0f73ce9845d4eab4924e9e1 md5: 8e194e7b992f99a5015edbd4ebd38efd @@ -10798,6 +12123,7 @@ packages: - libcxx >=19 license: Apache-2.0 license_family: APACHE + purls: [] size: 286025 timestamp: 1766034310103 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/simdjson-4.2.4-ha7d2532_0.conda @@ -10808,6 +12134,7 @@ packages: - libcxx >=19 license: Apache-2.0 license_family: APACHE + purls: [] size: 252462 timestamp: 1766034371359 - conda: https://conda.anaconda.org/conda-forge/win-64/simdjson-4.2.4-h49e36cd_0.conda @@ -10856,6 +12183,7 @@ packages: - libcxx >=19 license: MIT license_family: MIT + purls: [] size: 173402 timestamp: 1767782141460 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/spdlog-1.17.0-ha0f8610_1.conda @@ -10867,6 +12195,7 @@ packages: - libcxx >=19 license: MIT license_family: MIT + purls: [] size: 166603 timestamp: 1767781942683 - conda: https://conda.anaconda.org/conda-forge/win-64/spdlog-1.17.0-h9f585f1_1.conda @@ -10963,6 +12292,7 @@ packages: - __osx >=10.13 license: MIT license_family: MIT + purls: [] size: 4286090 timestamp: 1748302835791 - conda: https://conda.anaconda.org/conda-forge/osx-64/taplo-0.8.1-h7205ca4_0.conda @@ -10983,6 +12313,7 @@ packages: - __osx >=11.0 license: MIT license_family: MIT + purls: [] size: 4005794 timestamp: 1748302845549 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/taplo-0.8.1-h69fbcac_0.conda @@ -11066,6 +12397,7 @@ packages: - libzlib >=1.3.1,<2.0a0 license: TCL license_family: BSD + purls: [] size: 3282953 timestamp: 1769460532442 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h010d191_3.conda @@ -11076,6 +12408,7 @@ packages: - libzlib >=1.3.1,<2.0a0 license: TCL license_family: BSD + purls: [] size: 3127137 timestamp: 1769460817696 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h5083fa2_1.conda @@ -11112,18 +12445,6 @@ packages: - pkg:pypi/tomli?source=compressed-mapping size: 21453 timestamp: 1768146676791 -- conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda - sha256: 91cafdb64268e43e0e10d30bd1bef5af392e69f00edd34dfaf909f69ab2da6bd - md5: b5325cf06a000c5b14970462ff5e4d58 - depends: - - python >=3.10 - - python - license: MIT - license_family: MIT - purls: - - pkg:pypi/tomli?source=compressed-mapping - size: 21561 - timestamp: 1774492402955 - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda sha256: 9ef8e47cf00e4d6dcc114eb32a1504cc18206300572ef14d76634ba29dfe1eb6 md5: e5ce43272193b38c2e9037446c1d9206 @@ -11161,6 +12482,23 @@ packages: - pkg:pypi/truststore?source=hash-mapping size: 24279 timestamp: 1766494826559 +- pypi: https://files.pythonhosted.org/packages/3a/7a/882d99539b19b1490cac5d77c67338d126e4122c8276bf640e411650c830/twine-6.2.0-py3-none-any.whl + name: twine + version: 6.2.0 + sha256: 418ebf08ccda9a8caaebe414433b0ba5e25eb5e4a927667122fbe8f829f985d8 + requires_dist: + - readme-renderer>=35.0 + - requests>=2.20 + - requests-toolbelt>=0.8.0,!=0.9.0 + - urllib3>=1.26.0 + - importlib-metadata>=3.6 ; python_full_version < '3.10' + - keyring>=21.2.0 ; platform_machine != 'ppc64le' and platform_machine != 's390x' + - rfc3986>=1.4.0 + - rich>=12.0.0 + - packaging>=24.0 + - id + - keyring>=21.2.0 ; extra == 'keyring' + requires_python: '>=3.9' - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda sha256: 7c2df5721c742c2a47b2c8f960e718c930031663ac1174da67c1ed5999f7938c md5: edd329d7d3a4ab45dcf905899a7a6115 @@ -11244,6 +12582,8 @@ packages: - python_abi 3.14.* *_cp314 license: MIT license_family: MIT + purls: + - pkg:pypi/ukkonen?source=hash-mapping size: 15004 timestamp: 1769438727085 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ukkonen-1.1.0-py310h0992a49_0.conda @@ -11290,6 +12630,8 @@ packages: - python_abi 3.14.* *_cp314 license: MIT license_family: MIT + purls: + - pkg:pypi/ukkonen?source=hash-mapping size: 15756 timestamp: 1769438772414 - conda: https://conda.anaconda.org/conda-forge/osx-64/ukkonen-1.0.1-py310h88cfcbd_4.conda @@ -11331,6 +12673,8 @@ packages: - python_abi 3.14.* *_cp314 license: MIT license_family: MIT + purls: + - pkg:pypi/ukkonen?source=hash-mapping size: 14286 timestamp: 1769439103231 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ukkonen-1.0.1-py310h38f39d4_4.conda @@ -11375,6 +12719,8 @@ packages: - python_abi 3.14.* *_cp314 license: MIT license_family: MIT + purls: + - pkg:pypi/ukkonen?source=hash-mapping size: 14884 timestamp: 1769439056290 - conda: https://conda.anaconda.org/conda-forge/win-64/ukkonen-1.1.0-py310he9f1925_0.conda @@ -11421,6 +12767,8 @@ packages: - vc14_runtime >=14.44.35208 license: MIT license_family: MIT + purls: + - pkg:pypi/ukkonen?source=hash-mapping size: 18504 timestamp: 1769438844417 - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.5.0-pyhd8ed1ab_0.conda @@ -11605,6 +12953,7 @@ packages: - __osx >=10.13 license: MIT license_family: MIT + purls: [] size: 79419 timestamp: 1753484072608 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/yaml-0.2.5-h3422bc3_2.tar.bz2 @@ -11622,6 +12971,7 @@ packages: - __osx >=11.0 license: MIT license_family: MIT + purls: [] size: 83386 timestamp: 1753484079473 - conda: https://conda.anaconda.org/conda-forge/win-64/yaml-0.2.5-h6a83c73_3.conda @@ -11671,6 +13021,7 @@ packages: - __osx >=10.13 license: MIT license_family: MIT + purls: [] size: 145204 timestamp: 1745308032698 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/yaml-cpp-0.8.0-ha1acc90_0.conda @@ -11681,6 +13032,7 @@ packages: - __osx >=11.0 license: MIT license_family: MIT + purls: [] size: 136222 timestamp: 1745308075886 - conda: https://conda.anaconda.org/conda-forge/win-64/yaml-cpp-0.8.0-he0c23c2_0.conda @@ -11757,6 +13109,8 @@ packages: - python_abi 3.14.* *_cp314 license: BSD-3-Clause license_family: BSD + purls: + - pkg:pypi/zstandard?source=hash-mapping size: 473605 timestamp: 1762512687493 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstandard-0.25.0-py310hef25091_1.conda @@ -11806,6 +13160,8 @@ packages: - zstd >=1.5.7,<1.6.0a0 license: BSD-3-Clause license_family: BSD + purls: + - pkg:pypi/zstandard?source=hash-mapping size: 465094 timestamp: 1762512736835 - conda: https://conda.anaconda.org/conda-forge/osx-64/zstandard-0.22.0-py310hd88f66e_0.conda @@ -11850,6 +13206,8 @@ packages: - zstd >=1.5.7,<1.6.0a0 license: BSD-3-Clause license_family: BSD + purls: + - pkg:pypi/zstandard?source=hash-mapping size: 470136 timestamp: 1762512696464 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstandard-0.22.0-py310h6289e41_0.conda @@ -11897,6 +13255,8 @@ packages: - zstd >=1.5.7,<1.6.0a0 license: BSD-3-Clause license_family: BSD + purls: + - pkg:pypi/zstandard?source=hash-mapping size: 397786 timestamp: 1762512730914 - conda: https://conda.anaconda.org/conda-forge/win-64/zstandard-0.25.0-py310h1637853_1.conda @@ -11958,6 +13318,8 @@ packages: - python_abi 3.14.* *_cp314 license: BSD-3-Clause license_family: BSD + purls: + - pkg:pypi/zstandard?source=hash-mapping size: 381179 timestamp: 1762512709971 - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda @@ -11999,6 +13361,7 @@ packages: - libzlib >=1.3.1,<2.0a0 license: BSD-3-Clause license_family: BSD + purls: [] size: 528148 timestamp: 1764777156963 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.5-h4f39d0f_0.conda @@ -12019,6 +13382,7 @@ packages: - libzlib >=1.3.1,<2.0a0 license: BSD-3-Clause license_family: BSD + purls: [] size: 433413 timestamp: 1764777166076 - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.7-h534d264_6.conda diff --git a/pixi.toml b/pixi.toml index d69ee48d..5f89234d 100644 --- a/pixi.toml +++ b/pixi.toml @@ -135,12 +135,25 @@ python = ">=3.11,<3.12" #[feature.py314.dependencies] #python = ">=3.14,<3.15" +######################################## +# Publishing feature (no compilers needed) +######################################## +[feature.publish] +[feature.publish.dependencies] +python = ">=3.10" +gh = "*" +zstd = "*" + +[feature.publish.pypi-dependencies] +twine = ">=6.0" + ######################################## # Environments: compose features per target ######################################## [environments] +publish = ["publish"] linux-py310 = ["py310", "linux-build", "build-dev-tools", "python-dev-pkgs"] linux-py311 = ["py311", "linux-build", "build-dev-tools", "python-dev-pkgs"] @@ -188,3 +201,11 @@ cmd = "pre-commit install -f -t pre-commit -t prepare-commit-msg -t commit-msg - [tasks.pre-commit-run] cmd = "pre-commit run --all-files" + +[tasks.publish-wheels] +cmd = ["python", "scripts/publish_wheels.py"] +description = "Upload built wheels to PyPI (or TestPyPI with --test)" + +[tasks.publish-tarball-cache] +cmd = ["python", "scripts/publish_tarball_cache.py"] +description = "Upload .tar.zst/.zip build caches to GitHub Releases" diff --git a/scripts/publish_tarball_cache.py b/scripts/publish_tarball_cache.py new file mode 100644 index 00000000..5ea1e350 --- /dev/null +++ b/scripts/publish_tarball_cache.py @@ -0,0 +1,126 @@ +"""Upload ITK build cache tarballs to a GitHub Release. + +Usage: + pixi run -e publish publish-tarball-cache --itk-package-version v6.0b02 + pixi run -e publish publish-tarball-cache --itk-package-version v6.0b02 --create-release + +Authentication: + Set the GH_TOKEN environment variable, or run `gh auth login` beforehand. + +Cache files are expected at {build-dir-root}/../ITKPythonBuilds-*.tar.zst (POSIX) +or {build-dir-root}/ITKPythonBuilds-*.zip (Windows). +""" + +import argparse +import subprocess +import sys +from pathlib import Path + +ITKPYTHONBUILDS_REPO = "InsightSoftwareConsortium/ITKPythonBuilds" + + +def main() -> int: + parser = argparse.ArgumentParser( + description="Upload tarball caches to a GitHub Release on ITKPythonBuilds" + ) + parser.add_argument( + "--build-dir-root", + type=Path, + default=Path(__file__).resolve().parent.parent.parent + / "ITKPythonPackage-build", + help="Root of the build directory (tarballs are in its parent). Default: ../ITKPythonPackage-build", + ) + parser.add_argument( + "--itk-package-version", + required=True, + help="Release tag name, e.g. v6.0b02", + ) + parser.add_argument( + "--repo", + default=ITKPYTHONBUILDS_REPO, + help=f"GitHub repository for the release (default: {ITKPYTHONBUILDS_REPO})", + ) + parser.add_argument( + "--create-release", + action="store_true", + help="Create the GitHub release if it does not already exist", + ) + args = parser.parse_args() + + build_directory = Path(args.build_dir_root) + tarball_dir = build_directory.parent + # POSIX builds produce .tar.zst, Windows builds produce .zip in the build directory + tarballs = sorted( + list(tarball_dir.glob("ITKPythonBuilds-*.tar.zst")) + + list( + build_directory.glob("ITKPythonBuilds-*.zip") + ) # Windows builds will be in the build directory + ) + + if not tarballs: + print( + f"Error: No ITKPythonBuilds-*.tar.zst or .zip files found in {tarball_dir} or {build_directory}.", + file=sys.stderr, + ) + return 1 + + print( + f"Found {len(tarballs)} cache file(s) in {tarball_dir} and {build_directory}:" + ) + for tb in tarballs: + size_mb = tb.stat().st_size / (1024 * 1024) + print(f" {tb.name} ({size_mb:.1f} MB)") + + tag = args.itk_package_version + + # Check if the release exists + result = subprocess.run( + ["gh", "release", "view", tag, "--repo", args.repo], + capture_output=True, + text=True, + ) + if result.returncode != 0: + if args.create_release: + print(f"\nCreating release '{tag}' on {args.repo}...") + create_result = subprocess.run( + [ + "gh", + "release", + "create", + tag, + "--repo", + args.repo, + "--title", + tag, + "--notes", + f"ITK Python build cache for {tag}", + ], + ) + if create_result.returncode != 0: + print("Error: Failed to create release.", file=sys.stderr) + return 1 + else: + print( + f"Error: Failed to create release with code: {result.returncode}\nwith message:\n{result.stderr}", + file=sys.stderr, + ) + return 1 + else: + print(f"\nRelease '{tag}' exists on {args.repo}.") + + # Upload each tarball (--clobber replaces existing assets with the same name) + for tb in tarballs: + print(f"Uploading {tb.name}...") + upload_result = subprocess.run( + ["gh", "release", "upload", tag, str(tb), "--repo", args.repo, "--clobber"], + ) + if upload_result.returncode != 0: + print(f"Error: Failed to upload {tb.name}.", file=sys.stderr) + return 1 + + print("\nAll uploads complete.") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/scripts/publish_wheels.py b/scripts/publish_wheels.py new file mode 100644 index 00000000..e3e8f5f0 --- /dev/null +++ b/scripts/publish_wheels.py @@ -0,0 +1,93 @@ +"""Upload ITK Python wheels to PyPI or TestPyPI. + +Usage: + pixi run -e publish publish-wheels --dist-directory /path/to/dist + pixi run -e publish publish-wheels --dist-directory /path/to/dist --test + +Authentication: + Set TWINE_USERNAME and TWINE_PASSWORD environment variables. + For token-based auth: + TWINE_USERNAME=__token__ + TWINE_PASSWORD=pypi- + + Alternatively, configure ~/.pypirc (see .pypirc.example in the repo root). +""" + +import argparse +import subprocess +import sys +from pathlib import Path + +TESTPYPI_URL = "https://test.pypi.org/legacy/" + + +def main() -> int: + parser = argparse.ArgumentParser( + description="Upload ITK wheels to PyPI or TestPyPI" + ) + parser.add_argument( + "--dist-directory", + type=Path, + default=Path(__file__).resolve().parent.parent.parent + / "ITKPythonPackage-build/dist", + help="Root of the build dist directory containing dist/*.whl (default: ../ITKPythonPackage-build/dist)", + ) + parser.add_argument( + "--test", + action="store_true", + help="Upload to TestPyPI instead of production PyPI", + ) + parser.add_argument( + "--repository-url", + type=str, + default=None, + help="Custom repository URL (overrides --test)", + ) + parser.add_argument( + "--skip-existing", + action="store_true", + help="Skip wheels that have already been uploaded", + ) + args = parser.parse_args() + + dist_dir = args.dist_directory + wheels = sorted(dist_dir.glob("*.whl")) + + if not wheels: + print(f"Error: No .whl files found in {dist_dir}", file=sys.stderr) + return 1 + + print(f"Found {len(wheels)} wheel(s) in {dist_dir}:") + for w in wheels: + print(f" {w.name}") + + # Validate wheel metadata before uploading + print("\nRunning twine check...") + result = subprocess.run( + ["twine", "check", *(str(w) for w in wheels)], + ) + if result.returncode != 0: + print( + "Error: twine check failed. Fix metadata issues before uploading.", + file=sys.stderr, + ) + return 1 + + # Build upload command + cmd = ["twine", "upload"] + if args.repository_url: + cmd += ["--repository-url", args.repository_url] + elif args.test: + cmd += ["--repository-url", TESTPYPI_URL] + if args.skip_existing: + cmd.append("--skip-existing") + cmd += [str(w) for w in wheels] + + target = args.repository_url or (TESTPYPI_URL if args.test else "PyPI") + print(f"\nUploading to {target}...") + result = subprocess.run(cmd) + return result.returncode + + +if __name__ == "__main__": + raise SystemExit(main()) From dc7f51c699611c89689aa876127205ea3da4d6bd Mon Sep 17 00:00:00 2001 From: Hans Johnson Date: Fri, 3 Apr 2026 11:42:36 -0500 Subject: [PATCH 10/27] ENH: Add libitk-wrapping pixi-build package recipe Add a rattler-build recipe to produce a conda package containing ITK C++ libraries with full Python wrapping artifacts (SWIG interfaces, CastXML outputs, compiled Python modules, stubs). This package can be consumed as a host-dependency to skip the expensive ITK C++ build when generating Python wheels for ITK or remote modules. The recipe supports overriding the ITK source repository and tag via ITK_GIT_URL and ITK_GIT_TAG environment variables, enabling builds from feature branches and PRs for testing. Build scripts are provided for both Unix and Windows platforms. CMake flags match conda-forge's libitk-feedstock (using system libraries) plus the additional wrapping options needed for Python wheel generation. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../libitk-wrapping/build-libitk-wrapping.bat | 62 +++++++++++++++ .../libitk-wrapping/build-libitk-wrapping.sh | 77 +++++++++++++++++++ packages/libitk-wrapping/pixi.toml | 15 ++++ packages/libitk-wrapping/recipe.yaml | 56 ++++++++++++++ 4 files changed, 210 insertions(+) create mode 100644 packages/libitk-wrapping/build-libitk-wrapping.bat create mode 100755 packages/libitk-wrapping/build-libitk-wrapping.sh create mode 100644 packages/libitk-wrapping/pixi.toml create mode 100644 packages/libitk-wrapping/recipe.yaml diff --git a/packages/libitk-wrapping/build-libitk-wrapping.bat b/packages/libitk-wrapping/build-libitk-wrapping.bat new file mode 100644 index 00000000..781af091 --- /dev/null +++ b/packages/libitk-wrapping/build-libitk-wrapping.bat @@ -0,0 +1,62 @@ +@echo off +setlocal enabledelayedexpansion + +:: Build ITK C++ with Python wrapping for use as a conda package (Windows). + +set BUILD_DIR=%SRC_DIR%\..\build +mkdir %BUILD_DIR% +cd %BUILD_DIR% + +cmake ^ + -G "Ninja" ^ + %CMAKE_ARGS% ^ + -D BUILD_SHARED_LIBS:BOOL=ON ^ + -D BUILD_TESTING:BOOL=OFF ^ + -D BUILD_EXAMPLES:BOOL=OFF ^ + -D CMAKE_BUILD_TYPE:STRING=Release ^ + -D "CMAKE_INSTALL_PREFIX=%LIBRARY_PREFIX%" ^ + ^ + -D ITK_WRAP_PYTHON:BOOL=ON ^ + -D ITK_WRAP_DOC:BOOL=ON ^ + -D ITK_LEGACY_SILENT:BOOL=ON ^ + -D CMAKE_POSITION_INDEPENDENT_CODE:BOOL=ON ^ + ^ + -D ITK_WRAP_unsigned_short:BOOL=ON ^ + -D ITK_WRAP_double:BOOL=ON ^ + -D ITK_WRAP_complex_double:BOOL=ON ^ + -D "ITK_WRAP_IMAGE_DIMS:STRING=2;3;4" ^ + ^ + -D WRAP_ITK_INSTALL_COMPONENT_IDENTIFIER:STRING=PythonWheel ^ + -D WRAP_ITK_INSTALL_COMPONENT_PER_MODULE:BOOL=ON ^ + ^ + -D ITK_USE_SYSTEM_EXPAT:BOOL=ON ^ + -D ITK_USE_SYSTEM_HDF5:BOOL=ON ^ + -D ITK_USE_SYSTEM_JPEG:BOOL=ON ^ + -D ITK_USE_SYSTEM_PNG:BOOL=ON ^ + -D ITK_USE_SYSTEM_TIFF:BOOL=ON ^ + -D ITK_USE_SYSTEM_ZLIB:BOOL=ON ^ + -D ITK_USE_SYSTEM_FFTW:BOOL=ON ^ + -D ITK_USE_SYSTEM_EIGEN:BOOL=ON ^ + -D ITK_USE_FFTWD:BOOL=ON ^ + -D ITK_USE_FFTWF:BOOL=ON ^ + ^ + -D ITK_BUILD_DEFAULT_MODULES:BOOL=ON ^ + -D Module_ITKReview:BOOL=ON ^ + -D Module_ITKTBB:BOOL=ON ^ + -D Module_MGHIO:BOOL=ON ^ + -D Module_ITKIOTransformMINC:BOOL=ON ^ + -D Module_GenericLabelInterpolator:BOOL=ON ^ + -D Module_AdaptiveDenoising:BOOL=ON ^ + ^ + -D ITK_USE_KWSTYLE:BOOL=OFF ^ + -D "ITK_DEFAULT_THREADER:STRING=Pool" ^ + ^ + "%SRC_DIR%" + +if errorlevel 1 exit /b 1 + +cmake --build . --config Release +if errorlevel 1 exit /b 1 + +cmake --install . --config Release +if errorlevel 1 exit /b 1 diff --git a/packages/libitk-wrapping/build-libitk-wrapping.sh b/packages/libitk-wrapping/build-libitk-wrapping.sh new file mode 100755 index 00000000..994c6c4f --- /dev/null +++ b/packages/libitk-wrapping/build-libitk-wrapping.sh @@ -0,0 +1,77 @@ +#!/bin/bash +set -euo pipefail + +# Build ITK C++ with Python wrapping for use as a conda package. +# This produces headers, shared libraries, CMake config, and all +# wrapping metadata (SWIG .i/.idx/.mdx files, Python stubs) needed +# by downstream ITK remote modules. + +BUILD_DIR="${SRC_DIR}/../build" +mkdir -p "${BUILD_DIR}" +cd "${BUILD_DIR}" + +# Use TBB on Linux; macOS has known issues with conda TBB +use_tbb=ON +if [ "$(uname)" = "Darwin" ]; then + use_tbb=OFF +fi + +# Handle cross-compilation try-run results if available +if [[ "${CONDA_BUILD_CROSS_COMPILATION:-0}" == "1" ]]; then + try_run_results="${RECIPE_DIR}/TryRunResults-${target_platform}.cmake" + if [[ -f "${try_run_results}" ]]; then + CMAKE_ARGS="${CMAKE_ARGS} -C ${try_run_results}" + fi +fi + +cmake \ + -G "Ninja" \ + ${CMAKE_ARGS} \ + -D BUILD_SHARED_LIBS:BOOL=ON \ + -D BUILD_TESTING:BOOL=OFF \ + -D BUILD_EXAMPLES:BOOL=OFF \ + -D CMAKE_BUILD_TYPE:STRING=Release \ + -D "CMAKE_INSTALL_PREFIX=${PREFIX}" \ + \ + -D ITK_WRAP_PYTHON:BOOL=ON \ + -D ITK_WRAP_DOC:BOOL=ON \ + -D ITK_LEGACY_SILENT:BOOL=ON \ + -D CMAKE_POSITION_INDEPENDENT_CODE:BOOL=ON \ + \ + -D ITK_WRAP_unsigned_short:BOOL=ON \ + -D ITK_WRAP_double:BOOL=ON \ + -D ITK_WRAP_complex_double:BOOL=ON \ + -D "ITK_WRAP_IMAGE_DIMS:STRING=2;3;4" \ + \ + -D WRAP_ITK_INSTALL_COMPONENT_IDENTIFIER:STRING=PythonWheel \ + -D WRAP_ITK_INSTALL_COMPONENT_PER_MODULE:BOOL=ON \ + \ + -D ITK_USE_SYSTEM_EXPAT:BOOL=ON \ + -D ITK_USE_SYSTEM_HDF5:BOOL=ON \ + -D ITK_USE_SYSTEM_JPEG:BOOL=ON \ + -D ITK_USE_SYSTEM_PNG:BOOL=ON \ + -D ITK_USE_SYSTEM_TIFF:BOOL=ON \ + -D ITK_USE_SYSTEM_ZLIB:BOOL=ON \ + -D ITK_USE_SYSTEM_FFTW:BOOL=ON \ + -D ITK_USE_SYSTEM_EIGEN:BOOL=ON \ + -D ITK_USE_FFTWD:BOOL=ON \ + -D ITK_USE_FFTWF:BOOL=ON \ + \ + -D ITK_BUILD_DEFAULT_MODULES:BOOL=ON \ + -D Module_ITKReview:BOOL=ON \ + -D Module_ITKTBB:BOOL=${use_tbb} \ + -D Module_MGHIO:BOOL=ON \ + -D Module_ITKIOTransformMINC:BOOL=ON \ + -D Module_GenericLabelInterpolator:BOOL=ON \ + -D Module_AdaptiveDenoising:BOOL=ON \ + \ + -D ITK_USE_KWSTYLE:BOOL=OFF \ + -D NIFTI_SYSTEM_MATH_LIB= \ + -D GDCM_USE_COREFOUNDATION_LIBRARY:BOOL=OFF \ + -D "ITK_DEFAULT_THREADER:STRING=Pool" \ + \ + "${SRC_DIR}" + +cmake --build . --config Release + +cmake --install . --config Release diff --git a/packages/libitk-wrapping/pixi.toml b/packages/libitk-wrapping/pixi.toml new file mode 100644 index 00000000..6bf85641 --- /dev/null +++ b/packages/libitk-wrapping/pixi.toml @@ -0,0 +1,15 @@ +[workspace] +channels = ["https://prefix.dev/conda-forge"] +platforms = ["linux-64", "linux-aarch64", "osx-arm64", "osx-64", "win-64"] +preview = ["pixi-build"] + +[dependencies] +libitk-wrapping = { path = "." } +python = ">=3.10" + +[package] +name = "libitk-wrapping" +version = "6.99.0" + +[package.build] +backend = { name = "pixi-build-rattler-build", version = "0.3.*" } diff --git a/packages/libitk-wrapping/recipe.yaml b/packages/libitk-wrapping/recipe.yaml new file mode 100644 index 00000000..9cfe7a5b --- /dev/null +++ b/packages/libitk-wrapping/recipe.yaml @@ -0,0 +1,56 @@ +package: + name: libitk-wrapping + version: "6.99.0" + +source: + git: ${{ env.get("ITK_GIT_URL", "https://github.com/BRAINSia/ITK.git") }} + tag: ${{ env.get("ITK_GIT_TAG", "itk-conda-pythonpackage-support") }} + +build: + number: 0 + script: + - if: unix + then: bash ${RECIPE_DIR}/build-libitk-wrapping.sh + - if: win + then: cmd /c ${RECIPE_DIR}/build-libitk-wrapping.bat + +requirements: + build: + - ${{ compiler('c') }} + - ${{ compiler('cxx') }} + - cmake >=3.26 + - ninja + host: + - python + - swig >=4.1 + - castxml + - expat + - hdf5 + - libjpeg-turbo + - libtiff + - libpng + - eigen + - zlib + - fftw + - tbb-devel + - doxygen + run: + - python + - tbb + - hdf5 + - fftw + - libjpeg-turbo + - libtiff + - libpng + - expat + - zlib + +about: + home: https://itk.org + license: Apache-2.0 + license_file: LICENSE + summary: > + ITK C++ libraries with Python wrapping artifacts (SWIG interfaces, + CastXML outputs, compiled Python modules). Used as a build dependency + for ITK Python wheel generation and remote module packaging. + dev_url: https://github.com/InsightSoftwareConsortium/ITK From 1ad57ac6532e41dd0199f2a24ca9abe2c1ec62fa Mon Sep 17 00:00:00 2001 From: Hans Johnson Date: Fri, 3 Apr 2026 11:57:37 -0500 Subject: [PATCH 11/27] ENH: Detect conda-installed ITK and skip C++ build steps When a pre-built ITK is available in the conda/pixi environment (via the libitk-wrapping package), automatically skip the superbuild and C++ compilation steps and point the wheel builder at the installed ITK CMake config directory. Detection checks CONDA_PREFIX and PIXI_ENVIRONMENT_DIR for an ITK CMake config (lib/cmake/ITK-*/ITKConfig.cmake). When found, steps 01_superbuild_support_components and 02_build_wrapped_itk_cplusplus are replaced with no-op stubs, reducing remote module build times from ~1-2 hours to ~15 minutes. Co-Authored-By: Claude Opus 4.6 (1M context) --- scripts/build_python_instance_base.py | 59 +++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/scripts/build_python_instance_base.py b/scripts/build_python_instance_base.py index 33dac2e5..dca85a95 100644 --- a/scripts/build_python_instance_base.py +++ b/scripts/build_python_instance_base.py @@ -205,6 +205,35 @@ def update_venv_itk_build_configurations(self) -> None: "Python3_ROOT_DIR:PATH", f"{self.venv_info_dict['python_root_dir']}" ) + def _detect_conda_itk(self) -> Path | None: + """Detect a pre-installed ITK from a conda/pixi environment. + + Checks ``CONDA_PREFIX`` (or ``PIXI_ENVIRONMENT_DIR``) for an + installed ITK CMake config directory. When found, the superbuild + and C++ build steps can be skipped entirely. + + Returns + ------- + Path or None + Path to the ITK CMake config directory, or *None* if not found. + """ + for env_var in ("CONDA_PREFIX", "PIXI_ENVIRONMENT_DIR"): + prefix = os.environ.get(env_var, "") + if not prefix: + continue + # Search for lib/cmake/ITK-* (version may vary) + cmake_dir = Path(prefix) / "lib" / "cmake" + if cmake_dir.is_dir(): + for candidate in sorted(cmake_dir.glob("ITK-*")): + itk_config = candidate / "ITKConfig.cmake" + if itk_config.is_file(): + print( + f"Detected conda-installed ITK at {candidate} " + f"(via ${env_var})" + ) + return candidate + return None + def run(self) -> None: """Run the full build flow for this Python instance.""" # Use BuildManager to persist and resume build steps @@ -213,6 +242,21 @@ def run(self) -> None: if self.itk_module_deps: self._build_module_dependencies() + # Check for conda/pixi-provided ITK (libitk-wrapping package) + conda_itk_dir = self._detect_conda_itk() + if conda_itk_dir is not None: + # Point the build at the pre-installed ITK — skip compilation + self.cmake_itk_source_build_configurations.set( + "ITK_DIR:PATH", str(conda_itk_dir) + ) + # Set ITK_BINARY_DIR so wheel build and cleanup paths still resolve + self.cmake_itk_source_build_configurations.set( + "ITK_BINARY_DIR:PATH", str(conda_itk_dir) + ) + print( + "Using conda-installed ITK; skipping superbuild and C++ build steps." + ) + python_package_build_steps: OrderedDict[str, Callable] = OrderedDict( { "01_superbuild_support_components": self.build_superbuild_support_components, @@ -223,6 +267,21 @@ def run(self) -> None: } ) + if conda_itk_dir is not None: + # Skip both superbuild and C++ build when using conda ITK + python_package_build_steps = OrderedDict( + ( + (f"{k}_skipped", (lambda: None)) + if k + in ( + "01_superbuild_support_components", + "02_build_wrapped_itk_cplusplus", + ) + else (k, v) + ) + for k, v in python_package_build_steps.items() + ) + if self.skip_itk_build: # Skip these steps if we are in the CI environment python_package_build_steps = OrderedDict( From affbd85e40d94cb71239d7fb981c4da082ed5173 Mon Sep 17 00:00:00 2001 From: Hans Johnson Date: Fri, 3 Apr 2026 12:01:37 -0500 Subject: [PATCH 12/27] ENH: Skip tarball download when conda-installed ITK is available Update the Linux, macOS, and Windows download-cache-and-build scripts to detect a pre-installed ITK from a conda/pixi environment before attempting to download ITKPythonBuilds tarballs. When ITKConfig.cmake is found under CONDA_PREFIX or PIXI_ENVIRONMENT_DIR, the entire download/extract phase is skipped and the build proceeds directly using the conda-provided ITK. This is backward-compatible: when no conda ITK is detected, the scripts behave exactly as before (tarball download path). Co-Authored-By: Claude Opus 4.6 (1M context) --- ...-download-cache-and-build-module-wheels.sh | 61 +++++--- ...-download-cache-and-build-module-wheels.sh | 148 ++++++++++-------- ...download-cache-and-build-module-wheels.ps1 | 31 +++- 3 files changed, 158 insertions(+), 82 deletions(-) diff --git a/scripts/dockcross-manylinux-download-cache-and-build-module-wheels.sh b/scripts/dockcross-manylinux-download-cache-and-build-module-wheels.sh index 2381c459..d94e2d68 100755 --- a/scripts/dockcross-manylinux-download-cache-and-build-module-wheels.sh +++ b/scripts/dockcross-manylinux-download-cache-and-build-module-wheels.sh @@ -87,27 +87,52 @@ ITKPYTHONPACKAGE_ORG=${ITKPYTHONPACKAGE_ORG:-InsightSoftwareConsortium} ITKPYTHONPACKAGE_TAG=${ITKPYTHONPACKAGE_TAG:-main} # ----------------------------------------------------------------------- -# Download and extract cache +# Check for conda/pixi-provided ITK (libitk-wrapping package). +# When available, skip the tarball download entirely. -echo "Fetching https://raw.githubusercontent.com/${ITKPYTHONPACKAGE_ORG}/ITKPythonPackage/${ITKPYTHONPACKAGE_TAG}/scripts/dockcross-manylinux-download-cache.sh" -curl -L "https://raw.githubusercontent.com/${ITKPYTHONPACKAGE_ORG}/ITKPythonPackage/${ITKPYTHONPACKAGE_TAG}/scripts/dockcross-manylinux-download-cache.sh" -O -chmod u+x dockcross-manylinux-download-cache.sh -_download_cmd="ITK_GIT_TAG=${ITK_GIT_TAG} \ - ITK_PACKAGE_VERSION=${ITK_PACKAGE_VERSION} \ - ITKPYTHONPACKAGE_ORG=${ITKPYTHONPACKAGE_ORG} \ - ITKPYTHONPACKAGE_TAG=${ITKPYTHONPACKAGE_TAG} \ - MANYLINUX_VERSION=${MANYLINUX_VERSION} \ - TARGET_ARCH=${TARGET_ARCH} \ - bash -x \ - ${download_script_dir}/dockcross-manylinux-download-cache.sh $1" -echo "Running: ${_download_cmd}" -eval "${_download_cmd}" +_conda_itk_dir="" +for _prefix_var in CONDA_PREFIX PIXI_ENVIRONMENT_DIR; do + _prefix="${!_prefix_var:-}" + if [ -n "${_prefix}" ]; then + for _candidate in "${_prefix}"/lib/cmake/ITK-*; do + if [ -f "${_candidate}/ITKConfig.cmake" ]; then + _conda_itk_dir="${_candidate}" + echo "Detected conda-installed ITK at ${_conda_itk_dir} (via \$${_prefix_var})" + break 2 + fi + done + fi +done + +if [ -n "${_conda_itk_dir}" ]; then + echo "Using conda-installed ITK; skipping tarball download." + # Point to this repo's own scripts (already present on disk) + untarred_ipp_dir=${download_script_dir} + ITK_SOURCE_DIR="" +else + # ----------------------------------------------------------------------- + # Download and extract cache (legacy tarball path) + + echo "Fetching https://raw.githubusercontent.com/${ITKPYTHONPACKAGE_ORG}/ITKPythonPackage/${ITKPYTHONPACKAGE_TAG}/scripts/dockcross-manylinux-download-cache.sh" + curl -L "https://raw.githubusercontent.com/${ITKPYTHONPACKAGE_ORG}/ITKPythonPackage/${ITKPYTHONPACKAGE_TAG}/scripts/dockcross-manylinux-download-cache.sh" -O + chmod u+x dockcross-manylinux-download-cache.sh + _download_cmd="ITK_GIT_TAG=${ITK_GIT_TAG} \ + ITK_PACKAGE_VERSION=${ITK_PACKAGE_VERSION} \ + ITKPYTHONPACKAGE_ORG=${ITKPYTHONPACKAGE_ORG} \ + ITKPYTHONPACKAGE_TAG=${ITKPYTHONPACKAGE_TAG} \ + MANYLINUX_VERSION=${MANYLINUX_VERSION} \ + TARGET_ARCH=${TARGET_ARCH} \ + bash -x \ + ${download_script_dir}/dockcross-manylinux-download-cache.sh $1" + echo "Running: ${_download_cmd}" + eval "${_download_cmd}" -#NOTE: in this scenario, untarred_ipp_dir is extracted from tarball -# during ${download_script_dir}/dockcross-manylinux-download-cache.sh -untarred_ipp_dir=${download_script_dir}/ITKPythonPackage + #NOTE: in this scenario, untarred_ipp_dir is extracted from tarball + # during ${download_script_dir}/dockcross-manylinux-download-cache.sh + untarred_ipp_dir=${download_script_dir}/ITKPythonPackage -ITK_SOURCE_DIR=${download_script_dir}/ITKPythonPackage-build/ITK + ITK_SOURCE_DIR=${download_script_dir}/ITKPythonPackage-build/ITK +fi # ----------------------------------------------------------------------- # Build module wheels diff --git a/scripts/macpython-download-cache-and-build-module-wheels.sh b/scripts/macpython-download-cache-and-build-module-wheels.sh index a21bc854..f0189ab7 100755 --- a/scripts/macpython-download-cache-and-build-module-wheels.sh +++ b/scripts/macpython-download-cache-and-build-module-wheels.sh @@ -76,73 +76,95 @@ if [ ! -d "${DASHBOARD_BUILD_DIRECTORY}" ]; then fi cd "${DASHBOARD_BUILD_DIRECTORY}" || exit -# NOTE: download phase will install pixi in the DASHBOARD_BUILD_DIRECTORY (which is separate from the pixi -# environment used by ITKPythonPackage). -export PIXI_HOME=${DASHBOARD_BUILD_DIRECTORY}/.pixi -if [ ! -f "${PIXI_HOME}/.pixi/bin/pixi" ]; then - # Install pixi - curl -fsSL https://pixi.sh/install.sh | sh - # These are the tools needed for cross platform downloads of the ITK build caches stored in https://github.com/InsightSoftwareConsortium/ITKPythonBuilds - pixi global install zstd - pixi global install aria2 - pixi global install gnu-tar - pixi global install git - pixi global install rsync -fi -export PATH="${PIXI_HOME}/bin:$PATH" - -tarball_arch="-$(arch)" -TARBALL_NAME="ITKPythonBuilds-macosx${tarball_arch}.tar" - -if [[ ! -f ${TARBALL_NAME}.zst ]]; then - echo "Local ITK cache tarball file not found..." - # Fetch ITKPythonBuilds archive containing ITK build artifacts - echo "Fetching https://github.com/InsightSoftwareConsortium/ITKPythonBuilds/releases/download/${ITK_PACKAGE_VERSION}/ITKPythonBuilds-macosx${tarball_arch}.tar.zst" - if ! curl -L "https://github.com/InsightSoftwareConsortium/ITKPythonBuilds/releases/download/${ITK_PACKAGE_VERSION}/ITKPythonBuilds-macosx${tarball_arch}.tar.zst" -O; then - echo "FAILED Download:" - echo "curl -L https://github.com/InsightSoftwareConsortium/ITKPythonBuilds/releases/download/${ITK_PACKAGE_VERSION}/${TARBALL_NAME}.zst -O" - exit 1 - fi -fi +# ----------------------------------------------------------------------- +# Check for conda/pixi-provided ITK (libitk-wrapping package). +# When available, skip the tarball download entirely. -if [[ ! -f ./${TARBALL_NAME}.zst ]]; then - echo "ERROR: can not find required binary './${TARBALL_NAME}.zst'" - exit 255 -fi +_conda_itk_dir="" +for _prefix_var in CONDA_PREFIX PIXI_ENVIRONMENT_DIR; do + _prefix="${!_prefix_var:-}" + if [ -n "${_prefix}" ]; then + for _candidate in "${_prefix}"/lib/cmake/ITK-*; do + if [ -f "${_candidate}/ITKConfig.cmake" ]; then + _conda_itk_dir="${_candidate}" + echo "Detected conda-installed ITK at ${_conda_itk_dir} (via \$${_prefix_var})" + break 2 + fi + done + fi +done -local_compress_tarball_name=${DASHBOARD_BUILD_DIRECTORY}/ITKPythonBuilds-macosx${tarball_arch}.tar.zst -if [[ ! -f ${local_compress_tarball_name} ]]; then - aria2c -c --file-allocation=none -d "$(dirname "${local_compress_tarball_name}")" -o "$(basename "${local_compress_tarball_name}")" -s 10 -x 10 "https://github.com/InsightSoftwareConsortium/ITKPythonBuilds/releases/download/${ITK_PACKAGE_VERSION}/ITKPythonBuilds-macosx${tarball_arch}.tar.zst" -fi -local_tarball_name=${DASHBOARD_BUILD_DIRECTORY}/ITKPythonBuilds-macosx${tarball_arch}.tar -unzstd --long=31 "${local_compress_tarball_name}" -o "${local_tarball_name}" -# Find GNU tar (gtar from pixi or brew) for reliable extraction -if command -v gtar >/dev/null 2>&1; then - TAR_CMD=gtar - TAR_FLAGS=(--warning=no-unknown-keyword --checkpoint=10000 --checkpoint-action=dot) -elif tar --version 2>/dev/null | grep -q "GNU tar"; then - TAR_CMD=tar - TAR_FLAGS=(--warning=no-unknown-keyword --checkpoint=10000 --checkpoint-action=dot) +if [ -n "${_conda_itk_dir}" ]; then + echo "Using conda-installed ITK; skipping tarball download." else - TAR_CMD=tar - TAR_FLAGS=() -fi -"${TAR_CMD}" xf "${local_tarball_name}" "${TAR_FLAGS[@]}" -rm "${local_tarball_name}" - -# Optional: Update build scripts -if [[ -n ${ITKPYTHONPACKAGE_TAG} ]]; then - echo "Updating build scripts to ${ITKPYTHONPACKAGE_ORG}/ITKPythonPackage@${ITKPYTHONPACKAGE_TAG}" - local_clone_ipp=${DASHBOARD_BUILD_DIRECTORY}/ITKPythonPackage_${ITKPYTHONPACKAGE_TAG} - if [ ! -d "${local_clone_ipp}/.git" ]; then - git clone "https://github.com/${ITKPYTHONPACKAGE_ORG}/ITKPythonPackage.git" "${local_clone_ipp}" + # NOTE: download phase will install pixi in the DASHBOARD_BUILD_DIRECTORY (which is separate from the pixi + # environment used by ITKPythonPackage). + export PIXI_HOME=${DASHBOARD_BUILD_DIRECTORY}/.pixi + if [ ! -f "${PIXI_HOME}/.pixi/bin/pixi" ]; then + # Install pixi + curl -fsSL https://pixi.sh/install.sh | sh + # These are the tools needed for cross platform downloads of the ITK build caches stored in https://github.com/InsightSoftwareConsortium/ITKPythonBuilds + pixi global install zstd + pixi global install aria2 + pixi global install gnu-tar + pixi global install git + pixi global install rsync + fi + export PATH="${PIXI_HOME}/bin:$PATH" + + tarball_arch="-$(arch)" + TARBALL_NAME="ITKPythonBuilds-macosx${tarball_arch}.tar" + + if [[ ! -f ${TARBALL_NAME}.zst ]]; then + echo "Local ITK cache tarball file not found..." + # Fetch ITKPythonBuilds archive containing ITK build artifacts + echo "Fetching https://github.com/InsightSoftwareConsortium/ITKPythonBuilds/releases/download/${ITK_PACKAGE_VERSION}/ITKPythonBuilds-macosx${tarball_arch}.tar.zst" + if ! curl -L "https://github.com/InsightSoftwareConsortium/ITKPythonBuilds/releases/download/${ITK_PACKAGE_VERSION}/ITKPythonBuilds-macosx${tarball_arch}.tar.zst" -O; then + echo "FAILED Download:" + echo "curl -L https://github.com/InsightSoftwareConsortium/ITKPythonBuilds/releases/download/${ITK_PACKAGE_VERSION}/${TARBALL_NAME}.zst -O" + exit 1 + fi + fi + + if [[ ! -f ./${TARBALL_NAME}.zst ]]; then + echo "ERROR: can not find required binary './${TARBALL_NAME}.zst'" + exit 255 + fi + + local_compress_tarball_name=${DASHBOARD_BUILD_DIRECTORY}/ITKPythonBuilds-macosx${tarball_arch}.tar.zst + if [[ ! -f ${local_compress_tarball_name} ]]; then + aria2c -c --file-allocation=none -d "$(dirname "${local_compress_tarball_name}")" -o "$(basename "${local_compress_tarball_name}")" -s 10 -x 10 "https://github.com/InsightSoftwareConsortium/ITKPythonBuilds/releases/download/${ITK_PACKAGE_VERSION}/ITKPythonBuilds-macosx${tarball_arch}.tar.zst" + fi + local_tarball_name=${DASHBOARD_BUILD_DIRECTORY}/ITKPythonBuilds-macosx${tarball_arch}.tar + unzstd --long=31 "${local_compress_tarball_name}" -o "${local_tarball_name}" + # Find GNU tar (gtar from pixi or brew) for reliable extraction + if command -v gtar >/dev/null 2>&1; then + TAR_CMD=gtar + TAR_FLAGS=(--warning=no-unknown-keyword --checkpoint=10000 --checkpoint-action=dot) + elif tar --version 2>/dev/null | grep -q "GNU tar"; then + TAR_CMD=tar + TAR_FLAGS=(--warning=no-unknown-keyword --checkpoint=10000 --checkpoint-action=dot) + else + TAR_CMD=tar + TAR_FLAGS=() + fi + "${TAR_CMD}" xf "${local_tarball_name}" "${TAR_FLAGS[@]}" + rm "${local_tarball_name}" + + # Optional: Update build scripts + if [[ -n ${ITKPYTHONPACKAGE_TAG} ]]; then + echo "Updating build scripts to ${ITKPYTHONPACKAGE_ORG}/ITKPythonPackage@${ITKPYTHONPACKAGE_TAG}" + local_clone_ipp=${DASHBOARD_BUILD_DIRECTORY}/ITKPythonPackage_${ITKPYTHONPACKAGE_TAG} + if [ ! -d "${local_clone_ipp}/.git" ]; then + git clone "https://github.com/${ITKPYTHONPACKAGE_ORG}/ITKPythonPackage.git" "${local_clone_ipp}" + fi + pushd "${local_clone_ipp}" || exit + git checkout "${ITKPYTHONPACKAGE_TAG}" + git reset "origin/${ITKPYTHONPACKAGE_TAG}" --hard + git status + popd || exit + rsync -av "${local_clone_ipp}/" "${DASHBOARD_BUILD_DIRECTORY}/ITKPythonPackage/" fi - pushd "${local_clone_ipp}" || exit - git checkout "${ITKPYTHONPACKAGE_TAG}" - git reset "origin/${ITKPYTHONPACKAGE_TAG}" --hard - git status - popd || exit - rsync -av "${local_clone_ipp}/" "${DASHBOARD_BUILD_DIRECTORY}/ITKPythonPackage/" fi echo "Building module wheels" diff --git a/scripts/windows-download-cache-and-build-module-wheels.ps1 b/scripts/windows-download-cache-and-build-module-wheels.ps1 index 7f9a2ef7..512ca641 100644 --- a/scripts/windows-download-cache-and-build-module-wheels.ps1 +++ b/scripts/windows-download-cache-and-build-module-wheels.ps1 @@ -87,6 +87,31 @@ echo "ITK_PACKAGE_VERSION: $ITK_PACKAGE_VERSION" echo "ITK_GIT_TAG : $ITK_GIT_TAG" echo "Platform env : $platformEnv" +# --------------------------------------------------------------------------- +# Check for conda/pixi-provided ITK (libitk-wrapping package). +# When available, skip the archive download entirely. +# --------------------------------------------------------------------------- +$condaItkDir = $null +foreach ($prefixVar in @("CONDA_PREFIX", "PIXI_ENVIRONMENT_DIR")) { + $prefix = [System.Environment]::GetEnvironmentVariable($prefixVar) + if ($prefix -and (Test-Path "$prefix\lib\cmake")) { + foreach ($candidate in (Get-ChildItem "$prefix\lib\cmake" -Directory -Filter "ITK-*" -ErrorAction SilentlyContinue)) { + if (Test-Path "$($candidate.FullName)\ITKConfig.cmake") { + $condaItkDir = $candidate.FullName + echo "Detected conda-installed ITK at $condaItkDir (via `$$prefixVar)" + break + } + } + if ($condaItkDir) { break } + } +} + +if ($condaItkDir) { + echo "Using conda-installed ITK; skipping archive download." + # Use local ITKPythonPackage scripts + $ippDir = $PSScriptRoot | Split-Path +} else { + # Install pixi and required global tools # NOTE: Python and Doxygen are provided by the pixi environment; no need to # install them separately here. @@ -195,9 +220,13 @@ if ($ITKPYTHONPACKAGE_TAG) { Remove-Item -Recurse -Force $ippTmpDir } +} # end else (tarball download path) + # Build the module wheel # Assemble paths used by build_wheels.py -$ippDir = "$DASHBOARD_BUILD_DIRECTORY\IPP" +if (-not $ippDir) { + $ippDir = "$DASHBOARD_BUILD_DIRECTORY\IPP" +} $buildScript = "$ippDir\scripts\build_wheels.py" # build_wheels.py expects the cached ITK build at \build\ITK-windows-py3XX-... # Since the zip extracts directly into BDR (i.e. BDR\build\ITK-windows-py311-...), BDR is the root. From e6cadad15dbc705fb0ed6fad38094cb8c8f76ff0 Mon Sep 17 00:00:00 2001 From: Hans Johnson Date: Fri, 3 Apr 2026 12:06:13 -0500 Subject: [PATCH 13/27] ENH: Configure commitizen for ITK commit message convention Add commitizen configuration to pyproject.toml that enforces the ITK commit message convention (PREFIX: Description) with interactive prompts for selecting the change type. Valid prefixes: BUG, COMP, DOC, ENH, PERF, STYLE. The commitizen pre-commit hook in .pre-commit-config.yaml validates commit messages at the commit-msg stage. Co-Authored-By: Claude Opus 4.6 (1M context) --- pyproject.toml | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index d6f36352..5871eda1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,3 +19,47 @@ target-version = "py310" select = ["E", "F", "I", "UP", "B"] # E501 (line-too-long) is handled by black; suppress here to avoid duplication ignore = ["E501"] + +[tool.commitizen] +name = "cz_customize" + +[tool.commitizen.customize] +message_template = "{{change_type}}: {{message}}" +example = "ENH: Add support for Python 3.12" +schema = ": " +schema_pattern = "(BUG|COMP|DOC|ENH|PERF|STYLE): [A-Z].*" +bump_pattern = "^(ENH|BUG|COMP|PERF)" +bump_map = { "ENH" = "MINOR", "BUG" = "PATCH", "COMP" = "PATCH", "PERF" = "PATCH" } +commit_parser = "^(?PBUG|COMP|DOC|ENH|PERF|STYLE): (?P.*)" +changelog_pattern = "^(BUG|COMP|DOC|ENH|PERF|STYLE)?(!)?" +change_type_map = { "ENH" = "Enhancements", "BUG" = "Bug Fixes", "COMP" = "Build Fixes", "DOC" = "Documentation", "PERF" = "Performance", "STYLE" = "Style" } +change_type_order = ["Enhancements", "Bug Fixes", "Build Fixes", "Performance", "Documentation", "Style"] +info = """ +ITK commit message convention: PREFIX: Description + +Valid prefixes: + BUG: a bug fix + COMP: a compilation/build fix + DOC: documentation changes + ENH: new feature or enhancement + PERF: performance improvement + STYLE: code style/formatting (no logic change) +""" + +[[tool.commitizen.customize.questions]] +type = "list" +name = "change_type" +message = "Select the type of change:" +choices = [ + { value = "ENH", name = "ENH: A new feature or enhancement", key = "e" }, + { value = "BUG", name = "BUG: A bug fix", key = "b" }, + { value = "COMP", name = "COMP: A compilation/build fix", key = "c" }, + { value = "DOC", name = "DOC: Documentation changes", key = "d" }, + { value = "PERF", name = "PERF: A performance improvement", key = "p" }, + { value = "STYLE", name = "STYLE: Code style/formatting (no logic change)", key = "s" }, +] + +[[tool.commitizen.customize.questions]] +type = "input" +name = "message" +message = "Commit description (start with capital letter):" From 79695e76e1eb3ebe77d4ccd50985a98b1afa65ca Mon Sep 17 00:00:00 2001 From: Hans Johnson Date: Fri, 3 Apr 2026 12:07:27 -0500 Subject: [PATCH 14/27] DOC: Add conda-forge staged-recipes submission for libitk-wrapping Add conda-forge-ready recipe files (meta.yaml, build.sh, bld.bat) for the libitk-wrapping package. These are prepared for submission to conda-forge/staged-recipes once the ITK install rule changes are merged upstream and an ITK 6 release is tagged. The recipe builds ITK C++ with Python wrapping using conda-forge system libraries and includes the CMAKE_FIND_ROOT_PATH settings required by conda-build cross-compilation. Co-Authored-By: Claude Opus 4.6 (1M context) --- conda-forge/README.md | 36 +++++++++++ conda-forge/libitk-wrapping/bld.bat | 60 +++++++++++++++++++ conda-forge/libitk-wrapping/build.sh | 86 +++++++++++++++++++++++++++ conda-forge/libitk-wrapping/meta.yaml | 73 +++++++++++++++++++++++ 4 files changed, 255 insertions(+) create mode 100644 conda-forge/README.md create mode 100644 conda-forge/libitk-wrapping/bld.bat create mode 100755 conda-forge/libitk-wrapping/build.sh create mode 100644 conda-forge/libitk-wrapping/meta.yaml diff --git a/conda-forge/README.md b/conda-forge/README.md new file mode 100644 index 00000000..140624c7 --- /dev/null +++ b/conda-forge/README.md @@ -0,0 +1,36 @@ +# conda-forge Submission + +This directory contains recipe files for submitting ITK packages to conda-forge +via [staged-recipes](https://github.com/conda-forge/staged-recipes). + +## Packages + +### libitk-wrapping + +A conda package containing ITK C++ libraries with full Python wrapping +artifacts (SWIG interfaces, CastXML outputs, compiled Python modules). +This package enables building ITK Python wheels and remote module wheels +without recompiling ITK from source. + +### Submission Process + +1. Fork [conda-forge/staged-recipes](https://github.com/conda-forge/staged-recipes) +2. Copy `libitk-wrapping/` into `recipes/libitk-wrapping/` +3. Open a PR against staged-recipes +4. Address conda-forge review feedback +5. Once merged, a feedstock will be created automatically + +### Updating the existing libitk feedstock + +The existing [libitk-feedstock](https://github.com/conda-forge/libitk-feedstock) +(currently at v5.4.5) should be updated to ITK 6 separately. The `libitk-wrapping` +package will depend on `libitk-devel` once both are at ITK 6. + +## Environment Variables for Custom Builds + +When building from a non-default ITK branch (e.g., for PR testing): + +```bash +export ITK_GIT_URL="https://github.com/BRAINSia/ITK.git" +export ITK_GIT_TAG="itk-conda-pythonpackage-support" +``` diff --git a/conda-forge/libitk-wrapping/bld.bat b/conda-forge/libitk-wrapping/bld.bat new file mode 100644 index 00000000..cce966e5 --- /dev/null +++ b/conda-forge/libitk-wrapping/bld.bat @@ -0,0 +1,60 @@ +@echo off +setlocal enabledelayedexpansion + +set BUILD_DIR=%SRC_DIR%\..\build +mkdir %BUILD_DIR% +cd %BUILD_DIR% + +cmake ^ + -G "Ninja" ^ + %CMAKE_ARGS% ^ + -D BUILD_SHARED_LIBS:BOOL=ON ^ + -D BUILD_TESTING:BOOL=OFF ^ + -D BUILD_EXAMPLES:BOOL=OFF ^ + -D CMAKE_BUILD_TYPE:STRING=Release ^ + -D "CMAKE_INSTALL_PREFIX=%LIBRARY_PREFIX%" ^ + ^ + -D ITK_WRAP_PYTHON:BOOL=ON ^ + -D ITK_WRAP_DOC:BOOL=ON ^ + -D ITK_LEGACY_SILENT:BOOL=ON ^ + -D CMAKE_POSITION_INDEPENDENT_CODE:BOOL=ON ^ + ^ + -D ITK_WRAP_unsigned_short:BOOL=ON ^ + -D ITK_WRAP_double:BOOL=ON ^ + -D ITK_WRAP_complex_double:BOOL=ON ^ + -D "ITK_WRAP_IMAGE_DIMS:STRING=2;3;4" ^ + ^ + -D WRAP_ITK_INSTALL_COMPONENT_IDENTIFIER:STRING=PythonWheel ^ + -D WRAP_ITK_INSTALL_COMPONENT_PER_MODULE:BOOL=ON ^ + ^ + -D ITK_USE_SYSTEM_EXPAT:BOOL=ON ^ + -D ITK_USE_SYSTEM_HDF5:BOOL=ON ^ + -D ITK_USE_SYSTEM_JPEG:BOOL=ON ^ + -D ITK_USE_SYSTEM_PNG:BOOL=ON ^ + -D ITK_USE_SYSTEM_TIFF:BOOL=ON ^ + -D ITK_USE_SYSTEM_ZLIB:BOOL=ON ^ + -D ITK_USE_SYSTEM_FFTW:BOOL=ON ^ + -D ITK_USE_SYSTEM_EIGEN:BOOL=ON ^ + -D ITK_USE_FFTWD:BOOL=ON ^ + -D ITK_USE_FFTWF:BOOL=ON ^ + ^ + -D ITK_BUILD_DEFAULT_MODULES:BOOL=ON ^ + -D Module_ITKReview:BOOL=ON ^ + -D Module_ITKTBB:BOOL=ON ^ + -D Module_MGHIO:BOOL=ON ^ + -D Module_ITKIOTransformMINC:BOOL=ON ^ + -D Module_GenericLabelInterpolator:BOOL=ON ^ + -D Module_AdaptiveDenoising:BOOL=ON ^ + ^ + -D ITK_USE_KWSTYLE:BOOL=OFF ^ + -D "ITK_DEFAULT_THREADER:STRING=Pool" ^ + ^ + "%SRC_DIR%" + +if errorlevel 1 exit /b 1 + +cmake --build . --config Release +if errorlevel 1 exit /b 1 + +cmake --install . --config Release +if errorlevel 1 exit /b 1 diff --git a/conda-forge/libitk-wrapping/build.sh b/conda-forge/libitk-wrapping/build.sh new file mode 100755 index 00000000..48a9f657 --- /dev/null +++ b/conda-forge/libitk-wrapping/build.sh @@ -0,0 +1,86 @@ +#!/bin/bash +set -euo pipefail + +# Build ITK C++ with Python wrapping for conda-forge. +# Produces headers, shared libraries, CMake config, and all wrapping +# metadata (SWIG .i/.idx/.mdx, Python stubs) needed by downstream +# ITK remote modules. + +BUILD_DIR="${SRC_DIR}/../build" +mkdir -p "${BUILD_DIR}" +cd "${BUILD_DIR}" + +# TBB: enabled on Linux, disabled on macOS (conda TBB issues) +use_tbb=ON +if [ "$(uname)" = "Darwin" ]; then + use_tbb=OFF +fi + +# Cross-compilation support +if [[ "${CONDA_BUILD_CROSS_COMPILATION:-0}" == "1" ]]; then + try_run_results="${RECIPE_DIR}/TryRunResults-${target_platform}.cmake" + if [[ -f "${try_run_results}" ]]; then + CMAKE_ARGS="${CMAKE_ARGS} -C ${try_run_results}" + fi +fi + +cmake \ + -G "Ninja" \ + ${CMAKE_ARGS} \ + -D BUILD_SHARED_LIBS:BOOL=ON \ + -D BUILD_TESTING:BOOL=OFF \ + -D BUILD_EXAMPLES:BOOL=OFF \ + -D CMAKE_BUILD_TYPE:STRING=Release \ + -D "CMAKE_INSTALL_PREFIX=${PREFIX}" \ + \ + -D ITK_WRAP_PYTHON:BOOL=ON \ + -D ITK_WRAP_DOC:BOOL=ON \ + -D ITK_LEGACY_SILENT:BOOL=ON \ + -D CMAKE_POSITION_INDEPENDENT_CODE:BOOL=ON \ + \ + -D ITK_WRAP_unsigned_short:BOOL=ON \ + -D ITK_WRAP_double:BOOL=ON \ + -D ITK_WRAP_complex_double:BOOL=ON \ + -D "ITK_WRAP_IMAGE_DIMS:STRING=2;3;4" \ + \ + -D WRAP_ITK_INSTALL_COMPONENT_IDENTIFIER:STRING=PythonWheel \ + -D WRAP_ITK_INSTALL_COMPONENT_PER_MODULE:BOOL=ON \ + \ + -D ITK_USE_SYSTEM_EXPAT:BOOL=ON \ + -D ITK_USE_SYSTEM_HDF5:BOOL=ON \ + -D ITK_USE_SYSTEM_JPEG:BOOL=ON \ + -D ITK_USE_SYSTEM_PNG:BOOL=ON \ + -D ITK_USE_SYSTEM_TIFF:BOOL=ON \ + -D ITK_USE_SYSTEM_ZLIB:BOOL=ON \ + -D ITK_USE_SYSTEM_FFTW:BOOL=ON \ + -D ITK_USE_SYSTEM_EIGEN:BOOL=ON \ + -D ITK_USE_FFTWD:BOOL=ON \ + -D ITK_USE_FFTWF:BOOL=ON \ + \ + -D ITK_BUILD_DEFAULT_MODULES:BOOL=ON \ + -D Module_ITKReview:BOOL=ON \ + -D Module_ITKTBB:BOOL=${use_tbb} \ + -D Module_MGHIO:BOOL=ON \ + -D Module_ITKIOTransformMINC:BOOL=ON \ + -D Module_GenericLabelInterpolator:BOOL=ON \ + -D Module_AdaptiveDenoising:BOOL=ON \ + \ + -D ITK_USE_KWSTYLE:BOOL=OFF \ + -D NIFTI_SYSTEM_MATH_LIB= \ + -D GDCM_USE_COREFOUNDATION_LIBRARY:BOOL=OFF \ + -D "ITK_DEFAULT_THREADER:STRING=Pool" \ + \ + -D "CMAKE_FIND_ROOT_PATH:PATH=${PREFIX}" \ + -D "CMAKE_FIND_ROOT_PATH_MODE_INCLUDE:STRING=ONLY" \ + -D "CMAKE_FIND_ROOT_PATH_MODE_LIBRARY:STRING=ONLY" \ + -D "CMAKE_FIND_ROOT_PATH_MODE_PROGRAM:STRING=NEVER" \ + -D "CMAKE_FIND_ROOT_PATH_MODE_PACKAGE:STRING=ONLY" \ + -D "CMAKE_FIND_FRAMEWORK:STRING=NEVER" \ + -D "CMAKE_FIND_APPBUNDLE:STRING=NEVER" \ + -D "CMAKE_PROGRAM_PATH=${BUILD_PREFIX}" \ + \ + "${SRC_DIR}" + +cmake --build . --config Release + +cmake --install . --config Release diff --git a/conda-forge/libitk-wrapping/meta.yaml b/conda-forge/libitk-wrapping/meta.yaml new file mode 100644 index 00000000..cbbd755f --- /dev/null +++ b/conda-forge/libitk-wrapping/meta.yaml @@ -0,0 +1,73 @@ +{% set version = "6.0.0" %} +{% set itk_tag = "v" + version %} + +package: + name: libitk-wrapping + version: {{ version }} + +source: + url: https://github.com/InsightSoftwareConsortium/ITK/archive/{{ itk_tag }}.tar.gz + # sha256: UPDATE_WITH_ACTUAL_HASH + +build: + number: 0 + skip: true # [win and vc<14] + +requirements: + build: + - cmake >=3.26 + - ninja + - {{ compiler('c') }} + - {{ stdlib("c") }} + - {{ compiler('cxx') }} + host: + - python + - swig >=4.1 + - castxml + - expat # [not win] + - hdf5 + - libjpeg-turbo + - libtiff + - libpng # [not win] + - eigen + - zlib # [not win] + - fftw + - tbb-devel + - doxygen + run: + - python + - tbb + - hdf5 + - fftw + - libjpeg-turbo + - libtiff + - libpng # [not win] + - expat # [not win] + - zlib # [not win] + +test: + commands: + # Verify CMake config is installed and discoverable + - test -d $PREFIX/lib/cmake/ITK* # [not win] + - if not exist %LIBRARY_LIB%\\cmake\\ITK* exit 1 # [win] + # Verify Python wrapping modules are installed + - test -f $PREFIX/lib/python*/site-packages/itk/__init__.py # [not win] + # Verify wrapping metadata is installed + - test -d $PREFIX/lib/cmake/ITK*/WrapITK/Typedefs # [not win] + +about: + home: https://itk.org + license: Apache-2.0 + license_file: + - LICENSE + - NOTICE + summary: > + ITK C++ libraries with Python wrapping artifacts for building + ITK Python wheels and remote module packages. + dev_url: https://github.com/InsightSoftwareConsortium/ITK + +extra: + recipe-maintainers: + - hjmjohnson + - thewtex + - blowekamp From 293ad333cca78c2e14d547e5d2d30e1c8de17fe8 Mon Sep 17 00:00:00 2001 From: Hans Johnson Date: Fri, 3 Apr 2026 12:07:54 -0500 Subject: [PATCH 15/27] DOC: Update CLAUDE.md with conda/pixi-build and commit conventions Document the libitk-wrapping conda package integration, conda ITK auto-detection behavior, and the ITK commit message convention enforced via commitizen. Co-Authored-By: Claude Opus 4.6 (1M context) --- CLAUDE.md | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..d49e838e --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,108 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +ITKPythonPackage is a cross-platform build system for creating Python binary wheels for the Insight Toolkit (ITK) — an open-source C++ image analysis library. It builds wheels for ITK itself and for ITK external (remote) modules across Linux, macOS, and Windows (x86_64 and arm64/aarch64). + +ITK external modules require pre-built ITK artifacts. These are cached as [ITKPythonBuilds](https://github.com/InsightSoftwareConsortium/ITKPythonBuilds) releases to avoid rebuilding ITK for every module. + +## Build System + +### Running a build + +The primary entry point is `scripts/build_wheels.py`, orchestrated via pixi: + +```sh +pixi run build-itk-wheels +``` + +Or directly: +```sh +python scripts/build_wheels.py +``` + +### Environment management + +**pixi** (conda-like) manages reproducible build environments defined in `pixi.toml`. Environments are composed per-platform and per-Python-version (e.g., `manylinux228-py310`, `macosx-py311`). + +### Key environment variables (GitHub Actions compatible) + +- `ITK_PACKAGE_VERSION` — Version string for wheels +- `ITKPYTHONPACKAGE_TAG` — ITKPythonPackage version/tag to use +- `ITKPYTHONPACKAGE_ORG` — GitHub org (default: InsightSoftwareConsortium) +- `ITK_MODULE_PREQ` — Module dependencies (`org/repo@tag:org/repo@tag:...`) +- `CMAKE_OPTIONS` — Extra CMake flags +- `MANYLINUX_VERSION` — Manylinux ABI version (_2_28, _2_34, etc.) +- `MACOSX_DEPLOYMENT_TARGET` — macOS minimum deployment target + +### Linting + +```sh +pre-commit run --all-files +``` + +Shell script linting was previously via `.travis.yml`; now uses pre-commit hooks. + +## Architecture + +### Python build scripts (`scripts/`) + +Class hierarchy for platform-specific wheel building: + +- **`build_wheels.py`** — Main driver. Detects platform/arch, selects pixi environment, creates platform-specific build instance. +- **`build_python_instance_base.py`** — Abstract base class defining the shared build pipeline (download, configure, build, package). +- **`linux_build_python_instance.py`** — Linux: TBB support, `auditwheel` for manylinux compliance. +- **`macos_build_python_instance.py`** — macOS: `delocate` for dylib relocation. +- **`windows_build_python_instance.py`** — Windows: `delvewheel` for DLL bundling. + +Supporting scripts: +- **`pyproject_configure.py`** — Generates `pyproject.toml` from `pyproject.toml.in` template with platform-specific substitutions. +- **`wheel_builder_utils.py`** — Shared utilities (subprocess wrappers, path handling, env parsing). +- **`cmake_argument_builder.py`** — Builds CMake args for both direct invocation (`-DKEY=VALUE`) and scikit-build-core (`--config-setting=cmake.define.KEY=VALUE`). +- **`BuildManager.py`** — JSON-based build step tracking for resuming interrupted builds. + +### CMake layer (`cmake/`) + +- **`ITKPythonPackage_Utils.cmake`** — Utility functions for module dependency resolution, wheel-to-group mapping. +- **`ITKPythonPackage_BuildWheels.cmake`** — Wheel-specific CMake build configuration. +- **`ITKPythonPackage_SuperBuild.cmake`** — ITK + dependencies superbuild. + +### Wheel targets + +Defined in `BuildWheelsSupport/WHEEL_NAMES.txt`: itk-core, itk-numerics, itk-io, itk-filtering, itk-registration, itk-segmentation, itk-meta. + +### Build backend + +Uses **scikit-build-core**. The `pyproject.toml.in` template is the single source of truth for project metadata. + +### Conda/pixi-build integration (`packages/libitk-wrapping/`) + +The `libitk-wrapping` package is a rattler-build recipe that produces a conda package of ITK C++ with full Python wrapping artifacts. When installed in a pixi/conda environment, the build system automatically detects it and skips the expensive ITK C++ compilation (steps 01-02), reducing remote module build times from ~1-2 hours to ~15 minutes. + +- **`packages/libitk-wrapping/recipe.yaml`** — rattler-build recipe (configurable via `ITK_GIT_URL`/`ITK_GIT_TAG` env vars) +- **`packages/libitk-wrapping/build-libitk-wrapping.sh`** — Unix build script +- **`packages/libitk-wrapping/build-libitk-wrapping.bat`** — Windows build script +- **`conda-forge/`** — Prepared conda-forge staged-recipes submission + +Detection is in `build_python_instance_base.py:_detect_conda_itk()` — checks `CONDA_PREFIX` and `PIXI_ENVIRONMENT_DIR` for `lib/cmake/ITK-*/ITKConfig.cmake`. + +## Shell script entry points + +Legacy shell/PowerShell scripts are preserved for backward compatibility with existing CI workflows: +- `scripts/dockcross-manylinux-download-cache-and-build-module-wheels.sh` (Linux) +- `scripts/macpython-download-cache-and-build-module-wheels.sh` (macOS) +- `scripts/windows-download-cache-and-build-module-wheels.ps1` (Windows) + +These scripts delegate to the Python build system internally and will skip tarball downloads when a conda-installed ITK is detected. + +### Commit message convention + +This project follows the ITK commit message convention: `PREFIX: Description`. Valid prefixes: `BUG:`, `COMP:`, `DOC:`, `ENH:`, `PERF:`, `STYLE:`. Enforced via commitizen (configured in `pyproject.toml`, validated by the `commit-msg` pre-commit hook). + +## Related repositories + +- [ITK](https://github.com/InsightSoftwareConsortium/ITK) — The C++ toolkit itself +- [ITKPythonBuilds](https://github.com/InsightSoftwareConsortium/ITKPythonBuilds) — Cached ITK build artifacts +- [ITKRemoteModuleBuildTestPackageAction](https://github.com/InsightSoftwareConsortium/ITKRemoteModuleBuildTestPackageAction) — GitHub Actions reusable workflows for building/testing/packaging From d13691653b4da0a466aad41c6adedcf615fe8ae5 Mon Sep 17 00:00:00 2001 From: Hans Johnson Date: Fri, 3 Apr 2026 12:16:31 -0500 Subject: [PATCH 16/27] DOC: Add accelerated pixi-build workflow to build documentation Document the libitk-wrapping conda package workflow for building remote module wheels without recompiling ITK from source. Includes instructions for building and installing the package, environment variable overrides for custom ITK branches, and cross-references between the ITK and module build docs. Co-Authored-By: Claude Opus 4.6 (1M context) --- docs/Build_ITK_Module_Python_packages.rst | 46 +++++++++++++++++++++++ docs/Build_ITK_Python_packages.rst | 7 ++++ 2 files changed, 53 insertions(+) diff --git a/docs/Build_ITK_Module_Python_packages.rst b/docs/Build_ITK_Module_Python_packages.rst index ad134af5..2abdcfc8 100644 --- a/docs/Build_ITK_Module_Python_packages.rst +++ b/docs/Build_ITK_Module_Python_packages.rst @@ -198,6 +198,52 @@ For more control over build option, call ``build_wheels.py`` directly with --no-build-itk-tarball-cache +.. _accelerated-builds: + +Accelerated Builds with libitk-wrapping (pixi-build) +===================================================== + +When ITK is pre-installed in the conda/pixi environment via the +``libitk-wrapping`` package, the build system automatically skips the +expensive ITK C++ compilation (steps 01 and 02). This reduces remote +module build times from ~1-2 hours to ~15 minutes. + +To use this workflow, first build and install the ``libitk-wrapping`` +package: + +.. code-block:: bash + + cd packages/libitk-wrapping + pixi build + +Then build your module wheel — ITK will be detected automatically: + +.. code-block:: bash + + pixi run -e linux-py311 python scripts/build_wheels.py \ + --platform-env linux-py311 \ + --module-source-dir /path/to/ITKMyModule \ + --skip-itk-build \ + --skip-itk-wheel-build \ + --no-build-itk-tarball-cache + +The detection checks ``CONDA_PREFIX`` and ``PIXI_ENVIRONMENT_DIR`` for +``lib/cmake/ITK-*/ITKConfig.cmake``. When found, the console will print:: + + Detected conda-installed ITK at (via $CONDA_PREFIX) + Using conda-installed ITK; skipping superbuild and C++ build steps. + +To override the ITK source repository and tag for the ``libitk-wrapping`` +build (e.g., to test a feature branch): + +.. code-block:: bash + + export ITK_GIT_URL="https://github.com/MyOrg/ITK.git" + export ITK_GIT_TAG="my-feature-branch" + cd packages/libitk-wrapping + pixi build + + Module Dependencies =================== diff --git a/docs/Build_ITK_Python_packages.rst b/docs/Build_ITK_Python_packages.rst index f4172e3a..781bc61d 100644 --- a/docs/Build_ITK_Python_packages.rst +++ b/docs/Build_ITK_Python_packages.rst @@ -132,6 +132,13 @@ Finished wheels are placed in ``/dist/``. ``--build-itk-tarball-cache`` to save the result as a reusable tarball and avoid rebuilding on subsequent runs. +.. tip:: + For even faster builds, install the ``libitk-wrapping`` conda package + (see ``packages/libitk-wrapping/``). When present in the pixi/conda + environment, the build system automatically detects it and skips the + ITK C++ compilation entirely. See + :ref:`Build ITK Module Python Packages ` for details. + Key Options =========== From 91f40a541d2cf86c2c24d80502b63e72973c458b Mon Sep 17 00:00:00 2001 From: Hans Johnson Date: Fri, 3 Apr 2026 14:10:02 -0500 Subject: [PATCH 17/27] ENH: Dynamically update ITK dependency pins in remote module builds Remote modules hard-code ITK sub-package version pins in their pyproject.toml (e.g., itk-io == 5.4.*). When building against ITK 6, these pins cause pip install conflicts. Add _update_module_itk_deps() which rewrites exact ITK pins to minimum version constraints (>= 5.4) before invoking scikit-build-core. This runs automatically during build_external_module_python_wheel() when ITK_PACKAGE_VERSION is set, so remote module wheels always have dependency metadata compatible with the ITK version they were built against. Co-Authored-By: Claude Opus 4.6 (1M context) --- scripts/build_python_instance_base.py | 63 +++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/scripts/build_python_instance_base.py b/scripts/build_python_instance_base.py index dca85a95..56ff3424 100644 --- a/scripts/build_python_instance_base.py +++ b/scripts/build_python_instance_base.py @@ -710,12 +710,75 @@ def discover_python_venvs( """ pass + @staticmethod + def _update_module_itk_deps(pyproject_path: Path, itk_version: str) -> bool: + """Rewrite ITK dependency pins in a remote module's pyproject.toml. + + Replaces hard-coded ITK sub-package version pins (e.g. + ``itk-io == 5.4.*``) with a pin matching the ITK version being + built against (e.g. ``itk-io >= 5.4``). This ensures that + wheels produced for ITK 6 can be installed alongside ITK 6 + packages without pip dependency conflicts. + + Parameters + ---------- + pyproject_path : Path + Path to the module's ``pyproject.toml``. + itk_version : str + The ITK PEP 440 version string being built (e.g. ``6.0.0b2``). + Used to compute the minimum major version for the ``>=`` pin. + + Returns + ------- + bool + *True* if any dependency was rewritten. + """ + import re + + text = pyproject_path.read_text(encoding="utf-8") + # Match lines like: "itk-core == 5.4.*" or "itk-filtering==5.4.*" + pattern = re.compile( + r'"(itk-[a-z]+)\s*==\s*[\d]+\.[\d]+\.\*"' + ) + + # Determine the minimum version floor from the ITK version being built. + # For "6.0.0b2.post757" -> major "6", floor "5.4" (backward compat). + # For "5.4.0" -> floor "5.4". + try: + major = int(itk_version.split(".")[0]) + except (ValueError, IndexError): + major = 5 + min_floor = "5.4" if major >= 5 else itk_version.rsplit(".", 1)[0] + + changed = False + def _replace(m: re.Match) -> str: + nonlocal changed + changed = True + pkg = m.group(1) + return f'"{pkg} >= {min_floor}"' + + new_text = pattern.sub(_replace, text) + if changed: + pyproject_path.write_text(new_text, encoding="utf-8") + print( + f"Updated ITK dependency pins in {pyproject_path} " + f"(>= {min_floor} for ITK {itk_version})" + ) + return changed + def build_external_module_python_wheel(self): """Build a wheel for an external ITK remote module via scikit-build-core.""" self.module_source_dir = Path(self.module_source_dir) out_dir = self.module_source_dir / "dist" out_dir.mkdir(parents=True, exist_ok=True) + # Dynamically update ITK dependency pins to match the version being built + module_pyproject = self.module_source_dir / "pyproject.toml" + if module_pyproject.is_file(): + itk_ver = self.package_env_config.get("ITK_PACKAGE_VERSION", "") + if itk_ver: + self._update_module_itk_deps(module_pyproject, itk_ver) + # Ensure venv tools are first in PATH py_exe = str(self.package_env_config["PYTHON_EXECUTABLE"]) # Python3_EXECUTABLE From da9a6a66890bbafa94e21acdad623b534b84e520 Mon Sep 17 00:00:00 2001 From: Hans Johnson Date: Fri, 3 Apr 2026 14:16:29 -0500 Subject: [PATCH 18/27] ENH: Preserve module pyproject.toml when rewriting ITK deps Back up pyproject.toml to pyproject.toml.orig before rewriting ITK dependency pins, then restore the original after the wheel is built. The modified version is saved as pyproject.toml.whl for reference. Uses try/finally to guarantee restore even if the build fails. Co-Authored-By: Claude Opus 4.6 (1M context) --- scripts/build_python_instance_base.py | 30 +++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/scripts/build_python_instance_base.py b/scripts/build_python_instance_base.py index 56ff3424..e046b6b4 100644 --- a/scripts/build_python_instance_base.py +++ b/scripts/build_python_instance_base.py @@ -772,12 +772,20 @@ def build_external_module_python_wheel(self): out_dir = self.module_source_dir / "dist" out_dir.mkdir(parents=True, exist_ok=True) - # Dynamically update ITK dependency pins to match the version being built + # Dynamically update ITK dependency pins to match the version being built. + # Back up the original pyproject.toml so the working tree is restored + # after the wheel is produced. module_pyproject = self.module_source_dir / "pyproject.toml" + pyproject_orig = module_pyproject.with_suffix(".toml.orig") + pyproject_whl = module_pyproject.with_suffix(".toml.whl") + deps_rewritten = False if module_pyproject.is_file(): itk_ver = self.package_env_config.get("ITK_PACKAGE_VERSION", "") if itk_ver: - self._update_module_itk_deps(module_pyproject, itk_ver) + shutil.copy2(module_pyproject, pyproject_orig) + deps_rewritten = self._update_module_itk_deps( + module_pyproject, itk_ver + ) # Ensure venv tools are first in PATH py_exe = str(self.package_env_config["PYTHON_EXECUTABLE"]) # Python3_EXECUTABLE @@ -875,11 +883,21 @@ def build_external_module_python_wheel(self): # Module source directory to build cmd += [self.module_source_dir] - self.echo_check_call(cmd) + try: + self.echo_check_call(cmd) - # Post-process produced wheels (e.g., delocate on macOS x86_64) - for wheel in out_dir.glob("*.whl"): - self.fixup_wheel(str(wheel), remote_module_wheel=True) + # Post-process produced wheels (e.g., delocate on macOS x86_64) + for wheel in out_dir.glob("*.whl"): + self.fixup_wheel(str(wheel), remote_module_wheel=True) + finally: + # Restore original pyproject.toml so the working tree stays clean + if deps_rewritten and pyproject_orig.is_file(): + shutil.copy2(module_pyproject, pyproject_whl) + shutil.move(str(pyproject_orig), str(module_pyproject)) + print( + f"Restored {module_pyproject} " + f"(modified version saved as {pyproject_whl.name})" + ) def build_itk_python_wheels(self): """Build all ITK Python wheels listed in ``WHEEL_NAMES.txt``.""" From a63cb10e4d2cadf76bd19a34286bc50c3e445281 Mon Sep 17 00:00:00 2001 From: Hans Johnson Date: Fri, 3 Apr 2026 14:18:53 -0500 Subject: [PATCH 19/27] DOC: Add Strategy 3 migration plan to _update_module_itk_deps Document the plan to migrate from build-time pyproject.toml rewriting (Strategy 1) to a scikit-build-core dynamic metadata provider (Strategy 3) that resolves ITK dependency versions at build time without modifying source files. Co-Authored-By: Claude Opus 4.6 (1M context) --- scripts/build_python_instance_base.py | 43 +++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/scripts/build_python_instance_base.py b/scripts/build_python_instance_base.py index e046b6b4..bbc421ef 100644 --- a/scripts/build_python_instance_base.py +++ b/scripts/build_python_instance_base.py @@ -720,6 +720,49 @@ def _update_module_itk_deps(pyproject_path: Path, itk_version: str) -> bool: wheels produced for ITK 6 can be installed alongside ITK 6 packages without pip dependency conflicts. + .. note:: Strategy 1 (build-time rewrite) — interim solution. + + This approach rewrites the module's pyproject.toml on disk, + builds the wheel, then restores the original. It works today + with zero changes to remote modules but is inherently fragile + (regex-based, modifies the source tree). + + **Plan to migrate to Strategy 3 (scikit-build-core dynamic + metadata provider):** + + 1. Create a small installable package ``itk-build-metadata`` + that implements the scikit-build-core dynamic metadata + provider interface (see scikit-build-core docs: + ``tool.scikit-build.metadata..provider``). + + 2. The provider inspects the build environment at wheel-build + time to discover the ITK version — either from the + ``ITK_PACKAGE_VERSION`` env var (set by this build system), + from ``ITKConfig.cmake`` on ``CMAKE_PREFIX_PATH``, or from + an already-installed ``itk-core`` package. + + 3. It emits the correct ``Requires-Dist`` entries (e.g. + ``itk-io >= 5.4``) into the wheel metadata without + touching ``pyproject.toml`` on disk at all. + + 4. Remote modules opt in by declaring dynamic dependencies:: + + [project] + dynamic = ["dependencies"] + + [tool.scikit-build.metadata.dependencies] + provider = "itk_build_metadata" + provider-path = "." # or from installed package + + 5. Roll out incrementally: update ITKModuleTemplate first, + then migrate existing modules via the ``/update-itk-deps`` + skill (in REMOTE_MODULES/.claude/skills/). Modules that + have not migrated continue to work via this Strategy 1 + fallback, so both approaches coexist during the transition. + + 6. Once all ~60 remote modules have adopted Strategy 3, + this method can be removed. + Parameters ---------- pyproject_path : Path From b7a1dd039e499b78e01f6c6c269f2a4a88741c58 Mon Sep 17 00:00:00 2001 From: Hans Johnson Date: Fri, 3 Apr 2026 14:20:46 -0500 Subject: [PATCH 20/27] ENH: Branch between Strategy 3 and Strategy 1 for ITK dep resolution When a remote module declares dynamic = ["dependencies"] in its [project] table, skip the pyproject.toml rewrite (Strategy 1) and instead set ITK_PACKAGE_VERSION in the environment for the scikit-build-core metadata provider to pick up (Strategy 3). Modules that have not yet opted into dynamic dependencies continue to use the build-time rewrite fallback, so both approaches coexist during the transition. Co-Authored-By: Claude Opus 4.6 (1M context) --- scripts/build_python_instance_base.py | 28 ++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/scripts/build_python_instance_base.py b/scripts/build_python_instance_base.py index bbc421ef..bc8a62c8 100644 --- a/scripts/build_python_instance_base.py +++ b/scripts/build_python_instance_base.py @@ -778,6 +778,32 @@ def _update_module_itk_deps(pyproject_path: Path, itk_version: str) -> bool: """ import re + try: + import tomllib + except ModuleNotFoundError: + import tomli as tomllib # Python < 3.11 + + with open(pyproject_path, "rb") as f: + pyproject_data = tomllib.load(f) + + # --- Strategy 3: module declares dynamic dependencies ----------------- + dynamic_fields = ( + pyproject_data.get("project", {}).get("dynamic", []) + ) + if "dependencies" in dynamic_fields: + # The module has opted into dynamic dependency resolution. + # Set ITK_PACKAGE_VERSION in the environment so the + # scikit-build-core metadata provider (itk-build-metadata) + # can emit the correct Requires-Dist at build time. + os.environ["ITK_PACKAGE_VERSION"] = itk_version + print( + f"Strategy 3: {pyproject_path.name} declares " + f"dynamic=[\"dependencies\"]; set ITK_PACKAGE_VERSION=" + f"{itk_version} for metadata provider" + ) + return False # no file modification needed + + # --- Strategy 1: build-time rewrite (fallback) ------------------------ text = pyproject_path.read_text(encoding="utf-8") # Match lines like: "itk-core == 5.4.*" or "itk-filtering==5.4.*" pattern = re.compile( @@ -804,7 +830,7 @@ def _replace(m: re.Match) -> str: if changed: pyproject_path.write_text(new_text, encoding="utf-8") print( - f"Updated ITK dependency pins in {pyproject_path} " + f"Strategy 1: Updated ITK dependency pins in {pyproject_path} " f"(>= {min_floor} for ITK {itk_version})" ) return changed From cdbb486c64711e4a1f018a52c950c734fbfe21a6 Mon Sep 17 00:00:00 2001 From: Hans Johnson Date: Fri, 3 Apr 2026 14:31:48 -0500 Subject: [PATCH 21/27] ENH: Restrict Strategy 1 dep rewrite to ITK base sub-packages only MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Limit the build-time pyproject.toml rewrite to the six ITK base sub-packages (itk-core, itk-numerics, itk-io, itk-filtering, itk-registration, itk-segmentation) whose versions are tied to the ITK release. Remote module cross-deps like itk-meshtopolydata are versioned independently and are not rewritten — a warning is printed instead so they can be reviewed manually. Prevents incorrect rewriting of e.g. itk-meshtopolydata == 0.12.* in BSplineGradient and WebAssemblyInterface. Co-Authored-By: Claude Opus 4.6 (1M context) --- scripts/build_python_instance_base.py | 30 +++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/scripts/build_python_instance_base.py b/scripts/build_python_instance_base.py index bc8a62c8..7811fbc2 100644 --- a/scripts/build_python_instance_base.py +++ b/scripts/build_python_instance_base.py @@ -805,10 +805,36 @@ def _update_module_itk_deps(pyproject_path: Path, itk_version: str) -> bool: # --- Strategy 1: build-time rewrite (fallback) ------------------------ text = pyproject_path.read_text(encoding="utf-8") - # Match lines like: "itk-core == 5.4.*" or "itk-filtering==5.4.*" + + # Only rewrite ITK *base* sub-packages whose versions are tied to + # the ITK release. Remote module cross-deps (e.g. + # itk-meshtopolydata == 0.12.*) are versioned independently and + # must NOT be rewritten — flag them for manual review instead. + _ITK_BASE_PACKAGES = ( + "itk-core", + "itk-numerics", + "itk-io", + "itk-filtering", + "itk-registration", + "itk-segmentation", + ) + _base_pkg_alt = "|".join(re.escape(p) for p in _ITK_BASE_PACKAGES) pattern = re.compile( - r'"(itk-[a-z]+)\s*==\s*[\d]+\.[\d]+\.\*"' + rf'"({_base_pkg_alt})\s*==\s*[\d]+\.[\d]+\.\*"' + ) + + # Warn about pinned remote-module cross-deps that may also need + # attention but should not be auto-rewritten. + cross_dep_pattern = re.compile( + r'"(itk-[a-z][a-z0-9-]*)\s*==\s*[\d]+\.[\d]+\.\*"' ) + for m in cross_dep_pattern.finditer(text): + pkg = m.group(1) + if pkg not in _ITK_BASE_PACKAGES: + print( + f" WARNING: {pyproject_path.name} pins remote module " + f"cross-dep {m.group(0)} — review manually" + ) # Determine the minimum version floor from the ITK version being built. # For "6.0.0b2.post757" -> major "6", floor "5.4" (backward compat). From fb1583ee6afa3412165964b46aa979d5d6e8f7a7 Mon Sep 17 00:00:00 2001 From: Hans Johnson Date: Fri, 3 Apr 2026 14:34:32 -0500 Subject: [PATCH 22/27] BUG: Pin ITK dep floor to vMAJOR.MINOR of the ITK version being built The dependency floor must match the ITK series the wheel was compiled against, not a hardcoded backward-compatible value. For ITK 6.0.0b2 the rewrite now produces "itk-io >= 6.0" instead of "itk-io >= 5.4". This ensures wheels are only installable alongside the correct ITK release series. Co-Authored-By: Claude Opus 4.6 (1M context) --- scripts/build_python_instance_base.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/scripts/build_python_instance_base.py b/scripts/build_python_instance_base.py index 7811fbc2..16479f9c 100644 --- a/scripts/build_python_instance_base.py +++ b/scripts/build_python_instance_base.py @@ -837,13 +837,14 @@ def _update_module_itk_deps(pyproject_path: Path, itk_version: str) -> bool: ) # Determine the minimum version floor from the ITK version being built. - # For "6.0.0b2.post757" -> major "6", floor "5.4" (backward compat). - # For "5.4.0" -> floor "5.4". + # Pin to vMAJOR.MINOR of the ITK version so the wheel is only + # installable alongside the ITK series it was compiled against. + # For "6.0.0b2.post757" -> "6.0", for "5.4.0" -> "5.4". + parts = itk_version.split(".") try: - major = int(itk_version.split(".")[0]) - except (ValueError, IndexError): - major = 5 - min_floor = "5.4" if major >= 5 else itk_version.rsplit(".", 1)[0] + min_floor = f"{parts[0]}.{parts[1]}" + except IndexError: + min_floor = itk_version changed = False def _replace(m: re.Match) -> str: From cfeffd170f90d789907bc5f81cfb98711e5bbaee Mon Sep 17 00:00:00 2001 From: Hans Johnson Date: Fri, 3 Apr 2026 14:35:31 -0500 Subject: [PATCH 23/27] BUG: Use fixed >= 5.4 floor for ITK deps across all versions Remote modules must support installation with any ITK from v5.4.0 through the latest release. Use a fixed floor of >= 5.4 rather than pinning to the version being built, so wheels are installable across the full supported range. Co-Authored-By: Claude Opus 4.6 (1M context) --- scripts/build_python_instance_base.py | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/scripts/build_python_instance_base.py b/scripts/build_python_instance_base.py index 16479f9c..3660b8f7 100644 --- a/scripts/build_python_instance_base.py +++ b/scripts/build_python_instance_base.py @@ -836,15 +836,11 @@ def _update_module_itk_deps(pyproject_path: Path, itk_version: str) -> bool: f"cross-dep {m.group(0)} — review manually" ) - # Determine the minimum version floor from the ITK version being built. - # Pin to vMAJOR.MINOR of the ITK version so the wheel is only - # installable alongside the ITK series it was compiled against. - # For "6.0.0b2.post757" -> "6.0", for "5.4.0" -> "5.4". - parts = itk_version.split(".") - try: - min_floor = f"{parts[0]}.{parts[1]}" - except IndexError: - min_floor = itk_version + # Remote modules must support installation across the full + # ITK 5.4 → latest range. Use a fixed floor of 5.4 so that a + # wheel built against any ITK version (5.4.x, 6.0.x, etc.) is + # installable with any ITK >= 5.4. + min_floor = "5.4" changed = False def _replace(m: re.Match) -> str: From 221359df3ec37b725d07a6b4803c13e8186bdc1d Mon Sep 17 00:00:00 2001 From: Hans Johnson Date: Fri, 3 Apr 2026 14:37:44 -0500 Subject: [PATCH 24/27] BUG: Pin ITK dep floor to MAJOR.MINOR of the version being built MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A wheel compiled against ITK 6.0 must require >= 6.0 at install time, not >= 5.4. The floor reflects the ITK series the wheel was linked against. The build system supports building against any ITK from v5.4 through the latest — the floor is derived dynamically from ITK_PACKAGE_VERSION at build time. Co-Authored-By: Claude Opus 4.6 (1M context) --- scripts/build_python_instance_base.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/scripts/build_python_instance_base.py b/scripts/build_python_instance_base.py index 3660b8f7..fd5d3763 100644 --- a/scripts/build_python_instance_base.py +++ b/scripts/build_python_instance_base.py @@ -836,11 +836,17 @@ def _update_module_itk_deps(pyproject_path: Path, itk_version: str) -> bool: f"cross-dep {m.group(0)} — review manually" ) - # Remote modules must support installation across the full - # ITK 5.4 → latest range. Use a fixed floor of 5.4 so that a - # wheel built against any ITK version (5.4.x, 6.0.x, etc.) is - # installable with any ITK >= 5.4. - min_floor = "5.4" + # The minimum version floor is the MAJOR.MINOR of the ITK version + # being built. A wheel compiled against ITK 6.0 requires ITK >= 6.0 + # at install time; one compiled against ITK 5.4 requires >= 5.4. + # The build system itself supports building against any ITK from + # v5.4 through the latest (v5.5, v6.0, v7.1, etc.) — the floor + # simply reflects which ITK the wheel was actually linked against. + parts = itk_version.split(".") + try: + min_floor = f"{parts[0]}.{parts[1]}" + except IndexError: + min_floor = itk_version changed = False def _replace(m: re.Match) -> str: From eb281930fbe1504a542e063fb877c15aae0b65ff Mon Sep 17 00:00:00 2001 From: Hans Johnson Date: Fri, 3 Apr 2026 16:15:39 -0500 Subject: [PATCH 25/27] ENH: Add scripts to build all ITK + remote module wheels from latest main Add shell and Python scripts that clone ITK, ITKPythonPackage, and all remote modules from their latest main branches, then build ITK Python wheels followed by every remote module that has Python wrapping. All wheels are collected into a single /tmp/_LatestITKPython/dist directory. Both scripts parse ITK's Modules/Remote/*.remote.cmake files to discover remote module git repositories, filter to those with wrapping/ and pyproject.toml, and build each module wheel reusing the ITK build from the first step. Usage: ./scripts/build-all-latest-wheels.sh [platform-env] python scripts/build_all_latest_wheels.py --platform-env linux-py311 Co-Authored-By: Claude Opus 4.6 (1M context) --- scripts/build-all-latest-wheels.sh | 99 +++++++++++++++ scripts/build_all_latest_wheels.py | 192 +++++++++++++++++++++++++++++ 2 files changed, 291 insertions(+) create mode 100755 scripts/build-all-latest-wheels.sh create mode 100755 scripts/build_all_latest_wheels.py diff --git a/scripts/build-all-latest-wheels.sh b/scripts/build-all-latest-wheels.sh new file mode 100755 index 00000000..5df71ca3 --- /dev/null +++ b/scripts/build-all-latest-wheels.sh @@ -0,0 +1,99 @@ +#!/bin/bash +# Build ITK + all remote module Python wheels from latest main branches. +# Usage: ./scripts/build-all-latest-wheels.sh [platform-env] +# Example: ./scripts/build-all-latest-wheels.sh linux-py311 +set -euo pipefail + +PLATFORM_ENV="${1:-linux-py311}" +TIMESTAMP=$(date +%Y%m%d%H%M%S) +WORKDIR="/tmp/${TIMESTAMP}_LatestITKPython" +DIST_DIR="${WORKDIR}/dist" +ITK_REPO="https://github.com/InsightSoftwareConsortium/ITK.git" +IPP_REPO="https://github.com/BRAINSia/ITKPythonPackage.git" +IPP_BRANCH="python-build-system" + +mkdir -p "${DIST_DIR}" +echo "=== Build directory: ${WORKDIR}" +echo "=== Platform: ${PLATFORM_ENV}" + +# 1) Clone ITK +echo "=== Cloning ITK (main)..." +git clone --depth 1 --branch main "${ITK_REPO}" "${WORKDIR}/ITK" + +# 2) Clone ITKPythonPackage +echo "=== Cloning ITKPythonPackage (${IPP_BRANCH})..." +git clone --branch "${IPP_BRANCH}" "${IPP_REPO}" "${WORKDIR}/ITKPythonPackage" + +# 3) Parse remote modules from ITK and clone each +echo "=== Cloning remote modules..." +MODULES_DIR="${WORKDIR}/modules" +mkdir -p "${MODULES_DIR}" +module_list=() + +for rc in "${WORKDIR}"/ITK/Modules/Remote/*.remote.cmake; do + name=$(basename "${rc}" .remote.cmake) + repo=$(grep 'GIT_REPOSITORY' "${rc}" | sed 's/.*GIT_REPOSITORY *//;s/ *)//;s/[[:space:]]*$//') + [ -z "${repo}" ] && continue + + echo " Cloning ${name} from ${repo}..." + if git clone --depth 1 "${repo}" "${MODULES_DIR}/${name}" 2>/dev/null; then + # Only keep modules that have Python wrapping + if [ -d "${MODULES_DIR}/${name}/wrapping" ] && [ -f "${MODULES_DIR}/${name}/pyproject.toml" ]; then + module_list+=("${name}") + else + rm -rf "${MODULES_DIR}/${name}" + fi + else + echo " WARNING: Failed to clone ${name}, skipping" + fi +done + +echo "=== ${#module_list[@]} modules with Python wrapping" + +# 4) Build ITK wheels +cd "${WORKDIR}/ITKPythonPackage" +echo "=== Building ITK Python wheels..." +pixi run -e "${PLATFORM_ENV}" -- python scripts/build_wheels.py \ + --platform-env "${PLATFORM_ENV}" \ + --itk-git-tag main \ + --itk-source-dir "${WORKDIR}/ITK" \ + --no-build-itk-tarball-cache \ + --no-use-sudo \ + --build-dir-root "${WORKDIR}/build" + +# Copy ITK wheels to dist +cp "${WORKDIR}"/build/dist/*.whl "${DIST_DIR}/" 2>/dev/null || true + +# 5) Build each remote module wheel +failed_modules=() +for name in "${module_list[@]}"; do + echo "=== Building ${name}..." + if pixi run -e "${PLATFORM_ENV}" -- python scripts/build_wheels.py \ + --platform-env "${PLATFORM_ENV}" \ + --itk-git-tag main \ + --itk-source-dir "${WORKDIR}/ITK" \ + --module-source-dir "${MODULES_DIR}/${name}" \ + --no-build-itk-tarball-cache \ + --no-use-sudo \ + --skip-itk-build \ + --skip-itk-wheel-build \ + --build-dir-root "${WORKDIR}/build" 2>&1; then + cp "${MODULES_DIR}/${name}"/dist/*.whl "${DIST_DIR}/" 2>/dev/null || true + else + echo " FAILED: ${name}" + failed_modules+=("${name}") + fi +done + +# 6) Summary +echo "" +echo "=== Build complete ===" +echo "Wheels: ${DIST_DIR}" +ls -1 "${DIST_DIR}"/*.whl 2>/dev/null | wc -l +echo "total wheels produced" + +if [ ${#failed_modules[@]} -gt 0 ]; then + echo "" + echo "Failed modules (${#failed_modules[@]}):" + printf ' %s\n' "${failed_modules[@]}" +fi diff --git a/scripts/build_all_latest_wheels.py b/scripts/build_all_latest_wheels.py new file mode 100755 index 00000000..88066497 --- /dev/null +++ b/scripts/build_all_latest_wheels.py @@ -0,0 +1,192 @@ +#!/usr/bin/env python3 +"""Build ITK + all remote module Python wheels from latest main branches. + +Usage:: + + python scripts/build_all_latest_wheels.py [--platform-env linux-py311] + python scripts/build_all_latest_wheels.py --help +""" + +import argparse +import re +import shutil +import subprocess +import sys +from datetime import datetime +from pathlib import Path + + +def run(cmd: list[str], **kwargs) -> subprocess.CompletedProcess: + print(f" $ {' '.join(str(c) for c in cmd)}") + return subprocess.run(cmd, check=True, **kwargs) + + +def clone(repo: str, dest: Path, branch: str | None = None) -> bool: + cmd = ["git", "clone", "--depth", "1"] + if branch: + cmd += ["--branch", branch] + cmd += [repo, str(dest)] + try: + run(cmd, capture_output=True) + return True + except subprocess.CalledProcessError: + return False + + +def parse_remote_modules(itk_dir: Path) -> list[tuple[str, str]]: + """Parse ITK remote .cmake files, return [(name, git_url), ...].""" + modules = [] + for rc in sorted((itk_dir / "Modules" / "Remote").glob("*.remote.cmake")): + name = rc.stem.replace(".remote", "") + text = rc.read_text() + m = re.search(r"GIT_REPOSITORY\s+(\S+)", text) + if m: + modules.append((name, m.group(1))) + return modules + + +def build_wheels( + ipp_dir: Path, + platform_env: str, + build_dir: Path, + itk_source: Path, + module_source: Path | None = None, + skip_itk: bool = False, +) -> bool: + cmd = [ + "pixi", + "run", + "-e", + platform_env, + "--", + "python", + "scripts/build_wheels.py", + "--platform-env", + platform_env, + "--itk-git-tag", + "main", + "--itk-source-dir", + str(itk_source), + "--no-build-itk-tarball-cache", + "--no-use-sudo", + "--build-dir-root", + str(build_dir), + ] + if module_source: + cmd += ["--module-source-dir", str(module_source)] + if skip_itk: + cmd += ["--skip-itk-build", "--skip-itk-wheel-build"] + + try: + run(cmd, cwd=ipp_dir) + return True + except subprocess.CalledProcessError: + return False + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument( + "--platform-env", default="linux-py311", help="Pixi environment name" + ) + parser.add_argument( + "--ipp-branch", + default="python-build-system", + help="ITKPythonPackage branch to use", + ) + parser.add_argument( + "--ipp-repo", + default="https://github.com/BRAINSia/ITKPythonPackage.git", + help="ITKPythonPackage git URL", + ) + parser.add_argument( + "--itk-repo", + default="https://github.com/InsightSoftwareConsortium/ITK.git", + help="ITK git URL", + ) + args = parser.parse_args() + + timestamp = datetime.now().strftime("%Y%m%d%H%M%S") + workdir = Path(f"/tmp/{timestamp}_LatestITKPython") + dist_dir = workdir / "dist" + dist_dir.mkdir(parents=True) + build_dir = workdir / "build" + + print(f"=== Build directory: {workdir}") + print(f"=== Platform: {args.platform_env}") + + # 1) Clone ITK + print("=== Cloning ITK (main)...") + itk_dir = workdir / "ITK" + clone(args.itk_repo, itk_dir, branch="main") + + # 2) Clone ITKPythonPackage + print(f"=== Cloning ITKPythonPackage ({args.ipp_branch})...") + ipp_dir = workdir / "ITKPythonPackage" + clone(args.ipp_repo, ipp_dir, branch=args.ipp_branch) + + # 3) Clone remote modules + print("=== Cloning remote modules...") + modules_dir = workdir / "modules" + modules_dir.mkdir() + remote_modules = parse_remote_modules(itk_dir) + + module_list: list[str] = [] + for name, repo in remote_modules: + mod_dir = modules_dir / name + if not clone(repo, mod_dir): + print(f" WARNING: Failed to clone {name}, skipping") + continue + # Keep only modules with Python wrapping + if (mod_dir / "wrapping").is_dir() and (mod_dir / "pyproject.toml").is_file(): + module_list.append(name) + else: + shutil.rmtree(mod_dir) + + print(f"=== {len(module_list)} modules with Python wrapping") + + # 4) Build ITK wheels + print("=== Building ITK Python wheels...") + if not build_wheels(ipp_dir, args.platform_env, build_dir, itk_dir): + print("FATAL: ITK wheel build failed") + sys.exit(1) + + # Copy ITK wheels to dist + for whl in (build_dir / "dist").glob("*.whl"): + shutil.copy2(whl, dist_dir) + + # 5) Build each remote module wheel + failed: list[str] = [] + for name in module_list: + print(f"=== Building {name}...") + mod_dir = modules_dir / name + if build_wheels( + ipp_dir, + args.platform_env, + build_dir, + itk_dir, + module_source=mod_dir, + skip_itk=True, + ): + for whl in (mod_dir / "dist").glob("*.whl"): + shutil.copy2(whl, dist_dir) + else: + print(f" FAILED: {name}") + failed.append(name) + + # 6) Summary + wheels = list(dist_dir.glob("*.whl")) + print() + print("=== Build complete ===") + print(f"Wheels: {dist_dir}") + print(f"{len(wheels)} total wheels produced") + + if failed: + print(f"\nFailed modules ({len(failed)}):") + for name in failed: + print(f" {name}") + sys.exit(1) + + +if __name__ == "__main__": + main() From 86c9a681c3c849ffef3df03defc344f7734510c4 Mon Sep 17 00:00:00 2001 From: Hans Johnson Date: Fri, 3 Apr 2026 16:19:39 -0500 Subject: [PATCH 26/27] ENH: Allow specifying ITK branch, tag, or hash for build-all scripts Add --itk-ref option to both shell and Python build-all-latest-wheels scripts. Defaults to "main" but accepts any git ref (branch name, tag like v6.0b02, or commit hash). The ITK clone is now a full clone (not shallow) to support arbitrary refs. Co-Authored-By: Claude Opus 4.6 (1M context) --- scripts/build-all-latest-wheels.sh | 42 +++++++++++++++++++++++------- scripts/build_all_latest_wheels.py | 23 +++++++++++----- 2 files changed, 49 insertions(+), 16 deletions(-) diff --git a/scripts/build-all-latest-wheels.sh b/scripts/build-all-latest-wheels.sh index 5df71ca3..948c379e 100755 --- a/scripts/build-all-latest-wheels.sh +++ b/scripts/build-all-latest-wheels.sh @@ -1,24 +1,46 @@ #!/bin/bash -# Build ITK + all remote module Python wheels from latest main branches. -# Usage: ./scripts/build-all-latest-wheels.sh [platform-env] -# Example: ./scripts/build-all-latest-wheels.sh linux-py311 +# Build ITK + all remote module Python wheels. +# Usage: ./scripts/build-all-latest-wheels.sh [options] +# --platform-env ENV Pixi environment (default: linux-py311) +# --itk-ref REF ITK branch, tag, or commit hash (default: main) +# --itk-repo URL ITK git URL +# --ipp-branch BRANCH ITKPythonPackage branch (default: python-build-system) +# --ipp-repo URL ITKPythonPackage git URL +# Example: +# ./scripts/build-all-latest-wheels.sh --itk-ref v6.0b02 --platform-env linux-py311 set -euo pipefail -PLATFORM_ENV="${1:-linux-py311}" -TIMESTAMP=$(date +%Y%m%d%H%M%S) -WORKDIR="/tmp/${TIMESTAMP}_LatestITKPython" -DIST_DIR="${WORKDIR}/dist" +# Defaults +PLATFORM_ENV="linux-py311" +ITK_REF="main" ITK_REPO="https://github.com/InsightSoftwareConsortium/ITK.git" IPP_REPO="https://github.com/BRAINSia/ITKPythonPackage.git" IPP_BRANCH="python-build-system" +while [[ $# -gt 0 ]]; do + case "$1" in + --platform-env) PLATFORM_ENV="$2"; shift 2 ;; + --itk-ref) ITK_REF="$2"; shift 2 ;; + --itk-repo) ITK_REPO="$2"; shift 2 ;; + --ipp-branch) IPP_BRANCH="$2"; shift 2 ;; + --ipp-repo) IPP_REPO="$2"; shift 2 ;; + *) echo "Unknown option: $1"; exit 1 ;; + esac +done + +TIMESTAMP=$(date +%Y%m%d%H%M%S) +WORKDIR="/tmp/${TIMESTAMP}_LatestITKPython" +DIST_DIR="${WORKDIR}/dist" + mkdir -p "${DIST_DIR}" echo "=== Build directory: ${WORKDIR}" echo "=== Platform: ${PLATFORM_ENV}" +echo "=== ITK ref: ${ITK_REF}" # 1) Clone ITK -echo "=== Cloning ITK (main)..." -git clone --depth 1 --branch main "${ITK_REPO}" "${WORKDIR}/ITK" +echo "=== Cloning ITK (${ITK_REF})..." +git clone "${ITK_REPO}" "${WORKDIR}/ITK" +git -C "${WORKDIR}/ITK" checkout "${ITK_REF}" # 2) Clone ITKPythonPackage echo "=== Cloning ITKPythonPackage (${IPP_BRANCH})..." @@ -70,7 +92,7 @@ for name in "${module_list[@]}"; do echo "=== Building ${name}..." if pixi run -e "${PLATFORM_ENV}" -- python scripts/build_wheels.py \ --platform-env "${PLATFORM_ENV}" \ - --itk-git-tag main \ + --itk-git-tag "${ITK_REF}" \ --itk-source-dir "${WORKDIR}/ITK" \ --module-source-dir "${MODULES_DIR}/${name}" \ --no-build-itk-tarball-cache \ diff --git a/scripts/build_all_latest_wheels.py b/scripts/build_all_latest_wheels.py index 88066497..a75ee44c 100755 --- a/scripts/build_all_latest_wheels.py +++ b/scripts/build_all_latest_wheels.py @@ -21,8 +21,10 @@ def run(cmd: list[str], **kwargs) -> subprocess.CompletedProcess: return subprocess.run(cmd, check=True, **kwargs) -def clone(repo: str, dest: Path, branch: str | None = None) -> bool: - cmd = ["git", "clone", "--depth", "1"] +def clone(repo: str, dest: Path, branch: str | None = None, depth: int | None = 1) -> bool: + cmd = ["git", "clone"] + if depth is not None: + cmd += ["--depth", str(depth)] if branch: cmd += ["--branch", branch] cmd += [repo, str(dest)] @@ -50,6 +52,7 @@ def build_wheels( platform_env: str, build_dir: Path, itk_source: Path, + itk_ref: str = "main", module_source: Path | None = None, skip_itk: bool = False, ) -> bool: @@ -64,7 +67,7 @@ def build_wheels( "--platform-env", platform_env, "--itk-git-tag", - "main", + itk_ref, "--itk-source-dir", str(itk_source), "--no-build-itk-tarball-cache", @@ -104,6 +107,11 @@ def main(): default="https://github.com/InsightSoftwareConsortium/ITK.git", help="ITK git URL", ) + parser.add_argument( + "--itk-ref", + default="main", + help="ITK branch, tag, or commit hash (default: main)", + ) args = parser.parse_args() timestamp = datetime.now().strftime("%Y%m%d%H%M%S") @@ -114,11 +122,13 @@ def main(): print(f"=== Build directory: {workdir}") print(f"=== Platform: {args.platform_env}") + print(f"=== ITK ref: {args.itk_ref}") # 1) Clone ITK - print("=== Cloning ITK (main)...") + print(f"=== Cloning ITK ({args.itk_ref})...") itk_dir = workdir / "ITK" - clone(args.itk_repo, itk_dir, branch="main") + clone(args.itk_repo, itk_dir, depth=None) + run(["git", "checkout", args.itk_ref], cwd=itk_dir) # 2) Clone ITKPythonPackage print(f"=== Cloning ITKPythonPackage ({args.ipp_branch})...") @@ -147,7 +157,7 @@ def main(): # 4) Build ITK wheels print("=== Building ITK Python wheels...") - if not build_wheels(ipp_dir, args.platform_env, build_dir, itk_dir): + if not build_wheels(ipp_dir, args.platform_env, build_dir, itk_dir, args.itk_ref): print("FATAL: ITK wheel build failed") sys.exit(1) @@ -165,6 +175,7 @@ def main(): args.platform_env, build_dir, itk_dir, + args.itk_ref, module_source=mod_dir, skip_itk=True, ): From 578e4384fc4e06bda1a78f4b940ad2fea710716c Mon Sep 17 00:00:00 2001 From: Hans Johnson Date: Fri, 3 Apr 2026 16:23:54 -0500 Subject: [PATCH 27/27] STYLE: Move build-all-latest-wheels scripts to Utilities/scripts Co-Authored-By: Claude Opus 4.6 (1M context) --- {scripts => Utilities/scripts}/build-all-latest-wheels.sh | 0 {scripts => Utilities/scripts}/build_all_latest_wheels.py | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename {scripts => Utilities/scripts}/build-all-latest-wheels.sh (100%) rename {scripts => Utilities/scripts}/build_all_latest_wheels.py (100%) diff --git a/scripts/build-all-latest-wheels.sh b/Utilities/scripts/build-all-latest-wheels.sh similarity index 100% rename from scripts/build-all-latest-wheels.sh rename to Utilities/scripts/build-all-latest-wheels.sh diff --git a/scripts/build_all_latest_wheels.py b/Utilities/scripts/build_all_latest_wheels.py similarity index 100% rename from scripts/build_all_latest_wheels.py rename to Utilities/scripts/build_all_latest_wheels.py