reorg imports

This commit is contained in:
Thomas Waldmann 2026-02-26 00:30:58 +01:00
parent a708397612
commit be2b3363e2
No known key found for this signature in database
GPG key ID: 243ACFA951F78E01
41 changed files with 151 additions and 263 deletions

View file

@ -15,7 +15,6 @@ else:
sys.exit(2) # == EXIT_ERROR
try:
import argparse
import faulthandler
import functools
import inspect
@ -27,8 +26,6 @@ try:
import signal
from datetime import datetime, timezone
from jsonargparse import ArgumentParser, Namespace, SUPPRESS
from ..logger import create_logger, setup_logging
logger = create_logger()
@ -42,8 +39,7 @@ try:
from ..helpers import format_file_size
from ..helpers import remove_surrogates, text_to_json
from ..helpers import DatetimeWrapper, replace_placeholders
from ..helpers.jap_helpers import flatten_namespace
from ..helpers.jap_helpers import flatten_namespace, ArgumentTypeError, ArgumentParser, Namespace, SUPPRESS
from ..helpers import is_slow_msgpack, is_supported_msgpack, sysinfo
from ..helpers import signal_handler, raising_signal_handler, SigHup, SigTerm
from ..helpers import ErrorIgnoringTextIOWrapper
@ -643,7 +639,7 @@ def main(): # pragma: no cover
tb = format_tb(e)
print(tb, file=sys.stderr)
sys.exit(e.exit_code)
except argparse.ArgumentTypeError as e:
except ArgumentTypeError as e:
# we might not have logging setup yet, so get out quickly
print(str(e), file=sys.stderr)
sys.exit(CommandError.exit_mcode if modern_ec else EXIT_ERROR)

View file

@ -2,8 +2,6 @@ import functools
import os
import textwrap
from jsonargparse import SUPPRESS
import borg
from ..archive import Archive
from ..constants import * # NOQA
@ -11,6 +9,7 @@ from ..cache import Cache, assert_secure
from ..helpers import Error
from ..helpers import SortBySpec, positive_int_validator, location_validator, Location, relative_time_marker_validator
from ..helpers import Highlander
from ..helpers.jap_helpers import SUPPRESS
from ..helpers.nanorst import rst_to_terminal
from ..manifest import Manifest, AI_HUMAN_SORT_KEYS
from ..patterns import PatternMatcher

View file

@ -1,14 +1,12 @@
import argparse
from collections import defaultdict
import os
from jsonargparse import ArgumentParser
from ._common import with_repository, define_archive_filters_group
from ..archive import Archive
from ..constants import * # NOQA
from ..helpers import bin_to_hex, Error
from ..helpers import ProgressIndicatorPercent
from ..helpers.jap_helpers import ArgumentParser, RawDescriptionHelpFormatter
from ..manifest import Manifest
from ..remote import RemoteRepository
from ..repository import Repository
@ -133,7 +131,7 @@ class AnalyzeMixIn:
add_help=False,
description=self.do_analyze.__doc__,
epilog=analyze_epilog,
formatter_class=argparse.RawDescriptionHelpFormatter,
formatter_class=RawDescriptionHelpFormatter,
)
subparsers.add_subcommand("analyze", subparser, help="analyze archives")
define_archive_filters_group(subparser)

View file

@ -1,4 +1,3 @@
import argparse
from contextlib import contextmanager
import json
import logging
@ -6,14 +5,13 @@ import os
import tempfile
import time
from jsonargparse import ArgumentParser
from ..constants import * # NOQA
from ..crypto.key import FlexiKey
from ..helpers import format_file_size
from ..helpers import json_print
from ..helpers import msgpack
from ..helpers import get_reset_ec
from ..helpers.jap_helpers import ArgumentParser, RawDescriptionHelpFormatter
from ..item import Item
from ..platform import SyncFile
@ -361,7 +359,7 @@ class BenchmarkMixIn:
add_help=False,
description="benchmark command",
epilog=benchmark_epilog,
formatter_class=argparse.RawDescriptionHelpFormatter,
formatter_class=RawDescriptionHelpFormatter,
)
subparsers.add_subcommand("benchmark", subparser, help="benchmark command")
@ -413,7 +411,7 @@ class BenchmarkMixIn:
add_help=False,
description=self.do_benchmark_crud.__doc__,
epilog=bench_crud_epilog,
formatter_class=argparse.RawDescriptionHelpFormatter,
formatter_class=RawDescriptionHelpFormatter,
)
benchmark_parsers.add_subcommand(
"crud", subparser, help="benchmarks Borg CRUD (create, extract, update, delete)."
@ -438,7 +436,7 @@ class BenchmarkMixIn:
add_help=False,
description=self.do_benchmark_cpu.__doc__,
epilog=bench_cpu_epilog,
formatter_class=argparse.RawDescriptionHelpFormatter,
formatter_class=RawDescriptionHelpFormatter,
)
benchmark_parsers.add_subcommand("cpu", subparser, help="benchmarks Borg CPU-bound operations.")
subparser.add_argument("--json", action="store_true", help="format output as JSON")

View file

@ -1,12 +1,9 @@
import argparse
from jsonargparse import ArgumentParser
from ._common import with_repository, Highlander
from ..archive import ArchiveChecker
from ..constants import * # NOQA
from ..helpers import set_ec, EXIT_WARNING, CancelledByUser, CommandError, IntegrityError
from ..helpers import yes
from ..helpers.jap_helpers import ArgumentParser, RawDescriptionHelpFormatter
from ..logger import create_logger
@ -190,7 +187,7 @@ class CheckMixIn:
add_help=False,
description=self.do_check.__doc__,
epilog=check_epilog,
formatter_class=argparse.RawDescriptionHelpFormatter,
formatter_class=RawDescriptionHelpFormatter,
)
subparsers.add_subcommand("check", subparser, help="verify the repository")
subparser.add_argument(

View file

@ -1,13 +1,11 @@
import argparse
from pathlib import Path
from jsonargparse import ArgumentParser
from ._common import with_repository
from ..archive import Archive
from ..cache import write_chunkindex_to_repo_cache, build_chunkindex_from_repo
from ..cache import files_cache_name, discover_files_cache_names
from ..helpers import get_cache_dir
from ..helpers.jap_helpers import ArgumentParser, RawDescriptionHelpFormatter
from ..constants import * # NOQA
from ..hashindex import ChunkIndex, ChunkIndexEntry
from ..helpers import set_ec, EXIT_ERROR, format_file_size, bin_to_hex
@ -264,7 +262,7 @@ class CompactMixIn:
add_help=False,
description=self.do_compact.__doc__,
epilog=compact_epilog,
formatter_class=argparse.RawDescriptionHelpFormatter,
formatter_class=RawDescriptionHelpFormatter,
)
subparsers.add_subcommand("compact", subparser, help="compact the repository")
subparser.add_argument(

View file

@ -50,12 +50,10 @@ The following argument types have intelligent, context-aware completion:
- Suggests common file size values (500M, 1G, 10G, 100G, 1T, etc.)
"""
import argparse
import shtab
from jsonargparse import ArgumentParser
from jsonargparse._actions import _ActionSubCommands
from jsonargparse._completions import prepare_actions_context, shtab_prepare_actions, bash_compgen_typehint
from ._common import process_epilog
from ..constants import * # NOQA
@ -69,6 +67,7 @@ from ..helpers import (
relative_time_marker_validator,
parse_file_size,
)
from ..helpers.jap_helpers import ArgumentParser, RawDescriptionHelpFormatter
from ..helpers.time import timestamp
from ..compress import CompressionSpec
from ..helpers.parseformat import partial_format
@ -344,7 +343,6 @@ _borg_help_topics() {
}
"""
# Global zsh preamble providing dynamic completion for aid:<hex> archive IDs.
#
# Notes:
@ -735,16 +733,8 @@ class CompletionMixIn:
bash_preamble = partial_format(BASH_PREAMBLE_TMPL, mapping)
zsh_preamble = partial_format(ZSH_PREAMBLE_TMPL, mapping)
from jsonargparse._completions import (
prepare_actions_context,
shtab_prepare_actions,
norm_name,
bash_compgen_typehint,
)
prog = norm_name(parser.prog)
if not prog:
prog = "borg"
parser.prog = "borg"
prog = "borg"
preambles = []
if args.shell == "bash":
preambles.append(bash_compgen_typehint.strip().replace("%s", prog))
@ -777,7 +767,7 @@ class CompletionMixIn:
add_help=False,
description=self.do_completion.__doc__,
epilog=completion_epilog,
formatter_class=argparse.RawDescriptionHelpFormatter,
formatter_class=RawDescriptionHelpFormatter,
)
subparsers.add_subcommand("completion", subparser, help="output shell completion script")
subparser.add_argument(

View file

@ -1,6 +1,5 @@
import errno
import sys
import argparse
import logging
import os
import posixpath
@ -9,8 +8,6 @@ import subprocess
import time
from io import TextIOWrapper
from jsonargparse import ArgumentParser
from ._common import with_repository, Highlander
from .. import helpers
from ..archive import Archive, is_special
@ -33,6 +30,7 @@ from ..helpers import sig_int, ignore_sigint
from ..helpers import iter_separated
from ..helpers import MakePathSafeAction
from ..helpers import Error, CommandError, BackupWarning, FileChangedWarning
from ..helpers.jap_helpers import ArgumentParser, RawDescriptionHelpFormatter
from ..manifest import Manifest
from ..patterns import PatternMatcher
from ..platform import is_win32
@ -681,7 +679,6 @@ class CreateMixIn:
macOS examples are the apfs mounts of a typical macOS installation.
Therefore, when using ``--one-file-system``, you should double-check that the backup works as intended.
.. _list_item_flags:
Item flags
@ -779,7 +776,7 @@ class CreateMixIn:
add_help=False,
description=self.do_create.__doc__,
epilog=create_epilog,
formatter_class=argparse.RawDescriptionHelpFormatter,
formatter_class=RawDescriptionHelpFormatter,
)
subparsers.add_subcommand("create", subparser, help="create a backup")

View file

@ -1,9 +1,6 @@
import argparse
import json
import textwrap
from jsonargparse import ArgumentParser
from ..archive import Archive
from ..compress import CompressionSpec
from ..constants import * # NOQA
@ -14,6 +11,7 @@ from ..helpers import dash_open
from ..helpers import StableDict
from ..helpers import archivename_validator
from ..helpers import CommandError, RTError
from ..helpers.jap_helpers import ArgumentParser, RawDescriptionHelpFormatter
from ..manifest import Manifest
from ..platform import get_process_id
from ..repository import Repository, LIST_SCAN_LIMIT, repo_lister
@ -325,7 +323,7 @@ class DebugMixIn:
add_help=False,
description="debugging command (not intended for normal use)",
epilog=debug_epilog,
formatter_class=argparse.RawDescriptionHelpFormatter,
formatter_class=RawDescriptionHelpFormatter,
)
subparsers.add_subcommand("debug", subparser, help="debugging command (not intended for normal use)")
@ -343,7 +341,7 @@ class DebugMixIn:
add_help=False,
description=self.do_debug_info.__doc__,
epilog=debug_info_epilog,
formatter_class=argparse.RawDescriptionHelpFormatter,
formatter_class=RawDescriptionHelpFormatter,
)
debug_parsers.add_subcommand("info", subparser, help="show system infos for debugging / bug reports (debug)")
@ -357,7 +355,7 @@ class DebugMixIn:
add_help=False,
description=self.do_debug_dump_archive_items.__doc__,
epilog=debug_dump_archive_items_epilog,
formatter_class=argparse.RawDescriptionHelpFormatter,
formatter_class=RawDescriptionHelpFormatter,
)
debug_parsers.add_subcommand("dump-archive-items", subparser, help="dump archive items (metadata) (debug)")
subparser.add_argument("name", metavar="NAME", type=archivename_validator, help="specify the archive name")
@ -372,7 +370,7 @@ class DebugMixIn:
add_help=False,
description=self.do_debug_dump_archive.__doc__,
epilog=debug_dump_archive_epilog,
formatter_class=argparse.RawDescriptionHelpFormatter,
formatter_class=RawDescriptionHelpFormatter,
)
debug_parsers.add_subcommand("dump-archive", subparser, help="dump decoded archive metadata (debug)")
subparser.add_argument("name", metavar="NAME", type=archivename_validator, help="specify the archive name")
@ -388,7 +386,7 @@ class DebugMixIn:
add_help=False,
description=self.do_debug_dump_manifest.__doc__,
epilog=debug_dump_manifest_epilog,
formatter_class=argparse.RawDescriptionHelpFormatter,
formatter_class=RawDescriptionHelpFormatter,
)
debug_parsers.add_subcommand("dump-manifest", subparser, help="dump decoded repository metadata (debug)")
subparser.add_argument("path", metavar="PATH", type=str, help="file to dump data into")
@ -403,7 +401,7 @@ class DebugMixIn:
add_help=False,
description=self.do_debug_dump_repo_objs.__doc__,
epilog=debug_dump_repo_objs_epilog,
formatter_class=argparse.RawDescriptionHelpFormatter,
formatter_class=RawDescriptionHelpFormatter,
)
debug_parsers.add_subcommand("dump-repo-objs", subparser, help="dump repo objects (debug)")
@ -417,7 +415,7 @@ class DebugMixIn:
add_help=False,
description=self.do_debug_search_repo_objs.__doc__,
epilog=debug_search_repo_objs_epilog,
formatter_class=argparse.RawDescriptionHelpFormatter,
formatter_class=RawDescriptionHelpFormatter,
)
debug_parsers.add_subcommand("search-repo-objs", subparser, help="search repo objects (debug)")
subparser.add_argument(
@ -437,7 +435,7 @@ class DebugMixIn:
add_help=False,
description=self.do_debug_id_hash.__doc__,
epilog=debug_id_hash_epilog,
formatter_class=argparse.RawDescriptionHelpFormatter,
formatter_class=RawDescriptionHelpFormatter,
)
debug_parsers.add_subcommand("id-hash", subparser, help="compute id-hash for some file content (debug)")
subparser.add_argument(
@ -455,7 +453,7 @@ class DebugMixIn:
add_help=False,
description=self.do_debug_parse_obj.__doc__,
epilog=debug_parse_obj_epilog,
formatter_class=argparse.RawDescriptionHelpFormatter,
formatter_class=RawDescriptionHelpFormatter,
)
debug_parsers.add_subcommand("parse-obj", subparser, help="parse borg object file into meta dict and data")
subparser.add_argument("id", metavar="ID", type=str, help="hex object ID to get from the repo")
@ -480,7 +478,7 @@ class DebugMixIn:
add_help=False,
description=self.do_debug_format_obj.__doc__,
epilog=debug_format_obj_epilog,
formatter_class=argparse.RawDescriptionHelpFormatter,
formatter_class=RawDescriptionHelpFormatter,
)
debug_parsers.add_subcommand("format-obj", subparser, help="format file and metadata into a Borg object file")
subparser.add_argument("id", metavar="ID", type=str, help="hex object ID to get from the repo")
@ -517,7 +515,7 @@ class DebugMixIn:
add_help=False,
description=self.do_debug_get_obj.__doc__,
epilog=debug_get_obj_epilog,
formatter_class=argparse.RawDescriptionHelpFormatter,
formatter_class=RawDescriptionHelpFormatter,
)
debug_parsers.add_subcommand("get-obj", subparser, help="get object from repository (debug)")
subparser.add_argument("id", metavar="ID", type=str, help="hex object ID to get from the repo")
@ -533,7 +531,7 @@ class DebugMixIn:
add_help=False,
description=self.do_debug_put_obj.__doc__,
epilog=debug_put_obj_epilog,
formatter_class=argparse.RawDescriptionHelpFormatter,
formatter_class=RawDescriptionHelpFormatter,
)
debug_parsers.add_subcommand("put-obj", subparser, help="put object to repository (debug)")
subparser.add_argument("id", metavar="ID", type=str, help="hex object ID to put into the repo")
@ -549,7 +547,7 @@ class DebugMixIn:
add_help=False,
description=self.do_debug_delete_obj.__doc__,
epilog=debug_delete_obj_epilog,
formatter_class=argparse.RawDescriptionHelpFormatter,
formatter_class=RawDescriptionHelpFormatter,
)
debug_parsers.add_subcommand("delete-obj", subparser, help="delete object from repository (debug)")
subparser.add_argument(
@ -566,7 +564,7 @@ class DebugMixIn:
add_help=False,
description=self.do_debug_convert_profile.__doc__,
epilog=debug_convert_profile_epilog,
formatter_class=argparse.RawDescriptionHelpFormatter,
formatter_class=RawDescriptionHelpFormatter,
)
debug_parsers.add_subcommand(
"convert-profile", subparser, help="convert Borg profile to Python profile (debug)"

View file

@ -1,11 +1,9 @@
import argparse
import logging
from jsonargparse import ArgumentParser
from ._common import with_repository
from ..constants import * # NOQA
from ..helpers import format_archive, CommandError, bin_to_hex, archivename_validator
from ..helpers.jap_helpers import ArgumentParser, RawDescriptionHelpFormatter
from ..manifest import Manifest
from ..logger import create_logger
@ -87,7 +85,7 @@ class DeleteMixIn:
add_help=False,
description=self.do_delete.__doc__,
epilog=delete_epilog,
formatter_class=argparse.RawDescriptionHelpFormatter,
formatter_class=RawDescriptionHelpFormatter,
)
subparsers.add_subcommand("delete", subparser, help="delete archives")
subparser.add_argument(

View file

@ -1,16 +1,14 @@
import argparse
import textwrap
import json
import sys
import os
from jsonargparse import ArgumentParser
from ._common import with_repository, build_matcher, Highlander
from ..archive import Archive
from ..constants import * # NOQA
from ..helpers import BaseFormatter, DiffFormatter, archivename_validator, PathSpec, BorgJsonEncoder
from ..helpers import IncludePatternNeverMatchedWarning, remove_surrogates
from ..helpers.jap_helpers import ArgumentParser, ArgumentTypeError, RawDescriptionHelpFormatter
from ..item import ItemDiff
from ..manifest import Manifest
from ..logger import create_logger
@ -206,7 +204,6 @@ class DiffMixIn:
The following keys are always available:
"""
)
+ BaseFormatter.keys_help()
@ -271,7 +268,7 @@ class DiffMixIn:
def diff_sort_spec_validator(s):
if not isinstance(s, str):
raise argparse.ArgumentTypeError("unsupported sort field (not a string)")
raise ArgumentTypeError("unsupported sort field (not a string)")
allowed = {
"path",
"size_added",
@ -289,11 +286,11 @@ class DiffMixIn:
}
parts = [p.strip() for p in s.split(",") if p.strip()]
if not parts:
raise argparse.ArgumentTypeError("unsupported sort field: empty spec")
raise ArgumentTypeError("unsupported sort field: empty spec")
for spec in parts:
field = spec[1:] if spec and spec[0] in (">", "<") else spec
if field not in allowed:
raise argparse.ArgumentTypeError(f"unsupported sort field: {field}")
raise ArgumentTypeError(f"unsupported sort field: {field}")
return ",".join(parts)
subparser = ArgumentParser(
@ -301,7 +298,7 @@ class DiffMixIn:
add_help=False,
description=self.do_diff.__doc__,
epilog=diff_epilog,
formatter_class=argparse.RawDescriptionHelpFormatter,
formatter_class=RawDescriptionHelpFormatter,
)
subparsers.add_subcommand("diff", subparser, help="find differences in archive contents")
subparser.add_argument(

View file

@ -1,10 +1,7 @@
import sys
import argparse
import logging
import stat
from jsonargparse import ArgumentParser
from ._common import with_repository, with_archive
from ._common import build_filter, build_matcher
from ..archive import BackupError
@ -14,6 +11,7 @@ from ..helpers import remove_surrogates
from ..helpers import HardLinkManager
from ..helpers import ProgressIndicatorPercent
from ..helpers import BackupWarning, IncludePatternNeverMatchedWarning
from ..helpers.jap_helpers import ArgumentParser, RawDescriptionHelpFormatter
from ..manifest import Manifest
from ..logger import create_logger
@ -162,7 +160,7 @@ class ExtractMixIn:
add_help=False,
description=self.do_extract.__doc__,
epilog=extract_epilog,
formatter_class=argparse.RawDescriptionHelpFormatter,
formatter_class=RawDescriptionHelpFormatter,
)
subparsers.add_subcommand("extract", subparser, help="extract archive contents")
subparser.add_argument(

View file

@ -1,8 +1,7 @@
import collections
import textwrap
from jsonargparse import ArgumentParser
from ..helpers.jap_helpers import ArgumentParser
from ..constants import * # NOQA
from ..helpers.nanorst import rst_to_terminal
@ -162,7 +161,6 @@ class HelpMixIn:
# not '/home/user/importantjunk' or '/etc/junk':
$ borg create -e 'home/*/junk' archive /
# The contents of directories in '/home' are not backed up when their name
# ends in '.tmp'
$ borg create --exclude 're:^home/[^/]+\\.tmp/' archive /

View file

@ -1,13 +1,11 @@
import argparse
import textwrap
from datetime import timedelta
from jsonargparse import ArgumentParser
from ._common import with_repository
from ..archive import Archive
from ..constants import * # NOQA
from ..helpers import format_timedelta, json_print, basic_json_data, archivename_validator
from ..helpers.jap_helpers import ArgumentParser, RawDescriptionHelpFormatter
from ..manifest import Manifest
from ..logger import create_logger
@ -85,7 +83,7 @@ class InfoMixIn:
add_help=False,
description=self.do_info.__doc__,
epilog=info_epilog,
formatter_class=argparse.RawDescriptionHelpFormatter,
formatter_class=RawDescriptionHelpFormatter,
)
subparsers.add_subcommand("info", subparser, help="show repository or archive information")
subparser.add_argument("--json", action="store_true", help="format output as JSON")

View file

@ -1,13 +1,11 @@
import argparse
import os
from jsonargparse import ArgumentParser
from ..constants import * # NOQA
from ..crypto.key import AESOCBRepoKey, CHPORepoKey, Blake2AESOCBRepoKey, Blake2CHPORepoKey
from ..crypto.key import AESOCBKeyfileKey, CHPOKeyfileKey, Blake2AESOCBKeyfileKey, Blake2CHPOKeyfileKey
from ..crypto.keymanager import KeyManager
from ..helpers import PathSpec, CommandError
from ..helpers.jap_helpers import ArgumentParser, RawDescriptionHelpFormatter
from ..manifest import Manifest
from ._common import with_repository
@ -126,7 +124,7 @@ class KeysMixIn:
add_help=False,
description="Manage the keyfile or repokey of a repository",
epilog="",
formatter_class=argparse.RawDescriptionHelpFormatter,
formatter_class=RawDescriptionHelpFormatter,
)
subparsers.add_subcommand("key", subparser, help="manage the repository key")
@ -168,7 +166,7 @@ class KeysMixIn:
add_help=False,
description=self.do_key_export.__doc__,
epilog=key_export_epilog,
formatter_class=argparse.RawDescriptionHelpFormatter,
formatter_class=RawDescriptionHelpFormatter,
)
key_parsers.add_subcommand("export", subparser, help="export the repository key for backup")
subparser.add_argument("path", metavar="PATH", nargs="?", type=PathSpec, help="where to store the backup")
@ -208,7 +206,7 @@ class KeysMixIn:
add_help=False,
description=self.do_key_import.__doc__,
epilog=key_import_epilog,
formatter_class=argparse.RawDescriptionHelpFormatter,
formatter_class=RawDescriptionHelpFormatter,
)
key_parsers.add_subcommand("import", subparser, help="import the repository key from backup")
subparser.add_argument(
@ -237,7 +235,7 @@ class KeysMixIn:
add_help=False,
description=self.do_key_change_passphrase.__doc__,
epilog=change_passphrase_epilog,
formatter_class=argparse.RawDescriptionHelpFormatter,
formatter_class=RawDescriptionHelpFormatter,
)
key_parsers.add_subcommand("change-passphrase", subparser, help="change the repository passphrase")
@ -259,7 +257,7 @@ class KeysMixIn:
add_help=False,
description=self.do_key_change_location.__doc__,
epilog=change_location_epilog,
formatter_class=argparse.RawDescriptionHelpFormatter,
formatter_class=RawDescriptionHelpFormatter,
)
key_parsers.add_subcommand("change-location", subparser, help="change the key location")
subparser.add_argument(

View file

@ -1,15 +1,13 @@
import argparse
import os
import textwrap
import sys
from jsonargparse import ArgumentParser
from ._common import with_repository, build_matcher, Highlander
from ..archive import Archive
from ..cache import Cache
from ..constants import * # NOQA
from ..helpers import ItemFormatter, BaseFormatter, archivename_validator, PathSpec
from ..helpers.jap_helpers import ArgumentParser, RawDescriptionHelpFormatter
from ..manifest import Manifest
from ..logger import create_logger
@ -92,7 +90,6 @@ class ListMixIn:
The following keys are always available:
"""
)
+ BaseFormatter.keys_help()
@ -110,7 +107,7 @@ class ListMixIn:
add_help=False,
description=self.do_list.__doc__,
epilog=list_epilog,
formatter_class=argparse.RawDescriptionHelpFormatter,
formatter_class=RawDescriptionHelpFormatter,
)
subparsers.add_subcommand("list", subparser, help="list archive contents")
subparser.add_argument(

View file

@ -1,12 +1,10 @@
import argparse
import subprocess
from jsonargparse import ArgumentParser, REMAINDER
from ._common import with_repository
from ..cache import Cache
from ..constants import * # NOQA
from ..helpers import prepare_subprocess_env, set_ec, CommandError, ThreadRunner
from ..helpers.jap_helpers import ArgumentParser, RawDescriptionHelpFormatter, REMAINDER
from ..logger import create_logger
@ -52,7 +50,7 @@ class LocksMixIn:
add_help=False,
description=self.do_break_lock.__doc__,
epilog=break_lock_epilog,
formatter_class=argparse.RawDescriptionHelpFormatter,
formatter_class=RawDescriptionHelpFormatter,
)
subparsers.add_subcommand("break-lock", subparser, help="break the repository and cache locks")
@ -82,7 +80,7 @@ class LocksMixIn:
add_help=False,
description=self.do_with_lock.__doc__,
epilog=with_lock_epilog,
formatter_class=argparse.RawDescriptionHelpFormatter,
formatter_class=RawDescriptionHelpFormatter,
)
subparsers.add_subcommand("with-lock", subparser, help="run a user command with the lock held")
subparser.add_argument("command", metavar="COMMAND", help="command to run")

View file

@ -1,13 +1,11 @@
import argparse
import os
from jsonargparse import ArgumentParser
from ._common import with_repository, Highlander
from ..constants import * # NOQA
from ..helpers import RTError
from ..helpers import PathSpec
from ..helpers import umount
from ..helpers.jap_helpers import ArgumentParser, RawDescriptionHelpFormatter
from ..manifest import Manifest
from ..remote import cache_if_remote
@ -158,7 +156,7 @@ class MountMixIn:
add_help=False,
description=self.do_mount.__doc__,
epilog=mount_epilog,
formatter_class=argparse.RawDescriptionHelpFormatter,
formatter_class=RawDescriptionHelpFormatter,
)
subparsers.add_subcommand("mount", subparser, help="mount a repository")
self._define_borg_mount(subparser)
@ -176,7 +174,7 @@ class MountMixIn:
add_help=False,
description=self.do_umount.__doc__,
epilog=umount_epilog,
formatter_class=argparse.RawDescriptionHelpFormatter,
formatter_class=RawDescriptionHelpFormatter,
)
subparsers.add_subcommand("umount", subparser, help="unmount a repository")
subparser.add_argument(
@ -187,7 +185,7 @@ class MountMixIn:
assert parser.prog == "borgfs"
parser.description = self.do_mount.__doc__
parser.epilog = "For more information, see borg mount --help."
parser.formatter_class = argparse.RawDescriptionHelpFormatter
parser.formatter_class = RawDescriptionHelpFormatter
parser.help = "mount a repository"
self._define_borg_mount(parser)
return parser

View file

@ -1,16 +1,14 @@
import argparse
from collections import OrderedDict
from datetime import datetime, timezone, timedelta
import logging
from operator import attrgetter
import os
from jsonargparse import ArgumentParser
from ._common import with_repository, Highlander
from ..constants import * # NOQA
from ..helpers import ArchiveFormatter, interval, sig_int, ProgressIndicatorPercent, CommandError, Error
from ..helpers import archivename_validator
from ..helpers.jap_helpers import ArgumentParser, RawDescriptionHelpFormatter
from ..manifest import Manifest
from ..logger import create_logger
@ -280,7 +278,7 @@ class PruneMixIn:
add_help=False,
description=self.do_prune.__doc__,
epilog=prune_epilog,
formatter_class=argparse.RawDescriptionHelpFormatter,
formatter_class=RawDescriptionHelpFormatter,
)
subparsers.add_subcommand("prune", subparser, help="prune archives")
subparser.add_argument(

View file

@ -1,7 +1,3 @@
import argparse
from jsonargparse import ArgumentParser
from ._common import with_repository, Highlander
from ._common import build_matcher
from ..archive import ArchiveRecreater
@ -9,6 +5,7 @@ from ..constants import * # NOQA
from ..compress import CompressionSpec
from ..helpers import archivename_validator, comment_validator, PathSpec, ChunkerParams, bin_to_hex
from ..helpers import timestamp
from ..helpers.jap_helpers import ArgumentParser, RawDescriptionHelpFormatter
from ..manifest import Manifest
from ..logger import create_logger
@ -109,7 +106,7 @@ class RecreateMixIn:
add_help=False,
description=self.do_recreate.__doc__,
epilog=recreate_epilog,
formatter_class=argparse.RawDescriptionHelpFormatter,
formatter_class=RawDescriptionHelpFormatter,
)
subparsers.add_subcommand("recreate", subparser, help=self.do_recreate.__doc__)
subparser.add_argument(

View file

@ -1,10 +1,7 @@
import argparse
from jsonargparse import ArgumentParser
from ._common import with_repository, with_archive
from ..constants import * # NOQA
from ..helpers import archivename_validator
from ..helpers.jap_helpers import ArgumentParser, RawDescriptionHelpFormatter
from ..manifest import Manifest
from ..logger import create_logger
@ -35,7 +32,7 @@ class RenameMixIn:
add_help=False,
description=self.do_rename.__doc__,
epilog=rename_epilog,
formatter_class=argparse.RawDescriptionHelpFormatter,
formatter_class=RawDescriptionHelpFormatter,
)
subparsers.add_subcommand("rename", subparser, help="rename an archive")
subparser.add_argument(

View file

@ -1,13 +1,11 @@
import argparse
from collections import defaultdict
from jsonargparse import ArgumentParser
from ._common import with_repository, Highlander
from ..constants import * # NOQA
from ..compress import CompressionSpec, ObfuscateSize, Auto, COMPRESSOR_TABLE
from ..hashindex import ChunkIndex
from ..helpers import sig_int, ProgressIndicatorPercent, Error
from ..helpers.jap_helpers import ArgumentParser, RawDescriptionHelpFormatter
from ..repository import Repository
from ..remote import RemoteRepository
from ..manifest import Manifest
@ -187,7 +185,7 @@ class RepoCompressMixIn:
add_help=False,
description=self.do_repo_compress.__doc__,
epilog=repo_compress_epilog,
formatter_class=argparse.RawDescriptionHelpFormatter,
formatter_class=RawDescriptionHelpFormatter,
)
subparsers.add_subcommand("repo-compress", subparser, help=self.do_repo_compress.__doc__)

View file

@ -1,13 +1,10 @@
import argparse
from jsonargparse import ArgumentParser
from ._common import with_repository, with_other_repository, Highlander
from ..cache import Cache
from ..constants import * # NOQA
from ..crypto.key import key_creator, key_argument_names
from ..helpers import CancelledByUser
from ..helpers import location_validator, Location
from ..helpers.jap_helpers import ArgumentParser, RawDescriptionHelpFormatter
from ..manifest import Manifest
from ..logger import create_logger
@ -197,7 +194,7 @@ class RepoCreateMixIn:
add_help=False,
description=self.do_repo_create.__doc__,
epilog=repo_create_epilog,
formatter_class=argparse.RawDescriptionHelpFormatter,
formatter_class=RawDescriptionHelpFormatter,
)
subparsers.add_subcommand("repo-create", subparser, help="create a new, empty repository")
subparser.add_argument(

View file

@ -1,7 +1,3 @@
import argparse
from jsonargparse import ArgumentParser
from ._common import with_repository
from ..cache import Cache, SecurityManager
from ..constants import * # NOQA
@ -9,6 +5,7 @@ from ..helpers import CancelledByUser
from ..helpers import format_archive
from ..helpers import bin_to_hex
from ..helpers import yes
from ..helpers.jap_helpers import ArgumentParser, RawDescriptionHelpFormatter
from ..manifest import Manifest, NoManifestError
from ..logger import create_logger
@ -109,7 +106,7 @@ class RepoDeleteMixIn:
add_help=False,
description=self.do_repo_delete.__doc__,
epilog=repo_delete_epilog,
formatter_class=argparse.RawDescriptionHelpFormatter,
formatter_class=RawDescriptionHelpFormatter,
)
subparsers.add_subcommand("repo-delete", subparser, help="delete a repository")
subparser.add_argument(

View file

@ -1,11 +1,9 @@
import argparse
import textwrap
from jsonargparse import ArgumentParser
from ._common import with_repository
from ..constants import * # NOQA
from ..helpers import bin_to_hex, json_print, basic_json_data
from ..helpers.jap_helpers import ArgumentParser, RawDescriptionHelpFormatter
from ..manifest import Manifest
from ..logger import create_logger
@ -70,7 +68,7 @@ class RepoInfoMixIn:
add_help=False,
description=self.do_repo_info.__doc__,
epilog=repo_info_epilog,
formatter_class=argparse.RawDescriptionHelpFormatter,
formatter_class=RawDescriptionHelpFormatter,
)
subparsers.add_subcommand("repo-info", subparser, help="show repository information")
subparser.add_argument("--json", action="store_true", help="format output as JSON")

View file

@ -1,13 +1,11 @@
import argparse
import os
import textwrap
import sys
from jsonargparse import ArgumentParser
from ._common import with_repository, Highlander
from ..constants import * # NOQA
from ..helpers import BaseFormatter, ArchiveFormatter, json_print, basic_json_data
from ..helpers.jap_helpers import ArgumentParser, RawDescriptionHelpFormatter
from ..manifest import Manifest
from ..logger import create_logger
@ -74,7 +72,6 @@ class RepoListMixIn:
The following keys are always available:
"""
)
+ BaseFormatter.keys_help()
@ -92,7 +89,7 @@ class RepoListMixIn:
add_help=False,
description=self.do_repo_list.__doc__,
epilog=repo_list_epilog,
formatter_class=argparse.RawDescriptionHelpFormatter,
formatter_class=RawDescriptionHelpFormatter,
)
subparsers.add_subcommand("repo-list", subparser, help="list repository contents")
subparser.add_argument(

View file

@ -1,14 +1,12 @@
import argparse
import math
import os
from jsonargparse import ArgumentParser
from borgstore.store import ItemInfo
from ._common import with_repository, Highlander
from ..constants import * # NOQA
from ..helpers import parse_file_size, format_file_size
from ..helpers.jap_helpers import ArgumentParser, RawDescriptionHelpFormatter
from ..logger import create_logger
@ -84,7 +82,6 @@ class RepoSpaceMixIn:
$ borg compact -v # only this actually frees space of deleted archives
$ borg repo-space --reserve 1G # reserve space again for next time
Reserved space is always rounded up to full reservation blocks of 64 MiB.
"""
)
@ -93,7 +90,7 @@ class RepoSpaceMixIn:
add_help=False,
description=self.do_repo_space.__doc__,
epilog=repo_space_epilog,
formatter_class=argparse.RawDescriptionHelpFormatter,
formatter_class=RawDescriptionHelpFormatter,
)
subparsers.add_subcommand("repo-space", subparser, help="manage reserved space in a repository")
subparser.add_argument(

View file

@ -1,9 +1,8 @@
import argparse
from ..constants import * # NOQA
from ..remote import RepositoryServer
from ..logger import create_logger
from ..helpers.jap_helpers import RawDescriptionHelpFormatter, ArgumentParser
logger = create_logger()
@ -19,7 +18,6 @@ class ServeMixIn:
).serve()
def build_parser_serve(self, subparsers, common_parser, mid_common_parser):
from jsonargparse import ArgumentParser
from ._common import process_epilog
serve_epilog = process_epilog(
@ -58,7 +56,7 @@ class ServeMixIn:
add_help=False,
description=self.do_serve.__doc__,
epilog=serve_epilog,
formatter_class=argparse.RawDescriptionHelpFormatter,
formatter_class=RawDescriptionHelpFormatter,
)
subparsers.add_subcommand("serve", subparser, help="start the repository server process")
subparser.add_argument(

View file

@ -1,11 +1,8 @@
import argparse
from jsonargparse import ArgumentParser
from ._common import with_repository, define_archive_filters_group
from ..archive import Archive
from ..constants import * # NOQA
from ..helpers import bin_to_hex, archivename_validator, tag_validator, Error
from ..helpers.jap_helpers import ArgumentParser, RawDescriptionHelpFormatter
from ..manifest import Manifest
from ..logger import create_logger
@ -87,7 +84,7 @@ class TagMixIn:
add_help=False,
description=self.do_tag.__doc__,
epilog=tag_epilog,
formatter_class=argparse.RawDescriptionHelpFormatter,
formatter_class=RawDescriptionHelpFormatter,
)
subparsers.add_subcommand("tag", subparser, help="tag archives")
subparser.add_argument("--set", dest="set_tags", metavar="TAG", type=tag_validator, nargs="+", help="set tags")

View file

@ -1,12 +1,9 @@
import argparse
import base64
import logging
import os
import stat
import tarfile
from jsonargparse import ArgumentParser
from ..archive import Archive, TarfileObjectProcessors, ChunksProcessor
from ..compress import CompressionSpec
from ..constants import * # NOQA
@ -21,6 +18,7 @@ from ..helpers import remove_surrogates
from ..helpers import timestamp, archive_ts_now
from ..helpers import basic_json_data, json_print
from ..helpers import log_multi
from ..helpers.jap_helpers import ArgumentParser, RawDescriptionHelpFormatter
from ..manifest import Manifest
from ._common import with_repository, with_archive, Highlander, define_exclusion_group
@ -391,7 +389,7 @@ class TarMixIn:
add_help=False,
description=self.do_export_tar.__doc__,
epilog=export_tar_epilog,
formatter_class=argparse.RawDescriptionHelpFormatter,
formatter_class=RawDescriptionHelpFormatter,
)
subparsers.add_subcommand("export-tar", subparser, help="create tarball from archive")
subparser.add_argument(
@ -465,7 +463,7 @@ class TarMixIn:
add_help=False,
description=self.do_import_tar.__doc__,
epilog=import_tar_epilog,
formatter_class=argparse.RawDescriptionHelpFormatter,
formatter_class=RawDescriptionHelpFormatter,
)
subparsers.add_subcommand("import-tar", subparser, help=self.do_import_tar.__doc__)
subparser.add_argument(

View file

@ -1,7 +1,3 @@
import argparse
from jsonargparse import ArgumentParser
from ._common import with_repository, with_other_repository, Highlander
from ..archive import Archive, cached_hash, DownloadPipeline
from ..chunkers import get_chunker
@ -12,6 +8,7 @@ from ..helpers import Error
from ..helpers import location_validator, Location, archivename_validator, comment_validator
from ..helpers import format_file_size, bin_to_hex
from ..helpers import ChunkerParams, ChunkIteratorFileWrapper
from ..helpers.jap_helpers import ArgumentParser, ArgumentTypeError, RawDescriptionHelpFormatter
from ..item import ChunkListEntry
from ..manifest import Manifest
from ..legacyrepository import LegacyRepository
@ -158,7 +155,7 @@ class TransferMixIn:
for archive_info in archive_infos:
try:
archivename_validator(archive_info.name)
except argparse.ArgumentTypeError as err:
except ArgumentTypeError as err:
an_errors.append(str(err))
if an_errors:
an_errors.insert(0, "Invalid archive names detected, please rename them before transfer:")
@ -169,7 +166,7 @@ class TransferMixIn:
archive = Archive(other_manifest, archive_info.id)
try:
comment_validator(archive.metadata.get("comment", ""))
except argparse.ArgumentTypeError as err:
except ArgumentTypeError as err:
ac_errors.append(f"{archive_info.name}: {err}")
if ac_errors:
ac_errors.insert(0, "Invalid archive comments detected, please fix them before transfer:")
@ -311,7 +308,6 @@ class TransferMixIn:
borg --repo=DST_REPO transfer --other-repo=SRC_REPO # do it!
borg --repo=DST_REPO transfer --other-repo=SRC_REPO --dry-run # check! anything left?
Data migration / upgrade from borg 1.x
++++++++++++++++++++++++++++++++++++++
@ -332,7 +328,6 @@ class TransferMixIn:
borg --repo=DST_REPO transfer --other-repo=SRC_REPO \\
--chunker-params=buzhash,19,23,21,4095
"""
)
subparser = ArgumentParser(
@ -340,7 +335,7 @@ class TransferMixIn:
add_help=False,
description=self.do_transfer.__doc__,
epilog=transfer_epilog,
formatter_class=argparse.RawDescriptionHelpFormatter,
formatter_class=RawDescriptionHelpFormatter,
)
subparsers.add_subcommand("transfer", subparser, help="transfer of archives from another repository")
subparser.add_argument(

View file

@ -1,11 +1,9 @@
import argparse
import logging
from jsonargparse import ArgumentParser
from ._common import with_repository
from ..constants import * # NOQA
from ..helpers import format_archive, CommandError, bin_to_hex, archivename_validator
from ..helpers.jap_helpers import ArgumentParser, RawDescriptionHelpFormatter
from ..manifest import Manifest
from ..logger import create_logger
@ -79,7 +77,7 @@ class UnDeleteMixIn:
add_help=False,
description=self.do_undelete.__doc__,
epilog=undelete_epilog,
formatter_class=argparse.RawDescriptionHelpFormatter,
formatter_class=RawDescriptionHelpFormatter,
)
subparsers.add_subcommand("undelete", subparser, help="undelete archives")
subparser.add_argument(

View file

@ -1,7 +1,6 @@
import argparse
from .. import __version__
from ..constants import * # NOQA
from ..helpers.jap_helpers import RawDescriptionHelpFormatter, ArgumentParser
from ..remote import RemoteRepository
from ..logger import create_logger
@ -23,7 +22,6 @@ class VersionMixIn:
print(f"{format_version(client_version)} / {format_version(server_version)}")
def build_parser_version(self, subparsers, common_parser, mid_common_parser):
from jsonargparse import ArgumentParser
from ._common import process_epilog
version_epilog = process_epilog(
@ -57,6 +55,6 @@ class VersionMixIn:
add_help=False,
description=self.do_version.__doc__,
epilog=version_epilog,
formatter_class=argparse.RawDescriptionHelpFormatter,
formatter_class=RawDescriptionHelpFormatter,
)
subparsers.add_subcommand("version", subparser, help="display the Borg client and server versions")

View file

@ -15,10 +15,10 @@ which compressor has been used to compress the data and dispatch to the correct
decompressor.
"""
from argparse import ArgumentTypeError
import math
import random
from struct import Struct
import sys
import zlib
try:
@ -28,15 +28,13 @@ except ImportError:
from .constants import MAX_DATA_SIZE, ROBJ_FILE_STREAM
from .helpers import Buffer, DecompressionError
import sys
from .helpers.jap_helpers import ArgumentTypeError
if sys.version_info >= (3, 14):
from compression import zstd
else:
from backports import zstd
cdef extern from "lz4.h":
int LZ4_compress_default(const char* source, char* dest, int inputSize, int maxOutputSize) nogil
int LZ4_decompress_safe(const char* source, char* dest, int inputSize, int maxOutputSize) nogil
@ -120,7 +118,6 @@ cdef class CompressorBase:
else:
pass # raise ValueError("size not present and not in legacy mode")
cdef class DecidingCompressor(CompressorBase):
"""
base class for (de)compression classes that (based on an internal _decide
@ -188,7 +185,6 @@ class CNONE(CompressorBase):
self.check_fix_size(meta, data)
return meta, data
class LZ4(DecidingCompressor):
"""
raw LZ4 compression / decompression (liblz4).
@ -260,7 +256,6 @@ class LZ4(DecidingCompressor):
self.check_fix_size(meta, data)
return meta, data
class LZMA(DecidingCompressor):
"""
lzma compression / decompression
@ -355,7 +350,6 @@ class ZLIB(DecidingCompressor):
except zlib.error as e:
raise DecompressionError(str(e)) from None
class ZLIB_legacy(CompressorBase):
"""
zlib compression / decompression (python stdlib)
@ -402,7 +396,6 @@ class ZLIB_legacy(CompressorBase):
except zlib.error as e:
raise DecompressionError(str(e)) from None
class Auto(CompressorBase):
"""
Meta-Compressor that decides which compression to use based on LZ4's ratio.
@ -484,7 +477,6 @@ class Auto(CompressorBase):
def detect(cls, data):
raise NotImplementedError
class ObfuscateSize(CompressorBase):
"""
Meta-Compressor that obfuscates the compressed data size.
@ -569,7 +561,6 @@ class ObfuscateSize(CompressorBase):
self.compressor = compressor_cls()
return self.compressor.decompress(meta, compressed_data) # decompress data
# Maps valid compressor names to their class
COMPRESSOR_TABLE = {
CNONE.name: CNONE,
@ -624,7 +615,6 @@ class Compressor:
else:
raise ValueError('No decompressor for this data found: %r.', data[:2])
class CompressionSpec:
def __init__(self, s):
if isinstance(s, CompressionSpec):

View file

@ -1,6 +1,10 @@
from jsonargparse import Namespace
from typing import Any
# here are the only imports from argparse and jsonargparse,
# all other imports of these names import them from here:
from argparse import Action, ArgumentError, ArgumentTypeError, RawDescriptionHelpFormatter # noqa: F401
from jsonargparse import ArgumentParser, Namespace, SUPPRESS, REMAINDER # noqa: F401
def flatten_namespace(ns: Any) -> Namespace:
"""

View file

@ -1,5 +1,4 @@
import abc
import argparse
import base64
import binascii
import hashlib
@ -24,6 +23,7 @@ logger = create_logger()
from .errors import Error
from .fs import get_keys_dir, make_path_safe, slashify
from .jap_helpers import Action, ArgumentError, ArgumentTypeError
from .msgpack import Timestamp
from .time import OutputTimestamp, format_time, safe_timestamp
from .. import __version__ as borg_version
@ -124,7 +124,7 @@ def positive_int_validator(value):
"""argparse type for positive integers, N > 0."""
int_value = int(value)
if int_value <= 0:
raise argparse.ArgumentTypeError("A positive integer is required: %s" % value)
raise ArgumentTypeError("A positive integer is required: %s" % value)
return int_value
@ -152,7 +152,7 @@ def interval(s):
number = s[:-1]
suffix = s[-1]
else:
raise argparse.ArgumentTypeError(f'Unexpected time unit "{s[-1]}": choose from {", ".join(multiplier)}')
raise ArgumentTypeError(f'Unexpected time unit "{s[-1]}": choose from {", ".join(multiplier)}')
try:
seconds = int(number) * multiplier[suffix]
@ -160,7 +160,7 @@ def interval(s):
seconds = -1
if seconds <= 0:
raise argparse.ArgumentTypeError(f'Invalid number "{number}": expected positive integer')
raise ArgumentTypeError(f'Invalid number "{number}": expected positive integer')
return seconds
@ -171,7 +171,7 @@ def ChunkerParams(s):
params = s.strip().split(",")
count = len(params)
if count == 0:
raise argparse.ArgumentTypeError("no chunker params given")
raise ArgumentTypeError("no chunker params given")
algo = params[0].lower()
if algo == CH_FAIL and count == 3:
block_size = int(params[1])
@ -186,47 +186,37 @@ def ChunkerParams(s):
# or in-memory chunk management.
# choose the block (chunk) size wisely: if you have a lot of data and you cut
# it into very small chunks, you are asking for trouble!
raise argparse.ArgumentTypeError("block_size must not be less than 64 Bytes")
raise ArgumentTypeError("block_size must not be less than 64 Bytes")
if block_size > MAX_DATA_SIZE or header_size > MAX_DATA_SIZE:
raise argparse.ArgumentTypeError(
"block_size and header_size must not exceed MAX_DATA_SIZE [%d]" % MAX_DATA_SIZE
)
raise ArgumentTypeError("block_size and header_size must not exceed MAX_DATA_SIZE [%d]" % MAX_DATA_SIZE)
return algo, block_size, header_size
if algo == "default" and count == 1: # default
return CHUNKER_PARAMS
if algo == CH_BUZHASH64 and count == 5: # buzhash64, chunk_min, chunk_max, chunk_mask, window_size
chunk_min, chunk_max, chunk_mask, window_size = (int(p) for p in params[1:])
if not (chunk_min <= chunk_mask <= chunk_max):
raise argparse.ArgumentTypeError("required: chunk_min <= chunk_mask <= chunk_max")
raise ArgumentTypeError("required: chunk_min <= chunk_mask <= chunk_max")
if chunk_min < 6:
# see comment in 'fixed' algo check
raise argparse.ArgumentTypeError(
"min. chunk size exponent must not be less than 6 (2^6 = 64B min. chunk size)"
)
raise ArgumentTypeError("min. chunk size exponent must not be less than 6 (2^6 = 64B min. chunk size)")
if chunk_max > 23:
raise argparse.ArgumentTypeError(
"max. chunk size exponent must not be more than 23 (2^23 = 8MiB max. chunk size)"
)
raise ArgumentTypeError("max. chunk size exponent must not be more than 23 (2^23 = 8MiB max. chunk size)")
# note that for buzhash64, there is no problem with even window_size.
return CH_BUZHASH64, chunk_min, chunk_max, chunk_mask, window_size
# this must stay last as it deals with old-style compat mode (no algorithm, 4 params, buzhash):
if algo == CH_BUZHASH and count == 5 or count == 4: # [buzhash, ]chunk_min, chunk_max, chunk_mask, window_size
chunk_min, chunk_max, chunk_mask, window_size = (int(p) for p in params[count - 4 :])
if not (chunk_min <= chunk_mask <= chunk_max):
raise argparse.ArgumentTypeError("required: chunk_min <= chunk_mask <= chunk_max")
raise ArgumentTypeError("required: chunk_min <= chunk_mask <= chunk_max")
if chunk_min < 6:
# see comment in 'fixed' algo check
raise argparse.ArgumentTypeError(
"min. chunk size exponent must not be less than 6 (2^6 = 64B min. chunk size)"
)
raise ArgumentTypeError("min. chunk size exponent must not be less than 6 (2^6 = 64B min. chunk size)")
if chunk_max > 23:
raise argparse.ArgumentTypeError(
"max. chunk size exponent must not be more than 23 (2^23 = 8MiB max. chunk size)"
)
raise ArgumentTypeError("max. chunk size exponent must not be more than 23 (2^23 = 8MiB max. chunk size)")
if window_size % 2 == 0:
raise argparse.ArgumentTypeError("window_size must be an uneven (odd) number")
raise ArgumentTypeError("window_size must be an uneven (odd) number")
return CH_BUZHASH, chunk_min, chunk_max, chunk_mask, window_size
raise argparse.ArgumentTypeError("invalid chunker params")
raise ArgumentTypeError("invalid chunker params")
def FilesCacheMode(s):
@ -236,13 +226,11 @@ def FilesCacheMode(s):
return s
entries = set(s.strip().split(","))
if not entries <= set(ENTRIES_MAP):
raise argparse.ArgumentTypeError(
"cache mode must be a comma-separated list of: %s" % ",".join(sorted(ENTRIES_MAP))
)
raise ArgumentTypeError("cache mode must be a comma-separated list of: %s" % ",".join(sorted(ENTRIES_MAP)))
short_entries = {ENTRIES_MAP[entry] for entry in entries}
mode = "".join(sorted(short_entries))
if mode not in VALID_MODES:
raise argparse.ArgumentTypeError("cache mode short must be one of: %s" % ",".join(VALID_MODES))
raise ArgumentTypeError("cache mode short must be one of: %s" % ",".join(VALID_MODES))
return mode
@ -338,13 +326,13 @@ replace_placeholders = PlaceholderReplacer()
def PathSpec(text):
if not text:
raise argparse.ArgumentTypeError("Empty strings are not accepted as paths.")
raise ArgumentTypeError("Empty strings are not accepted as paths.")
return text
def FilesystemPathSpec(text):
if not text:
raise argparse.ArgumentTypeError("Empty strings are not accepted as paths.")
raise ArgumentTypeError("Empty strings are not accepted as paths.")
return slashify(text)
@ -353,7 +341,7 @@ def SortBySpec(text):
for sort_key in text.split(","):
if sort_key not in AI_HUMAN_SORT_KEYS and sort_key != "ts": # idempotency: do not reject ts
raise argparse.ArgumentTypeError("Invalid sort key: %s" % sort_key)
raise ArgumentTypeError("Invalid sort key: %s" % sort_key)
return text.replace("timestamp", "ts").replace("archive", "name")
@ -643,12 +631,12 @@ def location_validator(proto=None, other=False):
try:
loc = Location(text, other=other)
except ValueError as err:
raise argparse.ArgumentTypeError(str(err)) from None
raise ArgumentTypeError(str(err)) from None
if proto is not None and loc.proto != proto:
if proto == "file":
raise argparse.ArgumentTypeError('"%s": Repository must be local' % text)
raise ArgumentTypeError('"%s": Repository must be local' % text)
else:
raise argparse.ArgumentTypeError('"%s": Repository must be remote' % text)
raise ArgumentTypeError('"%s": Repository must be remote' % text)
return loc
return validator
@ -658,7 +646,7 @@ def relative_time_marker_validator(text: str):
time_marker_regex = r"^\d+[ymwdHMS]$"
match = re.compile(time_marker_regex).search(text)
if not match:
raise argparse.ArgumentTypeError(f"Invalid relative time marker used: {text}, choose from y, m, w, d, H, M, S")
raise ArgumentTypeError(f"Invalid relative time marker used: {text}, choose from y, m, w, d, H, M, S")
else:
return text
@ -667,22 +655,20 @@ def text_validator(*, name, max_length, min_length=0, invalid_ctrl_chars="\0", i
def validator(text):
assert isinstance(text, str)
if len(text) < min_length:
raise argparse.ArgumentTypeError(f'Invalid {name}: "{text}" [length < {min_length}]')
raise ArgumentTypeError(f'Invalid {name}: "{text}" [length < {min_length}]')
if len(text) > max_length:
raise argparse.ArgumentTypeError(f'Invalid {name}: "{text}" [length > {max_length}]')
raise ArgumentTypeError(f'Invalid {name}: "{text}" [length > {max_length}]')
if invalid_ctrl_chars and re.search(f"[{re.escape(invalid_ctrl_chars)}]", text):
raise argparse.ArgumentTypeError(f'Invalid {name}: "{text}" [invalid control chars detected]')
raise ArgumentTypeError(f'Invalid {name}: "{text}" [invalid control chars detected]')
if invalid_chars and re.search(f"[{re.escape(invalid_chars)}]", text):
raise argparse.ArgumentTypeError(
f'Invalid {name}: "{text}" [invalid chars detected matching "{invalid_chars}"]'
)
raise ArgumentTypeError(f'Invalid {name}: "{text}" [invalid chars detected matching "{invalid_chars}"]')
if no_blanks and (text.startswith(" ") or text.endswith(" ")):
raise argparse.ArgumentTypeError(f'Invalid {name}: "{text}" [leading or trailing blanks detected]')
raise ArgumentTypeError(f'Invalid {name}: "{text}" [leading or trailing blanks detected]')
try:
text.encode("utf-8", errors="strict")
except UnicodeEncodeError:
# looks like text contains surrogate-escapes
raise argparse.ArgumentTypeError(f'Invalid {name}: "{text}" [contains non-unicode characters]')
raise ArgumentTypeError(f'Invalid {name}: "{text}" [contains non-unicode characters]')
return text
return validator
@ -1318,7 +1304,7 @@ def prepare_dump_dict(d):
return decode(d)
class Highlander(argparse.Action):
class Highlander(Action):
"""make sure some option is only given once"""
def __init__(self, *args, **kwargs):
@ -1327,7 +1313,7 @@ class Highlander(argparse.Action):
def __call__(self, parser, namespace, values, option_string=None):
if self.__called:
raise argparse.ArgumentError(self, "There can be only one.")
raise ArgumentError(self, "There can be only one.")
self.__called = True
setattr(namespace, self.dest, values)
@ -1337,7 +1323,7 @@ class MakePathSafeAction(Highlander):
try:
sanitized_path = make_path_safe(path)
except ValueError as e:
raise argparse.ArgumentError(self, e)
raise ArgumentError(self, e)
if sanitized_path == ".":
raise argparse.ArgumentError(self, f"{path!r} is not a valid file name")
raise ArgumentError(self, f"{path!r} is not a valid file name")
setattr(namespace, self.dest, sanitized_path)

View file

@ -1,4 +1,3 @@
import argparse
import fnmatch
import posixpath
import re
@ -8,6 +7,7 @@ from collections import namedtuple
from enum import Enum
from .helpers import clean_lines, shellpattern
from .helpers.jap_helpers import Action, ArgumentTypeError
from .helpers.errors import Error
@ -36,7 +36,7 @@ def load_exclude_file(fileobj, patterns):
patterns.append(parse_exclude_pattern(patternstr))
class ArgparsePatternAction(argparse.Action):
class ArgparsePatternAction(Action):
def __init__(self, nargs=1, **kw):
super().__init__(nargs=nargs, **kw)
@ -44,7 +44,7 @@ class ArgparsePatternAction(argparse.Action):
parse_patternfile_line(values[0], args.pattern_roots, args.patterns, ShellPattern)
class ArgparsePatternFileAction(argparse.Action):
class ArgparsePatternFileAction(Action):
def __init__(self, nargs=1, **kw):
super().__init__(nargs=nargs, **kw)
@ -357,16 +357,16 @@ def parse_inclexcl_command(cmd_line_str, fallback=ShellPattern):
"p": IECommand.PatternStyle,
}
if not cmd_line_str:
raise argparse.ArgumentTypeError("A pattern/command must not be empty.")
raise ArgumentTypeError("A pattern/command must not be empty.")
cmd = cmd_prefix_map.get(cmd_line_str[0])
if cmd is None:
raise argparse.ArgumentTypeError("A pattern/command must start with any of: %s" % ", ".join(cmd_prefix_map))
raise ArgumentTypeError("A pattern/command must start with any of: %s" % ", ".join(cmd_prefix_map))
# remaining text on command-line following the command character
remainder_str = cmd_line_str[1:].lstrip()
if not remainder_str:
raise argparse.ArgumentTypeError("A pattern/command must have a value part.")
raise ArgumentTypeError("A pattern/command must have a value part.")
if cmd is IECommand.RootPath:
# TODO: validate string?
@ -376,7 +376,7 @@ def parse_inclexcl_command(cmd_line_str, fallback=ShellPattern):
try:
val = get_pattern_class(remainder_str)
except ValueError:
raise argparse.ArgumentTypeError(f"Invalid pattern style: {remainder_str}")
raise ArgumentTypeError(f"Invalid pattern style: {remainder_str}")
else:
# determine recurse_dir based on command type
recurse_dir = command_recurses_dir(cmd)

View file

@ -1,9 +1,7 @@
import argparse
import pytest
from jsonargparse import ArgumentParser
from . import Archiver, RK_ENCRYPTION, cmd
from ...helpers.jap_helpers import ArgumentParser, RawDescriptionHelpFormatter, flatten_namespace
def test_bad_filters(archiver):
@ -118,14 +116,12 @@ class TestCommonOptions:
@pytest.fixture
def parse_vars_from_line(self, parser, subcommands, common_parser):
from ...helpers.jap_helpers import flatten_namespace
subparser = ArgumentParser(
parents=[common_parser],
add_help=False,
description="foo",
epilog="bar",
formatter_class=argparse.RawDescriptionHelpFormatter,
formatter_class=RawDescriptionHelpFormatter,
)
subparser.add_argument("--foo-bar", dest="foo_bar", action="store_true")
subcommands.add_subcommand("subcmd", subparser, help="baz")

View file

@ -1,4 +1,3 @@
import argparse
import os
import zlib
@ -6,6 +5,7 @@ import pytest
from ..compress import get_compressor, Compressor, CompressionSpec, CNONE, ZLIB, LZ4, LZMA, ZSTD, Auto
from ..constants import ROBJ_FILE_STREAM, ROBJ_ARCHIVE_META
from ..helpers.jap_helpers import ArgumentTypeError
DATA = b"fooooooooobaaaaaaaar" * 10
params = dict(name="zlib", level=6)
@ -209,7 +209,7 @@ def test_specified_compression_level(c_type, c_name, c_levels):
@pytest.mark.parametrize("invalid_spec", ["", "lzma,9,invalid", "invalid"])
def test_invalid_compression_level(invalid_spec):
with pytest.raises(argparse.ArgumentTypeError):
with pytest.raises(ArgumentTypeError):
CompressionSpec(invalid_spec)

View file

@ -1,11 +1,12 @@
import base64
import os
from argparse import ArgumentTypeError
from datetime import datetime, timezone
import pytest
from ...constants import * # NOQA
from ...helpers.jap_helpers import ArgumentTypeError
from ...helpers.parseformat import (
bin_to_hex,
binary_to_json,

View file

@ -1,10 +1,10 @@
import argparse
import io
import os.path
import sys
import pytest
from ..helpers.jap_helpers import ArgumentTypeError
from ..patterns import PathFullPattern, PathPrefixPattern, FnmatchPattern, ShellPattern, RegexPattern
from ..patterns import load_exclude_file, load_pattern_file
from ..patterns import parse_pattern, PatternMatcher
@ -491,7 +491,7 @@ def test_load_invalid_patterns_from_file(tmpdir, lines):
with patternfile.open("wt") as fh:
fh.write("\n".join(lines))
filename = str(patternfile)
with pytest.raises(argparse.ArgumentTypeError):
with pytest.raises(ArgumentTypeError):
roots = []
inclexclpatterns = []
with open(filename) as f: