瀏覽代碼

Merge pull request #8919 from ThomasWaldmann/py314

support Python 3.14
TW 1 周之前
父節點
當前提交
7b9fe15b5d

+ 1 - 1
.coveragerc

@@ -1,6 +1,6 @@
 [run]
 branch = True
-disable_warnings = module-not-measured
+disable_warnings = module-not-measured, no-ctracer
 source = src/borg
 omit =
     */borg/__init__.py

+ 3 - 0
.github/workflows/ci.yml

@@ -84,6 +84,9 @@ jobs:
             - os: ubuntu-24.04
               python-version: '3.13'
               toxenv: py313-fuse3
+            - os: ubuntu-24.04
+              python-version: '3.14-dev'
+              toxenv: py314-fuse3
 
     env:
       TOXENV: ${{ matrix.toxenv }}

+ 5 - 4
pyproject.toml

@@ -23,6 +23,7 @@ classifiers = [
     "Programming Language :: Python :: 3.11",
     "Programming Language :: Python :: 3.12",
     "Programming Language :: Python :: 3.13",
+    "Programming Language :: Python :: 3.14",
     "Topic :: Security :: Cryptography",
     "Topic :: System :: Archiving :: Backup",
 ]
@@ -159,7 +160,7 @@ ignore_missing_imports = true
 
 [tool.tox]
 requires = ["tox>=4.19", "pkgconfig", "cython", "wheel", "setuptools_scm"]
-env_list = ["py{310,311,312,313}-{none,fuse2,fuse3}", "docs", "ruff", "mypy", "bandit"]
+env_list = ["py{310,311,312,313,314}-{none,fuse2,fuse3}", "docs", "ruff", "mypy", "bandit"]
 
 [tool.tox.env_run_base]
 package = "editable-legacy"  # without this it does not find setup_docs when running under fakeroot
@@ -171,15 +172,15 @@ pass_env = ["*"]  # fakeroot -u needs some env vars
 pass_env = ["*"]  # needed by tox4, so env vars are visible for building borg
 
 # Environment-specific configurations
-[tool.tox.env."py{310,311,312,313}-fuse2"]
+[tool.tox.env."py{310,311,312,313,314}-fuse2"]
 set_env = {BORG_FUSE_IMPL = "llfuse"}
 deps = ["-rrequirements.d/development.txt", "llfuse"]
 
-[tool.tox.env."py{310,311,312,313}-fuse3"]
+[tool.tox.env."py{310,311,312,313,314}-fuse3"]
 set_env = {BORG_FUSE_IMPL = "pyfuse3"}
 deps = ["-rrequirements.d/development.txt", "pyfuse3"]
 
-[tool.tox.env."py{310,311,312,313}-none"]
+[tool.tox.env."py{310,311,312,313,314}-none"]
 deps = ["-rrequirements.d/development.txt"]
 
 [tool.tox.env.ruff]

+ 5 - 5
requirements.d/development.lock.txt

@@ -5,10 +5,10 @@ wheel==0.45.1
 virtualenv==20.30.0
 build==1.2.2
 pkgconfig==1.5.5
-tox==4.24.2
-pytest==8.3.5
-pytest-xdist==3.6.1
-pytest-cov==6.0.0
+tox==4.26.0
+pytest==8.4.0
+pytest-xdist==3.7.0
+pytest-cov==6.2.1
 pytest-benchmark==5.1.0
-Cython==3.0.12
+Cython==3.1.2
 pre-commit==4.2.0

+ 4 - 4
src/borg/archiver/debug_cmd.py

@@ -305,8 +305,8 @@ class DebugMixIn:
         """convert Borg profile to Python profile"""
         import marshal
 
-        with args.output, args.input:
-            marshal.dump(msgpack.unpack(args.input, use_list=False, raw=False), args.output)
+        with open(args.output, "wb") as wfd, open(args.input, "rb") as rfd:
+            marshal.dump(msgpack.unpack(rfd, use_list=False, raw=False), wfd)
 
     def build_parser_debug(self, subparsers, common_parser, mid_common_parser):
         debug_epilog = process_epilog(
@@ -596,5 +596,5 @@ class DebugMixIn:
             help="convert Borg profile to Python profile (debug)",
         )
         subparser.set_defaults(func=self.do_debug_convert_profile)
-        subparser.add_argument("input", metavar="INPUT", type=argparse.FileType("rb"), help="Borg profile")
-        subparser.add_argument("output", metavar="OUTPUT", type=argparse.FileType("wb"), help="Output file")
+        subparser.add_argument("input", metavar="INPUT", type=str, help="Borg profile")
+        subparser.add_argument("output", metavar="OUTPUT", type=str, help="Output file")

+ 4 - 0
src/borg/testsuite/archiver/debug_cmds_test.py

@@ -1,6 +1,9 @@
 import json
 import os
 import pstats
+import sys
+
+import pytest
 
 from ...constants import *  # NOQA
 from .. import changedir
@@ -10,6 +13,7 @@ from . import cmd, create_test_files, create_regular_file, generate_archiver_tes
 pytest_generate_tests = lambda metafunc: generate_archiver_tests(metafunc, kinds="local,remote,binary")  # NOQA
 
 
+@pytest.mark.skipif(sys.version_info[:3] >= (3, 14, 0), reason="cProfile.Profile broken in Python 3.14.0b2")
 def test_debug_profile(archivers, request):
     archiver = request.getfixturevalue(archivers)
     create_test_files(archiver.input_path)

+ 1 - 1
src/borg/testsuite/legacyrepository_test.py

@@ -976,7 +976,7 @@ def test_remote_rpc_exception_transport(remote_repository):
             remote_repository.call("inject_exception", {"kind": "divide"})
         except LegacyRemoteRepository.RPCError as e:
             assert e.unpacked
-            assert e.get_message() == "ZeroDivisionError: integer division or modulo by zero\n"
+            assert e.get_message().startswith("ZeroDivisionError:")
             assert e.exception_class == "ZeroDivisionError"
             assert len(e.exception_full) > 0
 

+ 1 - 1
src/borg/testsuite/repository_test.py

@@ -224,7 +224,7 @@ def test_remote_rpc_exception_transport(remote_repository):
             remote_repository.call("inject_exception", {"kind": "divide"})
         except RemoteRepository.RPCError as e:
             assert e.unpacked
-            assert e.get_message() == "ZeroDivisionError: integer division or modulo by zero\n"
+            assert e.get_message().startswith("ZeroDivisionError:")
             assert e.exception_class == "ZeroDivisionError"
             assert len(e.exception_full) > 0