diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 4ae43c0..c1b8074 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -49,55 +49,77 @@ jobs: pytest tests/ build-wheels: - name: Build ${{ matrix.os }} ${{ matrix.cibw_build }} wheels + name: Build ${{ matrix.cibw_build }} wheels needs: build-sdist runs-on: ${{ matrix.os }} strategy: matrix: include: - os: ubuntu-20.04 - cibw_archs_linux: x86_64 + cibw_archs: x86_64 cibw_build: "cp3*-manylinux_x86_64" + compile_target: x86_64 + - os: ubuntu-20.04 + cibw_archs: x86_64 + cibw_build: "cp3*-musllinux_x86_64" + cibw_skip: "cp38-musllinux_*" + compile_target: x86_64 + - os: ubuntu-20.04 + cibw_archs: aarch64 + cibw_build: "cp3*-manylinux_aarch64" + compile_target: armv8 # - os: ubuntu-20.04 -# cibw_archs_linux: x86_64 -# cibw_build: "*-musllinux_*" -# - os: ubuntu-20.04 -# cibw_archs_linux: i686 -# cibw_build: "*-manylinux_*" -# - os: ubuntu-20.04 -# cibw_archs_linux: i686 -# cibw_build: "*-musllinux_*" +# cibw_archs: aarch64 +# cibw_build: "cp3*-musllinux_aarch64" +# compile_target: armv8 # - os: ubuntu-20.04 -# cibw_archs_linux: aarch64 -# cibw_build: "*-manylinux_*" +# cibw_archs: i686 +# cibw_build: "cp3*-manylinux_i686" +# compile_target: x86 # - os: ubuntu-20.04 -# cibw_archs_linux: aarch64 -# cibw_build: "*-musllinux_*" +# cibw_archs: i686 +# cibw_build: "cp3*-musllinux_i686" +# compile_target: x86 # - os: ubuntu-20.04 -# cibw_archs_linux: ppc64le -# cibw_build: "*-manylinux_*" +# cibw_archs: ppc64le +# cibw_build: "cp3*-manylinux_ppc64le" +# compile_target: ppc64le # - os: ubuntu-20.04 -# cibw_archs_linux: ppc64le -# cibw_build: "*-musllinux_*" +# cibw_archs: ppc64le +# cibw_build: "cp3*-musllinux_ppc64le" +# compile_target: ppc64le # - os: ubuntu-20.04 -# cibw_archs_linux: s390x -# cibw_build: "*-manylinux_*" +# cibw_archs: s390x +# cibw_build: "cp3*-manylinux_s390x" +# compile_target: s390x # - os: ubuntu-20.04 -# cibw_archs_linux: s390x -# cibw_build: "*-musllinux_*" +# cibw_archs: s390x +# cibw_build: "cp3*-musllinux_s390x" +# compile_target: s390x - os: windows-2019 - cibw_archs_windows: AMD64 + cibw_archs: AMD64 cibw_build: "cp3*-win_amd64" + compile_target: x86_64 # - os: windows-2019 -# cibw_archs_windows: x86 -# - os: windows-2019 -# cibw_archs_windows: ARM64 - - os: macos-11 - cibw_archs_macos: x86_64 - cibw_build: "cp3*-macosx_x86_64" +# cibw_archs: x86 +# cibw_build: "cp3*-win32" +# compile_target: x86 + - os: windows-2019 + cibw_archs: ARM64 + cibw_build: "cp3*-win_arm64" + compile_target: armv8 +# - os: macos-11 +# cibw_archs: x86_64 +# cibw_build: "cp3*-macosx_x86_64" +# compile_target: x86_64 +# - os: macos-11 +# cibw_archs: arm64 +# cibw_build: "cp3*-macosx_arm64" +# compile_target: armv8 - os: macos-11 - cibw_archs_macos: arm64 - cibw_build: "cp3*-macosx_arm64" + cibw_archs: universal2 + cibw_build: "cp3*-macosx_universal2" + compile_target: universal2 steps: - name: Fetch source distribution uses: actions/download-artifact@v3 @@ -105,12 +127,12 @@ jobs: name: sdist-${{ github.sha }} path: dist/ - run: mv dist/webp-*.tar.gz webp.tar.gz -# - name: Set up QEMU -# if: runner.os == 'Linux' -# uses: docker/setup-qemu-action@v2 -# with: -# platforms: all - - name: Build wheels + - name: Set up QEMU + if: runner.os == 'Linux' && runner.cibw_archs != 'x86_64' + uses: docker/setup-qemu-action@v2 + with: + platforms: all + - name: Build wheels for ${{ matrix.os }} ${{ matrix.cibw_archs }} ${{ matrix.cibw_build }} uses: pypa/cibuildwheel@v2.15.0 with: package-dir: webp.tar.gz @@ -118,11 +140,14 @@ jobs: env: CIBW_BUILD_FRONTEND: build CIBW_BUILD: ${{ matrix.cibw_build }} - CIBW_ARCHS_LINUX: ${{ matrix.cibw_archs_linux }} - CIBW_ARCHS_WINDOWS: ${{ matrix.cibw_archs_windows }} - CIBW_ARCHS_MACOS: ${{ matrix.cibw_archs_macos }} + CIBW_SKIP: ${{ matrix.cibw_skip }} + CIBW_ARCHS: ${{ matrix.cibw_archs }} + CIBW_ENVIRONMENT: PYWEBP_COMPILE_TARGET=${{ matrix.compile_target }} # TODO: Use arm64 CI runner when available CIBW_TEST_SKIP: "*_arm64" + # 3.12 will be ready when: + # - cffi releases a 3.12 wheel + # - numpy releases a 3.12 wheel CIBW_PROJECT_REQUIRES_PYTHON: '>=3.8,<3.12' CIBW_TEST_REQUIRES: pytest CIBW_TEST_COMMAND: pytest {package}/tests diff --git a/.gitignore b/.gitignore index 61e7547..e74c99c 100644 --- a/.gitignore +++ b/.gitignore @@ -19,4 +19,5 @@ core /dist/ /*.egg-info/ /.eggs/ +/conan_output/ *.so diff --git a/MANIFEST.in b/MANIFEST.in index 601e280..a4d3813 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,6 +1,6 @@ include README.md include LICENSE -include conanfile.txt +include conanfile.py include pyproject.toml graft webp_build diff --git a/conanfile.py b/conanfile.py new file mode 100644 index 0000000..94c28b8 --- /dev/null +++ b/conanfile.py @@ -0,0 +1,10 @@ +from conan import ConanFile +import shutil + +class LibwebpRecipe(ConanFile): + def requirements(self): + self.requires('libwebp/1.0.3') + + def build_requirements(self): + if not shutil.which('cmake'): + self.tool_requires('cmake/[>=3.5]') diff --git a/conanfile.txt b/conanfile.txt deleted file mode 100644 index 07522e1..0000000 --- a/conanfile.txt +++ /dev/null @@ -1,5 +0,0 @@ -[requires] -libwebp/1.0.3 - -[generators] -json diff --git a/pdm.lock b/pdm.lock index 0363f24..5e8f194 100644 --- a/pdm.lock +++ b/pdm.lock @@ -6,7 +6,7 @@ groups = ["default", "dev", "test"] cross_platform = true static_urls = false lock_version = "4.3" -content_hash = "sha256:a25591ba3748add9d005e0040b13fa3b9ad7f706999df829c6e0293953327882" +content_hash = "sha256:feca6d795895307710f5c9d8874ffb4ddea92b13975b9d1f5adea58bad93963d" [[package]] name = "annotated-types" @@ -30,32 +30,9 @@ files = [ {file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"}, ] -[[package]] -name = "bleach" -version = "6.0.0" -requires_python = ">=3.7" -summary = "An easy safelist-based HTML-sanitizing tool." -dependencies = [ - "six>=1.9.0", - "webencodings", -] -files = [ - {file = "bleach-6.0.0-py3-none-any.whl", hash = "sha256:33c16e3353dbd13028ab4799a0f89a83f113405c766e9c122df8a06f5b85b3f4"}, - {file = "bleach-6.0.0.tar.gz", hash = "sha256:1a1a85c1595e07d8db14c5f09f09e6433502c51c595970edc090551f0db99414"}, -] - -[[package]] -name = "bottle" -version = "0.12.25" -summary = "Fast and simple WSGI-framework for small web-applications." -files = [ - {file = "bottle-0.12.25-py3-none-any.whl", hash = "sha256:d6f15f9d422670b7c073d63bd8d287b135388da187a0f3e3c19293626ce034ea"}, - {file = "bottle-0.12.25.tar.gz", hash = "sha256:e1a9c94970ae6d710b3fb4526294dfeb86f2cb4a81eff3a4b98dc40fb0e5e021"}, -] - [[package]] name = "build" -version = "1.0.0" +version = "1.0.3" requires_python = ">= 3.7" summary = "A simple, correct Python build frontend" dependencies = [ @@ -66,8 +43,8 @@ dependencies = [ "tomli>=1.1.0; python_version < \"3.11\"", ] files = [ - {file = "build-1.0.0-py3-none-any.whl", hash = "sha256:f4c7b45e70e2c345e673902253d435a9a7729ff09ab574924420cf120c60bcc9"}, - {file = "build-1.0.0.tar.gz", hash = "sha256:49a60f212df4d9925727c2118e1cbe3abf30b393eff7d0e7287d2170eb36844d"}, + {file = "build-1.0.3-py3-none-any.whl", hash = "sha256:589bf99a67df7c9cf07ec0ac0e5e2ea5d4b37ac63301c4986d1acb126aa83f8f"}, + {file = "build-1.0.3.tar.gz", hash = "sha256:538aab1b64f9828977f84bc63ae570b060a8ed1be419e7870b8b4fc5e6ea553b"}, ] [[package]] @@ -293,34 +270,27 @@ files = [ [[package]] name = "conan" -version = "1.60.2" +version = "2.0.10" requires_python = ">=3.6" summary = "Conan C/C++ package manager" dependencies = [ - "Jinja2<4.0.0,>=3.0; python_version >= \"3\"", - "PyJWT<3.0.0,>=2.4.0", - "PyYAML<6.1,>=3.11", - "bottle<0.13,>=0.12.8", - "colorama<0.5.0,>=0.3.3", - "distro<=1.8.0,>=1.0.2; sys_platform == \"linux\" or sys_platform == \"linux2\"", - "fasteners>=0.14.1", - "node-semver==0.6.1", + "Jinja2<4.0.0,>=3.0", + "PyYAML<7.0,>=6.0", + "colorama<0.5.0,>=0.4.3", + "distro<=1.8.0,>=1.4.0; sys_platform == \"linux\" or sys_platform == \"linux2\"", + "fasteners>=0.15", "patch-ng<1.18,>=1.17.4", - "pluginbase>=0.5", - "pygments<3.0,>=2.0", - "python-dateutil<3,>=2.7.0", + "python-dateutil<3,>=2.8.0", "requests<3.0.0,>=2.25", - "six<=1.16.0,>=1.10.0", - "tqdm<5,>=4.28.1", "urllib3<1.27,>=1.26.6", ] files = [ - {file = "conan-1.60.2.tar.gz", hash = "sha256:3706eb21c189712cd2da3030fc4c7dad0db436043a4fdf5b4f4951f9619c99df"}, + {file = "conan-2.0.10.tar.gz", hash = "sha256:cbe1fa40a9f7e9ca076848617a4b58eed72b3afe228986d019c035c060494206"}, ] [[package]] name = "conda-lock" -version = "2.2.0" +version = "2.2.1" requires_python = ">=3.8" summary = "Lockfiles for conda" dependencies = [ @@ -349,8 +319,8 @@ dependencies = [ "virtualenv>=20.0.26", ] files = [ - {file = "conda_lock-2.2.0-py3-none-any.whl", hash = "sha256:38beae2d9eb40e54e5fce1c0b132d042a2c05e19ad593e5384241ed8c7298992"}, - {file = "conda_lock-2.2.0.tar.gz", hash = "sha256:0cfe264457b60a02fa7d6d740a2270a8c91f0c3f952b87447535583973490c96"}, + {file = "conda_lock-2.2.1-py3-none-any.whl", hash = "sha256:74c21f0f2c9b6a457ae4cacd12875dece975b5c9604de34cf96b646da5537a31"}, + {file = "conda_lock-2.2.1.tar.gz", hash = "sha256:5fe13e49877c7770d205e38e58ba2a4b6f98a88ebfe87576bac37ea55a6ae217"}, ] [[package]] @@ -490,15 +460,15 @@ files = [ [[package]] name = "gitpython" -version = "3.1.34" +version = "3.1.35" requires_python = ">=3.7" summary = "GitPython is a Python library used to interact with Git repositories" dependencies = [ "gitdb<5,>=4.0.1", ] files = [ - {file = "GitPython-3.1.34-py3-none-any.whl", hash = "sha256:5d3802b98a3bae1c2b8ae0e1ff2e4aa16bcdf02c145da34d092324f599f01395"}, - {file = "GitPython-3.1.34.tar.gz", hash = "sha256:85f7d365d1f6bf677ae51039c1ef67ca59091c7ebd5a3509aa399d4eda02d6dd"}, + {file = "GitPython-3.1.35-py3-none-any.whl", hash = "sha256:c19b4292d7a1d3c0f653858db273ff8a6614100d1eb1528b014ec97286193c09"}, + {file = "GitPython-3.1.35.tar.gz", hash = "sha256:9cbefbd1789a5fe9bcf621bb34d3f441f3a90c8461d377f84eda73e721d9b06b"}, ] [[package]] @@ -654,6 +624,16 @@ files = [ {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"}, {file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"}, {file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aa57bd9cf8ae831a362185ee444e15a93ecb2e344c8e52e4d721ea3ab6ef1823"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47d4f1c5f80fc62fdd7777d0d40a2e9dda0a05883ab11374334f6c4de38adffd"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f67c7038d560d92149c060157d623c542173016c4babc0c1913cca0564b9939"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9aad3c1755095ce347e26488214ef77e0485a3c34a50c5a5e2471dff60b9dd9c"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:14ff806850827afd6b07a5f32bd917fb7f45b046ba40c57abdb636674a8b559c"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8f9293864fe09b8149f0cc42ce56e3f0e54de883a9de90cd427f191c346eb2e1"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-win32.whl", hash = "sha256:715d3562f79d540f251b99ebd6d8baa547118974341db04f5ad06d5ea3eb8007"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-win_amd64.whl", hash = "sha256:1b8dd8c3fd14349433c79fa8abeb573a55fc0fdd769133baac1f5e07abf54aeb"}, {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:2ef12179d3a291be237280175b542c07a36e7f60718296278d8593d21ca937d4"}, {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2c1b19b3aaacc6e57b7e25710ff571c24d6c3613a45e905b1fde04d691b98ee0"}, {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8afafd99945ead6e075b973fefa56379c5b5c53fd8937dad92c662da5d8fd5ee"}, @@ -750,12 +730,26 @@ files = [ ] [[package]] -name = "node-semver" -version = "0.6.1" -summary = "port of node-semver" +name = "nh3" +version = "0.2.14" +summary = "Ammonia HTML sanitizer Python binding" files = [ - {file = "node-semver-0.6.1.tar.gz", hash = "sha256:4016f7c1071b0493f18db69ea02d3763e98a633606d7c7beca811e53b5ac66b7"}, - {file = "node_semver-0.6.1-py3-none-any.whl", hash = "sha256:d4bf83873894591a0cbb6591910d96917fbadc9731e8e39e782d3a2fbc2b841e"}, + {file = "nh3-0.2.14-cp37-abi3-macosx_10_7_x86_64.whl", hash = "sha256:9be2f68fb9a40d8440cbf34cbf40758aa7f6093160bfc7fb018cce8e424f0c3a"}, + {file = "nh3-0.2.14-cp37-abi3-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:f99212a81c62b5f22f9e7c3e347aa00491114a5647e1f13bbebd79c3e5f08d75"}, + {file = "nh3-0.2.14-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7771d43222b639a4cd9e341f870cee336b9d886de1ad9bec8dddab22fe1de450"}, + {file = "nh3-0.2.14-cp37-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:525846c56c2bcd376f5eaee76063ebf33cf1e620c1498b2a40107f60cfc6054e"}, + {file = "nh3-0.2.14-cp37-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:e8986f1dd3221d1e741fda0a12eaa4a273f1d80a35e31a1ffe579e7c621d069e"}, + {file = "nh3-0.2.14-cp37-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:18415df36db9b001f71a42a3a5395db79cf23d556996090d293764436e98e8ad"}, + {file = "nh3-0.2.14-cp37-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:377aaf6a9e7c63962f367158d808c6a1344e2b4f83d071c43fbd631b75c4f0b2"}, + {file = "nh3-0.2.14-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2b0be5c792bd43d0abef8ca39dd8acb3c0611052ce466d0401d51ea0d9aa7525"}, + {file = "nh3-0.2.14-cp37-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:93a943cfd3e33bd03f77b97baa11990148687877b74193bf777956b67054dcc6"}, + {file = "nh3-0.2.14-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:ac8056e937f264995a82bf0053ca898a1cb1c9efc7cd68fa07fe0060734df7e4"}, + {file = "nh3-0.2.14-cp37-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:203cac86e313cf6486704d0ec620a992c8bc164c86d3a4fd3d761dd552d839b5"}, + {file = "nh3-0.2.14-cp37-abi3-musllinux_1_2_i686.whl", hash = "sha256:5529a3bf99402c34056576d80ae5547123f1078da76aa99e8ed79e44fa67282d"}, + {file = "nh3-0.2.14-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:aed56a86daa43966dd790ba86d4b810b219f75b4bb737461b6886ce2bde38fd6"}, + {file = "nh3-0.2.14-cp37-abi3-win32.whl", hash = "sha256:116c9515937f94f0057ef50ebcbcc10600860065953ba56f14473ff706371873"}, + {file = "nh3-0.2.14-cp37-abi3-win_amd64.whl", hash = "sha256:88c753efbcdfc2644a5012938c6b9753f1c64a5723a67f0301ca43e7b85dcf0e"}, + {file = "nh3-0.2.14.tar.gz", hash = "sha256:a0c509894fd4dccdff557068e5074999ae3b75f4c5a2d6fb5415e782e25679c4"}, ] [[package]] @@ -916,14 +910,6 @@ files = [ {file = "pluggy-1.3.0.tar.gz", hash = "sha256:cf61ae8f126ac6f7c451172cf30e3e43d3ca77615509771b3a984a0730651e12"}, ] -[[package]] -name = "pluginbase" -version = "1.0.1" -summary = "PluginBase is a module for Python that enables the development of flexible plugin systems in Python." -files = [ - {file = "pluginbase-1.0.1.tar.gz", hash = "sha256:ff6c33a98fce232e9c73841d787a643de574937069f0d18147028d70d7dee287"}, -] - [[package]] name = "pycparser" version = "2.21" @@ -1064,16 +1050,6 @@ files = [ {file = "Pygments-2.16.1.tar.gz", hash = "sha256:1daff0494820c69bc8941e407aa20f577374ee88364ee10a98fdbe0aece96e29"}, ] -[[package]] -name = "pyjwt" -version = "2.8.0" -requires_python = ">=3.7" -summary = "JSON Web Token implementation in Python" -files = [ - {file = "PyJWT-2.8.0-py3-none-any.whl", hash = "sha256:59127c392cc44c2da5bb3192169a91f429924e17aff6534d70fdc02ab3e04320"}, - {file = "PyJWT-2.8.0.tar.gz", hash = "sha256:57e28d156e3d5c10088e0c68abb90bfac3df82b40a71bd0daa20c65ccd5c23de"}, -] - [[package]] name = "pylev" version = "1.4.0" @@ -1098,7 +1074,7 @@ files = [ [[package]] name = "pytest" -version = "7.4.1" +version = "7.4.2" requires_python = ">=3.7" summary = "pytest: simple powerful testing with Python" dependencies = [ @@ -1110,8 +1086,8 @@ dependencies = [ "tomli>=1.0.0; python_version < \"3.11\"", ] files = [ - {file = "pytest-7.4.1-py3-none-any.whl", hash = "sha256:460c9a59b14e27c602eb5ece2e47bec99dc5fc5f6513cf924a7d03a578991b1f"}, - {file = "pytest-7.4.1.tar.gz", hash = "sha256:2f2301e797521b23e4d2585a0a3d7b5e50fdddaaf7e7d6773ea26ddb17c213ab"}, + {file = "pytest-7.4.2-py3-none-any.whl", hash = "sha256:1d881c6124e08ff0a1bb75ba3ec0bfd8b5354a01c194ddd5a0a870a48d99b002"}, + {file = "pytest-7.4.2.tar.gz", hash = "sha256:a766259cfab564a2ad52cb1aae1b881a75c3eb7e34ca3779697c23ed47c47069"}, ] [[package]] @@ -1185,17 +1161,17 @@ files = [ [[package]] name = "readme-renderer" -version = "41.0" +version = "42.0" requires_python = ">=3.8" -summary = "readme_renderer is a library for rendering \"readme\" descriptions for Warehouse" +summary = "readme_renderer is a library for rendering readme descriptions for Warehouse" dependencies = [ "Pygments>=2.5.1", - "bleach>=2.1.0", "docutils>=0.13.1", + "nh3>=0.2.14", ] files = [ - {file = "readme_renderer-41.0-py3-none-any.whl", hash = "sha256:a38243d5b6741b700a850026e62da4bd739edc7422071e95fd5c4bb60171df86"}, - {file = "readme_renderer-41.0.tar.gz", hash = "sha256:4f4b11e5893f5a5d725f592c5a343e0dc74f5f273cb3dcf8c42d9703a27073f7"}, + {file = "readme_renderer-42.0-py3-none-any.whl", hash = "sha256:13d039515c1f24de668e2c93f2e877b9dbe6c6c32328b90a40a49d8b2b85f36d"}, + {file = "readme_renderer-42.0.tar.gz", hash = "sha256:2d55489f83be4992fe4454939d1a051c33edbab778e82761d060c9fc6b308cd1"}, ] [[package]] @@ -1362,19 +1338,6 @@ files = [ {file = "toolz-0.12.0.tar.gz", hash = "sha256:88c570861c440ee3f2f6037c4654613228ff40c93a6c25e0eba70d17282c6194"}, ] -[[package]] -name = "tqdm" -version = "4.66.1" -requires_python = ">=3.7" -summary = "Fast, Extensible Progress Meter" -dependencies = [ - "colorama; platform_system == \"Windows\"", -] -files = [ - {file = "tqdm-4.66.1-py3-none-any.whl", hash = "sha256:d302b3c5b53d47bce91fea46679d9c3c6508cf6332229aa1e7d8653723793386"}, - {file = "tqdm-4.66.1.tar.gz", hash = "sha256:d88e651f9db8d8551a62556d3cff9e3034274ca5d66e93197cf2490e2dcb69c7"}, -] - [[package]] name = "twine" version = "4.0.2" @@ -1418,7 +1381,7 @@ files = [ [[package]] name = "virtualenv" -version = "20.24.4" +version = "20.24.5" requires_python = ">=3.7" summary = "Virtual Python Environment builder" dependencies = [ @@ -1427,8 +1390,8 @@ dependencies = [ "platformdirs<4,>=3.9.1", ] files = [ - {file = "virtualenv-20.24.4-py3-none-any.whl", hash = "sha256:29c70bb9b88510f6414ac3e55c8b413a1f96239b6b789ca123437d5e892190cb"}, - {file = "virtualenv-20.24.4.tar.gz", hash = "sha256:772b05bfda7ed3b8ecd16021ca9716273ad9f4467c801f27e83ac73430246dca"}, + {file = "virtualenv-20.24.5-py3-none-any.whl", hash = "sha256:b80039f280f4919c77b30f1c23294ae357c4c8701042086e3fc005963e4e537b"}, + {file = "virtualenv-20.24.5.tar.gz", hash = "sha256:e8361967f6da6fbdf1426483bfe9fca8287c242ac0bc30429905721cefbff752"}, ] [[package]] diff --git a/pyproject.toml b/pyproject.toml index 9733860..62ef69a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "webp" -version = "0.1.8" +version = "0.2.0" description = "Python bindings for WebP" readme = { content-type = "text/markdown", file = "README.md" } authors = [{ name = "Aiden Nibali", email = "dismaldenizen@gmail.com" }] @@ -23,7 +23,7 @@ test = [ ] dev = [ "build>=1.0.0", - "conan>=1.8.0,<2.0", + "conan>=2.0", "conda-lock>=2.0.0", "twine", ] @@ -34,7 +34,7 @@ homepage = "https://github.com/anibali/pywebp" [build-system] requires = [ "cffi>=1.0.0", - "conan>=1.8.0,<2.0", + "conan>=2.0", "setuptools>=45", "wheel", ] diff --git a/webp_build/__init__.py b/webp_build/__init__.py index e69de29..7239e19 100644 --- a/webp_build/__init__.py +++ b/webp_build/__init__.py @@ -0,0 +1,15 @@ +import logging + + +def _create_logger(): + logger = logging.getLogger(__name__) + logger.propagate = False + ch = logging.StreamHandler() + ch.setLevel(logging.DEBUG) + formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') + ch.setFormatter(formatter) + logger.addHandler(ch) + return logger + + +logger = _create_logger() diff --git a/webp_build/builder.py b/webp_build/builder.py index 7906cd5..6f97519 100644 --- a/webp_build/builder.py +++ b/webp_build/builder.py @@ -1,75 +1,166 @@ import json +import os import platform -import tempfile +import shutil +import subprocess from importlib.resources import read_text -from os import path, getcwd, getenv from cffi import FFI -from conans.client import conan_api import webp_build -conan, _, _ = conan_api.ConanAPIV1.factory() - -# Use Conan to install libwebp -settings = [] -if platform.architecture()[0] == '32bit' and platform.machine().lower() in {'amd64', 'x86_64', 'x64', 'i686'}: - settings.append('arch=x86') -if getenv('CIBW_ARCHS_MACOS') == 'arm64': - # https://blog.conan.io/2021/09/21/m1.html - settings.append('os=Macos') - settings.append('arch=armv8') - settings.append('compiler=apple-clang') - settings.append('compiler.version=11.0') - settings.append('compiler.libcxx=libc++') -elif getenv('CIBW_ARCHS_WINDOWS') == 'ARM64': - settings.append('os=Windows') - settings.append('arch=armv8') -if getenv('CIBW_BUILD') and 'musllinux' in getenv('CIBW_BUILD'): - build_policy = ['always'] -else: - build_policy = ['missing'] - -with tempfile.TemporaryDirectory() as tmp_dir: - conan.install(path=getcwd(), cwd=tmp_dir, settings=settings, build=build_policy) - with open(path.join(tmp_dir, 'conanbuildinfo.json'), 'r') as f: - conan_info = json.load(f) - -# Find header files and libraries in libwebp -extra_objects = [] -extra_compile_args = [] -include_dirs = [] -libraries = [] -for dep in conan_info['dependencies']: - for lib_name in dep['libs']: - if platform.system() == 'Windows': - lib_filename = '{}.lib'.format(lib_name) +# Mapping from Conan architectures to Python machine types +CONAN_ARCHS = { + 'x86_64': ['amd64', 'x86_64', 'x64'], + 'x86': ['i386', 'i686', 'x86'], + 'armv8': ['arm64', 'aarch64', 'aarch64_be', 'armv8b', 'armv8l'], + 'ppc64le': ['ppc64le', 'powerpc'], + 's390x': ['s390', 's390x'], +} + + +def get_arch() -> str: + """Get the Conan compilation target architecture. + + If not explicitly set using the `PYWEBP_COMPILE_TARGET` environment variable, this will be determined using the + host machine's platform information. + """ + env_arch = os.getenv('PYWEBP_COMPILE_TARGET', '') + if env_arch: + return env_arch + + if ( + platform.architecture()[0] == '32bit' + and platform.machine().lower() in (CONAN_ARCHS['x86'] + CONAN_ARCHS['x86_64']) + ): + return 'x86' + + for k, v in CONAN_ARCHS.items(): + if platform.machine().lower() in v: + return k + + raise RuntimeError('Unable to determine the compilation target architecture') + + +def install_libwebp(arch: str) -> dict: + """Install libwebp using Conan. + """ + settings = [] + + if platform.system() == 'Windows': + settings.append('os=Windows') + elif platform.system() == 'Darwin': + settings.append('os=Macos') + if arch == 'x86_64': + settings.append('os.version=10.9') + else: + settings.append('os.version=11.0') + settings.append('compiler=apple-clang') + settings.append('compiler.libcxx=libc++') + elif platform.system() == 'Linux': + settings.append('os=Linux') + + settings.append(f'arch={arch}') + + build = ['missing'] + if os.path.isdir('/lib') and len([i for i in os.listdir('/lib') if i.startswith('libc.musl')]) != 0: + # Need to compile libwebp if musllinux + build.append('libwebp*') + + if ( + not shutil.which('cmake') and ( + platform.architecture()[0] == '32bit' or + platform.machine().lower() not in (CONAN_ARCHS['armv8'] + CONAN_ARCHS['x86']) + ) + ): + build.append('cmake*') + + subprocess.run(['conan', 'profile', 'detect']) + + conan_output = os.path.join('conan_output', arch) + + result = subprocess.run([ + 'conan', 'install', + *[x for s in settings for x in ('-s', s)], + *[x for b in build for x in ('-b', b)], + '-of', conan_output, '--deployer=direct_deploy', '--format=json', '.' + ], stdout=subprocess.PIPE).stdout.decode() + conan_info = json.loads(result) + + return conan_info + + +def fetch_cffi_settings(conan_info: dict, cffi_settings: dict): + """Find header files and libraries in libwebp. + """ + for dep in conan_info['graph']['nodes'].values(): + if dep.get('package_folder') is None: + continue + + for cpp_info in reversed(dep['cpp_info'].values()): + for include_dir in (cpp_info.get('includedirs') or []): + if include_dir not in cffi_settings['include_dirs']: + cffi_settings['include_dirs'].append(include_dir) + + for lib_name in (cpp_info.get('libs') or []): + if platform.system() == 'Windows': + lib_filename = '{}.lib'.format(lib_name) + else: + lib_filename = 'lib{}.a'.format(lib_name) + + for lib_dir in (cpp_info.get('libdirs') or []): + lib_path = os.path.join(lib_dir, lib_filename) + if os.path.isfile(lib_path): + cffi_settings['extra_objects'].append(lib_path) + else: + cffi_settings['libraries'].append(lib_name) + + return cffi_settings + + +def create_ffibuilder(): + cffi_settings = { + 'extra_objects': [], + 'extra_compile_args': [], + 'include_dirs': [], + 'libraries': [] + } + + arch = get_arch() + webp_build.logger.info(f'Detected system architecture as {arch}') + if platform.system() == 'Darwin': + if arch == 'x86_64': + cffi_settings['extra_compile_args'].append('-mmacosx-version-min=10.9') else: - lib_filename = 'lib{}.a'.format(lib_name) - for lib_path in dep['lib_paths']: - candidate = path.join(lib_path, lib_filename) - if path.isfile(candidate): - extra_objects.append(candidate) - else: - libraries.append(lib_name) - for include_path in dep['include_paths']: - include_dirs.append(include_path) - -if getenv('CIBW_ARCHS_MACOS') == 'arm64': - extra_compile_args.append('--target=arm64-apple-macos11') - -# Specify C sources to be built by CFFI -ffibuilder = FFI() -ffibuilder.set_source( - '_webp', - read_text(webp_build, 'source.c'), - extra_objects=extra_objects, - extra_compile_args=extra_compile_args, - include_dirs=include_dirs, - libraries=libraries, -) -ffibuilder.cdef(read_text(webp_build, 'cdef.h')) + cffi_settings['extra_compile_args'].append('-mmacosx-version-min=11.0') + + if arch == 'universal2': + conan_info = install_libwebp('x86_64') + cffi_settings = fetch_cffi_settings(conan_info, cffi_settings) + conan_info = install_libwebp('armv8') + cffi_settings = fetch_cffi_settings(conan_info, cffi_settings) + else: + conan_info = install_libwebp(arch) + cffi_settings = fetch_cffi_settings(conan_info, cffi_settings) + + webp_build.logger.info(f'{cffi_settings=}') + + # Specify C sources to be built by CFFI + ffibuilder = FFI() + ffibuilder.set_source( + '_webp', + read_text(webp_build, 'source.c'), + extra_objects=cffi_settings['extra_objects'], + extra_compile_args=cffi_settings['extra_compile_args'], + include_dirs=cffi_settings['include_dirs'], + libraries=cffi_settings['libraries'], + ) + ffibuilder.cdef(read_text(webp_build, 'cdef.h')) + + return ffibuilder + +ffibuilder = create_ffibuilder() if __name__ == '__main__': ffibuilder.compile(verbose=True)