From 435b6b3b7b6d32148fc5c4ce430e715bfdae6ac9 Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Sat, 17 Sep 2022 09:06:03 +0200 Subject: [PATCH 01/27] Fix links to reference in documentation --- doc/usage.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/usage.rst b/doc/usage.rst index 2c10f62..23b61e5 100644 --- a/doc/usage.rst +++ b/doc/usage.rst @@ -1,6 +1,8 @@ Usage ===== +.. py:currentmodule:: clr_loader + Getting a runtime ----------------- From c1e337592f5bb7c1fced8e27dc65c408a0a8eb78 Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Sat, 17 Sep 2022 17:01:02 +0200 Subject: [PATCH 02/27] Switch to Furo theme and use custom step (#33) The "published" step uses an ages old version of Sphinx (2.2.4). This should also fix issues with links to referenced functions. --- .github/workflows/docs.yml | 8 +++++--- doc/conf.py | 2 +- doc/requirements.txt | 6 +++++- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index ed89bc2..bce19d4 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -7,9 +7,11 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v1 - - uses: ammaraskar/sphinx-action@master - with: - docs-folder: doc/ + - name: Build Sphinx documentation + run: | + pip install -r doc/requirements.txt + sphinx-build doc/ ./doc/_build/html/ + - name: Upload artifact # Automatically uploads an artifact from the './_site' directory by default uses: actions/upload-pages-artifact@v1 diff --git a/doc/conf.py b/doc/conf.py index 5f97ad9..dac323a 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -45,7 +45,7 @@ # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # -html_theme = "sphinx_rtd_theme" +html_theme = "furo" # 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, diff --git a/doc/requirements.txt b/doc/requirements.txt index 483a4e9..97147a4 100644 --- a/doc/requirements.txt +++ b/doc/requirements.txt @@ -1 +1,5 @@ -sphinx_rtd_theme +sphinx + +# Theme, force pygments update +furo>=2022.9.15 +pygments>=2.7 From 1df0f23d7b5fe557c6082b8006247466db1a7ebb Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Fri, 23 Sep 2022 07:34:31 +0200 Subject: [PATCH 03/27] Fix autodoc not loading clr_loader from the repository --- doc/conf.py | 42 +++++------------------------------------- 1 file changed, 5 insertions(+), 37 deletions(-) diff --git a/doc/conf.py b/doc/conf.py index dac323a..3e0f45d 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -1,34 +1,13 @@ -# Configuration file for the Sphinx documentation builder. -# -# This file only contains a selection of the most common options. For a full -# list see the documentation: -# https://www.sphinx-doc.org/en/master/usage/configuration.html - -# -- Path setup -------------------------------------------------------------- - -# 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('.')) - - -# -- Project information ----------------------------------------------------- - project = "clr-loader" copyright = "2022, Benedikt Reinartz" author = "Benedikt Reinartz" - -# -- General configuration --------------------------------------------------- - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. extensions = ["sphinx.ext.autodoc"] +# Add parent to path for autodoc +import sys, os +sys.path.append(os.path.abspath('..')) + # autodoc_typehints = "both" # Add any paths that contain templates here, relative to this directory. @@ -38,16 +17,5 @@ # directories to ignore when looking for source files. # This pattern also affects html_static_path and html_extra_path. exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] - - -# -- 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 = "furo" - -# 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_static_path = ["_static"] +html_static_path = [] From cba6ebfdcd33eda54a1ae9e9bc81be92a74904bf Mon Sep 17 00:00:00 2001 From: DongGeon Lee Date: Mon, 10 Oct 2022 19:06:10 +0900 Subject: [PATCH 04/27] Fix to find dotnet root on 64-bits darwin system (#37) --- clr_loader/util/find.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/clr_loader/util/find.py b/clr_loader/util/find.py index daad769..c163240 100644 --- a/clr_loader/util/find.py +++ b/clr_loader/util/find.py @@ -42,7 +42,10 @@ def find_dotnet_root() -> Path: prog_files = Path(prog_files) dotnet_root = prog_files / "dotnet" elif sys.platform == "darwin": - dotnet_root = Path("/usr/local/share/dotnet") + if sys.maxsize > 2**32: # is_64bits + dotnet_root = Path("/usr/local/share/dotnet/x64") + else: + dotnet_root = Path("/usr/local/share/dotnet") if dotnet_root is not None and dotnet_root.is_dir(): return dotnet_root From 9c24c89ceabc608ed100bf9f884f98d2f7fe36f1 Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Wed, 12 Oct 2022 20:07:43 +0200 Subject: [PATCH 05/27] Define self._handle up-front to prevent warning in __del__ Since initialization failures happen (usually) in `get_handle`, the instance would not have a proper `self._handle` defined and fail on `__del__` which checks for this field's value. --- clr_loader/hostfxr.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/clr_loader/hostfxr.py b/clr_loader/hostfxr.py index dce5c82..522fec5 100644 --- a/clr_loader/hostfxr.py +++ b/clr_loader/hostfxr.py @@ -13,6 +13,8 @@ class DotnetCoreRuntime(Runtime): def __init__(self, runtime_config: Path, dotnet_root: Path, **params: str): + self._handle = None + if _IS_SHUTDOWN: raise RuntimeError("Runtime can not be reinitialized") From 15ede715c5248164d1a6a6e4f5c921b83ab329b9 Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Wed, 12 Oct 2022 20:08:30 +0200 Subject: [PATCH 06/27] Allow loading libhostfxr directly from the dotnet_root This is a prerequisite to load self-contained components (which is still not supported upstream, though). --- clr_loader/ffi/__init__.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/clr_loader/ffi/__init__.py b/clr_loader/ffi/__init__.py index 208824f..035541e 100644 --- a/clr_loader/ffi/__init__.py +++ b/clr_loader/ffi/__init__.py @@ -16,6 +16,7 @@ def load_hostfxr(dotnet_root: Path): hostfxr_name = _get_dll_name("hostfxr") + dotnet_root = dotnet_root.absolute() # This will fail as soon as .NET hits version 10, but hopefully by then # we'll have a more robust way of finding the libhostfxr @@ -28,6 +29,11 @@ def load_hostfxr(dotnet_root: Path): except Exception: pass + try: + return ffi.dlopen(str(dotnet_root / hostfxr_name)) + except Exception: + pass + raise RuntimeError(f"Could not find a suitable hostfxr library in {dotnet_root}") From ba0a3535e7518fc36d530e52aae38b46b5bbf82f Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Fri, 14 Oct 2022 15:48:00 +0200 Subject: [PATCH 07/27] Format --- clr_loader/util/find.py | 2 +- doc/conf.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/clr_loader/util/find.py b/clr_loader/util/find.py index c163240..22ba843 100644 --- a/clr_loader/util/find.py +++ b/clr_loader/util/find.py @@ -42,7 +42,7 @@ def find_dotnet_root() -> Path: prog_files = Path(prog_files) dotnet_root = prog_files / "dotnet" elif sys.platform == "darwin": - if sys.maxsize > 2**32: # is_64bits + if sys.maxsize > 2**32: # is_64bits dotnet_root = Path("/usr/local/share/dotnet/x64") else: dotnet_root = Path("/usr/local/share/dotnet") diff --git a/doc/conf.py b/doc/conf.py index 3e0f45d..1ad2427 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -6,7 +6,8 @@ # Add parent to path for autodoc import sys, os -sys.path.append(os.path.abspath('..')) + +sys.path.append(os.path.abspath("..")) # autodoc_typehints = "both" From ba68d160173f508b89fc973fc1d5cc53e8dc052d Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Fri, 14 Oct 2022 15:49:19 +0200 Subject: [PATCH 08/27] Parse the FXR version to properly select the newest one --- clr_loader/ffi/__init__.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/clr_loader/ffi/__init__.py b/clr_loader/ffi/__init__.py index 035541e..23debae 100644 --- a/clr_loader/ffi/__init__.py +++ b/clr_loader/ffi/__init__.py @@ -1,6 +1,6 @@ import sys from pathlib import Path -from typing import Optional +from typing import Optional, Tuple import cffi # type: ignore @@ -23,7 +23,7 @@ def load_hostfxr(dotnet_root: Path): hostfxr_path = dotnet_root / "host" / "fxr" hostfxr_paths = hostfxr_path.glob(f"?.*/{hostfxr_name}") - for hostfxr_path in reversed(sorted(hostfxr_paths)): + for hostfxr_path in reversed(sorted(hostfxr_paths, key=_path_to_version)): try: return ffi.dlopen(str(hostfxr_path)) except Exception: @@ -61,6 +61,15 @@ def load_netfx(): return ffi.dlopen(str(path)) +def _path_to_version(path: Path) -> Tuple[int, int, int]: + name = path.parent.name + try: + res = list(map(int, name.split("."))) + return tuple(res + [0, 0, 0])[:3] + except Exception: + return (0, 0, 0) + + def _get_dll_name(name: str) -> str: if sys.platform == "win32": return f"{name}.dll" From 0e7b2f16a76773aaad20ddee56cdab13a6e8cb0a Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Fri, 14 Oct 2022 22:52:29 +0200 Subject: [PATCH 09/27] Split package build from testing (#39) --- .github/workflows/ci.yml | 57 ++++++++++++++++++++++++++++++++-------- pyproject.toml | 8 ++++-- 2 files changed, 52 insertions(+), 13 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 55f5d65..b4e25f9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,14 +7,42 @@ on: [push, pull_request] jobs: build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + - uses: actions/setup-dotnet@v1 + - uses: actions/setup-python@v4 + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install build + - name: Build + run: python -m build + - name: Upload source distribution + uses: actions/upload-artifact@v3 + with: + name: sdist + path: "dist/*.tar.gz" + if-no-files-found: error + - name: Upload wheel + uses: actions/upload-artifact@v3 + with: + name: wheel + path: "dist/*.whl" + if-no-files-found: error + + test: runs-on: ${{ matrix.os }} + needs: build strategy: matrix: os: [ubuntu-latest, windows-latest, macos-latest] python: ['3.10', '3.9', '3.8', '3.7'] # pypy3 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Setup .NET uses: actions/setup-dotnet@v1 @@ -22,19 +50,10 @@ jobs: dotnet-version: '6.0.x' - name: Set up Python ${{ matrix.python }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: python-version: ${{ matrix.python }} - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install pytest cffi - - - name: Build - run: | - pip install -e . - - name: Cache Mono if: runner.os == 'Windows' uses: actions/cache@v2 @@ -47,6 +66,22 @@ jobs: run: | choco install -y mono ${{ matrix.python == 'pypy3' && '--x86' || '' }} + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install pytest + + - name: Download wheel + uses: actions/download-artifact@v3 + with: + name: wheel + path: dist/ + + - name: Install wheel + shell: bash + run: | + pip install dist/*.whl + - name: Test with pytest run: | pytest diff --git a/pyproject.toml b/pyproject.toml index d344968..5491c06 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,12 +1,12 @@ [build-system] -requires = ["setuptools>=61", "wheel"] +requires = ["setuptools>=61", "setuptools_scm[toml]", "wheel"] build-backend = "setuptools.build_meta" [project] name = "clr_loader" description = "Generic pure Python loader for .NET runtimes" license = {text = "MIT"} -version = "0.2.3" +requires-python = ">=3.7" readme = "README.md" @@ -22,6 +22,8 @@ classifiers = [ "Operating System :: MacOS :: MacOS X", ] +dynamic = ["version"] + [[project.authors]] name = "Benedikt Reinartz" email = "filmor@gmail.com" @@ -37,6 +39,8 @@ package-data = {"clr_loader.ffi" = ["dlls/x86/*.dll", "dlls/amd64/*.dll"]} [tool.setuptools.packages.find] include = ["clr_loader*"] +[tool.setuptools_scm] + [tool.pytest.ini_options] xfail_strict = true testpaths = [ From 690a756757a41ab6c1e951655079ad148c89b415 Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Sat, 15 Oct 2022 09:39:16 +0200 Subject: [PATCH 10/27] Add deployment to CI --- .github/workflows/ci.yml | 42 +++++++++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b4e25f9..45d1f06 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,14 +23,8 @@ jobs: - name: Upload source distribution uses: actions/upload-artifact@v3 with: - name: sdist - path: "dist/*.tar.gz" - if-no-files-found: error - - name: Upload wheel - uses: actions/upload-artifact@v3 - with: - name: wheel - path: "dist/*.whl" + name: build-output + path: "dist/*" if-no-files-found: error test: @@ -74,7 +68,7 @@ jobs: - name: Download wheel uses: actions/download-artifact@v3 with: - name: wheel + name: build-output path: dist/ - name: Install wheel @@ -85,3 +79,33 @@ jobs: - name: Test with pytest run: | pytest + + deploy: + runs-on: ubuntu-latest + needs: [build, test] + + steps: + - name: Download artifacts + uses: actions/download-artifact@v3 + with: + name: build-output + path: dist/ + + - name: Deploy to Test PyPI + uses: pypa/gh-action-pypi-publish@release/v1 + if: startsWith(github.ref, 'refs/head/master') + with: + password: ${{ secrets.TEST_PYPI_API_TOKEN }} + repository_url: https://test.pypi.org/legacy/ + + - name: Release + uses: softprops/action-gh-release@v1 + if: startsWith(github.ref, 'refs/tags/v') + with: + files: dist/* + + - name: Deploy to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 + if: startsWith(github.ref, 'refs/tags/v') + with: + password: ${{ secrets.PYPI_API_TOKEN }} From c5d1a92892e871a9feb79630b981836bae795ac4 Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Tue, 3 Jan 2023 12:57:47 +0100 Subject: [PATCH 11/27] Run test for autogenerated config in subprocess (#47) Only a single version of a dotnet-core runtime can be loaded at a given time. This off-loads one of our tests to a subprocess (the same pattern would work if we did this for the other test). Could be cleaner, but this will do for now. --- tests/test_common.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tests/test_common.py b/tests/test_common.py index 1191102..5e5338d 100644 --- a/tests/test_common.py +++ b/tests/test_common.py @@ -57,6 +57,17 @@ def test_coreclr(example_netcore): def test_coreclr_autogenerated_runtimeconfig(example_netstandard): + from multiprocessing import get_context + + p = get_context("spawn").Process( + target=_do_test_coreclr_autogenerated_runtimeconfig, args=(example_netstandard,) + ) + p.start() + p.join() + p.close() + + +def _do_test_coreclr_autogenerated_runtimeconfig(example_netstandard): from clr_loader import get_coreclr coreclr = get_coreclr() From c6b464942fab7a2b2325864c51c75ab897d5f9f8 Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Tue, 3 Jan 2023 12:58:41 +0100 Subject: [PATCH 12/27] Adjust CI to only run once on pull requests --- .github/workflows/ci-arm.yml | 8 ++++---- .github/workflows/ci.yml | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci-arm.yml b/.github/workflows/ci-arm.yml index 0c308bd..c451f0f 100644 --- a/.github/workflows/ci-arm.yml +++ b/.github/workflows/ci-arm.yml @@ -1,9 +1,9 @@ -# This workflow will install Python dependencies, run tests and lint with a variety of Python versions -# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions - name: ARM64 Tests -on: [push, pull_request] +on: + push: + branches: master + pull_request: jobs: build: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 45d1f06..f6f9e75 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,9 +1,9 @@ -# This workflow will install Python dependencies, run tests and lint with a variety of Python versions -# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions - name: Python Tests -on: [push, pull_request] +on: + push: + branches: master + pull_request: jobs: build: From 717e797616c6306edff0dd32f8d78679e66d5ca7 Mon Sep 17 00:00:00 2001 From: Mohamed Koubaa Date: Tue, 3 Jan 2023 06:08:04 -0600 Subject: [PATCH 13/27] Add support for mono_set_dirs (#43) * add support for mono_set_dirs * add set_signal_chaining flag * add tests --- clr_loader/__init__.py | 20 ++++++++++++++++++++ clr_loader/ffi/mono.py | 5 +++++ clr_loader/mono.py | 15 +++++++++++++++ tests/test_common.py | 15 +++++++++++++++ 4 files changed, 55 insertions(+) diff --git a/clr_loader/__init__.py b/clr_loader/__init__.py index d0d8ff2..4b08148 100644 --- a/clr_loader/__init__.py +++ b/clr_loader/__init__.py @@ -30,6 +30,9 @@ def get_mono( sgen: bool = True, debug: bool = False, jit_options: Optional[Sequence[str]] = None, + assembly_dir: Optional[str] = None, + config_dir: Optional[str] = None, + set_signal_chaining: bool = False ) -> Runtime: """Get a Mono runtime instance @@ -48,6 +51,20 @@ def get_mono( Whether to initialise Mono debugging :param jit_options: "Command line options" passed to Mono's ``mono_jit_parse_options`` + :param assembly_dir: + The base directory for assemblies, passed to ``mono_set_dirs`` + :param config_dir: + The base directory for configuration files, passed to ``mono_set_dirs`` + :param set_signal_chaining: + Whether to enable signal chaining, passed to ``mono_set_signal_chaining``. + If it is enabled, the runtime saves the original signal handlers before + installing its own, and calls the original ones in the following cases: + - SIGSEGV/SIGABRT while executing native code + - SIGPROF + - SIGFPE + - SIGQUIT + - SIGUSR2 + This currently only works on POSIX platforms """ from .mono import Mono @@ -62,6 +79,9 @@ def get_mono( config_file=_maybe_path(config_file), global_config_file=_maybe_path(global_config_file), libmono=libmono, + assembly_dir=assembly_dir, + config_dir=config_dir, + set_signal_chaining=set_signal_chaining, ) return impl diff --git a/clr_loader/ffi/mono.py b/clr_loader/ffi/mono.py index ed48cff..c194393 100644 --- a/clr_loader/ffi/mono.py +++ b/clr_loader/ffi/mono.py @@ -39,5 +39,10 @@ MonoObject* mono_runtime_invoke(MonoMethod *method, void *obj, void **params, MonoObject **exc); void* mono_object_unbox(MonoObject *object); + +void mono_set_dirs(const char *assembly_dir, const char* config_dir); + +void mono_set_signal_chaining(bool chain_signals); + """ ) diff --git a/clr_loader/mono.py b/clr_loader/mono.py index fb8ab1b..158ddb7 100644 --- a/clr_loader/mono.py +++ b/clr_loader/mono.py @@ -24,6 +24,9 @@ def __init__( jit_options: Optional[Sequence[str]] = None, config_file: Optional[Path] = None, global_config_file: Optional[Path] = None, + assembly_dir: Optional[str] = None, + config_dir: Optional[str] = None, + set_signal_chaining: bool = False, ): self._assemblies: Dict[Path, Any] = {} @@ -33,6 +36,9 @@ def __init__( jit_options=jit_options, global_config_file=optional_path_as_string(global_config_file), libmono=libmono, + assembly_dir=assembly_dir, + config_dir=config_dir, + set_signal_chaining=set_signal_chaining, ) if domain is None: @@ -121,11 +127,17 @@ def initialize( jit_options: Optional[Sequence[str]] = None, config_file: Optional[str] = None, global_config_file: Optional[str] = None, + assembly_dir: Optional[str] = None, + config_dir: Optional[str] = None, + set_signal_chaining: bool = False, ) -> str: global _MONO, _ROOT_DOMAIN if _MONO is None: _MONO = load_mono(libmono) + if assembly_dir is not None and config_dir is not None: + _MONO.mono_set_dirs(assembly_dir, config_dir) + # Load in global config (i.e /etc/mono/config) global_encoded = global_config_file or ffi.NULL _MONO.mono_config_parse(global_encoded) @@ -143,6 +155,9 @@ def initialize( else: options = [] + if set_signal_chaining: + _MONO.mono_set_signal_chaining(True) + if debug: _MONO.mono_debug_init(_MONO.MONO_DEBUG_FORMAT_MONO) diff --git a/tests/test_common.py b/tests/test_common.py index 5e5338d..f42020a 100644 --- a/tests/test_common.py +++ b/tests/test_common.py @@ -46,6 +46,21 @@ def test_mono_debug(example_netstandard): run_tests(asm) +def test_mono_signal_chaining(example_netstandard): + from clr_loader import get_mono + + mono = get_mono(set_signal_chaining=True) + asm = mono.get_assembly(example_netstandard / "example.dll") + + run_tests(asm) + +def test_mono_set_dir(example_netstandard): + from clr_loader import get_mono + + mono = get_mono(assembly_dir="/usr/lib", config_dir="/etc") + asm = mono.get_assembly(example_netstandard / "example.dll") + + run_tests(asm) def test_coreclr(example_netcore): from clr_loader import get_coreclr From a56d77cd98c145e65fb58bd510b108ac1614533c Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Tue, 3 Jan 2023 13:08:24 +0100 Subject: [PATCH 14/27] Fix macOS dotnet root discovery (#45) --- clr_loader/util/find.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/clr_loader/util/find.py b/clr_loader/util/find.py index 22ba843..d5d7b89 100644 --- a/clr_loader/util/find.py +++ b/clr_loader/util/find.py @@ -1,5 +1,5 @@ import os -import os.path +import platform import shutil import sys from pathlib import Path @@ -42,7 +42,8 @@ def find_dotnet_root() -> Path: prog_files = Path(prog_files) dotnet_root = prog_files / "dotnet" elif sys.platform == "darwin": - if sys.maxsize > 2**32: # is_64bits + if "ARM64" in os.uname().version and platform.machine() == "x86_64": + # Apple Silicon in Rosetta 2 mode dotnet_root = Path("/usr/local/share/dotnet/x64") else: dotnet_root = Path("/usr/local/share/dotnet") From 79d6c6792ebc09e43d514a3ce554b32a89a2eb19 Mon Sep 17 00:00:00 2001 From: Mohamed Koubaa Date: Fri, 13 Jan 2023 04:52:54 -0600 Subject: [PATCH 15/27] fix mono set dirs (#48) * fix mono set dirs * fix path --- clr_loader/__init__.py | 2 +- clr_loader/mono.py | 2 +- clr_loader/util/find.py | 11 +++++++---- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/clr_loader/__init__.py b/clr_loader/__init__.py index 4b08148..aa604ad 100644 --- a/clr_loader/__init__.py +++ b/clr_loader/__init__.py @@ -70,7 +70,7 @@ def get_mono( libmono = _maybe_path(libmono) if libmono is None: - libmono = find_libmono(sgen=sgen) + libmono = find_libmono(sgen=sgen, assembly_dir=assembly_dir) impl = Mono( # domain=domain, diff --git a/clr_loader/mono.py b/clr_loader/mono.py index 158ddb7..7c3f20d 100644 --- a/clr_loader/mono.py +++ b/clr_loader/mono.py @@ -136,7 +136,7 @@ def initialize( _MONO = load_mono(libmono) if assembly_dir is not None and config_dir is not None: - _MONO.mono_set_dirs(assembly_dir, config_dir) + _MONO.mono_set_dirs(assembly_dir.encode("utf8"), config_dir.encode("utf8")) # Load in global config (i.e /etc/mono/config) global_encoded = global_config_file or ffi.NULL diff --git a/clr_loader/util/find.py b/clr_loader/util/find.py index d5d7b89..6ef7bc3 100644 --- a/clr_loader/util/find.py +++ b/clr_loader/util/find.py @@ -105,7 +105,7 @@ def find_runtimes() -> Iterator[DotnetCoreRuntimeSpec]: return find_runtimes_in_root(dotnet_root) -def find_libmono(*, sgen: bool = True) -> Path: +def find_libmono(*, assembly_dir: str = None, sgen: bool = True) -> Path: """Find a suitable libmono dynamic library On Windows and macOS, we check the default installation directories. @@ -137,9 +137,12 @@ def find_libmono(*, sgen: bool = True) -> Path: ) else: - from ctypes.util import find_library - - path = find_library(unix_name) + if assembly_dir == None: + from ctypes.util import find_library + path = find_library(unix_name) + else: + libname = "lib" + unix_name + ".so" + path = Path(assembly_dir) / "lib" / libname if path is None: raise RuntimeError("Could not find libmono") From 7dd9b463099425087f4de51c7a68b365a4612344 Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Mon, 7 Aug 2023 14:10:46 +0200 Subject: [PATCH 16/27] Add Python 3.11 to CI --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f6f9e75..0c6749e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,7 +33,7 @@ jobs: strategy: matrix: os: [ubuntu-latest, windows-latest, macos-latest] - python: ['3.10', '3.9', '3.8', '3.7'] # pypy3 + python: ['3.11', '3.10', '3.9', '3.8', '3.7'] # pypy3 steps: - uses: actions/checkout@v3 From d8f51e9e28f41f2a495327e7cbecb50edd6af243 Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Mon, 7 Aug 2023 14:33:45 +0200 Subject: [PATCH 17/27] Drop CI for EOLd Python 3.7 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0c6749e..41f4e0c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,7 +33,7 @@ jobs: strategy: matrix: os: [ubuntu-latest, windows-latest, macos-latest] - python: ['3.11', '3.10', '3.9', '3.8', '3.7'] # pypy3 + python: ['3.11', '3.10', '3.9', '3.8'] # pypy3 steps: - uses: actions/checkout@v3 From 63d7f698d3be00bd1f609545e12f87cc3c549c42 Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Mon, 7 Aug 2023 14:39:44 +0200 Subject: [PATCH 18/27] Fix handling of non-ASCII assembly paths on .NET Framework (#62) --- netfx_loader/ClrLoader.cs | 6 +++--- tests/test_common.py | 35 +++++++++++++++++++++++++++-------- 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/netfx_loader/ClrLoader.cs b/netfx_loader/ClrLoader.cs index e8b2767..af89cee 100644 --- a/netfx_loader/ClrLoader.cs +++ b/netfx_loader/ClrLoader.cs @@ -51,9 +51,9 @@ public static IntPtr CreateAppDomain( [DllExport("pyclr_get_function", CallingConvention.Cdecl)] public static IntPtr GetFunction( IntPtr domain, - [MarshalAs(UnmanagedType.LPStr)] string assemblyPath, - [MarshalAs(UnmanagedType.LPStr)] string typeName, - [MarshalAs(UnmanagedType.LPStr)] string function + [MarshalAs(UnmanagedType.LPUTF8Str)] string assemblyPath, + [MarshalAs(UnmanagedType.LPUTF8Str)] string typeName, + [MarshalAs(UnmanagedType.LPUTF8Str)] string function ) { try diff --git a/tests/test_common.py b/tests/test_common.py index f42020a..250c290 100644 --- a/tests/test_common.py +++ b/tests/test_common.py @@ -1,3 +1,4 @@ +import shutil import pytest from subprocess import check_call import os @@ -24,7 +25,7 @@ def build_example(tmpdir_factory, framework): return out -def test_mono(example_netstandard): +def test_mono(example_netstandard: Path): from clr_loader import get_mono mono = get_mono() @@ -33,7 +34,7 @@ def test_mono(example_netstandard): run_tests(asm) -def test_mono_debug(example_netstandard): +def test_mono_debug(example_netstandard: Path): from clr_loader import get_mono mono = get_mono( @@ -46,7 +47,8 @@ def test_mono_debug(example_netstandard): run_tests(asm) -def test_mono_signal_chaining(example_netstandard): + +def test_mono_signal_chaining(example_netstandard: Path): from clr_loader import get_mono mono = get_mono(set_signal_chaining=True) @@ -54,7 +56,8 @@ def test_mono_signal_chaining(example_netstandard): run_tests(asm) -def test_mono_set_dir(example_netstandard): + +def test_mono_set_dir(example_netstandard: Path): from clr_loader import get_mono mono = get_mono(assembly_dir="/usr/lib", config_dir="/etc") @@ -62,7 +65,8 @@ def test_mono_set_dir(example_netstandard): run_tests(asm) -def test_coreclr(example_netcore): + +def test_coreclr(example_netcore: Path): from clr_loader import get_coreclr coreclr = get_coreclr(runtime_config=example_netcore / "example.runtimeconfig.json") @@ -71,7 +75,7 @@ def test_coreclr(example_netcore): run_tests(asm) -def test_coreclr_autogenerated_runtimeconfig(example_netstandard): +def test_coreclr_autogenerated_runtimeconfig(example_netstandard: Path): from multiprocessing import get_context p = get_context("spawn").Process( @@ -82,7 +86,7 @@ def test_coreclr_autogenerated_runtimeconfig(example_netstandard): p.close() -def _do_test_coreclr_autogenerated_runtimeconfig(example_netstandard): +def _do_test_coreclr_autogenerated_runtimeconfig(example_netstandard: Path): from clr_loader import get_coreclr coreclr = get_coreclr() @@ -94,9 +98,24 @@ def _do_test_coreclr_autogenerated_runtimeconfig(example_netstandard): @pytest.mark.skipif( sys.platform != "win32", reason=".NET Framework only exists on Windows" ) -def test_netfx(example_netstandard): +def test_netfx(example_netstandard: Path): + from clr_loader import get_netfx + + netfx = get_netfx() + asm = netfx.get_assembly(example_netstandard / "example.dll") + + run_tests(asm) + + +@pytest.mark.skipif( + sys.platform != "win32", reason=".NET Framework only exists on Windows" +) +def test_netfx_chinese_path(example_netstandard: Path, tmpdir_factory): from clr_loader import get_netfx + tmp_path = Path(tmpdir_factory.mktemp("example-中国")) + shutil.copytree(example_netstandard, tmp_path, dirs_exist_ok=True) + netfx = get_netfx() asm = netfx.get_assembly(os.path.join(example_netstandard, "example.dll")) From 000bc780b33b5dbb3f0c1891776fda0971cc2df2 Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Mon, 7 Aug 2023 15:21:26 +0200 Subject: [PATCH 19/27] Delay actually loading the runtime to fix property setting (#63) * Delay actually loading the runtime to fix property setting * Launch test for properties in separate process --- clr_loader/hostfxr.py | 20 +++++++++----------- tests/test_common.py | 21 ++++++++++++++++++--- 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/clr_loader/hostfxr.py b/clr_loader/hostfxr.py index 522fec5..225b4c7 100644 --- a/clr_loader/hostfxr.py +++ b/clr_loader/hostfxr.py @@ -20,9 +20,8 @@ def __init__(self, runtime_config: Path, dotnet_root: Path, **params: str): self._dotnet_root = Path(dotnet_root) self._dll = load_hostfxr(self._dotnet_root) - self._is_initialized = False self._handle = _get_handle(self._dll, self._dotnet_root, runtime_config) - self._load_func = _get_load_func(self._dll, self._handle) + self._load_func = None for key, value in params.items(): self[key] = value @@ -36,7 +35,7 @@ def dotnet_root(self) -> Path: @property def is_initialized(self) -> bool: - return self._is_initialized + return self._load_func is not None @property def is_shutdown(self) -> bool: @@ -81,10 +80,15 @@ def __iter__(self) -> Generator[Tuple[str, str], None, None]: for i in range(size_ptr[0]): yield (decode(keys_ptr[i]), decode(values_ptr[i])) + def _get_load_func(self): + if self._load_func is None: + self._load_func = _get_load_func(self._dll, self._handle) + + return self._load_func + def _get_callable(self, assembly_path: StrOrPath, typename: str, function: str): # TODO: Maybe use coreclr_get_delegate as well, supported with newer API # versions of hostfxr - self._is_initialized = True # Append assembly name to typename assembly_path = Path(assembly_path) @@ -92,7 +96,7 @@ def _get_callable(self, assembly_path: StrOrPath, typename: str, function: str): typename = f"{typename}, {assembly_name}" delegate_ptr = ffi.new("void**") - res = self._load_func( + res = self._get_load_func()( encode(str(assembly_path)), encode(typename), encode(function), @@ -103,12 +107,6 @@ def _get_callable(self, assembly_path: StrOrPath, typename: str, function: str): check_result(res) return ffi.cast("component_entry_point_fn", delegate_ptr[0]) - def _check_initialized(self) -> None: - if self._handle is None: - raise RuntimeError("Runtime is shut down") - elif not self._is_initialized: - raise RuntimeError("Runtime is not initialized") - def shutdown(self) -> None: if self._handle is not None: self._dll.hostfxr_close(self._handle) diff --git a/tests/test_common.py b/tests/test_common.py index 250c290..a33dec0 100644 --- a/tests/test_common.py +++ b/tests/test_common.py @@ -18,7 +18,7 @@ def example_netcore(tmpdir_factory): def build_example(tmpdir_factory, framework): out = Path(tmpdir_factory.mktemp(f"example-{framework}")) - proj_path = Path(__file__).parent.parent / "example" + proj_path = Path(__file__).parent.parent / "example" / "example.csproj" check_call(["dotnet", "build", str(proj_path), "-o", str(out), "-f", framework]) @@ -75,6 +75,19 @@ def test_coreclr(example_netcore: Path): run_tests(asm) +def test_coreclr_properties(example_netcore: Path): + from multiprocessing import get_context + + p = get_context("spawn").Process( + target=_do_test_coreclr_autogenerated_runtimeconfig, + args=(example_netstandard,), + kwargs=dict(properties=dict(APP_CONTEXT_BASE_DIRECTORY=str(example_netcore))), + ) + p.start() + p.join() + p.close() + + def test_coreclr_autogenerated_runtimeconfig(example_netstandard: Path): from multiprocessing import get_context @@ -86,10 +99,12 @@ def test_coreclr_autogenerated_runtimeconfig(example_netstandard: Path): p.close() -def _do_test_coreclr_autogenerated_runtimeconfig(example_netstandard: Path): +def _do_test_coreclr_autogenerated_runtimeconfig( + example_netstandard: Path, **properties +): from clr_loader import get_coreclr - coreclr = get_coreclr() + coreclr = get_coreclr(properties=properties) asm = coreclr.get_assembly(example_netstandard / "example.dll") run_tests(asm) From 70e2c72da9db0c769df1df195891da5c74a55dd5 Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Fri, 16 Dec 2022 16:33:59 +0100 Subject: [PATCH 20/27] Fix parameter passing for .NET Framework domains --- clr_loader/netfx.py | 11 +++++++++-- netfx_loader/ClrLoader.cs | 2 ++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/clr_loader/netfx.py b/clr_loader/netfx.py index 24460ca..4efe841 100644 --- a/clr_loader/netfx.py +++ b/clr_loader/netfx.py @@ -14,13 +14,15 @@ def __init__( ): initialize() if config_file is not None: - config_file_s = str(config_file) + config_file_s = str(config_file).encode("utf8") else: config_file_s = ffi.NULL + domain_s = domain.encode("utf8") if domain else ffi.NULL + self._domain_name = domain self._config_file = config_file - self._domain = _FW.pyclr_create_appdomain(domain or ffi.NULL, config_file_s) + self._domain = _FW.pyclr_create_appdomain(domain_s, config_file_s) def info(self) -> RuntimeInfo: return RuntimeInfo( @@ -41,6 +43,11 @@ def _get_callable(self, assembly_path: StrOrPath, typename: str, function: str): function.encode("utf8"), ) + if func == ffi.NULL: + raise RuntimeError( + f"Failed to resolve {typename}.{function} from {assembly_path}" + ) + return func def shutdown(self): diff --git a/netfx_loader/ClrLoader.cs b/netfx_loader/ClrLoader.cs index af89cee..32b4c01 100644 --- a/netfx_loader/ClrLoader.cs +++ b/netfx_loader/ClrLoader.cs @@ -32,8 +32,10 @@ public static IntPtr CreateAppDomain( { var setup = new AppDomainSetup { + ApplicationBase = AppDomain.CurrentDomain.BaseDirectory, ConfigurationFile = configFile }; + Print($"Base: {AppDomain.CurrentDomain.BaseDirectory}"); var domain = AppDomain.CreateDomain(name, null, setup); Print($"Located domain {domain}"); From 05235b979a6fa169898318af7d752428a1bbd850 Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Fri, 16 Dec 2022 16:40:08 +0100 Subject: [PATCH 21/27] Add unit test for using a separate domain --- tests/test_common.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/test_common.py b/tests/test_common.py index a33dec0..3cba3cd 100644 --- a/tests/test_common.py +++ b/tests/test_common.py @@ -137,6 +137,18 @@ def test_netfx_chinese_path(example_netstandard: Path, tmpdir_factory): run_tests(asm) +@pytest.mark.skipif( + sys.platform != "win32", reason=".NET Framework only exists on Windows" +) +def test_netfx_separate_domain(example_netstandard): + from clr_loader import get_netfx + + netfx = get_netfx(domain="some_domain") + asm = netfx.get_assembly(os.path.join(example_netstandard, "example.dll")) + + run_tests(asm) + + def run_tests(asm): func = asm.get_function("Example.TestClass", "Test") test_data = b"testy mctestface" From 59f47f9088da9cf999439bb15ff7ac131633fec7 Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Mon, 7 Aug 2023 16:22:10 +0200 Subject: [PATCH 22/27] Move netfx tests to individual subprocesses --- tests/test_common.py | 53 ++++++++++++++++++-------------------------- 1 file changed, 22 insertions(+), 31 deletions(-) diff --git a/tests/test_common.py b/tests/test_common.py index 3cba3cd..8a9e36d 100644 --- a/tests/test_common.py +++ b/tests/test_common.py @@ -76,27 +76,15 @@ def test_coreclr(example_netcore: Path): def test_coreclr_properties(example_netcore: Path): - from multiprocessing import get_context - - p = get_context("spawn").Process( - target=_do_test_coreclr_autogenerated_runtimeconfig, - args=(example_netstandard,), - kwargs=dict(properties=dict(APP_CONTEXT_BASE_DIRECTORY=str(example_netcore))), + run_in_subprocess( + _do_test_coreclr_autogenerated_runtimeconfig, + example_netstandard, + properties=dict(APP_CONTEXT_BASE_DIRECTORY=str(example_netcore)), ) - p.start() - p.join() - p.close() def test_coreclr_autogenerated_runtimeconfig(example_netstandard: Path): - from multiprocessing import get_context - - p = get_context("spawn").Process( - target=_do_test_coreclr_autogenerated_runtimeconfig, args=(example_netstandard,) - ) - p.start() - p.join() - p.close() + run_in_subprocess(_do_test_coreclr_autogenerated_runtimeconfig, example_netstandard) def _do_test_coreclr_autogenerated_runtimeconfig( @@ -114,37 +102,31 @@ def _do_test_coreclr_autogenerated_runtimeconfig( sys.platform != "win32", reason=".NET Framework only exists on Windows" ) def test_netfx(example_netstandard: Path): - from clr_loader import get_netfx - - netfx = get_netfx() - asm = netfx.get_assembly(example_netstandard / "example.dll") - - run_tests(asm) + run_in_subprocess(_do_test_netfx, example_netstandard) @pytest.mark.skipif( sys.platform != "win32", reason=".NET Framework only exists on Windows" ) def test_netfx_chinese_path(example_netstandard: Path, tmpdir_factory): - from clr_loader import get_netfx - tmp_path = Path(tmpdir_factory.mktemp("example-中国")) shutil.copytree(example_netstandard, tmp_path, dirs_exist_ok=True) - netfx = get_netfx() - asm = netfx.get_assembly(os.path.join(example_netstandard, "example.dll")) - - run_tests(asm) + run_in_subprocess(_do_test_netfx, tmp_path) @pytest.mark.skipif( sys.platform != "win32", reason=".NET Framework only exists on Windows" ) def test_netfx_separate_domain(example_netstandard): + run_in_subprocess(_do_test_netfx, example_netstandard, domain="some domain") + + +def _do_test_netfx(example_netstandard, **kwargs): from clr_loader import get_netfx - netfx = get_netfx(domain="some_domain") - asm = netfx.get_assembly(os.path.join(example_netstandard, "example.dll")) + netfx = get_netfx(**kwargs) + asm = netfx.get_assembly(example_netstandard / "example.dll") run_tests(asm) @@ -154,3 +136,12 @@ def run_tests(asm): test_data = b"testy mctestface" res = func(test_data) assert res == len(test_data) + + +def run_in_subprocess(func, *args, **kwargs): + from multiprocessing import get_context + + p = get_context("spawn").Process(target=func, args=args, kwargs=kwargs) + p.start() + p.join() + p.close() From f2058b49ee08817c373474d28c637f36feec4fa1 Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Tue, 21 Nov 2023 12:22:31 +0100 Subject: [PATCH 23/27] Ensure that an uninitialised NetFx object does not fail in shutdown --- clr_loader/netfx.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/clr_loader/netfx.py b/clr_loader/netfx.py index 4efe841..4d46b37 100644 --- a/clr_loader/netfx.py +++ b/clr_loader/netfx.py @@ -12,6 +12,8 @@ class NetFx(Runtime): def __init__( self, domain: Optional[str] = None, config_file: Optional[Path] = None ): + self._domain = None + initialize() if config_file is not None: config_file_s = str(config_file).encode("utf8") From 3e2dff02bc08a840c74c0910e0303c92c8a7c306 Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Wed, 10 Jul 2024 09:23:39 +0200 Subject: [PATCH 24/27] Add ruff formatting and linting (#65) --- .github/workflows/ci.yml | 14 ++++++++++++++ clr_loader/__init__.py | 2 +- clr_loader/mono.py | 3 ++- clr_loader/util/find.py | 3 ++- doc/conf.py | 7 ++++--- tests/test_common.py | 1 - 6 files changed, 23 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 41f4e0c..3495443 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,6 +27,20 @@ jobs: path: "dist/*" if-no-files-found: error + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + fetch-depths: 0 + - uses: actions/setup-python@v4 + - name: Install Ruff + run: pip install ruff + - name: Check format + run: ruff format --check + - name: Check lints + run: ruff check + test: runs-on: ${{ matrix.os }} needs: build diff --git a/clr_loader/__init__.py b/clr_loader/__init__.py index aa604ad..71eb09d 100644 --- a/clr_loader/__init__.py +++ b/clr_loader/__init__.py @@ -32,7 +32,7 @@ def get_mono( jit_options: Optional[Sequence[str]] = None, assembly_dir: Optional[str] = None, config_dir: Optional[str] = None, - set_signal_chaining: bool = False + set_signal_chaining: bool = False, ) -> Runtime: """Get a Mono runtime instance diff --git a/clr_loader/mono.py b/clr_loader/mono.py index 7c3f20d..1899ea3 100644 --- a/clr_loader/mono.py +++ b/clr_loader/mono.py @@ -86,7 +86,8 @@ class MethodDesc: def __init__(self, typename, function): self._desc = f"{typename}:{function}" self._ptr = _MONO.mono_method_desc_new( - self._desc.encode("utf8"), 1 # include_namespace + self._desc.encode("utf8"), + 1, # include_namespace ) def search(self, image): diff --git a/clr_loader/util/find.py b/clr_loader/util/find.py index 6ef7bc3..65bc7ac 100644 --- a/clr_loader/util/find.py +++ b/clr_loader/util/find.py @@ -137,8 +137,9 @@ def find_libmono(*, assembly_dir: str = None, sgen: bool = True) -> Path: ) else: - if assembly_dir == None: + if assembly_dir is None: from ctypes.util import find_library + path = find_library(unix_name) else: libname = "lib" + unix_name + ".so" diff --git a/doc/conf.py b/doc/conf.py index 1ad2427..385629c 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -1,3 +1,6 @@ +import sys +from pathlib import Path + project = "clr-loader" copyright = "2022, Benedikt Reinartz" author = "Benedikt Reinartz" @@ -5,9 +8,7 @@ extensions = ["sphinx.ext.autodoc"] # Add parent to path for autodoc -import sys, os - -sys.path.append(os.path.abspath("..")) +sys.path.append(str(Path("..").absolute())) # autodoc_typehints = "both" diff --git a/tests/test_common.py b/tests/test_common.py index 8a9e36d..139f192 100644 --- a/tests/test_common.py +++ b/tests/test_common.py @@ -1,7 +1,6 @@ import shutil import pytest from subprocess import check_call -import os import sys from pathlib import Path From 8e6dcd3cccc9bc98c877b9464f7f2000a108a49b Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Thu, 12 Dec 2024 20:53:06 +0100 Subject: [PATCH 25/27] Use uv and test 3.13 and 3.12 (#72) --- .github/workflows/ci.yml | 26 +++--- pyproject.toml | 10 ++- uv.lock | 174 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 194 insertions(+), 16 deletions(-) create mode 100644 uv.lock diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3495443..ae40be9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,13 +13,9 @@ jobs: with: fetch-depth: 0 - uses: actions/setup-dotnet@v1 - - uses: actions/setup-python@v4 - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install build + - uses: astral-sh/setup-uv@v4 - name: Build - run: python -m build + run: uv build - name: Upload source distribution uses: actions/upload-artifact@v3 with: @@ -33,9 +29,9 @@ jobs: - uses: actions/checkout@v3 with: fetch-depths: 0 - - uses: actions/setup-python@v4 + - uses: astral-sh/setup-uv@v4 - name: Install Ruff - run: pip install ruff + run: uv tool install ruff - name: Check format run: ruff format --check - name: Check lints @@ -46,8 +42,8 @@ jobs: needs: build strategy: matrix: - os: [ubuntu-latest, windows-latest, macos-latest] - python: ['3.11', '3.10', '3.9', '3.8'] # pypy3 + os: [ubuntu-22.04, windows-latest, macos-13] + python: ['3.13', '3.12', '3.11', '3.10', '3.9', '3.8'] # pypy3 steps: - uses: actions/checkout@v3 @@ -58,7 +54,7 @@ jobs: dotnet-version: '6.0.x' - name: Set up Python ${{ matrix.python }} - uses: actions/setup-python@v4 + uses: astral-sh/setup-uv@v4 with: python-version: ${{ matrix.python }} @@ -76,8 +72,8 @@ jobs: - name: Install dependencies run: | - python -m pip install --upgrade pip - pip install pytest + uv venv + uv pip install pytest - name: Download wheel uses: actions/download-artifact@v3 @@ -88,11 +84,11 @@ jobs: - name: Install wheel shell: bash run: | - pip install dist/*.whl + uv pip install dist/*.whl - name: Test with pytest run: | - pytest + uv run pytest deploy: runs-on: ubuntu-latest diff --git a/pyproject.toml b/pyproject.toml index 5491c06..94857e4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,7 +10,10 @@ requires-python = ">=3.7" readme = "README.md" -dependencies = ["cffi>=1.13"] +dependencies = [ + "cffi >= 1.13; python_version <= '3.8'", + "cffi >= 1.17; python_version >= '3.8'", +] classifiers = [ "Development Status :: 4 - Beta", @@ -32,6 +35,11 @@ email = "filmor@gmail.com" Sources = "https://github.com/pythonnet/clr-loader" Documentation = "https://pythonnet.github.io/clr-loader/" +[optional-dependencies] +dev = [ + "pytest" +] + [tool.setuptools] zip-safe = false package-data = {"clr_loader.ffi" = ["dlls/x86/*.dll", "dlls/amd64/*.dll"]} diff --git a/uv.lock b/uv.lock new file mode 100644 index 0000000..60809e6 --- /dev/null +++ b/uv.lock @@ -0,0 +1,174 @@ +version = 1 +requires-python = ">=3.7" +resolution-markers = [ + "python_full_version < '3.8'", + "python_full_version == '3.8.*'", + "python_full_version >= '3.9'", +] + +[[package]] +name = "cffi" +version = "1.15.1" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.8'", +] +dependencies = [ + { name = "pycparser", marker = "python_full_version < '3.8'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/2b/a8/050ab4f0c3d4c1b8aaa805f70e26e84d0e27004907c5b8ecc1d31815f92a/cffi-1.15.1.tar.gz", hash = "sha256:d400bfb9a37b1351253cb402671cea7e89bdecc294e8016a707f6d1d8ac934f9", size = 508501 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e8/ff/c4b7a358526f231efa46a375c959506c87622fb4a2c5726e827c55e6adf2/cffi-1.15.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:39d39875251ca8f612b6f33e6b1195af86d1b3e60086068be9cc053aa4376e21", size = 179233 }, + { url = "https://files.pythonhosted.org/packages/ea/be/c4ad40ad441ac847b67c7a37284ae3c58f39f3e638c6b0f85fb662233825/cffi-1.15.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:285d29981935eb726a4399badae8f0ffdff4f5050eaa6d0cfc3f64b857b77185", size = 174280 }, + { url = "https://files.pythonhosted.org/packages/ed/a3/c5f01988ddb70a187c3e6112152e01696188c9f8a4fa4c68aa330adbb179/cffi-1.15.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3eb6971dcff08619f8d91607cfc726518b6fa2a9eba42856be181c6d0d9515fd", size = 421712 }, + { url = "https://files.pythonhosted.org/packages/ef/41/19da352d341963d29a33bdb28433ba94c05672fb16155f794fad3fd907b0/cffi-1.15.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:21157295583fe8943475029ed5abdcf71eb3911894724e360acff1d61c1d54bc", size = 449886 }, + { url = "https://files.pythonhosted.org/packages/af/da/9441d56d7dd19d07dcc40a2a5031a1f51c82a27cee3705edf53dadcac398/cffi-1.15.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5635bd9cb9731e6d4a1132a498dd34f764034a8ce60cef4f5319c0541159392f", size = 450520 }, + { url = "https://files.pythonhosted.org/packages/aa/02/ab15b3aa572759df752491d5fa0f74128cd14e002e8e3257c1ab1587810b/cffi-1.15.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2012c72d854c2d03e45d06ae57f40d78e5770d252f195b93f581acf3ba44496e", size = 446015 }, + { url = "https://files.pythonhosted.org/packages/88/89/c34caf63029fb7628ec2ebd5c88ae0c9bd17db98c812e4065a4d020ca41f/cffi-1.15.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd86c085fae2efd48ac91dd7ccffcfc0571387fe1193d33b6394db7ef31fe2a4", size = 441830 }, + { url = "https://files.pythonhosted.org/packages/32/bd/d0809593f7976828f06a492716fbcbbfb62798bbf60ea1f65200b8d49901/cffi-1.15.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:fa6693661a4c91757f4412306191b6dc88c1703f780c8234035eac011922bc01", size = 434743 }, + { url = "https://files.pythonhosted.org/packages/0e/65/0d7b5dad821ced4dcd43f96a362905a68ce71e6b5f5cfd2fada867840582/cffi-1.15.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:59c0b02d0a6c384d453fece7566d1c7e6b7bae4fc5874ef2ef46d56776d61c9e", size = 464113 }, + { url = "https://files.pythonhosted.org/packages/9f/52/1e2b43cfdd7d9a39f48bc89fcaee8d8685b1295e205a4f1044909ac14d89/cffi-1.15.1-cp310-cp310-win32.whl", hash = "sha256:cba9d6b9a7d64d4bd46167096fc9d2f835e25d7e4c121fb2ddfc6528fb0413b2", size = 170412 }, + { url = "https://files.pythonhosted.org/packages/0e/e2/a23af3d81838c577571da4ff01b799b0c2bbde24bd924d97e228febae810/cffi-1.15.1-cp310-cp310-win_amd64.whl", hash = "sha256:ce4bcc037df4fc5e3d184794f27bdaab018943698f4ca31630bc7f84a7b69c6d", size = 179060 }, + { url = "https://files.pythonhosted.org/packages/23/8b/2e8c2469eaf89f7273ac685164949a7e644cdfe5daf1c036564208c3d26b/cffi-1.15.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3d08afd128ddaa624a48cf2b859afef385b720bb4b43df214f85616922e6a5ac", size = 179198 }, + { url = "https://files.pythonhosted.org/packages/f9/96/fc9e118c47b7adc45a0676f413b4a47554e5f3b6c99b8607ec9726466ef1/cffi-1.15.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3799aecf2e17cf585d977b780ce79ff0dc9b78d799fc694221ce814c2c19db83", size = 174221 }, + { url = "https://files.pythonhosted.org/packages/10/72/617ee266192223a38b67149c830bd9376b69cf3551e1477abc72ff23ef8e/cffi-1.15.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a591fe9e525846e4d154205572a029f653ada1a78b93697f3b5a8f1f2bc055b9", size = 441694 }, + { url = "https://files.pythonhosted.org/packages/91/bc/b7723c2fe7a22eee71d7edf2102cd43423d5f95ff3932ebaa2f82c7ec8d0/cffi-1.15.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3548db281cd7d2561c9ad9984681c95f7b0e38881201e157833a2342c30d5e8c", size = 470613 }, + { url = "https://files.pythonhosted.org/packages/5d/4e/4e0bb5579b01fdbfd4388bd1eb9394a989e1336203a4b7f700d887b233c1/cffi-1.15.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:91fc98adde3d7881af9b59ed0294046f3806221863722ba7d8d120c575314325", size = 472199 }, + { url = "https://files.pythonhosted.org/packages/37/5a/c37631a86be838bdd84cc0259130942bf7e6e32f70f4cab95f479847fb91/cffi-1.15.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94411f22c3985acaec6f83c6df553f2dbe17b698cc7f8ae751ff2237d96b9e3c", size = 462588 }, + { url = "https://files.pythonhosted.org/packages/71/d7/0fe0d91b0bbf610fb7254bb164fa8931596e660d62e90fb6289b7ee27b09/cffi-1.15.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:03425bdae262c76aad70202debd780501fabeaca237cdfddc008987c0e0f59ef", size = 450543 }, + { url = "https://files.pythonhosted.org/packages/d3/56/3e94aa719ae96eeda8b68b3ec6e347e0a23168c6841dc276ccdcdadc9f32/cffi-1.15.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cc4d65aeeaa04136a12677d3dd0b1c0c94dc43abac5860ab33cceb42b801c1e8", size = 474253 }, + { url = "https://files.pythonhosted.org/packages/87/ee/ddc23981fc0f5e7b5356e98884226bcb899f95ebaefc3e8e8b8742dd7e22/cffi-1.15.1-cp311-cp311-win32.whl", hash = "sha256:a0f100c8912c114ff53e1202d0078b425bee3649ae34d7b070e9697f93c5d52d", size = 170313 }, + { url = "https://files.pythonhosted.org/packages/43/a0/cc7370ef72b6ee586369bacd3961089ab3d94ae712febf07a244f1448ffd/cffi-1.15.1-cp311-cp311-win_amd64.whl", hash = "sha256:04ed324bda3cda42b9b695d51bb7d54b680b9719cfab04227cdd1e04e5de3104", size = 179001 }, + { url = "https://files.pythonhosted.org/packages/b5/7d/df6c088ef30e78a78b0c9cca6b904d5abb698afb5bc8f5191d529d83d667/cffi-1.15.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:198caafb44239b60e252492445da556afafc7d1e3ab7a1fb3f0584ef6d742375", size = 178906 }, + { url = "https://files.pythonhosted.org/packages/c2/0b/3b09a755ddb977c167e6d209a7536f6ade43bb0654bad42e08df1406b8e4/cffi-1.15.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5ef34d190326c3b1f822a5b7a45f6c4535e2f47ed06fec77d3d799c450b2651e", size = 405992 }, + { url = "https://files.pythonhosted.org/packages/5b/1a/e1ee5bed11d8b6540c05a8e3c32448832d775364d4461dd6497374533401/cffi-1.15.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8102eaf27e1e448db915d08afa8b41d6c7ca7a04b7d73af6514df10a3e74bd82", size = 435560 }, + { url = "https://files.pythonhosted.org/packages/d3/e1/e55ca2e0dd446caa2cc8f73c2b98879c04a1f4064ac529e1836683ca58b8/cffi-1.15.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5df2768244d19ab7f60546d0c7c63ce1581f7af8b5de3eb3004b9b6fc8a9f84b", size = 435478 }, + { url = "https://files.pythonhosted.org/packages/2e/7a/68c35c151e5b7a12650ecc12fdfb85211aa1da43e9924598451c4a0a3839/cffi-1.15.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8c4917bd7ad33e8eb21e9a5bbba979b49d9a97acb3a803092cbc1133e20343c", size = 430395 }, + { url = "https://files.pythonhosted.org/packages/93/d0/2e2b27ea2f69b0ec9e481647822f8f77f5fc23faca2dd00d1ff009940eb7/cffi-1.15.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2642fe3142e4cc4af0799748233ad6da94c62a8bec3a6648bf8ee68b1c7426", size = 427911 }, + { url = "https://files.pythonhosted.org/packages/50/34/4cc590ad600869502c9838b4824982c122179089ed6791a8b1c95f0ff55e/cffi-1.15.1-cp37-cp37m-win32.whl", hash = "sha256:e229a521186c75c8ad9490854fd8bbdd9a0c9aa3a524326b55be83b54d4e0ad9", size = 169721 }, + { url = "https://files.pythonhosted.org/packages/32/2a/63cb8c07d151de92ff9d897b2eb27ba6a0e78dda8e4c5f70d7b8c16cd6a2/cffi-1.15.1-cp37-cp37m-win_amd64.whl", hash = "sha256:a0b71b1b8fbf2b96e41c4d990244165e2c9be83d54962a9a1d118fd8657d2045", size = 179301 }, + { url = "https://files.pythonhosted.org/packages/87/4b/64e8bd9d15d6b22b6cb11997094fbe61edf453ea0a97c8675cb7d1c3f06f/cffi-1.15.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:320dab6e7cb2eacdf0e658569d2575c4dad258c0fcc794f46215e1e39f90f2c3", size = 178940 }, + { url = "https://files.pythonhosted.org/packages/22/c6/df826563f55f7e9dd9a1d3617866282afa969fe0d57decffa1911f416ed8/cffi-1.15.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e74c6b51a9ed6589199c787bf5f9875612ca4a8a0785fb2d4a84429badaf22a", size = 421947 }, + { url = "https://files.pythonhosted.org/packages/c1/25/16a082701378170559bb1d0e9ef2d293cece8dc62913d79351beb34c5ddf/cffi-1.15.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5c84c68147988265e60416b57fc83425a78058853509c1b0629c180094904a5", size = 449906 }, + { url = "https://files.pythonhosted.org/packages/df/02/aef53d4aa43154b829e9707c8c60bab413cd21819c4a36b0d7aaa83e2a61/cffi-1.15.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3b926aa83d1edb5aa5b427b4053dc420ec295a08e40911296b9eb1b6170f6cca", size = 451028 }, + { url = "https://files.pythonhosted.org/packages/79/4b/33494eb0adbcd884656c48f6db0c98ad8a5c678fb8fb5ed41ab546b04d8c/cffi-1.15.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:87c450779d0914f2861b8526e035c5e6da0a3199d8f1add1a665e1cbc6fc6d02", size = 446520 }, + { url = "https://files.pythonhosted.org/packages/b7/8b/06f30caa03b5b3ac006de4f93478dbd0239e2a16566d81a106c322dc4f79/cffi-1.15.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f2c9f67e9821cad2e5f480bc8d83b8742896f1242dba247911072d4fa94c192", size = 442655 }, + { url = "https://files.pythonhosted.org/packages/47/97/137f0e3d2304df2060abb872a5830af809d7559a5a4b6a295afb02728e65/cffi-1.15.1-cp38-cp38-win32.whl", hash = "sha256:8b7ee99e510d7b66cdb6c593f21c043c248537a32e0bedf02e01e9553a172314", size = 170236 }, + { url = "https://files.pythonhosted.org/packages/c9/e3/0a52838832408cfbbf3a59cb19bcd17e64eb33795c9710ca7d29ae10b5b7/cffi-1.15.1-cp38-cp38-win_amd64.whl", hash = "sha256:00a9ed42e88df81ffae7a8ab6d9356b371399b91dbdf0c3cb1e84c03a13aceb5", size = 178835 }, + { url = "https://files.pythonhosted.org/packages/18/8f/5ff70c7458d61fa8a9752e5ee9c9984c601b0060aae0c619316a1e1f1ee5/cffi-1.15.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:54a2db7b78338edd780e7ef7f9f6c442500fb0d41a5a4ea24fff1c929d5af585", size = 179249 }, + { url = "https://files.pythonhosted.org/packages/3a/75/a162315adeaf47e94a3b7f886a8e31d77b9e525a387eef2d6f0efc96a7c8/cffi-1.15.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fcd131dd944808b5bdb38e6f5b53013c5aa4f334c5cad0c72742f6eba4b73db0", size = 174297 }, + { url = "https://files.pythonhosted.org/packages/85/1f/a3c533f8d377da5ca7edb4f580cc3edc1edbebc45fac8bb3ae60f1176629/cffi-1.15.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7473e861101c9e72452f9bf8acb984947aa1661a7704553a9f6e4baa5ba64415", size = 420641 }, + { url = "https://files.pythonhosted.org/packages/77/b7/d3618d612be01e184033eab90006f8ca5b5edafd17bf247439ea4e167d8a/cffi-1.15.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c9a799e985904922a4d207a94eae35c78ebae90e128f0c4e521ce339396be9d", size = 448814 }, + { url = "https://files.pythonhosted.org/packages/a9/ba/e082df21ebaa9cb29f2c4e1d7e49a29b90fcd667d43632c6674a16d65382/cffi-1.15.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3bcde07039e586f91b45c88f8583ea7cf7a0770df3a1649627bf598332cb6984", size = 449647 }, + { url = "https://files.pythonhosted.org/packages/af/cb/53b7bba75a18372d57113ba934b27d0734206c283c1dfcc172347fbd9f76/cffi-1.15.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33ab79603146aace82c2427da5ca6e58f2b3f2fb5da893ceac0c42218a40be35", size = 445191 }, + { url = "https://files.pythonhosted.org/packages/2d/86/3ca57cddfa0419f6a95d1c8478f8f622ba597e3581fd501bbb915b20eb75/cffi-1.15.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d598b938678ebf3c67377cdd45e09d431369c3b1a5b331058c338e201f12b27", size = 441236 }, + { url = "https://files.pythonhosted.org/packages/ad/26/7b3a73ab7d82a64664c7c4ea470e4ec4a3c73bb4f02575c543a41e272de5/cffi-1.15.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:db0fbb9c62743ce59a9ff687eb5f4afbe77e5e8403d6697f7446e5f609976f76", size = 433865 }, + { url = "https://files.pythonhosted.org/packages/da/ff/ab939e2c7b3f40d851c0f7192c876f1910f3442080c9c846532993ec3cef/cffi-1.15.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:98d85c6a2bef81588d9227dde12db8a7f47f639f4a17c9ae08e773aa9c697bf3", size = 463090 }, + { url = "https://files.pythonhosted.org/packages/c6/3d/dd085bb831b22ce4d0b7ba8550e6d78960f02f770bbd1314fea3580727f8/cffi-1.15.1-cp39-cp39-win32.whl", hash = "sha256:40f4774f5a9d4f5e344f31a32b5096977b5d48560c5592e2f3d2c4374bd543ee", size = 170382 }, + { url = "https://files.pythonhosted.org/packages/a8/16/06b84a7063a4c0a2b081030fdd976022086da9c14e80a9ed4ba0183a98a9/cffi-1.15.1-cp39-cp39-win_amd64.whl", hash = "sha256:70df4e3b545a17496c9b3f41f5115e69a4f2e77e94e1d2a8e1070bc0c38c8a3c", size = 179079 }, +] + +[[package]] +name = "cffi" +version = "1.17.1" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version == '3.8.*'", + "python_full_version >= '3.9'", +] +dependencies = [ + { name = "pycparser", marker = "python_full_version >= '3.8'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/fc/97/c783634659c2920c3fc70419e3af40972dbaf758daa229a7d6ea6135c90d/cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824", size = 516621 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/90/07/f44ca684db4e4f08a3fdc6eeb9a0d15dc6883efc7b8c90357fdbf74e186c/cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14", size = 182191 }, + { url = "https://files.pythonhosted.org/packages/08/fd/cc2fedbd887223f9f5d170c96e57cbf655df9831a6546c1727ae13fa977a/cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67", size = 178592 }, + { url = "https://files.pythonhosted.org/packages/de/cc/4635c320081c78d6ffc2cab0a76025b691a91204f4aa317d568ff9280a2d/cffi-1.17.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382", size = 426024 }, + { url = "https://files.pythonhosted.org/packages/b6/7b/3b2b250f3aab91abe5f8a51ada1b717935fdaec53f790ad4100fe2ec64d1/cffi-1.17.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702", size = 448188 }, + { url = "https://files.pythonhosted.org/packages/d3/48/1b9283ebbf0ec065148d8de05d647a986c5f22586b18120020452fff8f5d/cffi-1.17.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3", size = 455571 }, + { url = "https://files.pythonhosted.org/packages/40/87/3b8452525437b40f39ca7ff70276679772ee7e8b394934ff60e63b7b090c/cffi-1.17.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6", size = 436687 }, + { url = "https://files.pythonhosted.org/packages/8d/fb/4da72871d177d63649ac449aec2e8a29efe0274035880c7af59101ca2232/cffi-1.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17", size = 446211 }, + { url = "https://files.pythonhosted.org/packages/ab/a0/62f00bcb411332106c02b663b26f3545a9ef136f80d5df746c05878f8c4b/cffi-1.17.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8", size = 461325 }, + { url = "https://files.pythonhosted.org/packages/36/83/76127035ed2e7e27b0787604d99da630ac3123bfb02d8e80c633f218a11d/cffi-1.17.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e", size = 438784 }, + { url = "https://files.pythonhosted.org/packages/21/81/a6cd025db2f08ac88b901b745c163d884641909641f9b826e8cb87645942/cffi-1.17.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be", size = 461564 }, + { url = "https://files.pythonhosted.org/packages/f8/fe/4d41c2f200c4a457933dbd98d3cf4e911870877bd94d9656cc0fcb390681/cffi-1.17.1-cp310-cp310-win32.whl", hash = "sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c", size = 171804 }, + { url = "https://files.pythonhosted.org/packages/d1/b6/0b0f5ab93b0df4acc49cae758c81fe4e5ef26c3ae2e10cc69249dfd8b3ab/cffi-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15", size = 181299 }, + { url = "https://files.pythonhosted.org/packages/6b/f4/927e3a8899e52a27fa57a48607ff7dc91a9ebe97399b357b85a0c7892e00/cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401", size = 182264 }, + { url = "https://files.pythonhosted.org/packages/6c/f5/6c3a8efe5f503175aaddcbea6ad0d2c96dad6f5abb205750d1b3df44ef29/cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf", size = 178651 }, + { url = "https://files.pythonhosted.org/packages/94/dd/a3f0118e688d1b1a57553da23b16bdade96d2f9bcda4d32e7d2838047ff7/cffi-1.17.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4", size = 445259 }, + { url = "https://files.pythonhosted.org/packages/2e/ea/70ce63780f096e16ce8588efe039d3c4f91deb1dc01e9c73a287939c79a6/cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41", size = 469200 }, + { url = "https://files.pythonhosted.org/packages/1c/a0/a4fa9f4f781bda074c3ddd57a572b060fa0df7655d2a4247bbe277200146/cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1", size = 477235 }, + { url = "https://files.pythonhosted.org/packages/62/12/ce8710b5b8affbcdd5c6e367217c242524ad17a02fe5beec3ee339f69f85/cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6", size = 459721 }, + { url = "https://files.pythonhosted.org/packages/ff/6b/d45873c5e0242196f042d555526f92aa9e0c32355a1be1ff8c27f077fd37/cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d", size = 467242 }, + { url = "https://files.pythonhosted.org/packages/1a/52/d9a0e523a572fbccf2955f5abe883cfa8bcc570d7faeee06336fbd50c9fc/cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6", size = 477999 }, + { url = "https://files.pythonhosted.org/packages/44/74/f2a2460684a1a2d00ca799ad880d54652841a780c4c97b87754f660c7603/cffi-1.17.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f", size = 454242 }, + { url = "https://files.pythonhosted.org/packages/f8/4a/34599cac7dfcd888ff54e801afe06a19c17787dfd94495ab0c8d35fe99fb/cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b", size = 478604 }, + { url = "https://files.pythonhosted.org/packages/34/33/e1b8a1ba29025adbdcda5fb3a36f94c03d771c1b7b12f726ff7fef2ebe36/cffi-1.17.1-cp311-cp311-win32.whl", hash = "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655", size = 171727 }, + { url = "https://files.pythonhosted.org/packages/3d/97/50228be003bb2802627d28ec0627837ac0bf35c90cf769812056f235b2d1/cffi-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0", size = 181400 }, + { url = "https://files.pythonhosted.org/packages/5a/84/e94227139ee5fb4d600a7a4927f322e1d4aea6fdc50bd3fca8493caba23f/cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4", size = 183178 }, + { url = "https://files.pythonhosted.org/packages/da/ee/fb72c2b48656111c4ef27f0f91da355e130a923473bf5ee75c5643d00cca/cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c", size = 178840 }, + { url = "https://files.pythonhosted.org/packages/cc/b6/db007700f67d151abadf508cbfd6a1884f57eab90b1bb985c4c8c02b0f28/cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36", size = 454803 }, + { url = "https://files.pythonhosted.org/packages/1a/df/f8d151540d8c200eb1c6fba8cd0dfd40904f1b0682ea705c36e6c2e97ab3/cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5", size = 478850 }, + { url = "https://files.pythonhosted.org/packages/28/c0/b31116332a547fd2677ae5b78a2ef662dfc8023d67f41b2a83f7c2aa78b1/cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff", size = 485729 }, + { url = "https://files.pythonhosted.org/packages/91/2b/9a1ddfa5c7f13cab007a2c9cc295b70fbbda7cb10a286aa6810338e60ea1/cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99", size = 471256 }, + { url = "https://files.pythonhosted.org/packages/b2/d5/da47df7004cb17e4955df6a43d14b3b4ae77737dff8bf7f8f333196717bf/cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93", size = 479424 }, + { url = "https://files.pythonhosted.org/packages/0b/ac/2a28bcf513e93a219c8a4e8e125534f4f6db03e3179ba1c45e949b76212c/cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3", size = 484568 }, + { url = "https://files.pythonhosted.org/packages/d4/38/ca8a4f639065f14ae0f1d9751e70447a261f1a30fa7547a828ae08142465/cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8", size = 488736 }, + { url = "https://files.pythonhosted.org/packages/86/c5/28b2d6f799ec0bdecf44dced2ec5ed43e0eb63097b0f58c293583b406582/cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65", size = 172448 }, + { url = "https://files.pythonhosted.org/packages/50/b9/db34c4755a7bd1cb2d1603ac3863f22bcecbd1ba29e5ee841a4bc510b294/cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903", size = 181976 }, + { url = "https://files.pythonhosted.org/packages/8d/f8/dd6c246b148639254dad4d6803eb6a54e8c85c6e11ec9df2cffa87571dbe/cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e", size = 182989 }, + { url = "https://files.pythonhosted.org/packages/8b/f1/672d303ddf17c24fc83afd712316fda78dc6fce1cd53011b839483e1ecc8/cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2", size = 178802 }, + { url = "https://files.pythonhosted.org/packages/0e/2d/eab2e858a91fdff70533cab61dcff4a1f55ec60425832ddfdc9cd36bc8af/cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3", size = 454792 }, + { url = "https://files.pythonhosted.org/packages/75/b2/fbaec7c4455c604e29388d55599b99ebcc250a60050610fadde58932b7ee/cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683", size = 478893 }, + { url = "https://files.pythonhosted.org/packages/4f/b7/6e4a2162178bf1935c336d4da8a9352cccab4d3a5d7914065490f08c0690/cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5", size = 485810 }, + { url = "https://files.pythonhosted.org/packages/c7/8a/1d0e4a9c26e54746dc08c2c6c037889124d4f59dffd853a659fa545f1b40/cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4", size = 471200 }, + { url = "https://files.pythonhosted.org/packages/26/9f/1aab65a6c0db35f43c4d1b4f580e8df53914310afc10ae0397d29d697af4/cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd", size = 479447 }, + { url = "https://files.pythonhosted.org/packages/5f/e4/fb8b3dd8dc0e98edf1135ff067ae070bb32ef9d509d6cb0f538cd6f7483f/cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed", size = 484358 }, + { url = "https://files.pythonhosted.org/packages/f1/47/d7145bf2dc04684935d57d67dff9d6d795b2ba2796806bb109864be3a151/cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9", size = 488469 }, + { url = "https://files.pythonhosted.org/packages/bf/ee/f94057fa6426481d663b88637a9a10e859e492c73d0384514a17d78ee205/cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d", size = 172475 }, + { url = "https://files.pythonhosted.org/packages/7c/fc/6a8cb64e5f0324877d503c854da15d76c1e50eb722e320b15345c4d0c6de/cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a", size = 182009 }, + { url = "https://files.pythonhosted.org/packages/48/08/15bf6b43ae9bd06f6b00ad8a91f5a8fe1069d4c9fab550a866755402724e/cffi-1.17.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:636062ea65bd0195bc012fea9321aca499c0504409f413dc88af450b57ffd03b", size = 182457 }, + { url = "https://files.pythonhosted.org/packages/c2/5b/f1523dd545f92f7df468e5f653ffa4df30ac222f3c884e51e139878f1cb5/cffi-1.17.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7eac2ef9b63c79431bc4b25f1cd649d7f061a28808cbc6c47b534bd789ef964", size = 425932 }, + { url = "https://files.pythonhosted.org/packages/53/93/7e547ab4105969cc8c93b38a667b82a835dd2cc78f3a7dad6130cfd41e1d/cffi-1.17.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e221cf152cff04059d011ee126477f0d9588303eb57e88923578ace7baad17f9", size = 448585 }, + { url = "https://files.pythonhosted.org/packages/56/c4/a308f2c332006206bb511de219efeff090e9d63529ba0a77aae72e82248b/cffi-1.17.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:31000ec67d4221a71bd3f67df918b1f88f676f1c3b535a7eb473255fdc0b83fc", size = 456268 }, + { url = "https://files.pythonhosted.org/packages/ca/5b/b63681518265f2f4060d2b60755c1c77ec89e5e045fc3773b72735ddaad5/cffi-1.17.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6f17be4345073b0a7b8ea599688f692ac3ef23ce28e5df79c04de519dbc4912c", size = 436592 }, + { url = "https://files.pythonhosted.org/packages/bb/19/b51af9f4a4faa4a8ac5a0e5d5c2522dcd9703d07fac69da34a36c4d960d3/cffi-1.17.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2b1fac190ae3ebfe37b979cc1ce69c81f4e4fe5746bb401dca63a9062cdaf1", size = 446512 }, + { url = "https://files.pythonhosted.org/packages/e2/63/2bed8323890cb613bbecda807688a31ed11a7fe7afe31f8faaae0206a9a3/cffi-1.17.1-cp38-cp38-win32.whl", hash = "sha256:7596d6620d3fa590f677e9ee430df2958d2d6d6de2feeae5b20e82c00b76fbf8", size = 171576 }, + { url = "https://files.pythonhosted.org/packages/2f/70/80c33b044ebc79527447fd4fbc5455d514c3bb840dede4455de97da39b4d/cffi-1.17.1-cp38-cp38-win_amd64.whl", hash = "sha256:78122be759c3f8a014ce010908ae03364d00a1f81ab5c7f4a7a5120607ea56e1", size = 181229 }, + { url = "https://files.pythonhosted.org/packages/b9/ea/8bb50596b8ffbc49ddd7a1ad305035daa770202a6b782fc164647c2673ad/cffi-1.17.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b2ab587605f4ba0bf81dc0cb08a41bd1c0a5906bd59243d56bad7668a6fc6c16", size = 182220 }, + { url = "https://files.pythonhosted.org/packages/ae/11/e77c8cd24f58285a82c23af484cf5b124a376b32644e445960d1a4654c3a/cffi-1.17.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:28b16024becceed8c6dfbc75629e27788d8a3f9030691a1dbf9821a128b22c36", size = 178605 }, + { url = "https://files.pythonhosted.org/packages/ed/65/25a8dc32c53bf5b7b6c2686b42ae2ad58743f7ff644844af7cdb29b49361/cffi-1.17.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d599671f396c4723d016dbddb72fe8e0397082b0a77a4fab8028923bec050e8", size = 424910 }, + { url = "https://files.pythonhosted.org/packages/42/7a/9d086fab7c66bd7c4d0f27c57a1b6b068ced810afc498cc8c49e0088661c/cffi-1.17.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca74b8dbe6e8e8263c0ffd60277de77dcee6c837a3d0881d8c1ead7268c9e576", size = 447200 }, + { url = "https://files.pythonhosted.org/packages/da/63/1785ced118ce92a993b0ec9e0d0ac8dc3e5dbfbcaa81135be56c69cabbb6/cffi-1.17.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7f5baafcc48261359e14bcd6d9bff6d4b28d9103847c9e136694cb0501aef87", size = 454565 }, + { url = "https://files.pythonhosted.org/packages/74/06/90b8a44abf3556599cdec107f7290277ae8901a58f75e6fe8f970cd72418/cffi-1.17.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98e3969bcff97cae1b2def8ba499ea3d6f31ddfdb7635374834cf89a1a08ecf0", size = 435635 }, + { url = "https://files.pythonhosted.org/packages/bd/62/a1f468e5708a70b1d86ead5bab5520861d9c7eacce4a885ded9faa7729c3/cffi-1.17.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cdf5ce3acdfd1661132f2a9c19cac174758dc2352bfe37d98aa7512c6b7178b3", size = 445218 }, + { url = "https://files.pythonhosted.org/packages/5b/95/b34462f3ccb09c2594aa782d90a90b045de4ff1f70148ee79c69d37a0a5a/cffi-1.17.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9755e4345d1ec879e3849e62222a18c7174d65a6a92d5b346b1863912168b595", size = 460486 }, + { url = "https://files.pythonhosted.org/packages/fc/fc/a1e4bebd8d680febd29cf6c8a40067182b64f00c7d105f8f26b5bc54317b/cffi-1.17.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f1e22e8c4419538cb197e4dd60acc919d7696e5ef98ee4da4e01d3f8cfa4cc5a", size = 437911 }, + { url = "https://files.pythonhosted.org/packages/e6/c3/21cab7a6154b6a5ea330ae80de386e7665254835b9e98ecc1340b3a7de9a/cffi-1.17.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c03e868a0b3bc35839ba98e74211ed2b05d2119be4e8a0f224fba9384f1fe02e", size = 460632 }, + { url = "https://files.pythonhosted.org/packages/cb/b5/fd9f8b5a84010ca169ee49f4e4ad6f8c05f4e3545b72ee041dbbcb159882/cffi-1.17.1-cp39-cp39-win32.whl", hash = "sha256:e31ae45bc2e29f6b2abd0de1cc3b9d5205aa847cafaecb8af1476a609a2f6eb7", size = 171820 }, + { url = "https://files.pythonhosted.org/packages/8c/52/b08750ce0bce45c143e1b5d7357ee8c55341b52bdef4b0f081af1eb248c2/cffi-1.17.1-cp39-cp39-win_amd64.whl", hash = "sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662", size = 181290 }, +] + +[[package]] +name = "clr-loader" +version = "0.2.7.dev2+g3e2dff0.d20241212" +source = { editable = "." } +dependencies = [ + { name = "cffi", version = "1.15.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.8'" }, + { name = "cffi", version = "1.17.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.8'" }, +] + +[package.metadata] +requires-dist = [ + { name = "cffi", marker = "python_full_version >= '3.8'", specifier = ">=1.17" }, + { name = "cffi", marker = "python_full_version < '3.9'", specifier = ">=1.13" }, +] + +[[package]] +name = "pycparser" +version = "2.21" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5e/0b/95d387f5f4433cb0f53ff7ad859bd2c6051051cebbb564f139a999ab46de/pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206", size = 170877 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/62/d5/5f610ebe421e85889f2e55e33b7f9a6795bd982198517d912eb1c76e1a53/pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9", size = 118697 }, +] From 9b5914e3cfcd57bf4f5d4afc8d40c4733aedc4aa Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Thu, 12 Dec 2024 21:14:08 +0100 Subject: [PATCH 26/27] Workaround for setuptools bug #4759 --- pyproject.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 94857e4..c3ed5df 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,5 @@ [build-system] -requires = ["setuptools>=61", "setuptools_scm[toml]", "wheel"] +requires = ["setuptools>=75", "setuptools_scm[toml]"] build-backend = "setuptools.build_meta" [project] @@ -43,6 +43,7 @@ dev = [ [tool.setuptools] zip-safe = false package-data = {"clr_loader.ffi" = ["dlls/x86/*.dll", "dlls/amd64/*.dll"]} +license-files = [] [tool.setuptools.packages.find] include = ["clr_loader*"] From cbe765c35ecf8c1885be4f2eef4e9aea7d8ce406 Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Thu, 12 Dec 2024 21:33:46 +0100 Subject: [PATCH 27/27] Use dependency group instead of optional deps --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index c3ed5df..2c643e2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -35,7 +35,7 @@ email = "filmor@gmail.com" Sources = "https://github.com/pythonnet/clr-loader" Documentation = "https://pythonnet.github.io/clr-loader/" -[optional-dependencies] +[dependency-groups] dev = [ "pytest" ]