diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index b4fb6a7a..666ecdcb 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -28,18 +28,17 @@ jobs: strategy: matrix: container: - - quay.io/pypa/manylinux1_x86_64 - - quay.io/pypa/manylinux2010_x86_64 - quay.io/pypa/manylinux2014_x86_64 python-version: - cp36-cp36m - cp37-cp37m - cp38-cp38 + - cp39-cp39 container: ${{ matrix.container }} steps: - uses: actions/checkout@v1 - name: Set PATH - run: echo "::add-path::/opt/python/${{ matrix.python-version }}/bin" + run: echo "/opt/python/${{ matrix.python-version }}/bin" >> $GITHUB_PATH - name: Install dependencies run: | python -m pip install --upgrade pip @@ -57,14 +56,14 @@ jobs: strategy: matrix: os: [macos-latest, windows-latest] - python-version: [3.6, 3.7, 3.8] + python-version: [3.6, 3.7, 3.8, 3.9] steps: - uses: actions/checkout@v1 - uses: actions/setup-python@v1 with: python-version: ${{ matrix.python-version }} - name: Set PATH # See actions/virtual-environments#294 - run: echo "::add-path::C:\Program Files (x86)\Windows Kits\10\bin\10.0.18362.0\x64" + run: echo "C:\Program Files (x86)\Windows Kits\10\bin\10.0.18362.0\x64" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append if: runner.os == 'Windows' - name: Install dependencies run: | diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 873612f0..a40e9ad6 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -14,23 +14,17 @@ jobs: strategy: matrix: container: - - quay.io/pypa/manylinux1_x86_64 - - quay.io/pypa/manylinux2010_x86_64 - quay.io/pypa/manylinux2014_x86_64 python-version: - cp36-cp36m - cp37-cp37m - cp38-cp38 - exclude: - - container: quay.io/pypa/manylinux2014_x86_64 - python-version: cp27-cp27m - - container: quay.io/pypa/manylinux2014_x86_64 - python-version: cp27-cp27mu + - cp39-cp39 container: ${{ matrix.container }} steps: - uses: actions/checkout@v1 - name: Set PATH - run: echo "::add-path::/opt/python/${{ matrix.python-version }}/bin" + run: echo "/opt/python/${{ matrix.python-version }}/bin" >> $GITHUB_PATH - name: Install dependencies run: python -m pip install --upgrade pip - name: Lint with flake8 @@ -40,21 +34,21 @@ jobs: flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics - name: Test run: | - pip install tox cython + pip install tox cython numpy tox -e py other: runs-on: ${{ matrix.os }} strategy: matrix: os: [macos-latest, windows-latest] - python-version: [3.6, 3.7, 3.8] + python-version: [3.6, 3.7, 3.8, 3.9] steps: - uses: actions/checkout@v2 - uses: actions/setup-python@v1 with: python-version: ${{ matrix.python-version }} - name: Set PATH # See actions/virtual-environments#294 - run: echo "::add-path::C:\Program Files (x86)\Windows Kits\10\bin\10.0.18362.0\x64" + run: echo "C:\Program Files (x86)\Windows Kits\10\bin\10.0.18362.0\x64" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append if: runner.os == 'Windows' - name: Install dependencies run: python -m pip install --upgrade pip @@ -65,5 +59,5 @@ jobs: flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics - name: Test run: | - pip install tox cython + pip install tox cython numpy tox -e py diff --git a/CHANGES.rst b/CHANGES.rst index 35bddadd..3349ad47 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,3 +1,18 @@ +1.9.17 (2021-01-15) +------------------- + +- [api] Fix incorrect fill layer parse (fix #254) + +1.9.16 (2020-09-24) +------------------- + +- [package] Drop py27 and py35 support +- [psd] Workaround Enum bug (fix #241) +- [composite] Fix transparency issue (fix #242) +- [composite] Fix mask disable flag (fix #243) +- [api] Add workaround for creating PSB (fix #246) +- [api] Fix incorrect adjustment parse (fix #247) + 1.9.15 (2020-07-17) ------------------- diff --git a/setup.cfg b/setup.cfg index e664892c..52312c08 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,5 +1,5 @@ [tox:tox] -envlist = clean,py36,py37,py38,report +envlist = clean,py36,py37,py38,py39,report [testenv] commands = py.test --cov=psd_tools --cov-append --cov-report=term [] @@ -10,7 +10,7 @@ deps= cython depends = {py36,py37,py38}: clean - report: py36,py37,py38 + report: py36,py37,py38,py39 [testenv:report] deps = coverage diff --git a/setup.py b/setup.py index 3be128a0..c30bb456 100755 --- a/setup.py +++ b/setup.py @@ -50,7 +50,7 @@ def get_version(): 'aggdraw', 'numpy', 'scipy', - 'scikit-image<=0.16.2', + 'scikit-image', ], keywords="photoshop psd pil pillow", package_dir={'': 'src'}, @@ -66,6 +66,7 @@ def get_version(): 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: 3.9', 'Topic :: Multimedia :: Graphics', 'Topic :: Multimedia :: Graphics :: Viewers', 'Topic :: Multimedia :: Graphics :: Graphics Conversion', diff --git a/src/psd_tools/api/psd_image.py b/src/psd_tools/api/psd_image.py index 83b34478..de13a4e8 100644 --- a/src/psd_tools/api/psd_image.py +++ b/src/psd_tools/api/psd_image.py @@ -10,7 +10,7 @@ from psd_tools.psd import PSD, FileHeader, ImageData, ImageResources from psd_tools.api.layers import ( Artboard, Group, PixelLayer, ShapeLayer, SmartObjectLayer, TypeLayer, - GroupMixin + GroupMixin, FillLayer ) from psd_tools.api import adjustments from psd_tools.api import deprecated @@ -582,19 +582,17 @@ def _init(self): break # If nothing applies, this is either a shape or pixel layer. + shape_condition = record.flags.pixel_data_irrelevant and ( + Tag.VECTOR_ORIGINATION_DATA in blocks or + Tag.VECTOR_MASK_SETTING1 in blocks or + Tag.VECTOR_MASK_SETTING2 in blocks or + Tag.VECTOR_STROKE_DATA in blocks or + Tag.VECTOR_STROKE_CONTENT_DATA in blocks) + if isinstance(layer, (type(None), FillLayer)) and shape_condition: + layer = ShapeLayer(self, record, channels, current_group) + if layer is None: - if ( - record.flags.pixel_data_irrelevant and ( - Tag.VECTOR_ORIGINATION_DATA in blocks or - Tag.VECTOR_MASK_SETTING1 in blocks or - Tag.VECTOR_MASK_SETTING2 in blocks or - Tag.VECTOR_STROKE_DATA in blocks or - Tag.VECTOR_STROKE_CONTENT_DATA in blocks - ) - ): - layer = ShapeLayer(self, record, channels, current_group) - else: - layer = PixelLayer(self, record, channels, current_group) + layer = PixelLayer(self, record, channels, current_group) assert layer is not None diff --git a/src/psd_tools/compression/__init__.py b/src/psd_tools/compression/__init__.py index 89e8ce1b..02135e07 100644 --- a/src/psd_tools/compression/__init__.py +++ b/src/psd_tools/compression/__init__.py @@ -109,7 +109,7 @@ def encode_prediction(data, w, h, depth): arr = array.array('B', data) arr = _shuffle_byte_order(arr, w, h) arr = _delta_encode(arr, 0x100, w * 4, h) - return getattr(arr, 'tobytes', getattr(arr, 'tostring'))() + return getattr(arr, 'tobytes', getattr(arr, 'tostring', None))() else: raise ValueError('Invalid pixel size %d' % (depth)) @@ -128,7 +128,7 @@ def decode_prediction(data, w, h, depth): else: raise ValueError('Invalid pixel size %d' % (depth)) - return getattr(arr, 'tobytes', getattr(arr, 'tostring'))() + return getattr(arr, 'tobytes', getattr(arr, 'tostring', None))() def _delta_encode(arr, mod, w, h): diff --git a/src/psd_tools/version.py b/src/psd_tools/version.py index 43bcd4cf..7e3e39ed 100644 --- a/src/psd_tools/version.py +++ b/src/psd_tools/version.py @@ -1 +1 @@ -__version__ = '1.9.16' +__version__ = '1.9.17' diff --git a/tests/psd_tools/api/test_layers.py b/tests/psd_tools/api/test_layers.py index 60e3c3de..b5c47954 100644 --- a/tests/psd_tools/api/test_layers.py +++ b/tests/psd_tools/api/test_layers.py @@ -3,7 +3,7 @@ import logging from psd_tools.api.psd_image import PSDImage -from psd_tools.api.layers import Group +from psd_tools.api.layers import Group, ShapeLayer, PixelLayer from psd_tools.constants import BlendMode from ..utils import full_name @@ -201,3 +201,11 @@ def test_group_extract_bbox(): psd = PSDImage.open(full_name('hidden-groups.psd')) assert Group.extract_bbox(psd[1:], False) == (40, 72, 83, 134) assert Group.extract_bbox(psd[1:], True) == (25, 34, 83, 134) + + +def test_shape_and_fill_layer(): + psd = PSDImage.open(full_name('vector-mask2.psd')) + for i in range(8): + assert isinstance(psd[i], ShapeLayer) + for i in range(8, 10): + assert isinstance(psd[i], PixelLayer)