argparsing: add ArgumentParser subclass with borg's usual defaults

Borg's ArgumentParser (in borg.helpers.argparsing) now subclasses
jsonargparse's ArgumentParser and pre-sets two defaults that every
borg parser uses:

  formatter_class = RawDescriptionHelpFormatter
  add_help        = False
This commit is contained in:
Thomas Waldmann 2026-02-27 13:54:56 +01:00
parent 975212bbec
commit 2f778b974b
No known key found for this signature in database
GPG key ID: 243ACFA951F78E01
34 changed files with 91 additions and 317 deletions

View file

@ -246,7 +246,7 @@ class Archiver(
def build_parser(self):
from ._common import define_common_options
parser = ArgumentParser(prog=self.prog, description="Borg - Deduplicated Backups", add_help=False)
parser = ArgumentParser(prog=self.prog, description="Borg - Deduplicated Backups")
# paths and patterns must have an empty list as default everywhere
parser.common_options = self.CommonOptions(define_common_options)
parser.add_argument(
@ -255,10 +255,10 @@ class Archiver(
parser.add_argument("--cockpit", dest="cockpit", action="store_true", help="Start the Borg TUI")
parser.common_options.add_common_group(parser, provide_defaults=True)
common_parser = ArgumentParser(add_help=False, prog=self.prog)
common_parser = ArgumentParser(prog=self.prog)
parser.common_options.add_common_group(common_parser)
mid_common_parser = ArgumentParser(add_help=False, prog=self.prog)
mid_common_parser = ArgumentParser(prog=self.prog)
parser.common_options.add_common_group(mid_common_parser)
if parser.prog == "borgfs":

View file

@ -6,7 +6,7 @@ from ..archive import Archive
from ..constants import * # NOQA
from ..helpers import bin_to_hex, Error
from ..helpers import ProgressIndicatorPercent
from ..helpers.argparsing import ArgumentParser, RawDescriptionHelpFormatter
from ..helpers.argparsing import ArgumentParser
from ..manifest import Manifest
from ..remote import RemoteRepository
from ..repository import Repository
@ -126,12 +126,6 @@ class AnalyzeMixIn:
to recreate existing archives without them.
"""
)
subparser = ArgumentParser(
parents=[common_parser],
add_help=False,
description=self.do_analyze.__doc__,
epilog=analyze_epilog,
formatter_class=RawDescriptionHelpFormatter,
)
subparser = ArgumentParser(parents=[common_parser], description=self.do_analyze.__doc__, epilog=analyze_epilog)
subparsers.add_subcommand("analyze", subparser, help="analyze archives")
define_archive_filters_group(subparser)

View file

@ -11,7 +11,7 @@ from ..helpers import format_file_size, CompressionSpec
from ..helpers import json_print
from ..helpers import msgpack
from ..helpers import get_reset_ec
from ..helpers.argparsing import ArgumentParser, RawDescriptionHelpFormatter
from ..helpers.argparsing import ArgumentParser
from ..item import Item
from ..platform import SyncFile
@ -353,11 +353,7 @@ class BenchmarkMixIn:
benchmark_epilog = process_epilog("These commands do various benchmarks.")
subparser = ArgumentParser(
parents=[mid_common_parser],
add_help=False,
description="benchmark command",
epilog=benchmark_epilog,
formatter_class=RawDescriptionHelpFormatter,
parents=[mid_common_parser], description="benchmark command", epilog=benchmark_epilog
)
subparsers.add_subcommand("benchmark", subparser, help="benchmark command")
@ -405,11 +401,7 @@ class BenchmarkMixIn:
"""
)
subparser = ArgumentParser(
parents=[common_parser],
add_help=False,
description=self.do_benchmark_crud.__doc__,
epilog=bench_crud_epilog,
formatter_class=RawDescriptionHelpFormatter,
parents=[common_parser], description=self.do_benchmark_crud.__doc__, epilog=bench_crud_epilog
)
benchmark_parsers.add_subcommand(
"crud", subparser, help="benchmarks Borg CRUD (create, extract, update, delete)."
@ -430,11 +422,7 @@ class BenchmarkMixIn:
"""
)
subparser = ArgumentParser(
parents=[common_parser],
add_help=False,
description=self.do_benchmark_cpu.__doc__,
epilog=bench_cpu_epilog,
formatter_class=RawDescriptionHelpFormatter,
parents=[common_parser], description=self.do_benchmark_cpu.__doc__, epilog=bench_cpu_epilog
)
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

@ -3,7 +3,7 @@ from ..archive import ArchiveChecker
from ..constants import * # NOQA
from ..helpers import set_ec, EXIT_WARNING, CancelledByUser, CommandError, IntegrityError
from ..helpers import yes
from ..helpers.argparsing import ArgumentParser, RawDescriptionHelpFormatter
from ..helpers.argparsing import ArgumentParser
from ..logger import create_logger
@ -182,13 +182,7 @@ class CheckMixIn:
``borg compact`` would remove the archives' data completely.
"""
)
subparser = ArgumentParser(
parents=[common_parser],
add_help=False,
description=self.do_check.__doc__,
epilog=check_epilog,
formatter_class=RawDescriptionHelpFormatter,
)
subparser = ArgumentParser(parents=[common_parser], description=self.do_check.__doc__, epilog=check_epilog)
subparsers.add_subcommand("check", subparser, help="verify the repository")
subparser.add_argument(
"--repository-only", dest="repo_only", action="store_true", help="only perform repository checks"

View file

@ -5,7 +5,7 @@ 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.argparsing import ArgumentParser, RawDescriptionHelpFormatter
from ..helpers.argparsing import ArgumentParser
from ..constants import * # NOQA
from ..hashindex import ChunkIndex, ChunkIndexEntry
from ..helpers import set_ec, EXIT_ERROR, format_file_size, bin_to_hex
@ -257,13 +257,7 @@ class CompactMixIn:
thus it cannot compute before/after compaction size statistics).
"""
)
subparser = ArgumentParser(
parents=[common_parser],
add_help=False,
description=self.do_compact.__doc__,
epilog=compact_epilog,
formatter_class=RawDescriptionHelpFormatter,
)
subparser = ArgumentParser(parents=[common_parser], description=self.do_compact.__doc__, epilog=compact_epilog)
subparsers.add_subcommand("compact", subparser, help="compact the repository")
subparser.add_argument(
"-n", "--dry-run", dest="dry_run", action="store_true", help="do not change the repository"

View file

@ -65,7 +65,7 @@ from ..helpers import (
relative_time_marker_validator,
parse_file_size,
)
from ..helpers.argparsing import ArgumentParser, RawDescriptionHelpFormatter
from ..helpers.argparsing import ArgumentParser
from ..helpers.argparsing import _ActionSubCommands
from ..helpers.argparsing import prepare_actions_context, shtab_prepare_actions, bash_compgen_typehint
from ..helpers.time import timestamp
@ -762,11 +762,7 @@ class CompletionMixIn:
)
subparser = ArgumentParser(
parents=[common_parser],
add_help=False,
description=self.do_completion.__doc__,
epilog=completion_epilog,
formatter_class=RawDescriptionHelpFormatter,
parents=[common_parser], description=self.do_completion.__doc__, epilog=completion_epilog
)
subparsers.add_subcommand("completion", subparser, help="output shell completion script")
subparser.add_argument(

View file

@ -29,7 +29,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.argparsing import ArgumentParser, RawDescriptionHelpFormatter
from ..helpers.argparsing import ArgumentParser
from ..manifest import Manifest
from ..patterns import PatternMatcher
from ..platform import is_win32
@ -770,13 +770,7 @@ class CreateMixIn:
"""
)
subparser = ArgumentParser(
parents=[common_parser],
add_help=False,
description=self.do_create.__doc__,
epilog=create_epilog,
formatter_class=RawDescriptionHelpFormatter,
)
subparser = ArgumentParser(parents=[common_parser], description=self.do_create.__doc__, epilog=create_epilog)
subparsers.add_subcommand("create", subparser, help="create a backup")
# note: --dry-run and --stats are mutually exclusive, but we do not want to abort when

View file

@ -10,7 +10,7 @@ from ..helpers import dash_open
from ..helpers import StableDict
from ..helpers import archivename_validator, CompressionSpec
from ..helpers import CommandError, RTError
from ..helpers.argparsing import ArgumentParser, RawDescriptionHelpFormatter
from ..helpers.argparsing import ArgumentParser
from ..manifest import Manifest
from ..platform import get_process_id
from ..repository import Repository, LIST_SCAN_LIMIT, repo_lister
@ -319,10 +319,8 @@ class DebugMixIn:
subparser = ArgumentParser(
parents=[mid_common_parser],
add_help=False,
description="debugging command (not intended for normal use)",
epilog=debug_epilog,
formatter_class=RawDescriptionHelpFormatter,
)
subparsers.add_subcommand("debug", subparser, help="debugging command (not intended for normal use)")
@ -336,11 +334,7 @@ class DebugMixIn:
"""
)
subparser = ArgumentParser(
parents=[mid_common_parser],
add_help=False,
description=self.do_debug_info.__doc__,
epilog=debug_info_epilog,
formatter_class=RawDescriptionHelpFormatter,
parents=[mid_common_parser], description=self.do_debug_info.__doc__, epilog=debug_info_epilog
)
debug_parsers.add_subcommand("info", subparser, help="show system infos for debugging / bug reports (debug)")
@ -351,10 +345,8 @@ class DebugMixIn:
)
subparser = ArgumentParser(
parents=[mid_common_parser],
add_help=False,
description=self.do_debug_dump_archive_items.__doc__,
epilog=debug_dump_archive_items_epilog,
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")
@ -366,10 +358,8 @@ class DebugMixIn:
)
subparser = ArgumentParser(
parents=[mid_common_parser],
add_help=False,
description=self.do_debug_dump_archive.__doc__,
epilog=debug_dump_archive_epilog,
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")
@ -382,10 +372,8 @@ class DebugMixIn:
)
subparser = ArgumentParser(
parents=[mid_common_parser],
add_help=False,
description=self.do_debug_dump_manifest.__doc__,
epilog=debug_dump_manifest_epilog,
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")
@ -397,10 +385,8 @@ class DebugMixIn:
)
subparser = ArgumentParser(
parents=[mid_common_parser],
add_help=False,
description=self.do_debug_dump_repo_objs.__doc__,
epilog=debug_dump_repo_objs_epilog,
formatter_class=RawDescriptionHelpFormatter,
)
debug_parsers.add_subcommand("dump-repo-objs", subparser, help="dump repo objects (debug)")
@ -411,10 +397,8 @@ class DebugMixIn:
)
subparser = ArgumentParser(
parents=[mid_common_parser],
add_help=False,
description=self.do_debug_search_repo_objs.__doc__,
epilog=debug_search_repo_objs_epilog,
formatter_class=RawDescriptionHelpFormatter,
)
debug_parsers.add_subcommand("search-repo-objs", subparser, help="search repo objects (debug)")
subparser.add_argument(
@ -430,11 +414,7 @@ class DebugMixIn:
"""
)
subparser = ArgumentParser(
parents=[mid_common_parser],
add_help=False,
description=self.do_debug_id_hash.__doc__,
epilog=debug_id_hash_epilog,
formatter_class=RawDescriptionHelpFormatter,
parents=[mid_common_parser], description=self.do_debug_id_hash.__doc__, epilog=debug_id_hash_epilog
)
debug_parsers.add_subcommand("id-hash", subparser, help="compute id-hash for some file content (debug)")
subparser.add_argument(
@ -448,11 +428,7 @@ class DebugMixIn:
"""
)
subparser = ArgumentParser(
parents=[mid_common_parser],
add_help=False,
description=self.do_debug_parse_obj.__doc__,
epilog=debug_parse_obj_epilog,
formatter_class=RawDescriptionHelpFormatter,
parents=[mid_common_parser], description=self.do_debug_parse_obj.__doc__, epilog=debug_parse_obj_epilog
)
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")
@ -473,11 +449,7 @@ class DebugMixIn:
"""
)
subparser = ArgumentParser(
parents=[mid_common_parser],
add_help=False,
description=self.do_debug_format_obj.__doc__,
epilog=debug_format_obj_epilog,
formatter_class=RawDescriptionHelpFormatter,
parents=[mid_common_parser], description=self.do_debug_format_obj.__doc__, epilog=debug_format_obj_epilog
)
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")
@ -510,11 +482,7 @@ class DebugMixIn:
"""
)
subparser = ArgumentParser(
parents=[mid_common_parser],
add_help=False,
description=self.do_debug_get_obj.__doc__,
epilog=debug_get_obj_epilog,
formatter_class=RawDescriptionHelpFormatter,
parents=[mid_common_parser], description=self.do_debug_get_obj.__doc__, epilog=debug_get_obj_epilog
)
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")
@ -526,11 +494,7 @@ class DebugMixIn:
"""
)
subparser = ArgumentParser(
parents=[mid_common_parser],
add_help=False,
description=self.do_debug_put_obj.__doc__,
epilog=debug_put_obj_epilog,
formatter_class=RawDescriptionHelpFormatter,
parents=[mid_common_parser], description=self.do_debug_put_obj.__doc__, epilog=debug_put_obj_epilog
)
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")
@ -542,11 +506,7 @@ class DebugMixIn:
"""
)
subparser = ArgumentParser(
parents=[mid_common_parser],
add_help=False,
description=self.do_debug_delete_obj.__doc__,
epilog=debug_delete_obj_epilog,
formatter_class=RawDescriptionHelpFormatter,
parents=[mid_common_parser], description=self.do_debug_delete_obj.__doc__, epilog=debug_delete_obj_epilog
)
debug_parsers.add_subcommand("delete-obj", subparser, help="delete object from repository (debug)")
subparser.add_argument(
@ -560,10 +520,8 @@ class DebugMixIn:
)
subparser = ArgumentParser(
parents=[mid_common_parser],
add_help=False,
description=self.do_debug_convert_profile.__doc__,
epilog=debug_convert_profile_epilog,
formatter_class=RawDescriptionHelpFormatter,
)
debug_parsers.add_subcommand(
"convert-profile", subparser, help="convert Borg profile to Python profile (debug)"

View file

@ -3,7 +3,7 @@ import logging
from ._common import with_repository
from ..constants import * # NOQA
from ..helpers import format_archive, CommandError, bin_to_hex, archivename_validator
from ..helpers.argparsing import ArgumentParser, RawDescriptionHelpFormatter
from ..helpers.argparsing import ArgumentParser
from ..manifest import Manifest
from ..logger import create_logger
@ -80,13 +80,7 @@ class DeleteMixIn:
patterns, see :ref:`borg_patterns`).
"""
)
subparser = ArgumentParser(
parents=[common_parser],
add_help=False,
description=self.do_delete.__doc__,
epilog=delete_epilog,
formatter_class=RawDescriptionHelpFormatter,
)
subparser = ArgumentParser(parents=[common_parser], description=self.do_delete.__doc__, epilog=delete_epilog)
subparsers.add_subcommand("delete", subparser, help="delete archives")
subparser.add_argument(
"-n", "--dry-run", dest="dry_run", action="store_true", help="do not change the repository"

View file

@ -8,7 +8,7 @@ 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.argparsing import ArgumentParser, ArgumentTypeError, RawDescriptionHelpFormatter
from ..helpers.argparsing import ArgumentParser, ArgumentTypeError
from ..item import ItemDiff
from ..manifest import Manifest
from ..logger import create_logger
@ -293,13 +293,7 @@ class DiffMixIn:
raise ArgumentTypeError(f"unsupported sort field: {field}")
return ",".join(parts)
subparser = ArgumentParser(
parents=[common_parser],
add_help=False,
description=self.do_diff.__doc__,
epilog=diff_epilog,
formatter_class=RawDescriptionHelpFormatter,
)
subparser = ArgumentParser(parents=[common_parser], description=self.do_diff.__doc__, epilog=diff_epilog)
subparsers.add_subcommand("diff", subparser, help="find differences in archive contents")
subparser.add_argument(
"--numeric-ids",

View file

@ -11,7 +11,7 @@ from ..helpers import remove_surrogates
from ..helpers import HardLinkManager
from ..helpers import ProgressIndicatorPercent
from ..helpers import BackupWarning, IncludePatternNeverMatchedWarning
from ..helpers.argparsing import ArgumentParser, RawDescriptionHelpFormatter
from ..helpers.argparsing import ArgumentParser
from ..manifest import Manifest
from ..logger import create_logger
@ -155,13 +155,7 @@ class ExtractMixIn:
group, permissions, etc.
"""
)
subparser = ArgumentParser(
parents=[common_parser],
add_help=False,
description=self.do_extract.__doc__,
epilog=extract_epilog,
formatter_class=RawDescriptionHelpFormatter,
)
subparser = ArgumentParser(parents=[common_parser], description=self.do_extract.__doc__, epilog=extract_epilog)
subparsers.add_subcommand("extract", subparser, help="extract archive contents")
subparser.add_argument(
"--list", dest="output_list", action="store_true", help="output a verbose list of items (files, dirs, ...)"

View file

@ -553,7 +553,7 @@ class HelpMixIn:
do_maincommand_help = do_subcommand_help
def build_parser_help(self, subparsers, common_parser, mid_common_parser, parser):
subparser = ArgumentParser(parents=[common_parser], add_help=False, description="Extra help")
subparser = ArgumentParser(parents=[common_parser], description="Extra help")
subparsers.add_subcommand("help", subparser, help="Extra help")
subparser.add_argument("--epilog-only", dest="epilog_only", action="store_true")
subparser.add_argument("--usage-only", dest="usage_only", action="store_true")

View file

@ -5,7 +5,7 @@ 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.argparsing import ArgumentParser, RawDescriptionHelpFormatter
from ..helpers.argparsing import ArgumentParser
from ..manifest import Manifest
from ..logger import create_logger
@ -78,13 +78,7 @@ class InfoMixIn:
= all chunks in the repository.
"""
)
subparser = ArgumentParser(
parents=[common_parser],
add_help=False,
description=self.do_info.__doc__,
epilog=info_epilog,
formatter_class=RawDescriptionHelpFormatter,
)
subparser = ArgumentParser(parents=[common_parser], description=self.do_info.__doc__, epilog=info_epilog)
subparsers.add_subcommand("info", subparser, help="show repository or archive information")
subparser.add_argument("--json", action="store_true", help="format output as JSON")
define_archive_filters_group(subparser)

View file

@ -5,7 +5,7 @@ from ..crypto.key import AESOCBRepoKey, CHPORepoKey, Blake2AESOCBRepoKey, Blake2
from ..crypto.key import AESOCBKeyfileKey, CHPOKeyfileKey, Blake2AESOCBKeyfileKey, Blake2CHPOKeyfileKey
from ..crypto.keymanager import KeyManager
from ..helpers import PathSpec, CommandError
from ..helpers.argparsing import ArgumentParser, RawDescriptionHelpFormatter
from ..helpers.argparsing import ArgumentParser
from ..manifest import Manifest
from ._common import with_repository
@ -120,11 +120,7 @@ class KeysMixIn:
from ._common import process_epilog
subparser = ArgumentParser(
parents=[mid_common_parser],
add_help=False,
description="Manage the keyfile or repokey of a repository",
epilog="",
formatter_class=RawDescriptionHelpFormatter,
parents=[mid_common_parser], description="Manage the keyfile or repokey of a repository", epilog=""
)
subparsers.add_subcommand("key", subparser, help="manage the repository key")
@ -162,11 +158,7 @@ class KeysMixIn:
"""
)
subparser = ArgumentParser(
parents=[common_parser],
add_help=False,
description=self.do_key_export.__doc__,
epilog=key_export_epilog,
formatter_class=RawDescriptionHelpFormatter,
parents=[common_parser], description=self.do_key_export.__doc__, epilog=key_export_epilog
)
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")
@ -202,11 +194,7 @@ class KeysMixIn:
"""
)
subparser = ArgumentParser(
parents=[common_parser],
add_help=False,
description=self.do_key_import.__doc__,
epilog=key_import_epilog,
formatter_class=RawDescriptionHelpFormatter,
parents=[common_parser], description=self.do_key_import.__doc__, epilog=key_import_epilog
)
key_parsers.add_subcommand("import", subparser, help="import the repository key from backup")
subparser.add_argument(
@ -231,11 +219,7 @@ class KeysMixIn:
"""
)
subparser = ArgumentParser(
parents=[common_parser],
add_help=False,
description=self.do_key_change_passphrase.__doc__,
epilog=change_passphrase_epilog,
formatter_class=RawDescriptionHelpFormatter,
parents=[common_parser], description=self.do_key_change_passphrase.__doc__, epilog=change_passphrase_epilog
)
key_parsers.add_subcommand("change-passphrase", subparser, help="change the repository passphrase")
@ -253,11 +237,7 @@ class KeysMixIn:
"""
)
subparser = ArgumentParser(
parents=[common_parser],
add_help=False,
description=self.do_key_change_location.__doc__,
epilog=change_location_epilog,
formatter_class=RawDescriptionHelpFormatter,
parents=[common_parser], description=self.do_key_change_location.__doc__, epilog=change_location_epilog
)
key_parsers.add_subcommand("change-location", subparser, help="change the key location")
subparser.add_argument(

View file

@ -7,7 +7,7 @@ from ..archive import Archive
from ..cache import Cache
from ..constants import * # NOQA
from ..helpers import ItemFormatter, BaseFormatter, archivename_validator, PathSpec
from ..helpers.argparsing import ArgumentParser, RawDescriptionHelpFormatter
from ..helpers.argparsing import ArgumentParser
from ..manifest import Manifest
from ..logger import create_logger
@ -102,13 +102,7 @@ class ListMixIn:
)
+ ItemFormatter.keys_help()
)
subparser = ArgumentParser(
parents=[common_parser],
add_help=False,
description=self.do_list.__doc__,
epilog=list_epilog,
formatter_class=RawDescriptionHelpFormatter,
)
subparser = ArgumentParser(parents=[common_parser], description=self.do_list.__doc__, epilog=list_epilog)
subparsers.add_subcommand("list", subparser, help="list archive contents")
subparser.add_argument(
"--short", dest="short", action="store_true", help="only print file/directory names, nothing else"

View file

@ -4,7 +4,7 @@ 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.argparsing import ArgumentParser, RawDescriptionHelpFormatter, REMAINDER
from ..helpers.argparsing import ArgumentParser, REMAINDER
from ..logger import create_logger
@ -46,11 +46,7 @@ class LocksMixIn:
"""
)
subparser = ArgumentParser(
parents=[common_parser],
add_help=False,
description=self.do_break_lock.__doc__,
epilog=break_lock_epilog,
formatter_class=RawDescriptionHelpFormatter,
parents=[common_parser], description=self.do_break_lock.__doc__, epilog=break_lock_epilog
)
subparsers.add_subcommand("break-lock", subparser, help="break the repository and cache locks")
@ -76,11 +72,7 @@ class LocksMixIn:
"""
)
subparser = ArgumentParser(
parents=[common_parser],
add_help=False,
description=self.do_with_lock.__doc__,
epilog=with_lock_epilog,
formatter_class=RawDescriptionHelpFormatter,
parents=[common_parser], description=self.do_with_lock.__doc__, epilog=with_lock_epilog
)
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

@ -5,7 +5,7 @@ from ..constants import * # NOQA
from ..helpers import RTError
from ..helpers import PathSpec
from ..helpers import umount
from ..helpers.argparsing import ArgumentParser, RawDescriptionHelpFormatter
from ..helpers.argparsing import ArgumentParser
from ..manifest import Manifest
from ..remote import cache_if_remote
@ -151,13 +151,7 @@ class MountMixIn:
the logger to output to a file.
"""
)
subparser = ArgumentParser(
parents=[common_parser],
add_help=False,
description=self.do_mount.__doc__,
epilog=mount_epilog,
formatter_class=RawDescriptionHelpFormatter,
)
subparser = ArgumentParser(parents=[common_parser], description=self.do_mount.__doc__, epilog=mount_epilog)
subparsers.add_subcommand("mount", subparser, help="mount a repository")
self._define_borg_mount(subparser)
@ -169,13 +163,7 @@ class MountMixIn:
command - usually this is either umount or fusermount -u.
"""
)
subparser = ArgumentParser(
parents=[common_parser],
add_help=False,
description=self.do_umount.__doc__,
epilog=umount_epilog,
formatter_class=RawDescriptionHelpFormatter,
)
subparser = ArgumentParser(parents=[common_parser], description=self.do_umount.__doc__, epilog=umount_epilog)
subparsers.add_subcommand("umount", subparser, help="unmount a repository")
subparser.add_argument(
"mountpoint", metavar="MOUNTPOINT", type=str, help="mountpoint of the filesystem to unmount"
@ -185,7 +173,6 @@ class MountMixIn:
assert parser.prog == "borgfs"
parser.description = self.do_mount.__doc__
parser.epilog = "For more information, see borg mount --help."
parser.formatter_class = RawDescriptionHelpFormatter
parser.help = "mount a repository"
self._define_borg_mount(parser)
return parser

View file

@ -8,7 +8,7 @@ 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.argparsing import ArgumentParser, RawDescriptionHelpFormatter
from ..helpers.argparsing import ArgumentParser
from ..manifest import Manifest
from ..logger import create_logger
@ -273,13 +273,7 @@ class PruneMixIn:
the ``borg repo-list`` description for more details about the format string).
"""
)
subparser = ArgumentParser(
parents=[common_parser],
add_help=False,
description=self.do_prune.__doc__,
epilog=prune_epilog,
formatter_class=RawDescriptionHelpFormatter,
)
subparser = ArgumentParser(parents=[common_parser], description=self.do_prune.__doc__, epilog=prune_epilog)
subparsers.add_subcommand("prune", subparser, help="prune archives")
subparser.add_argument(
"-n", "--dry-run", dest="dry_run", action="store_true", help="do not change the repository"

View file

@ -4,7 +4,7 @@ from ..archive import ArchiveRecreater
from ..constants import * # NOQA
from ..helpers import archivename_validator, comment_validator, PathSpec, ChunkerParams, bin_to_hex, CompressionSpec
from ..helpers import timestamp
from ..helpers.argparsing import ArgumentParser, RawDescriptionHelpFormatter
from ..helpers.argparsing import ArgumentParser
from ..manifest import Manifest
from ..logger import create_logger
@ -101,11 +101,7 @@ class RecreateMixIn:
"""
)
subparser = ArgumentParser(
parents=[common_parser],
add_help=False,
description=self.do_recreate.__doc__,
epilog=recreate_epilog,
formatter_class=RawDescriptionHelpFormatter,
parents=[common_parser], description=self.do_recreate.__doc__, epilog=recreate_epilog
)
subparsers.add_subcommand("recreate", subparser, help=self.do_recreate.__doc__)
subparser.add_argument(

View file

@ -1,7 +1,7 @@
from ._common import with_repository, with_archive
from ..constants import * # NOQA
from ..helpers import archivename_validator
from ..helpers.argparsing import ArgumentParser, RawDescriptionHelpFormatter
from ..helpers.argparsing import ArgumentParser
from ..manifest import Manifest
from ..logger import create_logger
@ -27,13 +27,7 @@ class RenameMixIn:
This results in a different archive ID.
"""
)
subparser = ArgumentParser(
parents=[common_parser],
add_help=False,
description=self.do_rename.__doc__,
epilog=rename_epilog,
formatter_class=RawDescriptionHelpFormatter,
)
subparser = ArgumentParser(parents=[common_parser], description=self.do_rename.__doc__, epilog=rename_epilog)
subparsers.add_subcommand("rename", subparser, help="rename an archive")
subparser.add_argument(
"name", metavar="OLDNAME", type=archivename_validator, help="specify the current archive name"

View file

@ -5,7 +5,7 @@ from ..constants import * # NOQA
from ..compress import ObfuscateSize, Auto, COMPRESSOR_TABLE
from ..hashindex import ChunkIndex
from ..helpers import sig_int, ProgressIndicatorPercent, Error, CompressionSpec
from ..helpers.argparsing import ArgumentParser, RawDescriptionHelpFormatter
from ..helpers.argparsing import ArgumentParser
from ..repository import Repository
from ..remote import RemoteRepository
from ..manifest import Manifest
@ -181,11 +181,7 @@ class RepoCompressMixIn:
"""
)
subparser = ArgumentParser(
parents=[common_parser],
add_help=False,
description=self.do_repo_compress.__doc__,
epilog=repo_compress_epilog,
formatter_class=RawDescriptionHelpFormatter,
parents=[common_parser], description=self.do_repo_compress.__doc__, epilog=repo_compress_epilog
)
subparsers.add_subcommand("repo-compress", subparser, help=self.do_repo_compress.__doc__)

View file

@ -4,7 +4,7 @@ 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.argparsing import ArgumentParser, RawDescriptionHelpFormatter
from ..helpers.argparsing import ArgumentParser
from ..manifest import Manifest
from ..logger import create_logger
@ -190,11 +190,7 @@ class RepoCreateMixIn:
"""
)
subparser = ArgumentParser(
parents=[common_parser],
add_help=False,
description=self.do_repo_create.__doc__,
epilog=repo_create_epilog,
formatter_class=RawDescriptionHelpFormatter,
parents=[common_parser], description=self.do_repo_create.__doc__, epilog=repo_create_epilog
)
subparsers.add_subcommand("repo-create", subparser, help="create a new, empty repository")
subparser.add_argument(

View file

@ -5,7 +5,7 @@ from ..helpers import CancelledByUser
from ..helpers import format_archive
from ..helpers import bin_to_hex
from ..helpers import yes
from ..helpers.argparsing import ArgumentParser, RawDescriptionHelpFormatter
from ..helpers.argparsing import ArgumentParser
from ..manifest import Manifest, NoManifestError
from ..logger import create_logger
@ -102,11 +102,7 @@ class RepoDeleteMixIn:
"""
)
subparser = ArgumentParser(
parents=[common_parser],
add_help=False,
description=self.do_repo_delete.__doc__,
epilog=repo_delete_epilog,
formatter_class=RawDescriptionHelpFormatter,
parents=[common_parser], description=self.do_repo_delete.__doc__, epilog=repo_delete_epilog
)
subparsers.add_subcommand("repo-delete", subparser, help="delete a repository")
subparser.add_argument(

View file

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

View file

@ -5,7 +5,7 @@ import sys
from ._common import with_repository, Highlander
from ..constants import * # NOQA
from ..helpers import BaseFormatter, ArchiveFormatter, json_print, basic_json_data
from ..helpers.argparsing import ArgumentParser, RawDescriptionHelpFormatter
from ..helpers.argparsing import ArgumentParser
from ..manifest import Manifest
from ..logger import create_logger
@ -85,11 +85,7 @@ class RepoListMixIn:
+ ArchiveFormatter.keys_help()
)
subparser = ArgumentParser(
parents=[common_parser],
add_help=False,
description=self.do_repo_list.__doc__,
epilog=repo_list_epilog,
formatter_class=RawDescriptionHelpFormatter,
parents=[common_parser], description=self.do_repo_list.__doc__, epilog=repo_list_epilog
)
subparsers.add_subcommand("repo-list", subparser, help="list repository contents")
subparser.add_argument(

View file

@ -6,7 +6,7 @@ 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.argparsing import ArgumentParser, RawDescriptionHelpFormatter
from ..helpers.argparsing import ArgumentParser
from ..logger import create_logger
@ -86,11 +86,7 @@ class RepoSpaceMixIn:
"""
)
subparser = ArgumentParser(
parents=[common_parser],
add_help=False,
description=self.do_repo_space.__doc__,
epilog=repo_space_epilog,
formatter_class=RawDescriptionHelpFormatter,
parents=[common_parser], description=self.do_repo_space.__doc__, epilog=repo_space_epilog
)
subparsers.add_subcommand("repo-space", subparser, help="manage reserved space in a repository")
subparser.add_argument(

View file

@ -2,7 +2,7 @@ from ..constants import * # NOQA
from ..remote import RepositoryServer
from ..logger import create_logger
from ..helpers.argparsing import RawDescriptionHelpFormatter, ArgumentParser
from ..helpers.argparsing import ArgumentParser
logger = create_logger()
@ -51,13 +51,7 @@ class ServeMixIn:
Existing archives can be read, but no archives can be created or deleted.
"""
)
subparser = ArgumentParser(
parents=[common_parser],
add_help=False,
description=self.do_serve.__doc__,
epilog=serve_epilog,
formatter_class=RawDescriptionHelpFormatter,
)
subparser = ArgumentParser(parents=[common_parser], description=self.do_serve.__doc__, epilog=serve_epilog)
subparsers.add_subcommand("serve", subparser, help="start the repository server process")
subparser.add_argument(
"--restrict-to-path",

View file

@ -2,7 +2,7 @@ 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.argparsing import ArgumentParser, RawDescriptionHelpFormatter
from ..helpers.argparsing import ArgumentParser
from ..manifest import Manifest
from ..logger import create_logger
@ -79,13 +79,7 @@ class TagMixIn:
removed).
"""
)
subparser = ArgumentParser(
parents=[common_parser],
add_help=False,
description=self.do_tag.__doc__,
epilog=tag_epilog,
formatter_class=RawDescriptionHelpFormatter,
)
subparser = ArgumentParser(parents=[common_parser], description=self.do_tag.__doc__, epilog=tag_epilog)
subparsers.add_subcommand("tag", subparser, help="tag archives")
subparser.add_argument("--set", dest="set_tags", metavar="TAG", type=tag_validator, nargs="+", help="set tags")
subparser.add_argument("--add", dest="add_tags", metavar="TAG", type=tag_validator, nargs="+", help="add tags")

View file

@ -17,7 +17,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.argparsing import ArgumentParser, RawDescriptionHelpFormatter
from ..helpers.argparsing import ArgumentParser
from ..manifest import Manifest
from ._common import with_repository, with_archive, Highlander, define_exclusion_group
@ -384,11 +384,7 @@ class TarMixIn:
"""
)
subparser = ArgumentParser(
parents=[common_parser],
add_help=False,
description=self.do_export_tar.__doc__,
epilog=export_tar_epilog,
formatter_class=RawDescriptionHelpFormatter,
parents=[common_parser], description=self.do_export_tar.__doc__, epilog=export_tar_epilog
)
subparsers.add_subcommand("export-tar", subparser, help="create tarball from archive")
subparser.add_argument(
@ -458,11 +454,7 @@ class TarMixIn:
"""
)
subparser = ArgumentParser(
parents=[common_parser],
add_help=False,
description=self.do_import_tar.__doc__,
epilog=import_tar_epilog,
formatter_class=RawDescriptionHelpFormatter,
parents=[common_parser], description=self.do_import_tar.__doc__, epilog=import_tar_epilog
)
subparsers.add_subcommand("import-tar", subparser, help=self.do_import_tar.__doc__)
subparser.add_argument(

View file

@ -7,7 +7,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, CompressionSpec
from ..helpers.argparsing import ArgumentParser, ArgumentTypeError, RawDescriptionHelpFormatter
from ..helpers.argparsing import ArgumentParser, ArgumentTypeError
from ..item import ChunkListEntry
from ..manifest import Manifest
from ..legacyrepository import LegacyRepository
@ -330,11 +330,7 @@ class TransferMixIn:
"""
)
subparser = ArgumentParser(
parents=[common_parser],
add_help=False,
description=self.do_transfer.__doc__,
epilog=transfer_epilog,
formatter_class=RawDescriptionHelpFormatter,
parents=[common_parser], description=self.do_transfer.__doc__, epilog=transfer_epilog
)
subparsers.add_subcommand("transfer", subparser, help="transfer of archives from another repository")
subparser.add_argument(

View file

@ -3,7 +3,7 @@ import logging
from ._common import with_repository
from ..constants import * # NOQA
from ..helpers import format_archive, CommandError, bin_to_hex, archivename_validator
from ..helpers.argparsing import ArgumentParser, RawDescriptionHelpFormatter
from ..helpers.argparsing import ArgumentParser
from ..manifest import Manifest
from ..logger import create_logger
@ -73,11 +73,7 @@ class UnDeleteMixIn:
"""
)
subparser = ArgumentParser(
parents=[common_parser],
add_help=False,
description=self.do_undelete.__doc__,
epilog=undelete_epilog,
formatter_class=RawDescriptionHelpFormatter,
parents=[common_parser], description=self.do_undelete.__doc__, epilog=undelete_epilog
)
subparsers.add_subcommand("undelete", subparser, help="undelete archives")
subparser.add_argument(

View file

@ -1,6 +1,6 @@
from .. import __version__
from ..constants import * # NOQA
from ..helpers.argparsing import RawDescriptionHelpFormatter, ArgumentParser
from ..helpers.argparsing import ArgumentParser
from ..remote import RemoteRepository
from ..logger import create_logger
@ -50,11 +50,5 @@ class VersionMixIn:
You can also use ``borg --version`` to display a potentially more precise client version.
"""
)
subparser = ArgumentParser(
parents=[common_parser],
add_help=False,
description=self.do_version.__doc__,
epilog=version_epilog,
formatter_class=RawDescriptionHelpFormatter,
)
subparser = ArgumentParser(parents=[common_parser], description=self.do_version.__doc__, epilog=version_epilog)
subparsers.add_subcommand("version", subparser, help="display the Borg client and server versions")

View file

@ -99,7 +99,8 @@ 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
from jsonargparse import ArgumentParser as _ArgumentParser # we subclass that to add custom behavior
from jsonargparse import Namespace, SUPPRESS, REMAINDER # noqa: F401
# borg completion uses these private symbols, so we need to import them:
from jsonargparse._actions import _ActionSubCommands # noqa: F401
@ -107,6 +108,12 @@ from jsonargparse._completions import prepare_actions_context, shtab_prepare_act
from jsonargparse._completions import bash_compgen_typehint # noqa: F401
class ArgumentParser(_ArgumentParser):
# the borg code always uses RawDescriptionHelpFormatter and add_help=False:
def __init__(self, *args, formatter_class=RawDescriptionHelpFormatter, add_help=False, **kwargs):
super().__init__(*args, formatter_class=formatter_class, add_help=add_help, **kwargs)
def flatten_namespace(ns: Any) -> Namespace:
"""
Flattens the nested namespace jsonargparse produces for subcommands into a

View file

@ -1,7 +1,7 @@
import pytest
from . import Archiver, RK_ENCRYPTION, cmd
from ...helpers.argparsing import ArgumentParser, RawDescriptionHelpFormatter, flatten_namespace
from ...helpers.argparsing import ArgumentParser, flatten_namespace
def test_bad_filters(archiver):
@ -93,7 +93,7 @@ class TestCommonOptions:
@pytest.fixture
def basic_parser(self):
parser = ArgumentParser(prog="test", description="test parser", add_help=False)
parser = ArgumentParser(prog="test", description="test parser")
parser.common_options = Archiver.CommonOptions(self.define_common_options)
return parser
@ -108,19 +108,13 @@ class TestCommonOptions:
@pytest.fixture
def common_parser(self, parser):
common_parser = ArgumentParser(add_help=False, prog="test")
common_parser = ArgumentParser(prog="test")
parser.common_options.add_common_group(common_parser)
return common_parser
@pytest.fixture
def parse_vars_from_line(self, parser, subcommands, common_parser):
subparser = ArgumentParser(
parents=[common_parser],
add_help=False,
description="foo",
epilog="bar",
formatter_class=RawDescriptionHelpFormatter,
)
subparser = ArgumentParser(parents=[common_parser], description="foo", epilog="bar")
subparser.add_argument("--foo-bar", dest="foo_bar", action="store_true")
subcommands.add_subcommand("subcmd", subparser, help="baz")