diff options
-rw-r--r-- | .appveyor.yml | 62 | ||||
-rw-r--r-- | .travis.yml | 223 | ||||
-rw-r--r-- | README.md | 2 | ||||
-rw-r--r-- | azure-pipelines.yml | 328 | ||||
-rw-r--r-- | azure-pipelines/build.bash | 5 | ||||
-rw-r--r-- | debian/changelog | 6 | ||||
-rw-r--r-- | docs/installation.rst | 5 | ||||
-rw-r--r-- | docs/release_notes.rst | 11 | ||||
-rw-r--r-- | setup.py | 8 | ||||
-rw-r--r-- | src/qpdf/object.cpp | 5 | ||||
-rw-r--r-- | src/qpdf/pikepdf.h | 2 | ||||
-rw-r--r-- | src/qpdf/shims.cpp | 45 | ||||
-rw-r--r-- | src/qpdf/shims.h | 30 | ||||
-rw-r--r-- | tests/test_object.py | 18 | ||||
-rw-r--r-- | tests/test_pages.py | 41 |
15 files changed, 282 insertions, 509 deletions
diff --git a/.appveyor.yml b/.appveyor.yml deleted file mode 100644 index 83a108e..0000000 --- a/.appveyor.yml +++ /dev/null @@ -1,62 +0,0 @@ -version: "{build}" -image: Visual Studio 2015 -platform: - - x64 - - x86 -environment: - global: - DISTUTILS_USE_SDK: 1 - MSSdk: 1 - matrix: - - PYTHON: 35 - - PYTHON: 36 - - PYTHON: 37 - #- PYTHON: 38 - TWINE_PASSWORD: - secure: RZZXYbbTOzKMSE/GdzIG/x+eqehSEeu98j0Ggs+/fG8= -install: - - cmd: '"%VS140COMNTOOLS%\..\..\VC\vcvarsall.bat" %PLATFORM%' - - ps: | - $userpath = "$env:APPDATA\Python\Python$env:PYTHON\Scripts" - if ($env:PLATFORM -eq "x64") { - $env:PYTHON = "$env:PYTHON-x64" - $qpdfzip = "https://github.com/qpdf/qpdf/releases/download/release-qpdf-9.0.0/qpdf-9.0.0-bin-msvc64.zip" - } else { - $qpdfzip = "https://github.com/qpdf/qpdf/releases/download/release-qpdf-9.0.0/qpdf-9.0.0-bin-msvc32.zip" - } - $env:PATH = "C:\Python$env:PYTHON;C:\Python$env:PYTHON\Scripts;$userpath;$env:PATH" - echo $env:PATH - python -m pip install --disable-pip-version-check --upgrade pip setuptools wheel - pip install pybind11 - - Invoke-WebRequest -Uri $qpdfzip -OutFile "qpdf-release.zip" - 7z x "qpdf-release.zip" -oc:\ - $qpdfdir = Get-ChildItem c:\qpdf-* - Move-Item -Path $qpdfdir -Destination c:\qpdf - -build_script: - - ps: | - cp c:\qpdf\bin\qpdf*.dll src\pikepdf - $env:INCLUDE += ";c:\qpdf\include" - $env:LIB += ";c:\qpdf\lib" - $env:LIBPATH +=";c:\qpdf\lib" - python setup.py bdist_wheel - $wheel = Get-ChildItem -Path dist\pikepdf*.whl - pip install --verbose $wheel - -test_script: - - pip install -r requirements/test.txt - - pytest -n auto - -artifacts: - - path: dist\*.whl - name: pypi - -deploy_script: - - ps: | - if ($env:APPVEYOR_REPO_TAG -eq "true") - { - pip install twine - $env:TWINE_USERNAME = "ocrmypdf-travis" - twine upload dist\*.whl - } diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 4aefe18..0000000 --- a/.travis.yml +++ /dev/null @@ -1,223 +0,0 @@ -language: python -dist: trusty -sudo: false -cache: - ccache: true - directories: - - $HOME/Library/Caches/Homebrew - -env: - global: - - QPDF_RELEASE=https://github.com/qpdf/qpdf/releases/download/release-qpdf-9.0.0/qpdf-9.0.0.tar.gz - - JPEG_RELEASE=https://www.ijg.org/files/jpegsrc.v9c.tar.gz - - ZLIB_RELEASE=https://www.zlib.net/zlib-1.2.11.tar.gz - - TWINE_USERNAME=ocrmypdf-travis - # TWINE_PASSWORD - - secure: "d1PfCVoqvFFwAqm0QEozLLoUdEHaY0kAvawfc4lKdLSjI+yOJYoNdknU0r3TdwttNEF2VV+aY9q/4wVnYrEiF4L13E3s+UtDqIXwGk/b14JrdExIx/0yj642kbCJPycZqqRZgvGwYuhb6EF7e/QrsNYMwZ95E9oTyWa0ZaEkiPrrVJh9XSNDpw9I8REL3GecpfvF/GpHWX0VBHoaJfCgDzDDvHQPdfIXAZg+OLJOLNrR2ivvUD3gR371376fYPMPNsqMNqBghLdX8lnX2zkEc67An9ZBLi1dx46PhHjn8c06QOBQ25wcwtCxSnaXygkq5HXUXnpWmCbPcy3n98bJBE1P86M1eWo5c3KV4zwY3pvC6/ldFFAX0nC5Qr8xVpiBZIZKhqBEsX7HlCIRdN5OzmWXTkRhO05GtloH+IPuS8PH09vlaGfdCmBdJkvQjnkXL9Jdw5JJcIt9c//CgRjJ4CtHySA3I0XEnqbLHRhsYAyfJfM4ya3ou+eETpWVpnkZ4kbn8fuUkIpZL6YS9XtJCVCfh5uNpJ7BV0DzlZqdV//K3s9CTNyFac0L521YcFRwl0Nb72AlzbtGwWgWh1C8qmlJ/ENf0XI3dafvcqzPL61rwBlo0sah9DWxwUDWMUicUtp8qP5GK8VxHse+QlolJQVSb07jD6bf7+mILX0B3Mg=" - # RTD_TOKEN - - secure: "jD4S2pEvuf9oWv7RTWkdgrRw62WoUISiLFnPN9gPJ5ZeqdLeL8r3/+2x7tKa9xo6u6HWKVzo88+gg+HZCHIIZafWqxbhYsdl2g4dp3v807UVdp7rdqd7KkFl8/0XDR9p1J1g0RnRHp2qYtORqPZ0hustXnBQyiA0cA+a7qH9AWfhiU6iUV193YJAwYumSBeDAWgJN6OXAYKaZdLqynC/bmXYMfYM7Xg3sEnKv8eig+gQeSxyN2A/foTG/OgwUc8KVNTvO7w3xqXvfVUc7zm9P8Pdalay0V/8/0DAgZVSLjjnxqfOhmlDfE8OQeDLITBrD2GW0mPlSHP9ic0ymsltayR5Bg8opf3//+HBGoAyVDl0zwDVje4KX1QW2FzRri2ZQ+Lr25nvLkFIwQva2H+PuNUqB3Xw2JzZc4wsEqA83Y8Ijj8Cfc7Xd6hHIttWNe1D+n1tLSf123IW1QNMj7n2xr0AJi3ty1sTnr5WAgBEIR5WSy/roFdbHtLy/8wLE2AtKmhqKWndkSx17K45c35geuxmfthPrh6v1XPAgZZU0sza6dnrdD53WXwV8Z5+y4U+KD9YLf2gydfMSCrImdFWfjy3wMZci8Mn14uAZawwWyo2mfXvRXIVuUQdAx+uPnbkV4KzoAp7Xj7dJlpCxzphnX//1DLczOUJ6EdknbeIH6o=" - -matrix: - include: - - env: PYTHON=3.5 GCC=4.8 - os: linux - sudo: required - python: "3.5" - addons: &gcc48 - apt: - sources: [ubuntu-toolchain-r-test] - packages: [g++-4.8, libexempi-dev] # g++-4.8 supports c++11 but not c++14 at all; g++-4.9 won't work - config: - retries: true - - - env: PYTHON=3.6 GCC=4.8 - os: linux - sudo: required - python: "3.6" - addons: *gcc48 - - - env: PYTHON=3.6 GCC=8 - os: linux - sudo: required - python: "3.6" - addons: - apt: - sources: [ubuntu-toolchain-r-test] - packages: [g++-8, libexempi-dev] # g++-7 supports c++14 - config: - retries: true - - - env: PYTHON=3.7 GCC=5 - os: linux - sudo: required - dist: xenial - python: "3.7" - addons: &gcc5_xenial - apt: - sources: - - sourceline: "ppa:deadsnakes/ppa" - packages: [python3.7-dev, python3.7-venv, g++-5, libexempi-dev] - config: - retries: true - - - env: PYTHON=3.8 GCC=5 - os: linux - sudo: required - dist: xenial - python: "3.8" - addons: &gcc5_xenial - apt: - sources: - - sourceline: "ppa:deadsnakes/ppa" - packages: [python3.8-dev, python3.8-venv, g++-5, libexempi-dev] - config: - retries: true - - - os: osx - osx_image: xcode9.4 - language: generic - addons: - homebrew: - update: true - packages: - - ccache - - exempi - - python - - qpdf - - - stage: wheels - os: osx - osx_image: xcode9.4 - language: cpp # osx + language: python is broken - addons: - homebrew: - update: true - packages: - - python - - qpdf - install: - - clang --version - - $PYTHON_CMD --version - - echo "CC=$CC CXX=$CXX" - - $PYTHON_CMD -m pip install --user cibuildwheel==0.12.0 - script: - - $PYTHON_CMD setup.py sdist -d wheelhouse - - export CCACHE_BASEDIR=`python3 -c "import tempfile; import os; print(os.path.realpath(tempfile.gettempdir()))"` - - export CIBW_BEFORE_BUILD='pip install pybind11' - - export CIBW_SKIP="cp27-* cp34-*" - - $PYTHON_CMD -m cibuildwheel --output-dir wheelhouse - - | - if [[ $TRAVIS_TAG ]]; then - $PYTHON_CMD -m pip install --user twine - $PYTHON_CMD -m twine upload wheelhouse/*.whl wheelhouse/*.tar.gz - fi - - - stage: wheels - os: linux - python: "3.6" # only need one environment to build all linux wheels - sudo: required - services: - - docker - install: - - $PYTHON_CMD -m pip install cibuildwheel==0.12.0 - #- mkdir gcc-x86_64 && wget -q https://github.com/Noctem/pogeo-toolchain/releases/download/v1.4/gcc-7.2-binutils-2.29-centos5-x86-64.tar.bz2 -O - | tar xj -C gcc-x86_64 --strip-components=1 - #- mkdir ccache && wget -q https://www.samba.org/ftp/ccache/ccache-3.3.4.tar.bz2 -O - | tar xj -C ccache --strip-components=1 - - mkdir zlib && wget -q $ZLIB_RELEASE -O - | tar xz -C zlib --strip-components=1 - - mkdir jpeg && wget -q $JPEG_RELEASE -O - | tar xz -C jpeg --strip-components=1 - - mkdir qpdf && wget -q $QPDF_RELEASE -O - | tar xz -C qpdf --strip-components=1 - script: - #- export CIBW_ENVIRONMENT='ARCH=x86_64 PATH="`pwd`/gcc-$ARCH/bin:$PATH" CC="ccache cc" CXX="ccache c++" CXXFLAGS="-static-libstdc++" LD_LIBRARY_PATH="`pwd`/gcc-$ARCH/lib" CCACHE_BASEDIR=`python -c "import tempfile; import os; print(os.path.realpath(tempfile.gettempdir()))"` CCACHE_DIR=/host'$HOME'/.ccache' - #- export CIBW_BEFORE_BUILD='pip install pybind11 && [ -d ccache/$ARCH ] || (unset CC CXX CXXFLAGS && mkdir ccache/$ARCH && cd ccache/$ARCH && ../configure && make install)' - #- export CIBW_ENVIRONMENT='ARCH=x86_64 PATH="`pwd`/gcc-$ARCH/bin:$PATH" CC="cc" CXX="c++" CXXFLAGS="-static-libstdc++" LD_LIBRARY_PATH="`pwd`/gcc-$ARCH/lib:$LD_LIBRARY_PATH"' - - >- - export CIBW_ENVIRONMENT=' - LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH - CXXFLAGS="-I/usr/local/include" - LDFLAGS="-L/usr/local/lib"' - - >- - export CIBW_BEFORE_BUILD=' - [ ! -f /usr/local/lib/libz.a ] && - cd zlib && - ./configure && - make -j install && - cd .. ; - [ ! -f /usr/local/lib/libjpeg.a ] && - cd jpeg && - ./configure && - make -j install && - cd .. ; - [ ! -f /usr/local/lib/libqpdf.a ] && - cd qpdf && - ./autogen.sh && - ./configure && - make -j install && - cd .. ; - pip install pybind11' - - export CIBW_SKIP="cp27-* cp34-* *i686" - - export CIBW_TEST_REQUIRES="-r requirements/test.txt" - - export CIBW_TEST_COMMAND="pytest -nauto {project}/tests" - - cibuildwheel --output-dir wheelhouse - - | - if [[ $TRAVIS_TAG ]]; then - $PYTHON_CMD -m pip install twine - $PYTHON_CMD -m twine upload wheelhouse/*.whl - fi - after_script: - - curl -X POST -d "token=$RTD_TOKEN" https://readthedocs.org/api/v2/webhook/pikepdf/39557/ - -stages: - - name: test - - name: wheels - -before_install: - - | - if [ "$TRAVIS_OS_NAME" = "linux" ]; then - if [ -n "$GCC" ]; then - export CC="gcc-$GCC" - export CXX="g++-$GCC" - export LD_LIBRARY_PATH="/lib:/usr/lib:/usr/local/lib" - elif [ -n "$CLANG" ]; then - CC="ccache clang-$CLANG" - CXX="ccache clang++-$CLANG" - export CFLAGS="-Qunused-arguments" - export CXXFLAGS="-Qunused-arguments -stdlib=libc++" - fi - if [ "$PYTHON" = "3.6" ]; then - pyenv global system $PYTHON # https://github.com/travis-ci/travis-ci/issues/8363 - else - python$PYTHON -m ensurepip - fi - PYTHON_CMD=python$PYTHON - elif [ "$TRAVIS_OS_NAME" == "osx" ]; then - export PATH=/usr/local/opt/ccache/libexec:/usr/local/bin:$PATH - CC=clang - CXX=clang++ - PYTHON_CMD=python3 - fi - $PYTHON_CMD -m pip install --upgrade pip wheel - -install: - - | - if [ "$TRAVIS_OS_NAME" = "linux" ]; then - mkdir qpdf - wget -q $QPDF_RELEASE -O - | tar xz -C qpdf --strip-components=1 - cd qpdf/ - ./configure CC="ccache $CC" CXX="ccache $CXX" - make -j 2 - sudo make install - cd .. - elif [ "$TRAVIS_OS_NAME" = "osx" ]; then - : # no op for now - fi - - $PYTHON_CMD setup.py sdist - - $PYTHON_CMD -m pip install pybind11 - - $PYTHON_CMD -m pip install --verbose dist/*.tar.gz - - $PYTHON_CMD -m pip install -r requirements/test.txt - -script: - - python3 -m pytest - -branches: - except: - - docs - - azure-pipelines @@ -3,7 +3,7 @@ pikepdf **pikepdf** is a Python library for reading and writing PDF files. -[![Travis CI build status (Linux and macOS)](https://img.shields.io/travis/pikepdf/pikepdf/master.svg?label=Linux%2fmacOS%20build)](https://travis-ci.org/pikepdf/pikepdf) [![AppVeyor CI build status (Windows)](https://img.shields.io/appveyor/ci/jbarlow83/pikepdf/master.svg?label=Windows%20build)](https://ci.appveyor.com/project/jbarlow83/pikepdf) [![PyPI](https://img.shields.io/pypi/v/pikepdf.svg)](https://pypi.org/project/pikepdf/) ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/pikepdf) +[![Build Status](https://dev.azure.com/jim0585/pikepdf/_apis/build/status/pikepdf.pikepdf?branchName=master)](https://dev.azure.com/jim0585/pikepdf/_build/latest?definitionId=1&branchName=master) [![PyPI](https://img.shields.io/pypi/v/pikepdf.svg)](https://pypi.org/project/pikepdf/) ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/pikepdf) pikepdf is based on [QPDF](https://github.com/qpdf/qpdf), a powerful PDF manipulation and repair library. diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 93d39e6..db6a4d7 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -4,141 +4,199 @@ variables: jpeg_release: "https://www.ijg.org/files/jpegsrc.v9c.tar.gz" zlib_release: "https://www.zlib.net/zlib-1.2.11.tar.gz" cibw_skip: "cp27-* cp34-*" - cibw_test_command: "pytest -nauto {project}/tests" + cibw_test_command: "pytest -nauto --junitxml=test.xml {project}/tests" cibw_test_requires: "-r requirements/test.txt" - cibuildwheel_version: "0.12.0" + cibuildwheel_version: "0375e92110113689025a5f05376f77d220d8b5c9" cibw_before_build: "pip install pybind11" -jobs: - - job: linux_sdist - pool: { vmImage: "Ubuntu-16.04" } - steps: - - task: UsePythonVersion@0 - - bash: | - mkdir qpdf && wget -q $QPDF_RELEASE -O - | tar xz -C qpdf --strip-components=1 - cd qpdf/ - ./configure - make -j 2 - sudo make install - cd .. - displayName: "Build QPDF" - - bash: | - python -m pip install --upgrade pip - python setup.py sdist - python -m pip install pybind11 - python -m pip install --verbose dist/*.tar.gz - python -m pip install -r requirements/test.txt - displayName: "Build sdist" - - bash: | - export LD_LIBRARY_PATH="/usr/local/lib:$LD_LIBRARY_PATH" - python -m pytest -nauto - displayName: "Test" - - task: PublishBuildArtifacts@1 - inputs: { pathtoPublish: "dist" } - - job: linux - pool: { vmImage: "Ubuntu-16.04" } - variables: - cibw_environment: >- - LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH - CXXFLAGS="-I/usr/local/include" - LDFLAGS="-L/usr/local/lib" - cibw_before_build: >- # yaml: folded newlines to spaces, no newline at end - [ ! -f /usr/local/lib/libz.a ] && - cd zlib && - ./configure && - make -j install && - cd .. ; - [ ! -f /usr/local/lib/libjpeg.a ] && - cd jpeg && - ./configure && - make -j install && - cd .. ; - [ ! -f /usr/local/lib/libqpdf.a ] && - cd qpdf && - ./autogen.sh && - ./configure && - make -j install && - cd .. ; - pip install pybind11 - steps: - - task: UsePythonVersion@0 - - bash: | - mkdir zlib && wget -q $ZLIB_RELEASE -O - | tar xz -C zlib --strip-components=1 - mkdir jpeg && wget -q $JPEG_RELEASE -O - | tar xz -C jpeg --strip-components=1 - mkdir qpdf && wget -q $QPDF_RELEASE -O - | tar xz -C qpdf --strip-components=1 - - bash: source azure-pipelines/build.bash - - task: PublishBuildArtifacts@1 - inputs: { pathtoPublish: "wheelhouse" } - - job: macos - pool: { vmImage: "macOS-10.13" } - variables: - cibw_before_build: >- - pip install pybind11 && - brew install qpdf - steps: - - task: UsePythonVersion@0 - - bash: source azure-pipelines/build.bash - - task: PublishBuildArtifacts@1 - inputs: { pathtoPublish: "wheelhouse" } - - job: windows64 - pool: { vmImage: "vs2017-win2016" } - variables: - qpdf_windows: ${{ format('https://github.com/qpdf/qpdf/releases/download/release-qpdf-{0}/qpdf-{0}-bin-msvc64.zip', variables.qpdf_version) }} - cibw_skip: "cp27-* cp34-* cp35-win32* cp36-win32* cp37-win32* cp38-win32*" - cibw_environment: >- - INCLUDE="$INCLUDE;c:\\qpdf\\include" - LIB="$LIB;c:\\qpdf\\lib" - LIBPATH="$LIBPATH;c:\\qpdf\\lib" - steps: - - { - task: UsePythonVersion@0, - inputs: { versionSpec: "3.5", architecture: x64 }, - } - - { - task: UsePythonVersion@0, - inputs: { versionSpec: "3.6", architecture: x64 }, - } - - { - task: UsePythonVersion@0, - inputs: { versionSpec: "3.7", architecture: x64 }, - } - # - { - # task: UsePythonVersion@0, - # inputs: { versionSpec: "3.8", architecture: x64 }, - # } - - powershell: azure-pipelines/win-download-qpdf.ps1 - displayName: "Download QPDF" - - bash: source azure-pipelines/build.bash - - task: PublishBuildArtifacts@1 - inputs: { pathtoPublish: "wheelhouse" } - - job: windows32 - pool: { vmImage: "vs2017-win2016" } - variables: - qpdf_windows: ${{ format('https://github.com/qpdf/qpdf/releases/download/release-qpdf-{0}/qpdf-{0}-bin-msvc32.zip', variables.qpdf_version) }} - cibw_skip: "cp27-* cp34-* cp35-win_amd64* cp36-win_amd64* cp37-win_amd64* cp38-win_amd64*" - cibw_environment: >- - INCLUDE="$INCLUDE;c:\\qpdf\\include" - LIB="$LIB;c:\\qpdf\\lib" - LIBPATH="$LIBPATH;c:\\qpdf\\lib" - steps: - - { - task: UsePythonVersion@0, - inputs: { versionSpec: "3.5", architecture: x86 }, - } - - { - task: UsePythonVersion@0, - inputs: { versionSpec: "3.6", architecture: x86 }, - } - - { - task: UsePythonVersion@0, - inputs: { versionSpec: "3.7", architecture: x86 }, - } - # - { - # task: UsePythonVersion@0, - # inputs: { versionSpec: "3.8", architecture: x64 }, - # } - - powershell: azure-pipelines/win-download-qpdf.ps1 - displayName: "Download QPDF" - - bash: source azure-pipelines/build.bash - - task: PublishBuildArtifacts@1 - inputs: { pathtoPublish: "wheelhouse" } +trigger: + tags: + include: + - v* + branches: + include: + - "*" + +stages: + - stage: "Build_and_test" + jobs: + - job: linux_sdist + pool: { vmImage: "Ubuntu-16.04" } + steps: + - task: UsePythonVersion@0 + - bash: | + mkdir qpdf && wget -q $QPDF_RELEASE -O - | tar xz -C qpdf --strip-components=1 + cd qpdf/ + ./configure + make -j 2 + sudo make install + cd .. + displayName: "Build QPDF" + - bash: | + python -m pip install --upgrade pip + python setup.py sdist + python -m pip install pybind11 + python -m pip install --verbose dist/*.tar.gz + python -m pip install -r requirements/test.txt + displayName: "Build sdist" + - bash: | + export LD_LIBRARY_PATH="/usr/local/lib:$LD_LIBRARY_PATH" + python -m pytest -nauto --junitxml=test-sdist.xml + displayName: "Test" + - task: PublishTestResults@2 + inputs: + testResultsFiles: "test-sdist.xml" + testRunTitle: "$(Agent.OS) - $(Build.DefinitionName) - Python $(python.version)" + condition: succeededOrFailed() + - publish: dist + artifact: sdist + - job: linux + pool: { vmImage: "Ubuntu-16.04" } + variables: + cibw_environment: >- + LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH + CXXFLAGS="-I/usr/local/include" + LDFLAGS="-L/usr/local/lib" + cibw_before_build: + >- # yaml: folded newlines to spaces, no newline at end + [ ! -f /usr/local/lib/libz.a ] && + cd zlib && + ./configure && + make -j install && + cd .. ; + [ ! -f /usr/local/lib/libjpeg.a ] && + cd jpeg && + ./configure && + make -j install && + cd .. ; + [ ! -f /usr/local/lib/libqpdf.a ] && + cd qpdf && + ./autogen.sh && + ./configure && + make -j install && + cd .. ; + pip install pybind11 + steps: + - task: UsePythonVersion@0 + - bash: | + mkdir zlib && wget -q $ZLIB_RELEASE -O - | tar xz -C zlib --strip-components=1 + mkdir jpeg && wget -q $JPEG_RELEASE -O - | tar xz -C jpeg --strip-components=1 + mkdir qpdf && wget -q $QPDF_RELEASE -O - | tar xz -C qpdf --strip-components=1 + displayName: "Download QPDF and components" + - bash: source azure-pipelines/build.bash + displayName: "cibuildwheel" + - task: PublishTestResults@2 + inputs: + testResultsFiles: "test.xml" + testRunTitle: "$(Agent.OS) - $(Build.DefinitionName) - Python $(python.version)" + condition: succeededOrFailed() + - publish: dist + artifact: linux + - job: macos + pool: { vmImage: "macOS-10.13" } + variables: + cibw_before_build: >- + pip install pybind11 && + brew install qpdf + steps: + - task: UsePythonVersion@0 + - bash: source azure-pipelines/build.bash + displayName: cibuildwheel + - publish: dist + artifact: macos + - job: windows64 + pool: { vmImage: "vs2017-win2016" } + variables: + qpdf_windows: ${{ format('https://github.com/qpdf/qpdf/releases/download/release-qpdf-{0}/qpdf-{0}-bin-msvc64.zip', variables.qpdf_version) }} + cibw_skip: "cp27-* cp34-* cp35-win32* cp36-win32* cp37-win32* cp38-win32*" + cibw_environment: >- + INCLUDE="$INCLUDE;c:\\qpdf\\include" + LIB="$LIB;c:\\qpdf\\lib" + LIBPATH="$LIBPATH;c:\\qpdf\\lib" + steps: + - task: UsePythonVersion@0 + - powershell: azure-pipelines/win-download-qpdf.ps1 + displayName: "Download QPDF" + - bash: source azure-pipelines/build.bash + displayName: "cibuildwheel" + - publish: dist + artifact: win64 + - job: windows32 + pool: { vmImage: "vs2017-win2016" } + variables: + qpdf_windows: ${{ format('https://github.com/qpdf/qpdf/releases/download/release-qpdf-{0}/qpdf-{0}-bin-msvc32.zip', variables.qpdf_version) }} + cibw_skip: "cp27-* cp34-* cp35-win_amd64* cp36-win_amd64* cp37-win_amd64* cp38-win_amd64*" + cibw_environment: >- + INCLUDE="$INCLUDE;c:\\qpdf\\include" + LIB="$LIB;c:\\qpdf\\lib" + LIBPATH="$LIBPATH;c:\\qpdf\\lib" + steps: + - task: UsePythonVersion@0 + - powershell: azure-pipelines/win-download-qpdf.ps1 + displayName: "Download QPDF" + - bash: source azure-pipelines/build.bash + displayName: "cibuildwheel" + - publish: dist + artifact: win32 + + - stage: "Deploy" + jobs: + - deployment: "PyPI" + pool: { vmImage: "ubuntu-18.04" } + environment: "deploy" + strategy: + runOnce: + deploy: + steps: + - task: UsePythonVersion@0 + inputs: + versionSpec: "3.8" + architecture: x64 + - download: current + artifact: sdist + - download: current + artifact: linux + - download: current + artifact: macos + - download: current + artifact: win64 + - download: current + artifact: win32 + - script: | + mkdir -p dist + mv $(Pipeline.Workspace)/sdist/* dist + mv $(Pipeline.Workspace)/linux/* dist + mv $(Pipeline.Workspace)/macos/* dist + mv $(Pipeline.Workspace)/win64/* dist + mv $(Pipeline.Workspace)/win32/* dist + displayName: "Organize artifacts" + - script: | + python -m pip install -U pip + python -m pip install -U twine + cat <<FILE >.pypirc + [distutils] + index-servers = + pypi + testpypi + + [pypi] + username: __token__ + password: $(TOKEN_PYPI) + + [testpypi] + repository: https://test.pypi.org/legacy/ + username: __token__ + password: $(TOKEN_TESTPYPI) + FILE + displayName: "Generate PyPI auth file" + - script: | + python -m twine upload -r "testpypi" --config-file .pypirc dist/* + displayName: "Upload to TestPyPI" + condition: not(startsWith(variables['Build.SourceBranch'], 'refs/tags/')) + - script: | + python -m twine upload --config-file .pypirc dist/* + displayName: "Upload to PyPI" + condition: startsWith(variables['Build.SourceBranch'], 'refs/tags/') + - script: | + curl -X POST -d "token=$(RTD_TOKEN)" https://readthedocs.org/api/v2/webhook/pikepdf/39557/ + displayName: "Trigger ReadTheDocs" diff --git a/azure-pipelines/build.bash b/azure-pipelines/build.bash index 0f57954..7b1b765 100644 --- a/azure-pipelines/build.bash +++ b/azure-pipelines/build.bash @@ -1,5 +1,6 @@ #!/bin/bash set -ex python -m pip install --upgrade pip -pip install cibuildwheel==$CIBUILDWHEEL_VERSION -cibuildwheel --output-dir wheelhouse . +pip install cibuildwheel==$CIBUILDWHEEL_VERSION || \ + pip install git+git://github.com/joerick/cibuildwheel.git@$CIBUILDWHEEL_VERSION +cibuildwheel --output-dir dist . diff --git a/debian/changelog b/debian/changelog index d1fae08..499aaa8 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +pikepdf (1.7.0+dfsg-1) unstable; urgency=medium + + * New upstream release. + + -- Sean Whitton <spwhitton@spwhitton.name> Tue, 12 Nov 2019 09:40:42 -0700 + pikepdf (1.6.5+dfsg-1) unstable; urgency=medium * New upstream release. diff --git a/docs/installation.rst b/docs/installation.rst index 2ae0d7a..28af78a 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -116,8 +116,7 @@ Building from source pikepdf requires: -- a C++11 compliant compiler - GCC (4.8 and up) and clang (3.3 and up); C++14 - is recommended and will produced smaller binaries +- a C++14 compliant compiler - GCC (5 and up) and clang (3.3 and up) - `pybind11 <https://github.com/pybind/pybind11>`_ - libqpdf |qpdf-version| or higher from the `QPDF <https://github.com/qpdf/qpdf>`_ project. @@ -152,7 +151,7 @@ libqpdf.) .. |msvc-zip| replace:: qpdf-|qpdf-version|-bin-msvc64.zip -pikepdf requires a C++11 compliant compiler (i.e. Visual Studio 2015 on +pikepdf requires a C++14 compliant compiler (i.e. Visual Studio 2015 on Windows). See our continuous integration build script in ``.appveyor.yml`` for detailed and current instructions. Or use the wheels which save this pain. diff --git a/docs/release_notes.rst b/docs/release_notes.rst index c306f13..713fcea 100644 --- a/docs/release_notes.rst +++ b/docs/release_notes.rst @@ -18,11 +18,20 @@ is in production use. Note that the C++ extension module ``pikepdf._qpdf`` is a private interface within pikepdf that applications should not access directly, along with any modules with a prefixed underscore. +v1.7.0 +====== + +- Shallow object copy with ``copy.copy(pikepdf.Object)`` is now supported. +- Support for building on C++11 has been removed. A C++14 compiler is now required. +- pikepdf now generates manylinux2010 wheels on Linux. +- Build and deploy infrastructure migrated to Azure Pipelines. +- All wheels are now available for Python 3.5 through 3.8. + v1.6.5 ====== - Fixed build settings to support Python 3.8 on macOS and Linux. Windows support - for Python 3.8 is not currently available since continuous integration providers + for Python 3.8 is not currently tested since continuous integration providers have not updated to Python 3.8 yet. - pybind11 2.4.3 is now required, to support Python 3.8. @@ -74,17 +74,17 @@ def has_flag(compiler, flagname): def cpp_flag(compiler): - """Return the -std=c++[11/14] compiler flag. + """Return the -std=c++[XX] compiler flag. Notes on c++17 and macOS: https://github.com/pybind/python_example/issues/44 """ - flags = ['-std=c++14', '-std=c++11'] + flags = ['-std=c++14'] for flag in flags: if has_flag(compiler, flag): return flag - raise RuntimeError('Unsupported compiler -- at least C++11 support ' 'is needed!') + raise RuntimeError('Unsupported compiler -- at least C++14 support ' 'is needed!') class BuildExt(build_ext): @@ -94,7 +94,7 @@ class BuildExt(build_ext): l_opts = {'msvc': [], 'unix': []} if sys.platform == 'darwin': - darwin_opts = ['-stdlib=libc++', '-mmacosx-version-min=10.7'] + darwin_opts = ['-stdlib=libc++', '-mmacosx-version-min=10.9'] c_opts['unix'] += darwin_opts l_opts['unix'] += darwin_opts diff --git a/src/qpdf/object.cpp b/src/qpdf/object.cpp index 0aed39b..190bf97 100644 --- a/src/qpdf/object.cpp +++ b/src/qpdf/object.cpp @@ -302,6 +302,11 @@ void init_object(py::module& m) return py::bool_(result); } ) + .def("__copy__", + [](QPDFObjectHandle &h) { + return h.shallowCopy(); + } + ) .def("__len__", [](QPDFObjectHandle &h) { if (h.isDictionary()) diff --git a/src/qpdf/pikepdf.h b/src/qpdf/pikepdf.h index 5fa9e53..3499847 100644 --- a/src/qpdf/pikepdf.h +++ b/src/qpdf/pikepdf.h @@ -12,8 +12,6 @@ #include <vector> #include <map> -#include "shims.h" - #include <qpdf/PointerHolder.hh> #include <qpdf/QPDF.hh> #include <qpdf/QPDFObjectHandle.hh> diff --git a/src/qpdf/shims.cpp b/src/qpdf/shims.cpp deleted file mode 100644 index 0020f12..0000000 --- a/src/qpdf/shims.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * Copyright (C) 2017, James R. Barlow (https://github.com/jbarlow83/) - */ - -/* Support for features missing from C++11, minimal versions */ - -#if __cplusplus < 201402L // If C++11 - -#include <string> -#include <sstream> - -#include "pikepdf.h" - -namespace std { - -string quoted(const string &s) -{ - stringstream ss; - ss << '"'; - for (const char &c : s) { - if (c == '"') { - ss << "\\\""; - } else if (c == '\\') { - ss << "\\\\"; - } else { - ss << c; - } - } - ss << '"'; - return ss.str(); -} - -string quoted(const char* s) -{ - return quoted(string(s)); -} - - -}; - -#endif // End C++11
\ No newline at end of file diff --git a/src/qpdf/shims.h b/src/qpdf/shims.h deleted file mode 100644 index 1f14388..0000000 --- a/src/qpdf/shims.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * Copyright (C) 2017, James R. Barlow (https://github.com/jbarlow83/) - */ - -#if __cplusplus < 201402L // If C++11 - -#include <memory> -#include <type_traits> -#include <utility> -#include <string> - -namespace std { - // Provide make_unique for C++11 (not array-capable) - // See https://stackoverflow.com/questions/17902405/how-to-implement-make-unique-function-in-c11/17902439#17902439 for full version if needed - template<typename T, typename ...Args> - unique_ptr<T> make_unique( Args&& ...args ) - { - return unique_ptr<T>( new T( std::forward<Args>(args)... ) ); - } - - // Provide basic std::quoted for C++11 - string quoted(const char* s); - string quoted(const string &s); -}; - -#endif // }} diff --git a/tests/test_object.py b/tests/test_object.py index d100ed6..55cb314 100644 --- a/tests/test_object.py +++ b/tests/test_object.py @@ -1,5 +1,6 @@ import json import sys +from copy import copy from decimal import Decimal, InvalidOperation from math import isclose, isfinite from zlib import compress @@ -465,3 +466,20 @@ class TestStreamReadWrite: def test_stream_bytes(self, stream_object): stream_object.write(b'pi') assert bytes(stream_object) == b'pi' + + +def test_copy(): + d = Dictionary( + { + '/Boolean': True, + '/Integer': 42, + '/Real': Decimal('42.42'), + '/String': String('hi'), + '/Array': Array([1, 2, 3.14]), + '/Dictionary': Dictionary({'/Color': 'Red'}), + } + ) + d2 = copy(d) + assert d2 == d + assert d2 is not d + assert d2['/Dictionary'] == d['/Dictionary'] diff --git a/tests/test_pages.py b/tests/test_pages.py index c3b2ec9..a6d0053 100644 --- a/tests/test_pages.py +++ b/tests/test_pages.py @@ -250,7 +250,6 @@ def test_negative_indexing(fourpages, graph): def test_concatenate(resources, outdir): # Issue #22 def concatenate(n): - print('concatenating same page', n, 'times') output_pdf = Pdf.new() for i in range(n): print(i) @@ -268,3 +267,43 @@ def test_emplace(fourpages): assert fourpages.pages[0].keys() == fourpages.pages[1].keys() for k in fourpages.pages[0].keys(): assert fourpages.pages[0][k] == fourpages.pages[1][k] + + +def test_duplicate_page(sandwich, outpdf): + sandwich.pages.append(sandwich.pages[0]) + assert len(sandwich.pages) == 2 + sandwich.save(outpdf) + + +def test_repeat_using_intermediate(graph, outpdf): + def _repeat_page(pdf_in, page, count, pdf_out): + for dup in range(count): + pdf_new = Pdf.new() + pdf_new.pages.append(pdf_in.pages[page]) + pdf_out.pages.extend(pdf_new.pages) + return pdf_out + + with Pdf.new() as out: + _repeat_page(graph, 0, 3, out) + assert len(out.pages) == 3 + out.save(outpdf) + + +def test_repeat(graph, outpdf): + def _repeat_page(pdf, page, count): + for dup in range(count): + pdf.pages.append(pdf.pages[page]) + return pdf + + _repeat_page(graph, 0, 3) + assert len(graph.pages) == 4 + graph.save(outpdf) + + +def test_add_foreign_twice(graph, outpdf): + out = Pdf.new() + out.pages.append(out.copy_foreign(graph.pages[0])) + assert len(out.pages) == 1 + out.pages.append(out.copy_foreign(graph.pages[0])) + assert len(out.pages) == 2 + out.save(outpdf) |