mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-03-13 09:15:46 +03:00
Merge branch 'main' into zlib-ng
This commit is contained in:
commit
01bc487ff4
|
@ -1 +1 @@
|
||||||
cibuildwheel==2.21.3
|
cibuildwheel==2.22.0
|
||||||
|
|
1
.github/CONTRIBUTING.md
vendored
1
.github/CONTRIBUTING.md
vendored
|
@ -19,7 +19,6 @@ Please send a pull request to the `main` branch. Please include [documentation](
|
||||||
- Follow PEP 8.
|
- Follow PEP 8.
|
||||||
- When committing only documentation changes please include `[ci skip]` in the commit message to avoid running tests on AppVeyor.
|
- When committing only documentation changes please include `[ci skip]` in the commit message to avoid running tests on AppVeyor.
|
||||||
- Include [release notes](https://github.com/python-pillow/Pillow/tree/main/docs/releasenotes) as needed or appropriate with your bug fixes, feature additions and tests.
|
- Include [release notes](https://github.com/python-pillow/Pillow/tree/main/docs/releasenotes) as needed or appropriate with your bug fixes, feature additions and tests.
|
||||||
- Do not add to the [changelog](https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst) for proposed changes, as that is updated after changes are merged.
|
|
||||||
|
|
||||||
## Reporting Issues
|
## Reporting Issues
|
||||||
|
|
||||||
|
|
11
.github/release-drafter.yml
vendored
11
.github/release-drafter.yml
vendored
|
@ -3,18 +3,19 @@ tag-template: "$NEXT_MINOR_VERSION"
|
||||||
change-template: '- $TITLE #$NUMBER [@$AUTHOR]'
|
change-template: '- $TITLE #$NUMBER [@$AUTHOR]'
|
||||||
|
|
||||||
categories:
|
categories:
|
||||||
- title: "Dependencies"
|
- title: "Removals"
|
||||||
label: "Dependency"
|
label: "Removal"
|
||||||
- title: "Deprecations"
|
- title: "Deprecations"
|
||||||
label: "Deprecation"
|
label: "Deprecation"
|
||||||
- title: "Documentation"
|
- title: "Documentation"
|
||||||
label: "Documentation"
|
label: "Documentation"
|
||||||
- title: "Removals"
|
- title: "Dependencies"
|
||||||
label: "Removal"
|
label: "Dependency"
|
||||||
- title: "Testing"
|
- title: "Testing"
|
||||||
label: "Testing"
|
label: "Testing"
|
||||||
- title: "Type hints"
|
- title: "Type hints"
|
||||||
label: "Type hints"
|
label: "Type hints"
|
||||||
|
- title: "Other changes"
|
||||||
|
|
||||||
exclude-labels:
|
exclude-labels:
|
||||||
- "changelog: skip"
|
- "changelog: skip"
|
||||||
|
@ -23,6 +24,4 @@ template: |
|
||||||
|
|
||||||
https://pillow.readthedocs.io/en/stable/releasenotes/$NEXT_MINOR_VERSION.html
|
https://pillow.readthedocs.io/en/stable/releasenotes/$NEXT_MINOR_VERSION.html
|
||||||
|
|
||||||
## Changes
|
|
||||||
|
|
||||||
$CHANGES
|
$CHANGES
|
||||||
|
|
2
.github/workflows/macos-install.sh
vendored
2
.github/workflows/macos-install.sh
vendored
|
@ -8,8 +8,8 @@ fi
|
||||||
brew install \
|
brew install \
|
||||||
freetype \
|
freetype \
|
||||||
ghostscript \
|
ghostscript \
|
||||||
|
jpeg-turbo \
|
||||||
libimagequant \
|
libimagequant \
|
||||||
libjpeg \
|
|
||||||
libtiff \
|
libtiff \
|
||||||
little-cms2 \
|
little-cms2 \
|
||||||
openjpeg \
|
openjpeg \
|
||||||
|
|
5
.github/workflows/test-cygwin.yml
vendored
5
.github/workflows/test-cygwin.yml
vendored
|
@ -133,11 +133,12 @@ jobs:
|
||||||
- name: After success
|
- name: After success
|
||||||
run: |
|
run: |
|
||||||
bash.exe .ci/after_success.sh
|
bash.exe .ci/after_success.sh
|
||||||
|
rm C:\cygwin\bin\bash.EXE
|
||||||
|
|
||||||
- name: Upload coverage
|
- name: Upload coverage
|
||||||
uses: codecov/codecov-action@v4
|
uses: codecov/codecov-action@v5
|
||||||
with:
|
with:
|
||||||
file: ./coverage.xml
|
files: ./coverage.xml
|
||||||
flags: GHA_Cygwin
|
flags: GHA_Cygwin
|
||||||
name: Cygwin Python 3.${{ matrix.python-minor-version }}
|
name: Cygwin Python 3.${{ matrix.python-minor-version }}
|
||||||
token: ${{ secrets.CODECOV_ORG_TOKEN }}
|
token: ${{ secrets.CODECOV_ORG_TOKEN }}
|
||||||
|
|
2
.github/workflows/test-docker.yml
vendored
2
.github/workflows/test-docker.yml
vendored
|
@ -100,7 +100,7 @@ jobs:
|
||||||
MATRIX_DOCKER: ${{ matrix.docker }}
|
MATRIX_DOCKER: ${{ matrix.docker }}
|
||||||
|
|
||||||
- name: Upload coverage
|
- name: Upload coverage
|
||||||
uses: codecov/codecov-action@v4
|
uses: codecov/codecov-action@v5
|
||||||
with:
|
with:
|
||||||
flags: GHA_Docker
|
flags: GHA_Docker
|
||||||
name: ${{ matrix.docker }}
|
name: ${{ matrix.docker }}
|
||||||
|
|
4
.github/workflows/test-mingw.yml
vendored
4
.github/workflows/test-mingw.yml
vendored
|
@ -85,9 +85,9 @@ jobs:
|
||||||
.ci/test.sh
|
.ci/test.sh
|
||||||
|
|
||||||
- name: Upload coverage
|
- name: Upload coverage
|
||||||
uses: codecov/codecov-action@v4
|
uses: codecov/codecov-action@v5
|
||||||
with:
|
with:
|
||||||
file: ./coverage.xml
|
files: ./coverage.xml
|
||||||
flags: GHA_Windows
|
flags: GHA_Windows
|
||||||
name: "MSYS2 MinGW"
|
name: "MSYS2 MinGW"
|
||||||
token: ${{ secrets.CODECOV_ORG_TOKEN }}
|
token: ${{ secrets.CODECOV_ORG_TOKEN }}
|
||||||
|
|
4
.github/workflows/test-windows.yml
vendored
4
.github/workflows/test-windows.yml
vendored
|
@ -215,9 +215,9 @@ jobs:
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
|
|
||||||
- name: Upload coverage
|
- name: Upload coverage
|
||||||
uses: codecov/codecov-action@v4
|
uses: codecov/codecov-action@v5
|
||||||
with:
|
with:
|
||||||
file: ./coverage.xml
|
files: ./coverage.xml
|
||||||
flags: GHA_Windows
|
flags: GHA_Windows
|
||||||
name: ${{ runner.os }} Python ${{ matrix.python-version }}
|
name: ${{ runner.os }} Python ${{ matrix.python-version }}
|
||||||
token: ${{ secrets.CODECOV_ORG_TOKEN }}
|
token: ${{ secrets.CODECOV_ORG_TOKEN }}
|
||||||
|
|
17
.github/workflows/test.yml
vendored
17
.github/workflows/test.yml
vendored
|
@ -42,6 +42,7 @@ jobs:
|
||||||
]
|
]
|
||||||
python-version: [
|
python-version: [
|
||||||
"pypy3.10",
|
"pypy3.10",
|
||||||
|
"3.13t",
|
||||||
"3.13",
|
"3.13",
|
||||||
"3.12",
|
"3.12",
|
||||||
"3.11",
|
"3.11",
|
||||||
|
@ -52,14 +53,14 @@ jobs:
|
||||||
- { python-version: "3.11", PYTHONOPTIMIZE: 1, REVERSE: "--reverse" }
|
- { python-version: "3.11", PYTHONOPTIMIZE: 1, REVERSE: "--reverse" }
|
||||||
- { python-version: "3.10", PYTHONOPTIMIZE: 2 }
|
- { python-version: "3.10", PYTHONOPTIMIZE: 2 }
|
||||||
# Free-threaded
|
# Free-threaded
|
||||||
- { os: "ubuntu-latest", python-version: "3.13-dev", disable-gil: true }
|
- { python-version: "3.13t", disable-gil: true }
|
||||||
# M1 only available for 3.10+
|
# M1 only available for 3.10+
|
||||||
- { os: "macos-13", python-version: "3.9" }
|
- { os: "macos-13", python-version: "3.9" }
|
||||||
exclude:
|
exclude:
|
||||||
- { os: "macos-latest", python-version: "3.9" }
|
- { os: "macos-latest", python-version: "3.9" }
|
||||||
|
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
name: ${{ matrix.os }} Python ${{ matrix.python-version }} ${{ matrix.disable-gil && 'free-threaded' || '' }}
|
name: ${{ matrix.os }} Python ${{ matrix.python-version }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
@ -67,8 +68,7 @@ jobs:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
||||||
- name: Set up Python ${{ matrix.python-version }}
|
- name: Set up Python ${{ matrix.python-version }}
|
||||||
uses: actions/setup-python@v5
|
uses: Quansight-Labs/setup-python@v5
|
||||||
if: "${{ !matrix.disable-gil }}"
|
|
||||||
with:
|
with:
|
||||||
python-version: ${{ matrix.python-version }}
|
python-version: ${{ matrix.python-version }}
|
||||||
allow-prereleases: true
|
allow-prereleases: true
|
||||||
|
@ -77,13 +77,6 @@ jobs:
|
||||||
".ci/*.sh"
|
".ci/*.sh"
|
||||||
"pyproject.toml"
|
"pyproject.toml"
|
||||||
|
|
||||||
- name: Set up Python ${{ matrix.python-version }} (free-threaded)
|
|
||||||
uses: deadsnakes/action@v3.2.0
|
|
||||||
if: "${{ matrix.disable-gil }}"
|
|
||||||
with:
|
|
||||||
python-version: ${{ matrix.python-version }}
|
|
||||||
nogil: ${{ matrix.disable-gil }}
|
|
||||||
|
|
||||||
- name: Set PYTHON_GIL
|
- name: Set PYTHON_GIL
|
||||||
if: "${{ matrix.disable-gil }}"
|
if: "${{ matrix.disable-gil }}"
|
||||||
run: |
|
run: |
|
||||||
|
@ -156,7 +149,7 @@ jobs:
|
||||||
.ci/after_success.sh
|
.ci/after_success.sh
|
||||||
|
|
||||||
- name: Upload coverage
|
- name: Upload coverage
|
||||||
uses: codecov/codecov-action@v4
|
uses: codecov/codecov-action@v5
|
||||||
with:
|
with:
|
||||||
flags: ${{ matrix.os == 'ubuntu-latest' && 'GHA_Ubuntu' || 'GHA_macOS' }}
|
flags: ${{ matrix.os == 'ubuntu-latest' && 'GHA_Ubuntu' || 'GHA_macOS' }}
|
||||||
name: ${{ matrix.os }} Python ${{ matrix.python-version }}
|
name: ${{ matrix.os }} Python ${{ matrix.python-version }}
|
||||||
|
|
9
.github/workflows/wheels-dependencies.sh
vendored
9
.github/workflows/wheels-dependencies.sh
vendored
|
@ -38,10 +38,10 @@ ARCHIVE_SDIR=pillow-depends-main
|
||||||
|
|
||||||
# Package versions for fresh source builds
|
# Package versions for fresh source builds
|
||||||
FREETYPE_VERSION=2.13.2
|
FREETYPE_VERSION=2.13.2
|
||||||
HARFBUZZ_VERSION=10.0.1
|
HARFBUZZ_VERSION=10.1.0
|
||||||
LIBPNG_VERSION=1.6.44
|
LIBPNG_VERSION=1.6.44
|
||||||
JPEGTURBO_VERSION=3.0.4
|
JPEGTURBO_VERSION=3.1.0
|
||||||
OPENJPEG_VERSION=2.5.2
|
OPENJPEG_VERSION=2.5.3
|
||||||
XZ_VERSION=5.6.3
|
XZ_VERSION=5.6.3
|
||||||
TIFF_VERSION=4.6.0
|
TIFF_VERSION=4.6.0
|
||||||
LCMS2_VERSION=2.16
|
LCMS2_VERSION=2.16
|
||||||
|
@ -82,10 +82,9 @@ function build_zlib_ng {
|
||||||
|
|
||||||
function build_brotli {
|
function build_brotli {
|
||||||
if [ -e brotli-stamp ]; then return; fi
|
if [ -e brotli-stamp ]; then return; fi
|
||||||
local cmake=$(get_modern_cmake)
|
|
||||||
local out_dir=$(fetch_unpack https://github.com/google/brotli/archive/v$BROTLI_VERSION.tar.gz brotli-$BROTLI_VERSION.tar.gz)
|
local out_dir=$(fetch_unpack https://github.com/google/brotli/archive/v$BROTLI_VERSION.tar.gz brotli-$BROTLI_VERSION.tar.gz)
|
||||||
(cd $out_dir \
|
(cd $out_dir \
|
||||||
&& $cmake -DCMAKE_INSTALL_PREFIX=$BUILD_PREFIX -DCMAKE_INSTALL_LIBDIR=$BUILD_PREFIX/lib -DCMAKE_INSTALL_NAME_DIR=$BUILD_PREFIX/lib . \
|
&& cmake -DCMAKE_INSTALL_PREFIX=$BUILD_PREFIX -DCMAKE_INSTALL_LIBDIR=$BUILD_PREFIX/lib -DCMAKE_INSTALL_NAME_DIR=$BUILD_PREFIX/lib . \
|
||||||
&& make install)
|
&& make install)
|
||||||
touch brotli-stamp
|
touch brotli-stamp
|
||||||
}
|
}
|
||||||
|
|
8
.github/workflows/wheels.yml
vendored
8
.github/workflows/wheels.yml
vendored
|
@ -85,7 +85,7 @@ jobs:
|
||||||
CIBW_ARCHS: "aarch64"
|
CIBW_ARCHS: "aarch64"
|
||||||
# Likewise, select only one Python version per job to speed this up.
|
# Likewise, select only one Python version per job to speed this up.
|
||||||
CIBW_BUILD: "${{ matrix.python-version }}-${{ matrix.spec == 'musllinux' && 'musllinux' || 'manylinux' }}*"
|
CIBW_BUILD: "${{ matrix.python-version }}-${{ matrix.spec == 'musllinux' && 'musllinux' || 'manylinux' }}*"
|
||||||
CIBW_PRERELEASE_PYTHONS: True
|
CIBW_ENABLE: cpython-prerelease
|
||||||
# Extra options for manylinux.
|
# Extra options for manylinux.
|
||||||
CIBW_MANYLINUX_AARCH64_IMAGE: ${{ matrix.spec }}
|
CIBW_MANYLINUX_AARCH64_IMAGE: ${{ matrix.spec }}
|
||||||
CIBW_MANYLINUX_PYPY_AARCH64_IMAGE: ${{ matrix.spec }}
|
CIBW_MANYLINUX_PYPY_AARCH64_IMAGE: ${{ matrix.spec }}
|
||||||
|
@ -150,10 +150,9 @@ jobs:
|
||||||
env:
|
env:
|
||||||
CIBW_ARCHS: ${{ matrix.cibw_arch }}
|
CIBW_ARCHS: ${{ matrix.cibw_arch }}
|
||||||
CIBW_BUILD: ${{ matrix.build }}
|
CIBW_BUILD: ${{ matrix.build }}
|
||||||
CIBW_FREE_THREADED_SUPPORT: True
|
CIBW_ENABLE: cpython-prerelease cpython-freethreading
|
||||||
CIBW_MANYLINUX_PYPY_X86_64_IMAGE: ${{ matrix.manylinux }}
|
CIBW_MANYLINUX_PYPY_X86_64_IMAGE: ${{ matrix.manylinux }}
|
||||||
CIBW_MANYLINUX_X86_64_IMAGE: ${{ matrix.manylinux }}
|
CIBW_MANYLINUX_X86_64_IMAGE: ${{ matrix.manylinux }}
|
||||||
CIBW_PRERELEASE_PYTHONS: True
|
|
||||||
CIBW_SKIP: pp39-*
|
CIBW_SKIP: pp39-*
|
||||||
MACOSX_DEPLOYMENT_TARGET: ${{ matrix.macosx_deployment_target }}
|
MACOSX_DEPLOYMENT_TARGET: ${{ matrix.macosx_deployment_target }}
|
||||||
|
|
||||||
|
@ -228,8 +227,7 @@ jobs:
|
||||||
CIBW_ARCHS: ${{ matrix.cibw_arch }}
|
CIBW_ARCHS: ${{ matrix.cibw_arch }}
|
||||||
CIBW_BEFORE_ALL: "{package}\\winbuild\\build\\build_dep_all.cmd"
|
CIBW_BEFORE_ALL: "{package}\\winbuild\\build\\build_dep_all.cmd"
|
||||||
CIBW_CACHE_PATH: "C:\\cibw"
|
CIBW_CACHE_PATH: "C:\\cibw"
|
||||||
CIBW_FREE_THREADED_SUPPORT: True
|
CIBW_ENABLE: cpython-prerelease cpython-freethreading
|
||||||
CIBW_PRERELEASE_PYTHONS: True
|
|
||||||
CIBW_SKIP: pp39-*
|
CIBW_SKIP: pp39-*
|
||||||
CIBW_TEST_SKIP: "*-win_arm64"
|
CIBW_TEST_SKIP: "*-win_arm64"
|
||||||
CIBW_TEST_COMMAND: 'docker run --rm
|
CIBW_TEST_COMMAND: 'docker run --rm
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
repos:
|
repos:
|
||||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||||
rev: v0.7.2
|
rev: v0.8.1
|
||||||
hooks:
|
hooks:
|
||||||
- id: ruff
|
- id: ruff
|
||||||
args: [--exit-non-zero-on-fix]
|
args: [--exit-non-zero-on-fix]
|
||||||
|
@ -11,7 +11,7 @@ repos:
|
||||||
- id: black
|
- id: black
|
||||||
|
|
||||||
- repo: https://github.com/PyCQA/bandit
|
- repo: https://github.com/PyCQA/bandit
|
||||||
rev: 1.7.10
|
rev: 1.8.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: bandit
|
- id: bandit
|
||||||
args: [--severity-level=high]
|
args: [--severity-level=high]
|
||||||
|
@ -24,7 +24,7 @@ repos:
|
||||||
exclude: (Makefile$|\.bat$|\.cmake$|\.eps$|\.fits$|\.gd$|\.opt$)
|
exclude: (Makefile$|\.bat$|\.cmake$|\.eps$|\.fits$|\.gd$|\.opt$)
|
||||||
|
|
||||||
- repo: https://github.com/pre-commit/mirrors-clang-format
|
- repo: https://github.com/pre-commit/mirrors-clang-format
|
||||||
rev: v19.1.3
|
rev: v19.1.4
|
||||||
hooks:
|
hooks:
|
||||||
- id: clang-format
|
- id: clang-format
|
||||||
types: [c]
|
types: [c]
|
||||||
|
@ -50,7 +50,7 @@ repos:
|
||||||
exclude: ^.github/.*TEMPLATE|^Tests/(fonts|images)/
|
exclude: ^.github/.*TEMPLATE|^Tests/(fonts|images)/
|
||||||
|
|
||||||
- repo: https://github.com/python-jsonschema/check-jsonschema
|
- repo: https://github.com/python-jsonschema/check-jsonschema
|
||||||
rev: 0.29.4
|
rev: 0.30.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: check-github-workflows
|
- id: check-github-workflows
|
||||||
- id: check-readthedocs
|
- id: check-readthedocs
|
||||||
|
@ -67,7 +67,7 @@ repos:
|
||||||
- id: pyproject-fmt
|
- id: pyproject-fmt
|
||||||
|
|
||||||
- repo: https://github.com/abravalheri/validate-pyproject
|
- repo: https://github.com/abravalheri/validate-pyproject
|
||||||
rev: v0.22
|
rev: v0.23
|
||||||
hooks:
|
hooks:
|
||||||
- id: validate-pyproject
|
- id: validate-pyproject
|
||||||
additional_dependencies: [trove-classifiers>=2024.10.12]
|
additional_dependencies: [trove-classifiers>=2024.10.12]
|
||||||
|
|
22
CHANGES.rst
22
CHANGES.rst
|
@ -2,26 +2,12 @@
|
||||||
Changelog (Pillow)
|
Changelog (Pillow)
|
||||||
==================
|
==================
|
||||||
|
|
||||||
11.1.0 (unreleased)
|
11.1.0 and newer
|
||||||
-------------------
|
----------------
|
||||||
|
|
||||||
- Removed use of os.path.realpath #8545
|
See GitHub Releases:
|
||||||
[radarhere]
|
|
||||||
|
|
||||||
- Allow linking to zlib import library on Windows #8519
|
- https://github.com/python-pillow/Pillow/releases
|
||||||
[cubanpit, nulano]
|
|
||||||
|
|
||||||
- Detach PyQt6 QPixmap instance before returning #8509
|
|
||||||
[radarhere]
|
|
||||||
|
|
||||||
- Corrected EMF DPI #8485
|
|
||||||
[radarhere]
|
|
||||||
|
|
||||||
- Fix IFDRational with a zero denominator #8474
|
|
||||||
[radarhere]
|
|
||||||
|
|
||||||
- Fixed disabling a feature during install #8469
|
|
||||||
[radarhere]
|
|
||||||
|
|
||||||
11.0.0 (2024-10-15)
|
11.0.0 (2024-10-15)
|
||||||
-------------------
|
-------------------
|
||||||
|
|
2
LICENSE
2
LICENSE
|
@ -5,7 +5,7 @@ The Python Imaging Library (PIL) is
|
||||||
|
|
||||||
Pillow is the friendly PIL fork. It is
|
Pillow is the friendly PIL fork. It is
|
||||||
|
|
||||||
Copyright © 2010-2024 by Jeffrey A. Clark and contributors
|
Copyright © 2010 by Jeffrey A. Clark and contributors
|
||||||
|
|
||||||
Like PIL, Pillow is licensed under the open source MIT-CMU License:
|
Like PIL, Pillow is licensed under the open source MIT-CMU License:
|
||||||
|
|
||||||
|
|
|
@ -107,7 +107,7 @@ The core image library is designed for fast access to data stored in a few basic
|
||||||
- [Issues](https://github.com/python-pillow/Pillow/issues)
|
- [Issues](https://github.com/python-pillow/Pillow/issues)
|
||||||
- [Pull requests](https://github.com/python-pillow/Pillow/pulls)
|
- [Pull requests](https://github.com/python-pillow/Pillow/pulls)
|
||||||
- [Release notes](https://pillow.readthedocs.io/en/stable/releasenotes/index.html)
|
- [Release notes](https://pillow.readthedocs.io/en/stable/releasenotes/index.html)
|
||||||
- [Changelog](https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst)
|
- [Changelog](https://github.com/python-pillow/Pillow/releases)
|
||||||
- [Pre-fork](https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst#pre-fork)
|
- [Pre-fork](https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst#pre-fork)
|
||||||
|
|
||||||
## Report a Vulnerability
|
## Report a Vulnerability
|
||||||
|
|
|
@ -12,7 +12,6 @@ Released quarterly on January 2nd, April 1st, July 1st and October 15th.
|
||||||
* [ ] Check [GitHub Actions](https://github.com/python-pillow/Pillow/actions) and [AppVeyor](https://ci.appveyor.com/project/python-pillow/Pillow) to confirm passing tests in `main` branch.
|
* [ ] Check [GitHub Actions](https://github.com/python-pillow/Pillow/actions) and [AppVeyor](https://ci.appveyor.com/project/python-pillow/Pillow) to confirm passing tests in `main` branch.
|
||||||
* [ ] Check that all the wheel builds pass the tests in the [GitHub Actions "Wheels" workflow](https://github.com/python-pillow/Pillow/actions/workflows/wheels.yml) jobs by manually triggering them.
|
* [ ] Check that all the wheel builds pass the tests in the [GitHub Actions "Wheels" workflow](https://github.com/python-pillow/Pillow/actions/workflows/wheels.yml) jobs by manually triggering them.
|
||||||
* [ ] In compliance with [PEP 440](https://peps.python.org/pep-0440/), update version identifier in `src/PIL/_version.py`
|
* [ ] In compliance with [PEP 440](https://peps.python.org/pep-0440/), update version identifier in `src/PIL/_version.py`
|
||||||
* [ ] Update `CHANGES.rst`.
|
|
||||||
* [ ] Run pre-release check via `make release-test` in a freshly cloned repo.
|
* [ ] Run pre-release check via `make release-test` in a freshly cloned repo.
|
||||||
* [ ] Create branch and tag for release e.g.:
|
* [ ] Create branch and tag for release e.g.:
|
||||||
```bash
|
```bash
|
||||||
|
@ -34,7 +33,6 @@ Released quarterly on January 2nd, April 1st, July 1st and October 15th.
|
||||||
Released as needed for security, installation or critical bug fixes.
|
Released as needed for security, installation or critical bug fixes.
|
||||||
|
|
||||||
* [ ] Make necessary changes in `main` branch.
|
* [ ] Make necessary changes in `main` branch.
|
||||||
* [ ] Update `CHANGES.rst`.
|
|
||||||
* [ ] Check out release branch e.g.:
|
* [ ] Check out release branch e.g.:
|
||||||
```bash
|
```bash
|
||||||
git checkout -t remotes/origin/5.2.x
|
git checkout -t remotes/origin/5.2.x
|
||||||
|
|
|
@ -1098,6 +1098,25 @@ class TestFileLibTiff(LibTiffTestCase):
|
||||||
|
|
||||||
assert_image_similar(base_im, im, 0.7)
|
assert_image_similar(base_im, im, 0.7)
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"test_file",
|
||||||
|
[
|
||||||
|
"Tests/images/old-style-jpeg-compression-no-samplesperpixel.tif",
|
||||||
|
"Tests/images/old-style-jpeg-compression.tif",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_buffering(self, test_file: str) -> None:
|
||||||
|
# load exif first
|
||||||
|
with Image.open(open(test_file, "rb", buffering=1048576)) as im:
|
||||||
|
exif = dict(im.getexif())
|
||||||
|
|
||||||
|
# load image before exif
|
||||||
|
with Image.open(open(test_file, "rb", buffering=1048576)) as im2:
|
||||||
|
im2.load()
|
||||||
|
exif_after_load = dict(im2.getexif())
|
||||||
|
|
||||||
|
assert exif == exif_after_load
|
||||||
|
|
||||||
@pytest.mark.valgrind_known_error(reason="Backtrace in Python Core")
|
@pytest.mark.valgrind_known_error(reason="Backtrace in Python Core")
|
||||||
def test_sampleformat_not_corrupted(self) -> None:
|
def test_sampleformat_not_corrupted(self) -> None:
|
||||||
# Assert that a TIFF image with SampleFormat=UINT tag is not corrupted
|
# Assert that a TIFF image with SampleFormat=UINT tag is not corrupted
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# Documentation: https://docs.codecov.com/docs/codecov-yaml
|
# Documentation: https://docs.codecov.com/docs/codecov-yaml
|
||||||
|
|
||||||
codecov:
|
codecov:
|
||||||
# Avoid "Missing base report" due to committing CHANGES.rst with "[CI skip]"
|
# Avoid "Missing base report" due to committing with "[CI skip]"
|
||||||
# https://github.com/codecov/support/issues/363
|
# https://github.com/codecov/support/issues/363
|
||||||
# https://docs.codecov.com/docs/comparing-commits
|
# https://docs.codecov.com/docs/comparing-commits
|
||||||
allow_coverage_offsets: true
|
allow_coverage_offsets: true
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# install openjpeg
|
# install openjpeg
|
||||||
|
|
||||||
archive=openjpeg-2.5.2
|
archive=openjpeg-2.5.3
|
||||||
|
|
||||||
./download-and-extract.sh $archive https://raw.githubusercontent.com/python-pillow/pillow-depends/main/$archive.tar.gz
|
./download-and-extract.sh $archive https://raw.githubusercontent.com/python-pillow/pillow-depends/main/$archive.tar.gz
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ The Python Imaging Library (PIL) is
|
||||||
|
|
||||||
Pillow is the friendly PIL fork. It is
|
Pillow is the friendly PIL fork. It is
|
||||||
|
|
||||||
Copyright © 2010-2024 by Jeffrey A. Clark and contributors
|
Copyright © 2010 by Jeffrey A. Clark and contributors
|
||||||
|
|
||||||
Like PIL, Pillow is licensed under the open source PIL
|
Like PIL, Pillow is licensed under the open source PIL
|
||||||
Software License:
|
Software License:
|
||||||
|
|
|
@ -55,7 +55,7 @@ master_doc = "index"
|
||||||
project = "Pillow (PIL Fork)"
|
project = "Pillow (PIL Fork)"
|
||||||
copyright = (
|
copyright = (
|
||||||
"1995-2011 Fredrik Lundh and contributors, "
|
"1995-2011 Fredrik Lundh and contributors, "
|
||||||
"2010-2024 Jeffrey A. Clark and contributors."
|
"2010 Jeffrey A. Clark and contributors."
|
||||||
)
|
)
|
||||||
author = "Fredrik Lundh (PIL), Jeffrey A. Clark (Pillow)"
|
author = "Fredrik Lundh (PIL), Jeffrey A. Clark (Pillow)"
|
||||||
|
|
||||||
|
|
|
@ -678,7 +678,7 @@ Reading from URL
|
||||||
|
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
from urllib.request import urlopen
|
from urllib.request import urlopen
|
||||||
url = "https://python-pillow.org/assets/images/pillow-logo.png"
|
url = "https://python-pillow.github.io/assets/images/pillow-logo.png"
|
||||||
img = Image.open(urlopen(url))
|
img = Image.open(urlopen(url))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -58,7 +58,7 @@ Many of Pillow's features require external libraries:
|
||||||
* **openjpeg** provides JPEG 2000 functionality.
|
* **openjpeg** provides JPEG 2000 functionality.
|
||||||
|
|
||||||
* Pillow has been tested with openjpeg **2.0.0**, **2.1.0**, **2.3.1**,
|
* Pillow has been tested with openjpeg **2.0.0**, **2.1.0**, **2.3.1**,
|
||||||
**2.4.0**, **2.5.0** and **2.5.2**.
|
**2.4.0**, **2.5.0**, **2.5.2** and **2.5.3**.
|
||||||
* Pillow does **not** support the earlier **1.5** series which ships
|
* Pillow does **not** support the earlier **1.5** series which ships
|
||||||
with Debian Jessie.
|
with Debian Jessie.
|
||||||
|
|
||||||
|
@ -148,13 +148,7 @@ Many of Pillow's features require external libraries:
|
||||||
The easiest way to install external libraries is via `Homebrew
|
The easiest way to install external libraries is via `Homebrew
|
||||||
<https://brew.sh/>`_. After you install Homebrew, run::
|
<https://brew.sh/>`_. After you install Homebrew, run::
|
||||||
|
|
||||||
brew install libjpeg libtiff little-cms2 openjpeg webp
|
brew install libjpeg libraqm libtiff little-cms2 openjpeg webp
|
||||||
|
|
||||||
To install libraqm on macOS use Homebrew to install its dependencies::
|
|
||||||
|
|
||||||
brew install freetype harfbuzz fribidi
|
|
||||||
|
|
||||||
Then see ``depends/install_raqm_cmake.sh`` to install libraqm.
|
|
||||||
|
|
||||||
.. tab:: Windows
|
.. tab:: Windows
|
||||||
|
|
||||||
|
|
|
@ -55,7 +55,7 @@ These platforms are built and tested for every change.
|
||||||
| +----------------------------+---------------------+
|
| +----------------------------+---------------------+
|
||||||
| | 3.13 | x86 |
|
| | 3.13 | x86 |
|
||||||
| +----------------------------+---------------------+
|
| +----------------------------+---------------------+
|
||||||
| | 3.9 (MinGW) | x86-64 |
|
| | 3.12 (MinGW) | x86-64 |
|
||||||
| +----------------------------+---------------------+
|
| +----------------------------+---------------------+
|
||||||
| | 3.9 (Cygwin) | x86-64 |
|
| | 3.9 (Cygwin) | x86-64 |
|
||||||
+----------------------------------+----------------------------+---------------------+
|
+----------------------------------+----------------------------+---------------------+
|
||||||
|
|
|
@ -73,10 +73,10 @@ optional-dependencies.typing = [
|
||||||
optional-dependencies.xmp = [
|
optional-dependencies.xmp = [
|
||||||
"defusedxml",
|
"defusedxml",
|
||||||
]
|
]
|
||||||
urls.Changelog = "https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst"
|
urls.Changelog = "https://github.com/python-pillow/Pillow/releases"
|
||||||
urls.Documentation = "https://pillow.readthedocs.io"
|
urls.Documentation = "https://pillow.readthedocs.io"
|
||||||
urls.Funding = "https://tidelift.com/subscription/pkg/pypi-pillow?utm_source=pypi-pillow&utm_medium=pypi"
|
urls.Funding = "https://tidelift.com/subscription/pkg/pypi-pillow?utm_source=pypi-pillow&utm_medium=pypi"
|
||||||
urls.Homepage = "https://python-pillow.org"
|
urls.Homepage = "https://python-pillow.github.io"
|
||||||
urls.Mastodon = "https://fosstodon.org/@pillow"
|
urls.Mastodon = "https://fosstodon.org/@pillow"
|
||||||
urls."Release notes" = "https://pillow.readthedocs.io/en/stable/releasenotes/index.html"
|
urls."Release notes" = "https://pillow.readthedocs.io/en/stable/releasenotes/index.html"
|
||||||
urls.Source = "https://github.com/python-pillow/Pillow"
|
urls.Source = "https://github.com/python-pillow/Pillow"
|
||||||
|
|
17
setup.py
17
setup.py
|
@ -393,13 +393,14 @@ class pil_build_ext(build_ext):
|
||||||
self.feature.required.discard(x)
|
self.feature.required.discard(x)
|
||||||
_dbg("Disabling %s", x)
|
_dbg("Disabling %s", x)
|
||||||
if getattr(self, f"enable_{x}"):
|
if getattr(self, f"enable_{x}"):
|
||||||
msg = f"Conflicting options: --enable-{x} and --disable-{x}"
|
msg = f"Conflicting options: '-C {x}=enable' and '-C {x}=disable'"
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
if x == "freetype":
|
if x == "freetype":
|
||||||
_dbg("--disable-freetype implies --disable-raqm")
|
_dbg("'-C freetype=disable' implies '-C raqm=disable'")
|
||||||
if getattr(self, "enable_raqm"):
|
if getattr(self, "enable_raqm"):
|
||||||
msg = (
|
msg = (
|
||||||
"Conflicting options: --enable-raqm and --disable-freetype"
|
"Conflicting options: "
|
||||||
|
"'-C raqm=enable' and '-C freetype=disable'"
|
||||||
)
|
)
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
setattr(self, "disable_raqm", True)
|
setattr(self, "disable_raqm", True)
|
||||||
|
@ -407,15 +408,17 @@ class pil_build_ext(build_ext):
|
||||||
_dbg("Requiring %s", x)
|
_dbg("Requiring %s", x)
|
||||||
self.feature.required.add(x)
|
self.feature.required.add(x)
|
||||||
if x == "raqm":
|
if x == "raqm":
|
||||||
_dbg("--enable-raqm implies --enable-freetype")
|
_dbg("'-C raqm=enable' implies '-C freetype=enable'")
|
||||||
self.feature.required.add("freetype")
|
self.feature.required.add("freetype")
|
||||||
for x in ("raqm", "fribidi"):
|
for x in ("raqm", "fribidi"):
|
||||||
if getattr(self, f"vendor_{x}"):
|
if getattr(self, f"vendor_{x}"):
|
||||||
if getattr(self, "disable_raqm"):
|
if getattr(self, "disable_raqm"):
|
||||||
msg = f"Conflicting options: --vendor-{x} and --disable-raqm"
|
msg = f"Conflicting options: '-C {x}=vendor' and '-C raqm=disable'"
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
if x == "fribidi" and not getattr(self, "vendor_raqm"):
|
if x == "fribidi" and not getattr(self, "vendor_raqm"):
|
||||||
msg = f"Conflicting options: --vendor-{x} and not --vendor-raqm"
|
msg = (
|
||||||
|
f"Conflicting options: '-C {x}=vendor' and not '-C raqm=vendor'"
|
||||||
|
)
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
_dbg("Using vendored version of %s", x)
|
_dbg("Using vendored version of %s", x)
|
||||||
self.feature.vendor.add(x)
|
self.feature.vendor.add(x)
|
||||||
|
@ -1047,7 +1050,7 @@ except DependencyException as err:
|
||||||
msg = f"""
|
msg = f"""
|
||||||
|
|
||||||
The headers or library files could not be found for {str(err)},
|
The headers or library files could not be found for {str(err)},
|
||||||
which was requested by the option flag --enable-{str(err)}
|
which was requested by the option flag '-C {str(err)}=enable'
|
||||||
|
|
||||||
"""
|
"""
|
||||||
sys.stderr.write(msg)
|
sys.stderr.write(msg)
|
||||||
|
|
|
@ -357,7 +357,7 @@ def _save(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
|
||||||
name = "".join([name[: 92 - len(ext)], ext])
|
name = "".join([name[: 92 - len(ext)], ext])
|
||||||
|
|
||||||
fp.write(f"Name: {name}\r\n".encode("ascii"))
|
fp.write(f"Name: {name}\r\n".encode("ascii"))
|
||||||
fp.write(("Image size (x*y): %d*%d\r\n" % im.size).encode("ascii"))
|
fp.write(f"Image size (x*y): {im.size[0]}*{im.size[1]}\r\n".encode("ascii"))
|
||||||
fp.write(f"File size (no of images): {frames}\r\n".encode("ascii"))
|
fp.write(f"File size (no of images): {frames}\r\n".encode("ascii"))
|
||||||
if im.mode in ["P", "PA"]:
|
if im.mode in ["P", "PA"]:
|
||||||
fp.write(b"Lut: 1\r\n")
|
fp.write(b"Lut: 1\r\n")
|
||||||
|
|
|
@ -692,13 +692,10 @@ class Image:
|
||||||
)
|
)
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
return "<%s.%s image mode=%s size=%dx%d at 0x%X>" % (
|
return (
|
||||||
self.__class__.__module__,
|
f"<{self.__class__.__module__}.{self.__class__.__name__} "
|
||||||
self.__class__.__name__,
|
f"image mode={self.mode} size={self.size[0]}x{self.size[1]} "
|
||||||
self.mode,
|
f"at 0x{id(self):X}>"
|
||||||
self.size[0],
|
|
||||||
self.size[1],
|
|
||||||
id(self),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def _repr_pretty_(self, p: PrettyPrinter, cycle: bool) -> None:
|
def _repr_pretty_(self, p: PrettyPrinter, cycle: bool) -> None:
|
||||||
|
@ -707,14 +704,8 @@ class Image:
|
||||||
# Same as __repr__ but without unpredictable id(self),
|
# Same as __repr__ but without unpredictable id(self),
|
||||||
# to keep Jupyter notebook `text/plain` output stable.
|
# to keep Jupyter notebook `text/plain` output stable.
|
||||||
p.text(
|
p.text(
|
||||||
"<%s.%s image mode=%s size=%dx%d>"
|
f"<{self.__class__.__module__}.{self.__class__.__name__} "
|
||||||
% (
|
f"image mode={self.mode} size={self.size[0]}x{self.size[1]}>"
|
||||||
self.__class__.__module__,
|
|
||||||
self.__class__.__name__,
|
|
||||||
self.mode,
|
|
||||||
self.size[0],
|
|
||||||
self.size[1],
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def _repr_image(self, image_format: str, **kwargs: Any) -> bytes | None:
|
def _repr_image(self, image_format: str, **kwargs: Any) -> bytes | None:
|
||||||
|
|
|
@ -120,7 +120,7 @@ class ImageFile(Image.Image):
|
||||||
self.custom_mimetype: str | None = None
|
self.custom_mimetype: str | None = None
|
||||||
|
|
||||||
self.tile: list[_Tile] = []
|
self.tile: list[_Tile] = []
|
||||||
""" A list of tile descriptors, or ``None`` """
|
""" A list of tile descriptors """
|
||||||
|
|
||||||
self.readonly = 1 # until we know better
|
self.readonly = 1 # until we know better
|
||||||
|
|
||||||
|
|
|
@ -72,7 +72,7 @@ def APP(self: JpegImageFile, marker: int) -> None:
|
||||||
n = i16(self.fp.read(2)) - 2
|
n = i16(self.fp.read(2)) - 2
|
||||||
s = ImageFile._safe_read(self.fp, n)
|
s = ImageFile._safe_read(self.fp, n)
|
||||||
|
|
||||||
app = "APP%d" % (marker & 15)
|
app = f"APP{marker & 15}"
|
||||||
|
|
||||||
self.app[app] = s # compatibility
|
self.app[app] = s # compatibility
|
||||||
self.applist.append((app, s))
|
self.applist.append((app, s))
|
||||||
|
|
|
@ -86,7 +86,7 @@ class PcxImageFile(ImageFile.ImageFile):
|
||||||
|
|
||||||
elif bits == 1 and planes in (2, 4):
|
elif bits == 1 and planes in (2, 4):
|
||||||
mode = "P"
|
mode = "P"
|
||||||
rawmode = "P;%dL" % planes
|
rawmode = f"P;{planes}L"
|
||||||
self.palette = ImagePalette.raw("RGB", s[16:64])
|
self.palette = ImagePalette.raw("RGB", s[16:64])
|
||||||
|
|
||||||
elif version == 5 and bits == 8 and planes == 1:
|
elif version == 5 and bits == 8 and planes == 1:
|
||||||
|
|
|
@ -523,7 +523,7 @@ class PngStream(ChunkStream):
|
||||||
|
|
||||||
assert self.fp is not None
|
assert self.fp is not None
|
||||||
s = ImageFile._safe_read(self.fp, length)
|
s = ImageFile._safe_read(self.fp, length)
|
||||||
raw_vals = struct.unpack(">%dI" % (len(s) // 4), s)
|
raw_vals = struct.unpack(f">{len(s) // 4}I", s)
|
||||||
self.im_info["chromaticity"] = tuple(elt / 100000.0 for elt in raw_vals)
|
self.im_info["chromaticity"] = tuple(elt / 100000.0 for elt in raw_vals)
|
||||||
return s
|
return s
|
||||||
|
|
||||||
|
|
|
@ -935,9 +935,9 @@ class ImageFileDirectory_v2(_IFDv2Base):
|
||||||
self._tagdata[tag] = data
|
self._tagdata[tag] = data
|
||||||
self.tagtype[tag] = typ
|
self.tagtype[tag] = typ
|
||||||
|
|
||||||
msg += " - value: " + (
|
bytes_value = size if size > 32 else repr(data)
|
||||||
"<table: %d bytes>" % size if size > 32 else repr(data)
|
msg += f" - value: <table: {bytes_value} bytes>"
|
||||||
)
|
|
||||||
logger.debug(msg)
|
logger.debug(msg)
|
||||||
|
|
||||||
(self.next,) = (
|
(self.next,) = (
|
||||||
|
@ -981,9 +981,10 @@ class ImageFileDirectory_v2(_IFDv2Base):
|
||||||
|
|
||||||
tagname = TiffTags.lookup(tag, self.group).name
|
tagname = TiffTags.lookup(tag, self.group).name
|
||||||
typname = "ifd" if is_ifd else TYPES.get(typ, "unknown")
|
typname = "ifd" if is_ifd else TYPES.get(typ, "unknown")
|
||||||
msg = f"save: {tagname} ({tag}) - type: {typname} ({typ})"
|
bytes_value = len(data) if len(data) >= 16 else str(values)
|
||||||
msg += " - value: " + (
|
msg = (
|
||||||
"<table: %d bytes>" % len(data) if len(data) >= 16 else str(values)
|
f"save: {tagname} ({tag}) - type: {typname} ({typ})"
|
||||||
|
f" - value: <table: {bytes_value} bytes>"
|
||||||
)
|
)
|
||||||
logger.debug(msg)
|
logger.debug(msg)
|
||||||
|
|
||||||
|
@ -1216,10 +1217,6 @@ class TiffImageFile(ImageFile.ImageFile):
|
||||||
def _seek(self, frame: int) -> None:
|
def _seek(self, frame: int) -> None:
|
||||||
self.fp = self._fp
|
self.fp = self._fp
|
||||||
|
|
||||||
# reset buffered io handle in case fp
|
|
||||||
# was passed to libtiff, invalidating the buffer
|
|
||||||
self.fp.tell()
|
|
||||||
|
|
||||||
while len(self._frame_pos) <= frame:
|
while len(self._frame_pos) <= frame:
|
||||||
if not self.__next:
|
if not self.__next:
|
||||||
msg = "no more images in TIFF file"
|
msg = "no more images in TIFF file"
|
||||||
|
@ -1303,10 +1300,6 @@ class TiffImageFile(ImageFile.ImageFile):
|
||||||
if not self.is_animated:
|
if not self.is_animated:
|
||||||
self._close_exclusive_fp_after_loading = True
|
self._close_exclusive_fp_after_loading = True
|
||||||
|
|
||||||
# reset buffered io handle in case fp
|
|
||||||
# was passed to libtiff, invalidating the buffer
|
|
||||||
self.fp.tell()
|
|
||||||
|
|
||||||
# load IFD data from fp before it is closed
|
# load IFD data from fp before it is closed
|
||||||
exif = self.getexif()
|
exif = self.getexif()
|
||||||
for key in TiffTags.TAGS_V2_GROUPS:
|
for key in TiffTags.TAGS_V2_GROUPS:
|
||||||
|
@ -1381,8 +1374,17 @@ class TiffImageFile(ImageFile.ImageFile):
|
||||||
logger.debug("have fileno, calling fileno version of the decoder.")
|
logger.debug("have fileno, calling fileno version of the decoder.")
|
||||||
if not close_self_fp:
|
if not close_self_fp:
|
||||||
self.fp.seek(0)
|
self.fp.seek(0)
|
||||||
|
# Save and restore the file position, because libtiff will move it
|
||||||
|
# outside of the Python runtime, and that will confuse
|
||||||
|
# io.BufferedReader and possible others.
|
||||||
|
# NOTE: This must use os.lseek(), and not fp.tell()/fp.seek(),
|
||||||
|
# because the buffer read head already may not equal the actual
|
||||||
|
# file position, and fp.seek() may just adjust it's internal
|
||||||
|
# pointer and not actually seek the OS file handle.
|
||||||
|
pos = os.lseek(fp, 0, os.SEEK_CUR)
|
||||||
# 4 bytes, otherwise the trace might error out
|
# 4 bytes, otherwise the trace might error out
|
||||||
n, err = decoder.decode(b"fpfp")
|
n, err = decoder.decode(b"fpfp")
|
||||||
|
os.lseek(fp, pos, os.SEEK_SET)
|
||||||
else:
|
else:
|
||||||
# we have something else.
|
# we have something else.
|
||||||
logger.debug("don't have fileno or getvalue. just reading")
|
logger.debug("don't have fileno or getvalue. just reading")
|
||||||
|
|
|
@ -44,7 +44,7 @@ _T_co = TypeVar("_T_co", covariant=True)
|
||||||
|
|
||||||
|
|
||||||
class SupportsRead(Protocol[_T_co]):
|
class SupportsRead(Protocol[_T_co]):
|
||||||
def read(self, __length: int = ...) -> _T_co: ...
|
def read(self, length: int = ..., /) -> _T_co: ...
|
||||||
|
|
||||||
|
|
||||||
StrOrBytesPath = Union[str, bytes, os.PathLike[str], os.PathLike[bytes]]
|
StrOrBytesPath = Union[str, bytes, os.PathLike[str], os.PathLike[bytes]]
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 9a9d1275f025f737cdaa3c451ba07129dd95f361
|
Subproject commit 74a9795bc64ff786b7e7d33bdec2843cf17e512e
|
|
@ -112,12 +112,12 @@ V = {
|
||||||
"BROTLI": "1.1.0",
|
"BROTLI": "1.1.0",
|
||||||
"FREETYPE": "2.13.3",
|
"FREETYPE": "2.13.3",
|
||||||
"FRIBIDI": "1.0.16",
|
"FRIBIDI": "1.0.16",
|
||||||
"HARFBUZZ": "10.0.1",
|
"HARFBUZZ": "10.1.0",
|
||||||
"JPEGTURBO": "3.0.4",
|
"JPEGTURBO": "3.1.0",
|
||||||
"LCMS2": "2.16",
|
"LCMS2": "2.16",
|
||||||
"LIBPNG": "1.6.44",
|
"LIBPNG": "1.6.44",
|
||||||
"LIBWEBP": "1.4.0",
|
"LIBWEBP": "1.4.0",
|
||||||
"OPENJPEG": "2.5.2",
|
"OPENJPEG": "2.5.3",
|
||||||
"TIFF": "4.6.0",
|
"TIFF": "4.6.0",
|
||||||
"XZ": "5.6.3",
|
"XZ": "5.6.3",
|
||||||
"ZLIBNG": "2.2.2",
|
"ZLIBNG": "2.2.2",
|
||||||
|
@ -154,7 +154,7 @@ DEPS: dict[str, dict[str, Any]] = {
|
||||||
cmd_copy("cjpeg-static.exe", "cjpeg.exe"),
|
cmd_copy("cjpeg-static.exe", "cjpeg.exe"),
|
||||||
cmd_copy("djpeg-static.exe", "djpeg.exe"),
|
cmd_copy("djpeg-static.exe", "djpeg.exe"),
|
||||||
],
|
],
|
||||||
"headers": ["j*.h"],
|
"headers": ["jconfig.h", r"src\j*.h"],
|
||||||
"libs": ["libjpeg.lib"],
|
"libs": ["libjpeg.lib"],
|
||||||
"bins": ["cjpeg.exe", "djpeg.exe"],
|
"bins": ["cjpeg.exe", "djpeg.exe"],
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue
Block a user