From 721fa633bc5c339dbace4b99aafb74fa12f5ceba Mon Sep 17 00:00:00 2001 From: Daniel Hillier Date: Tue, 12 May 2026 12:15:55 +1000 Subject: [PATCH 1/9] Update tests from cPython to run with newer Python versions --- test/support/__init__.py | 1 - test/test_zipfile.py | 18 +++++++++++++++--- test/test_zipfile2.py | 18 +++++++++++++++--- 3 files changed, 30 insertions(+), 7 deletions(-) diff --git a/test/support/__init__.py b/test/support/__init__.py index 53aee0f..d610a31 100644 --- a/test/support/__init__.py +++ b/test/support/__init__.py @@ -16,7 +16,6 @@ import importlib.util import io import logging.handlers -import nntplib import os import platform import re diff --git a/test/test_zipfile.py b/test/test_zipfile.py index e1a3bae..c753bce 100644 --- a/test/test_zipfile.py +++ b/test/test_zipfile.py @@ -2627,12 +2627,24 @@ def test_from_dir(self): class CommandLineTest(unittest.TestCase): def zipfilecmd(self, *args, **kwargs): - rc, out, err = script_helper.assert_python_ok('-m', 'pyzipper.zipfile', *args, - **kwargs) + rc, out, err = script_helper.assert_python_ok( + '-m', + 'pyzipper.zipfile', + *args, + __cwd=os.getcwd(), + __cleanenv=True, + **kwargs, + ) return out.replace(os.linesep.encode(), b'\n') def zipfilecmd_failure(self, *args): - return script_helper.assert_python_failure('-m', 'pyzipper.zipfile', *args) + return script_helper.assert_python_failure( + '-m', + 'pyzipper.zipfile', + *args, + __cleanenv=True, + __cwd=os.getcwd(), + ) def test_bad_use(self): rc, out, err = self.zipfilecmd_failure() diff --git a/test/test_zipfile2.py b/test/test_zipfile2.py index 37c626a..859c863 100644 --- a/test/test_zipfile2.py +++ b/test/test_zipfile2.py @@ -2293,12 +2293,24 @@ def test_from_dir(self): class CommandLineTest(unittest.TestCase): def zipfilecmd(self, *args, **kwargs): - rc, out, err = script_helper.assert_python_ok('-m', 'pyzipper.zipfile', *args, - **kwargs) + rc, out, err = script_helper.assert_python_ok( + '-m', + 'pyzipper.zipfile', + *args, + __cwd=os.getcwd(), + __cleanenv=True, + **kwargs, + ) return out.replace(os.linesep.encode(), b'\n') def zipfilecmd_failure(self, *args): - return script_helper.assert_python_failure('-m', 'pyzipper.zipfile', *args) + return script_helper.assert_python_failure( + '-m', + 'pyzipper.zipfile', + *args, + __cleanenv=True, + __cwd=os.getcwd(), + ) def test_bad_use(self): rc, out, err = self.zipfilecmd_failure() From 29a9d57f71c9e3a62a4766c59eb145abc6604b70 Mon Sep 17 00:00:00 2001 From: Daniel Hillier Date: Tue, 12 May 2026 12:20:24 +1000 Subject: [PATCH 2/9] Update dependency versions --- requirements_build.txt | 3 +++ requirements_dev.txt | 20 +++++--------------- 2 files changed, 8 insertions(+), 15 deletions(-) create mode 100644 requirements_build.txt diff --git a/requirements_build.txt b/requirements_build.txt new file mode 100644 index 0000000..b54105b --- /dev/null +++ b/requirements_build.txt @@ -0,0 +1,3 @@ +pip==26.1.1 +twine==6.2.0 +build==1.5.0 diff --git a/requirements_dev.txt b/requirements_dev.txt index 8aa2767..72c7aff 100644 --- a/requirements_dev.txt +++ b/requirements_dev.txt @@ -1,18 +1,8 @@ -pip>=18.1 -bumpversion>=0.5.3 -twine>=1.12.1 -wheel>=0.32.1 - # fixed version of pycryptodomex so pyup bot can send PR's on updates -pycryptodomex==3.7.3 - -# documentation dependencies -Sphinx>=1.8.1 -sphinx-rtd-theme>=0.3.1 +pycryptodomex==3.23.0 # testing dependencies -flake8>=3.5.0 -tox>=3.5.2 -pytest>=4.0.0 -pytest-cov>=2.5.1 -coverage>=4.5.1 +flake8==7.3.0 +tox==4.53.1 +pytest==9.0.3 +pytest-cov==7.1.0 From d8fccde15b2c45ac3844d4dd7682c3fcf9f54845 Mon Sep 17 00:00:00 2001 From: Daniel Hillier Date: Tue, 12 May 2026 12:21:23 +1000 Subject: [PATCH 3/9] Update python versions in tox.ini --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index 651b112..1783639 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py{34,35,36,37,38,39}, flake8 +envlist = py{310,311,312,313,314}, flake8 [flake8] max-line-length = 99 From 4941937b177c02993da5682a40a1a7c195deb05f Mon Sep 17 00:00:00 2001 From: Daniel Hillier Date: Tue, 12 May 2026 12:22:13 +1000 Subject: [PATCH 4/9] Update trove python versions --- setup.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/setup.py b/setup.py index 6668f35..15c2a87 100644 --- a/setup.py +++ b/setup.py @@ -116,6 +116,11 @@ def run(self): 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: 3.9', + 'Programming Language :: Python :: 3.10', + 'Programming Language :: Python :: 3.11', + 'Programming Language :: Python :: 3.12', + 'Programming Language :: Python :: 3.13', + 'Programming Language :: Python :: 3.14', ], # $ setup.py publish support. cmdclass={ From 5ba7962b9d6f0377f1a932b0bcc4af08a6f62aa6 Mon Sep 17 00:00:00 2001 From: Daniel Hillier Date: Tue, 12 May 2026 12:22:46 +1000 Subject: [PATCH 5/9] Update github test workflow --- .github/workflows/tests.yml | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index e24302e..7600913 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -1,6 +1,12 @@ --- name: Tests -on: [push, pull_request] +on: + push: + branches: + - master + pull_request: + +permissions: {} jobs: tests: @@ -8,17 +14,20 @@ jobs: strategy: fail-fast: false matrix: - python-version: [3.6, 3.7, 3.8, 3.9] + python-version: [3.10, 3.11, 3.12, 3.13, 3.14] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: ${{ matrix.python-version }} - name: Install dependencies run: | - python -m pip install --upgrade pip tox tox-factor + python -m pip install pip==26.1.1 + python -m pip install tox==4.53.1 - name: Run tox targets for ${{ matrix.python-version }} run: | PYVERSION=$(python -c "import sys; print(''.join([str(sys.version_info.major), str(sys.version_info.minor)]))") From 08c0046890fa1daba7ae8cddde2f1a061efdff4f Mon Sep 17 00:00:00 2001 From: Daniel Hillier Date: Tue, 12 May 2026 14:36:58 +1000 Subject: [PATCH 6/9] Move to pyproject.toml to fix build issues Includes other package improvements such as properly referencing Python's license. --- LICENSE | 3 +- LICENSE.python | 287 +++++++++++++++++++++++++++++++++++++++++++++++++ MANIFEST.in | 2 + pyproject.toml | 47 ++++++++ setup.py | 129 ---------------------- 5 files changed, 337 insertions(+), 131 deletions(-) create mode 100644 LICENSE.python create mode 100644 pyproject.toml delete mode 100644 setup.py diff --git a/LICENSE b/LICENSE index ca9a7b3..6ec914b 100644 --- a/LICENSE +++ b/LICENSE @@ -1,5 +1,4 @@ -This project is adapted from Python's zipfile module and tests. The intention -is to get as much of this project into mainline Python as possible. +MIT License Copyright (c) 2017 Daniel Hillier diff --git a/LICENSE.python b/LICENSE.python new file mode 100644 index 0000000..9c46f53 --- /dev/null +++ b/LICENSE.python @@ -0,0 +1,287 @@ +pyzipper is licensed under the MIT license; see the file LICENSE for details. + +pyzipper is forked from the Python standard library and its tests, which are +licensed under the Python license, a permissive open source license. The +copyright and license is included below for compliance with Python's terms. + +---------------------------------------------------------------------- + +Copyright (c) 2001-present Python Software Foundation; All Rights Reserved + +A. HISTORY OF THE SOFTWARE +========================== + +Python was created in the early 1990s by Guido van Rossum at Stichting +Mathematisch Centrum (CWI, see https://www.cwi.nl) in the Netherlands +as a successor of a language called ABC. Guido remains Python's +principal author, although it includes many contributions from others. + +In 1995, Guido continued his work on Python at the Corporation for +National Research Initiatives (CNRI, see https://www.cnri.reston.va.us) +in Reston, Virginia where he released several versions of the +software. + +In May 2000, Guido and the Python core development team moved to +BeOpen.com to form the BeOpen PythonLabs team. In October of the same +year, the PythonLabs team moved to Digital Creations, which became +Zope Corporation. In 2001, the Python Software Foundation (PSF, see +https://www.python.org/psf/) was formed, a non-profit organization +created specifically to own Python-related Intellectual Property. +Zope Corporation was a sponsoring member of the PSF. + +All Python releases are Open Source (see https://opensource.org for +the Open Source Definition). Historically, most, but not all, Python +releases have also been GPL-compatible; the table below summarizes +the various releases. + + Release Derived Year Owner GPL- + from compatible? (1) + + 0.9.0 thru 1.2 1991-1995 CWI yes + 1.3 thru 1.5.2 1.2 1995-1999 CNRI yes + 1.6 1.5.2 2000 CNRI no + 2.0 1.6 2000 BeOpen.com no + 1.6.1 1.6 2001 CNRI yes (2) + 2.1 2.0+1.6.1 2001 PSF no + 2.0.1 2.0+1.6.1 2001 PSF yes + 2.1.1 2.1+2.0.1 2001 PSF yes + 2.1.2 2.1.1 2002 PSF yes + 2.1.3 2.1.2 2002 PSF yes + 2.2 and above 2.1.1 2001-now PSF yes + +Footnotes: + +(1) GPL-compatible doesn't mean that we're distributing Python under + the GPL. All Python licenses, unlike the GPL, let you distribute + a modified version without making your changes open source. The + GPL-compatible licenses make it possible to combine Python with + other software that is released under the GPL; the others don't. + +(2) According to Richard Stallman, 1.6.1 is not GPL-compatible, + because its license has a choice of law clause. According to + CNRI, however, Stallman's lawyer has told CNRI's lawyer that 1.6.1 + is "not incompatible" with the GPL. + +Thanks to the many outside volunteers who have worked under Guido's +direction to make these releases possible. + + +B. TERMS AND CONDITIONS FOR ACCESSING OR OTHERWISE USING PYTHON +=============================================================== + +Python software and documentation are licensed under the +Python Software Foundation License Version 2. + +Starting with Python 3.8.6, examples, recipes, and other code in +the documentation are dual licensed under the PSF License Version 2 +and the Zero-Clause BSD license. + +Some software incorporated into Python is under different licenses. +The licenses are listed with code falling under that license. + + +PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2 +-------------------------------------------- + +1. This LICENSE AGREEMENT is between the Python Software Foundation +("PSF"), and the Individual or Organization ("Licensee") accessing and +otherwise using this software ("Python") in source or binary form and +its associated documentation. + +2. Subject to the terms and conditions of this License Agreement, PSF hereby +grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, +analyze, test, perform and/or display publicly, prepare derivative works, +distribute, and otherwise use Python alone or in any derivative version, +provided, however, that PSF's License Agreement and PSF's notice of copyright, +i.e., "Copyright (c) 2001 Python Software Foundation; All Rights Reserved" +are retained in Python alone or in any derivative version prepared by Licensee. + +3. In the event Licensee prepares a derivative work that is based on +or incorporates Python or any part thereof, and wants to make +the derivative work available to others as provided herein, then +Licensee hereby agrees to include in any such work a brief summary of +the changes made to Python. + +4. PSF is making Python available to Licensee on an "AS IS" +basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR +IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND +DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS +FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT +INFRINGE ANY THIRD PARTY RIGHTS. + +5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON +FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS +A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON, +OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. + +6. This License Agreement will automatically terminate upon a material +breach of its terms and conditions. + +7. Nothing in this License Agreement shall be deemed to create any +relationship of agency, partnership, or joint venture between PSF and +Licensee. This License Agreement does not grant permission to use PSF +trademarks or trade name in a trademark sense to endorse or promote +products or services of Licensee, or any third party. + +8. By copying, installing or otherwise using Python, Licensee +agrees to be bound by the terms and conditions of this License +Agreement. + + +BEOPEN.COM LICENSE AGREEMENT FOR PYTHON 2.0 +------------------------------------------- + +BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1 + +1. This LICENSE AGREEMENT is between BeOpen.com ("BeOpen"), having an +office at 160 Saratoga Avenue, Santa Clara, CA 95051, and the +Individual or Organization ("Licensee") accessing and otherwise using +this software in source or binary form and its associated +documentation ("the Software"). + +2. Subject to the terms and conditions of this BeOpen Python License +Agreement, BeOpen hereby grants Licensee a non-exclusive, +royalty-free, world-wide license to reproduce, analyze, test, perform +and/or display publicly, prepare derivative works, distribute, and +otherwise use the Software alone or in any derivative version, +provided, however, that the BeOpen Python License is retained in the +Software, alone or in any derivative version prepared by Licensee. + +3. BeOpen is making the Software available to Licensee on an "AS IS" +basis. BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR +IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND +DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS +FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE WILL NOT +INFRINGE ANY THIRD PARTY RIGHTS. + +4. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE +SOFTWARE FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS +AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY +DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. + +5. This License Agreement will automatically terminate upon a material +breach of its terms and conditions. + +6. This License Agreement shall be governed by and interpreted in all +respects by the law of the State of California, excluding conflict of +law provisions. Nothing in this License Agreement shall be deemed to +create any relationship of agency, partnership, or joint venture +between BeOpen and Licensee. This License Agreement does not grant +permission to use BeOpen trademarks or trade names in a trademark +sense to endorse or promote products or services of Licensee, or any +third party. As an exception, the "BeOpen Python" logos available at +http://www.pythonlabs.com/logos.html may be used according to the +permissions granted on that web page. + +7. By copying, installing or otherwise using the software, Licensee +agrees to be bound by the terms and conditions of this License +Agreement. + + +CNRI LICENSE AGREEMENT FOR PYTHON 1.6.1 +--------------------------------------- + +1. This LICENSE AGREEMENT is between the Corporation for National +Research Initiatives, having an office at 1895 Preston White Drive, +Reston, VA 20191 ("CNRI"), and the Individual or Organization +("Licensee") accessing and otherwise using Python 1.6.1 software in +source or binary form and its associated documentation. + +2. Subject to the terms and conditions of this License Agreement, CNRI +hereby grants Licensee a nonexclusive, royalty-free, world-wide +license to reproduce, analyze, test, perform and/or display publicly, +prepare derivative works, distribute, and otherwise use Python 1.6.1 +alone or in any derivative version, provided, however, that CNRI's +License Agreement and CNRI's notice of copyright, i.e., "Copyright (c) +1995-2001 Corporation for National Research Initiatives; All Rights +Reserved" are retained in Python 1.6.1 alone or in any derivative +version prepared by Licensee. Alternately, in lieu of CNRI's License +Agreement, Licensee may substitute the following text (omitting the +quotes): "Python 1.6.1 is made available subject to the terms and +conditions in CNRI's License Agreement. This Agreement together with +Python 1.6.1 may be located on the internet using the following +unique, persistent identifier (known as a handle): 1895.22/1013. This +Agreement may also be obtained from a proxy server on the internet +using the following URL: http://hdl.handle.net/1895.22/1013". + +3. In the event Licensee prepares a derivative work that is based on +or incorporates Python 1.6.1 or any part thereof, and wants to make +the derivative work available to others as provided herein, then +Licensee hereby agrees to include in any such work a brief summary of +the changes made to Python 1.6.1. + +4. CNRI is making Python 1.6.1 available to Licensee on an "AS IS" +basis. CNRI MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR +IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, CNRI MAKES NO AND +DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS +FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 1.6.1 WILL NOT +INFRINGE ANY THIRD PARTY RIGHTS. + +5. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON +1.6.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS +A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6.1, +OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. + +6. This License Agreement will automatically terminate upon a material +breach of its terms and conditions. + +7. This License Agreement shall be governed by the federal +intellectual property law of the United States, including without +limitation the federal copyright law, and, to the extent such +U.S. federal law does not apply, by the law of the Commonwealth of +Virginia, excluding Virginia's conflict of law provisions. +Notwithstanding the foregoing, with regard to derivative works based +on Python 1.6.1 that incorporate non-separable material that was +previously distributed under the GNU General Public License (GPL), the +law of the Commonwealth of Virginia shall govern this License +Agreement only as to issues arising under or with respect to +Paragraphs 4, 5, and 7 of this License Agreement. Nothing in this +License Agreement shall be deemed to create any relationship of +agency, partnership, or joint venture between CNRI and Licensee. This +License Agreement does not grant permission to use CNRI trademarks or +trade name in a trademark sense to endorse or promote products or +services of Licensee, or any third party. + +8. By clicking on the "ACCEPT" button where indicated, or by copying, +installing or otherwise using Python 1.6.1, Licensee agrees to be +bound by the terms and conditions of this License Agreement. + + ACCEPT + + +CWI LICENSE AGREEMENT FOR PYTHON 0.9.0 THROUGH 1.2 +-------------------------------------------------- + +Copyright (c) 1991 - 1995, Stichting Mathematisch Centrum Amsterdam, +The Netherlands. All rights reserved. + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Stichting Mathematisch +Centrum or CWI not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior +permission. + +STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO +THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE +FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +ZERO-CLAUSE BSD LICENSE FOR CODE IN THE PYTHON DOCUMENTATION +---------------------------------------------------------------------- + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. diff --git a/MANIFEST.in b/MANIFEST.in index 1613d90..8e9bc1d 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,3 +1,5 @@ +include AUTHORS.rst include LICENSE +include LICENSE.python include README.rst prune test diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..d26a591 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,47 @@ +[build-system] +requires = ["setuptools>=77.0.3"] +build-backend = "setuptools.build_meta" + +[project] +name = "pyzipper" +dynamic = ["version"] +requires-python = ">= 3.4" +dependencies = [ + 'pycryptodomex', +] +authors = [ + {name = "Daniel Hillier", email = "daniel.hillier@gmail.com"}, +] +description = 'AES encryption for zipfile.' +readme = "README.rst" +license = "MIT" +license-files = ["LICENSE", "LICENSE.python", "AUTHORS.rst"] +classifiers = [ + 'Development Status :: 4 - Beta', + 'Topic :: System :: Archiving :: Compression', + 'Intended Audience :: Developers', + 'Operating System :: MacOS :: MacOS X', + 'Operating System :: Microsoft :: Windows', + 'Operating System :: POSIX :: Linux', + 'Operating System :: POSIX', + 'Operating System :: OS Independent', + 'Programming Language :: Python', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: 3.9', + 'Programming Language :: Python :: 3.10', + 'Programming Language :: Python :: 3.11', + 'Programming Language :: Python :: 3.12', + 'Programming Language :: Python :: 3.13', + 'Programming Language :: Python :: 3.14', +] + +[project.urls] +Homepage = "https://github.com/danifus/pyzipper" + +[tool.setuptools.dynamic] +version = {attr = "pyzipper.__version__.__version__"} diff --git a/setup.py b/setup.py deleted file mode 100644 index 15c2a87..0000000 --- a/setup.py +++ /dev/null @@ -1,129 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -# Note: To use the 'upload' functionality of this file, you must: -# $ pip install twine - -import io -import os -import sys -from shutil import rmtree - -from setuptools import find_packages, setup, Command - -# Package meta-data. -NAME = 'pyzipper' -DESCRIPTION = 'AES encryption for zipfile.' -URL = 'https://github.com/danifus/pyzipper' -EMAIL = 'daniel.hillier@gmail.com' -AUTHOR = 'Daniel Hillier' -REQUIRES_PYTHON = '>=3.4' -VERSION = None - -# What packages are required for this module to be executed? -REQUIRED = [ - 'pycryptodomex', -] - -# The rest you shouldn't have to touch too much :) -# ------------------------------------------------ -# Except, perhaps the License and Trove Classifiers! -# If you do change the License, remember to change the Trove Classifier for that! - -here = os.path.abspath(os.path.dirname(__file__)) - -# Import the README and use it as the long-description. -# Note: this will only work if 'README.rst' is present in your MANIFEST.in file! -with io.open(os.path.join(here, 'README.rst'), encoding='utf-8') as f: - long_description = '\n' + f.read() - -# Load the package's __version__.py module as a dictionary. -about = {} -if not VERSION: - with open(os.path.join(here, 'pyzipper', '__version__.py')) as f: - exec(f.read(), about) -else: - about['__version__'] = VERSION - - -class UploadCommand(Command): - """Support setup.py upload.""" - - description = 'Build and publish the package.' - user_options = [] - - @staticmethod - def status(s): - """Prints things in bold.""" - print('\033[1m{0}\033[0m'.format(s)) - - def initialize_options(self): - pass - - def finalize_options(self): - pass - - def run(self): - try: - self.status('Removing previous builds…') - rmtree(os.path.join(here, 'dist')) - except OSError: - pass - - self.status('Building Source and Wheel (universal) distribution…') - os.system('{0} setup.py sdist bdist_wheel --universal'.format(sys.executable)) - - self.status('Uploading the package to PyPi via Twine…') - os.system('twine upload dist/*') - - self.status('Pushing git tags…') - os.system('git tag v{0}'.format(about['__version__'])) - os.system('git push --tags') - - sys.exit() - - -# Where the magic happens: -setup( - name=NAME, - version=about['__version__'], - description=DESCRIPTION, - long_description=long_description, - author=AUTHOR, - author_email=EMAIL, - keywords="zip aes encrypt decrypt", - python_requires=REQUIRES_PYTHON, - url=URL, - packages=find_packages(exclude=('test', 'docs')), - install_requires=REQUIRED, - include_package_data=True, - license='MIT', - classifiers=[ - 'Development Status :: 4 - Beta', - 'Topic :: System :: Archiving :: Compression', - 'Intended Audience :: Developers', - 'Operating System :: MacOS :: MacOS X', - 'Operating System :: Microsoft :: Windows', - 'Operating System :: POSIX :: Linux', - 'Operating System :: POSIX', - 'License :: OSI Approved :: MIT License', - 'Operating System :: OS Independent', - 'Programming Language :: Python', - 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.4', - 'Programming Language :: Python :: 3.5', - 'Programming Language :: Python :: 3.6', - 'Programming Language :: Python :: 3.7', - 'Programming Language :: Python :: 3.8', - 'Programming Language :: Python :: 3.9', - 'Programming Language :: Python :: 3.10', - 'Programming Language :: Python :: 3.11', - 'Programming Language :: Python :: 3.12', - 'Programming Language :: Python :: 3.13', - 'Programming Language :: Python :: 3.14', - ], - # $ setup.py publish support. - cmdclass={ - 'upload': UploadCommand, - }, -) From d69b1ee8bd640b18177282e3eb16c3bfff881e31 Mon Sep 17 00:00:00 2001 From: Daniel Hillier Date: Tue, 12 May 2026 14:40:31 +1000 Subject: [PATCH 7/9] Remove shield pictures from README --- README.rst | 9 --------- 1 file changed, 9 deletions(-) diff --git a/README.rst b/README.rst index d9784d8..eab72a7 100644 --- a/README.rst +++ b/README.rst @@ -1,12 +1,3 @@ -.. image:: https://img.shields.io/pypi/v/pyzipper.svg - :target: https://pypi.org/project/pyzipper/ - :alt: Current Version on PyPi - -.. image:: https://img.shields.io/pypi/pyversions/pyzipper.svg - :target: https://pypi.org/project/pyzipper/ - :alt: Supported Python Versions - - pyzipper ======== From 3e25a2162350d08d94009d956b4640e2cadcddd8 Mon Sep 17 00:00:00 2001 From: Daniel Hillier Date: Wed, 13 May 2026 11:57:51 +1000 Subject: [PATCH 8/9] Remove unused docs / appveyor files --- appveyor.yml | 78 ----------- docs/Makefile | 25 ---- docs/_templates/autosummary/class.rst | 50 -------- docs/_templates/autosummary/method.rst | 4 - docs/authors.rst | 1 - docs/conf.py | 171 ------------------------- docs/contributing.rst | 1 - docs/history.rst | 1 - docs/index.rst | 20 --- docs/installation.rst | 51 -------- docs/make.bat | 47 ------- docs/modules.rst | 15 --- docs/readme.rst | 1 - docs/usage.rst | 45 ------- readthedocs.yml | 6 - 15 files changed, 516 deletions(-) delete mode 100644 appveyor.yml delete mode 100644 docs/Makefile delete mode 100644 docs/_templates/autosummary/class.rst delete mode 100644 docs/_templates/autosummary/method.rst delete mode 100644 docs/authors.rst delete mode 100644 docs/conf.py delete mode 100644 docs/contributing.rst delete mode 100644 docs/history.rst delete mode 100644 docs/index.rst delete mode 100644 docs/installation.rst delete mode 100644 docs/make.bat delete mode 100644 docs/modules.rst delete mode 100644 docs/readme.rst delete mode 100644 docs/usage.rst delete mode 100644 readthedocs.yml diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index b9c5736..0000000 --- a/appveyor.yml +++ /dev/null @@ -1,78 +0,0 @@ -# As config was originally based on an example by Olivier Grisel. Thanks! -# https://github.com/pyinstaller/pyinstaller/blob/develop/appveyor.yml - -clone_depth: 50 - -environment: - PYTEST: py.test -n3 --maxfail 5 --durations=10 --junitxml=junit-results.xml - # uncomment to disable cache restore -# APPVEYOR_CACHE_SKIP_RESTORE: true - APPVEYOR_SAVE_CACHE_ON_ERROR: true - - matrix: - - PYTHON: C:\Python36-x64 - PYTHON_VERSION: 3.6 - PYTHON_ARCH: 64 - -init: - - "ECHO %PYTHON% %PYTHON_VERSION% %PYTHON_ARCH%" - - "ECHO \"%APPVEYOR_SCHEDULED_BUILD%\"" - # If there is a newer build queued for the same PR, cancel this one. - # The AppVeyor 'rollout builds' option is supposed to serve the same - # purpose but it is problematic because it tends to cancel builds pushed - # directly to master instead of just PR builds (or the converse). - # credits: JuliaLang developers. - - ps: if ($env:APPVEYOR_PULL_REQUEST_NUMBER -and $env:APPVEYOR_BUILD_NUMBER -ne ((Invoke-RestMethod ` - https://ci.appveyor.com/api/projects/$env:APPVEYOR_ACCOUNT_NAME/$env:APPVEYOR_PROJECT_SLUG/history?recordsNumber=50).builds | ` - Where-Object pullRequestId -eq $env:APPVEYOR_PULL_REQUEST_NUMBER)[0].buildNumber) { ` - throw "There are newer queued builds for this pull request, failing early." } - -cache: - # Cache downloaded pip packages and built wheels. - - '%LOCALAPPDATA%\pip\Cache\http' - - '%LOCALAPPDATA%\pip\Cache\wheels' - # Cache Tox envs - - 'C:\projects\pyzipper\.tox' - - -install: - # Show size of cache - - if exist "%LOCALAPPDATA%\pip\Cache" C:\cygwin\bin\du -hs "%LOCALAPPDATA%\pip\Cache" - - if exist "C:\projects\pyzipper\.tox" C:\cygwin\bin\du -hs "C:\projects\pyzipper\.tox" - # set python path - - SET PATH=%PYTHON%;%PYTHON%\Scripts;%PATH% - - # Upgrade to the latest pip. - # calling pip with "%CMD_IN_ENV% python -m" prevents an access denied error - - '%CMD_IN_ENV% python -m pip install -U pip setuptools wheel' - - # install tox - - '%CMD_IN_ENV% python -m pip install -U tox coverage' - -build: none - -test_script: - # delete old .coverage file - - coverage erase - - tox -e py{36,37} - -artifacts: - - path: .coverage - -on_finish: - # Remove old or huge cache files to hopefully not exceed the 1GB cache limit. - # - # If the cache limit is reached, the cache will not be updated (of not even - # created in the first run). So this is a trade of between keeping the cache - # current and having a cache at all. - # NB: This is done only `on_success` since the cache in uploaded only on - # success anyway. - - C:\cygwin\bin\find "%LOCALAPPDATA%\pip" -type f -mtime +360 -delete - - C:\cygwin\bin\find "%LOCALAPPDATA%\pip" -type f -size +10M -delete - - C:\cygwin\bin\find "%LOCALAPPDATA%\pip" -empty -delete - - C:\cygwin\bin\find "C:\projects\pyzipper\.tox" -type f -mtime +360 -delete - - C:\cygwin\bin\find "C:\projects\pyzipper\.tox" -empty -delete - # Show size of cache - - C:\cygwin\bin\du -hs "%LOCALAPPDATA%\pip\Cache" - - C:\cygwin\bin\du -hs "C:\projects\pyzipper\.tox" - - \ No newline at end of file diff --git a/docs/Makefile b/docs/Makefile deleted file mode 100644 index b208991..0000000 --- a/docs/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -# Minimal makefile for Sphinx documentation -# - -# You can set these variables from the command line. -SPHINXOPTS = -W -SPHINXBUILD = python -msphinx -SPHINXPROJ = pyzipper -SOURCEDIR = . -BUILDDIR = _build -API_TOCTREE_DIR = api - -# Put it first so that "make" without argument is like "make help". -help: - @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) - -.PHONY: help Makefile - -clean_all: - rm -rf $(BUILDDIR)/* - rm -rf $(API_TOCTREE_DIR)/* - -# Catch-all target: route all unknown targets to Sphinx using the new -# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). -%: Makefile - @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/_templates/autosummary/class.rst b/docs/_templates/autosummary/class.rst deleted file mode 100644 index 633a3e5..0000000 --- a/docs/_templates/autosummary/class.rst +++ /dev/null @@ -1,50 +0,0 @@ -{{ objname | escape | underline}} - -.. currentmodule:: {{ module }} - -.. autoclass:: {{ objname }} - - {% block attributes_summary %} - {% if attributes %} - - .. rubric:: Attributes Summary - - .. autosummary:: - {% for item in attributes %} - ~{{ item }} - {%- endfor %} - - {% endif %} - {% endblock %} - - {% block methods_summary %} - {% if methods %} - - {% if '__init__' in methods %} - {% set caught_result = methods.remove('__init__') %} - {% endif %} - - .. rubric:: Methods Summary - - .. autosummary:: - :toctree: {{ objname }}/methods - :nosignatures: - - {% for item in methods %} - ~{{ name }}.{{ item }} - {%- endfor %} - - {% endif %} - {% endblock %} - - {% block methods_documentation %} - {% if methods %} - - .. rubric:: Methods Documentation - - {% for item in methods %} - .. automethod:: {{ name }}.{{ item }} - {%- endfor %} - - {% endif %} - {% endblock %} diff --git a/docs/_templates/autosummary/method.rst b/docs/_templates/autosummary/method.rst deleted file mode 100644 index fb55241..0000000 --- a/docs/_templates/autosummary/method.rst +++ /dev/null @@ -1,4 +0,0 @@ -{{ name | escape | underline }} - -.. automethod:: {{ fullname }} - :noindex: diff --git a/docs/authors.rst b/docs/authors.rst deleted file mode 100644 index e122f91..0000000 --- a/docs/authors.rst +++ /dev/null @@ -1 +0,0 @@ -.. include:: ../AUTHORS.rst diff --git a/docs/conf.py b/docs/conf.py deleted file mode 100644 index 2d86e59..0000000 --- a/docs/conf.py +++ /dev/null @@ -1,171 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -# pyzipper documentation build configuration file, created by -# sphinx-quickstart on Fri Jun 9 13:47:02 2017. -# -# This file is execfile()d with the current directory set to its -# containing dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. - -# If extensions (or modules to document with autodoc) are in another -# directory, add these directories to sys.path here. If the directory is -# relative to the documentation root, use os.path.abspath to make it -# absolute, like shown here. -# -import os -import sys -sys.path.insert(0, os.path.abspath('..')) - -import pyzipper - -# -- General configuration --------------------------------------------- - -# If your documentation needs a minimal Sphinx version, state it here. -# -# needs_sphinx = '1.0' - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = ['sphinx.ext.autodoc', - 'sphinx.ext.autosummary', - 'sphinx.ext.viewcode', - 'sphinx.ext.napoleon'] - -autoclass_content = "both" -autosummary_generate = True -add_module_names = False -autodoc_member_order = "bysource" - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# The suffix(es) of source filenames. -# You can specify multiple suffix as a list of string: -# -# source_suffix = ['.rst', '.md'] -source_suffix = '.rst' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -project = u'pyzipper' -copyright = u"2018, Daniel Hillier" -author = u"Daniel Hillier" - -# The version info for the project you're documenting, acts as replacement -# for |version| and |release|, also used in various other places throughout -# the built documents. -# -# The short X.Y version. -version = pyzipper.__version__ -# The full version, including alpha/beta/rc tags. -release = pyzipper.__version__ - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -# -# This is also used if you do content translation via gettext catalogs. -# Usually you set "language" from the command line for these cases. -language = None - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -# This patterns also effect to html_static_path and html_extra_path -exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - -# If true, `todo` and `todoList` produce output, else they produce nothing. -todo_include_todos = False - - -# -- Options for HTML output ------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -# -html_theme = 'sphinx_rtd_theme' - -# Theme options are theme-specific and customize the look and feel of a -# theme further. For a list of options available for each theme, see the -# documentation. -# -# html_theme_options = {} - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -# html_static_path = ['_static'] - - -# -- Options for HTMLHelp output --------------------------------------- - -# Output file base name for HTML help builder. -htmlhelp_basename = 'pyzipperdoc' - - -# -- Options for LaTeX output ------------------------------------------ - -latex_elements = { - # The paper size ('letterpaper' or 'a4paper'). - # - # 'papersize': 'letterpaper', - - # The font size ('10pt', '11pt' or '12pt'). - # - # 'pointsize': '10pt', - - # Additional stuff for the LaTeX preamble. - # - # 'preamble': '', - - # Latex figure (float) alignment - # - # 'figure_align': 'htbp', -} - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, author, documentclass -# [howto, manual, or own class]). -latex_documents = [ - (master_doc, 'pyzipper.tex', - u'pyzipper Documentation', - u'Daniel Hillier', 'manual'), -] - - -# -- Options for manual page output ------------------------------------ - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [ - (master_doc, 'pyzipper', - u'pyzipper Documentation', - [author], 1) -] - - -# -- Options for Texinfo output ---------------------------------------- - -# Grouping the document tree into Texinfo files. List of tuples -# (source start file, target name, title, author, -# dir menu entry, description, category) -texinfo_documents = [ - (master_doc, 'pyzipper', - u'pyzipper Documentation', - author, - 'pyzipper', - 'Python AES encryption for zipfile.', - 'Miscellaneous'), -] - - - diff --git a/docs/contributing.rst b/docs/contributing.rst deleted file mode 100644 index e582053..0000000 --- a/docs/contributing.rst +++ /dev/null @@ -1 +0,0 @@ -.. include:: ../CONTRIBUTING.rst diff --git a/docs/history.rst b/docs/history.rst deleted file mode 100644 index 2506499..0000000 --- a/docs/history.rst +++ /dev/null @@ -1 +0,0 @@ -.. include:: ../HISTORY.rst diff --git a/docs/index.rst b/docs/index.rst deleted file mode 100644 index 43d4b37..0000000 --- a/docs/index.rst +++ /dev/null @@ -1,20 +0,0 @@ -Welcome to pyzipper's documentation! -====================================== - -.. toctree:: - :maxdepth: 2 - :caption: Contents: - - readme - installation - usage - modules - contributing - authors - history - -Indices and tables -================== -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` diff --git a/docs/installation.rst b/docs/installation.rst deleted file mode 100644 index 73a5ea2..0000000 --- a/docs/installation.rst +++ /dev/null @@ -1,51 +0,0 @@ -.. highlight:: shell - -============ -Installation -============ - - -Stable release --------------- - -To install pyzipper, run this command in your terminal: - -.. code-block:: console - - $ pip install pyzipper - -This is the preferred method to install pyzipper, as it will always install the most recent stable release. - -If you don't have `pip`_ installed, this `Python installation guide`_ can guide -you through the process. - -.. _pip: https://pip.pypa.io/en/stable/ -.. _Python installation guide: https://docs.python-guide.org/starting/installation/ - - -From sources ------------- - -The sources for pyzipper can be downloaded from the `Github repo`_. - -You can either clone the public repository: - -.. code-block:: console - - $ git clone git://github.com/danifus/pyzipper - -Or download the `tarball`_: - -.. code-block:: console - - $ curl -OL https://github.com/danifus/pyzipper/tarball/master - -Once you have a copy of the source, you can install it with: - -.. code-block:: console - - $ python setup.py install - - -.. _Github repo: https://github.com/danifus/pyzipper -.. _tarball: https://github.com/danifus/pyzipper/tarball/master diff --git a/docs/make.bat b/docs/make.bat deleted file mode 100644 index 98d1e65..0000000 --- a/docs/make.bat +++ /dev/null @@ -1,47 +0,0 @@ -@ECHO OFF - -pushd %~dp0 - -REM Command file for Sphinx documentation - -if "%SPHINXBUILD%" == "" ( - set SPHINXBUILD=python -msphinx -) -set SOURCEDIR=. -set BUILDDIR=_build -set API_TOCTREE_DIR=api -set SPHINXPROJ=pyzipper -set SPHINXOPTS=-W - -if "%1" == "" goto help - -if "%1" == "clean_all" ( - for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i - del /q /s %BUILDDIR%\* - for /d %%i in (%API_TOCTREE_DIR%\*) do rmdir /q /s %%i - del /q /s %API_TOCTREE_DIR%\* - goto end -) - -%SPHINXBUILD% >NUL 2>NUL -if errorlevel 9009 ( - echo. - echo.The Sphinx module was not found. Make sure you have Sphinx installed, - echo.then set the SPHINXBUILD environment variable to point to the full - echo.path of the 'sphinx-build' executable. Alternatively you may add the - echo.Sphinx directory to PATH. - echo. - echo.If you don't have Sphinx installed, grab it from - echo.http://sphinx-doc.org/ - exit /b 1 -) - -%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% -goto end - - -:help -%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% - -:end -popd diff --git a/docs/modules.rst b/docs/modules.rst deleted file mode 100644 index ddb687f..0000000 --- a/docs/modules.rst +++ /dev/null @@ -1,15 +0,0 @@ -================= -API Documentation -================= - -This is the detailed documentation of ``AESZipFile``, which -holds all the functionality of ``pyzipper``. - -.. currentmodule:: pyzipper.zipfile_aes - -.. autosummary:: - :nosignatures: - :toctree: api/ - - AESZipFile - AESZipInfo diff --git a/docs/readme.rst b/docs/readme.rst deleted file mode 100644 index 72a3355..0000000 --- a/docs/readme.rst +++ /dev/null @@ -1 +0,0 @@ -.. include:: ../README.rst diff --git a/docs/usage.rst b/docs/usage.rst deleted file mode 100644 index f7f212f..0000000 --- a/docs/usage.rst +++ /dev/null @@ -1,45 +0,0 @@ -===== -Usage -===== - -.. code-block:: python - - import pyzipper - - secret_password = b'lost art of keeping a secret' - - with pyzipper.AESZipFile('new_test.zip', - 'w', - compression=pyzipper.ZIP_LZMA, - encryption=pyzipper.WZ_AES) as zf: - zf.pwd = secret_password - zf.writestr('test.txt', "What ever you do, don't tell anyone!") - - with pyzipper.AESZipFile('new_test.zip') as zf: - zf.pwd = secret_password - my_secrets = zf.read('test.txt') - - -AES Strength ------------- - -The strength of the AES encryption can be configure to be 128, 192 or 256 bits. -By default it is 256 bits. Use the ``setencryption()`` method to specify the -encryption kwargs: - -.. code-block:: python - - import pyzipper - - secret_password = b'lost art of keeping a secret' - - with pyzipper.AESZipFile('new_test.zip', - 'w', - compression=pyzipper.ZIP_LZMA) as zf: - zf.pwd = secret_password - zf.setencryption(pyzipper.WZ_AES, nbits=128) - zf.writestr('test.txt', "What ever you do, don't tell anyone!") - - with pyzipper.AESZipFile('new_test.zip') as zf: - zf.pwd = secret_password - my_secrets = zf.read('test.txt') diff --git a/readthedocs.yml b/readthedocs.yml deleted file mode 100644 index 4057211..0000000 --- a/readthedocs.yml +++ /dev/null @@ -1,6 +0,0 @@ -build: - image: latest - -python: - version: 3.6 - setup_py_install: true From 61d3529205b1f01154b1247a28da357ac886a167 Mon Sep 17 00:00:00 2001 From: Daniel Hillier Date: Wed, 13 May 2026 12:07:38 +1000 Subject: [PATCH 9/9] Quote python versions in github workflow to fix 3.10 --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 7600913..e5e5307 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -14,7 +14,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: [3.10, 3.11, 3.12, 3.13, 3.14] + python-version: ['3.10', '3.11', '3.12', '3.13', '3.14'] steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2