From 429a5009a3be8c3ce846a3827f974eb514acbced Mon Sep 17 00:00:00 2001 From: Adal Chiriliuc Date: Tue, 30 Apr 2024 15:40:42 +0300 Subject: [PATCH] added file large subcommand --- b2/_internal/console_tool.py | 169 ++++++++++++------ changelog.d/+command-file-large.added.md | 1 + changelog.d/+command-file-large.deprecated.md | 3 + 3 files changed, 123 insertions(+), 50 deletions(-) create mode 100644 changelog.d/+command-file-large.added.md create mode 100644 changelog.d/+command-file-large.deprecated.md diff --git a/b2/_internal/console_tool.py b/b2/_internal/console_tool.py index 7da72e73..f6eabf2f 100644 --- a/b2/_internal/console_tool.py +++ b/b2/_internal/console_tool.py @@ -1343,51 +1343,32 @@ def _get_user_requested_realm(cls, args) -> str | None: return os.environ.get(B2_ENVIRONMENT_ENV_VAR) -class CancelAllUnfinishedLargeFiles(Command): +class FileLargeUnfinishedCancelBase(Command): """ - Lists all large files that have been started but not - finished and cancels them. Any parts that have been - uploaded will be deleted. - - Requires capability: - - - **listFiles** - - **writeFiles** - """ - - @classmethod - def _setup_parser(cls, parser): - add_bucket_name_argument(parser) - super()._setup_parser(parser) - - def _run(self, args): - bucket = self.api.get_bucket_by_name(args.bucketName) - for file_version in bucket.list_unfinished_large_files(): - bucket.cancel_large_file(file_version.file_id) - self._print(file_version.file_id, 'canceled') - return 0 - - -class CancelLargeFile(Command): - """ - Cancels a large file upload. Used to undo a ``start-large-file``. - + When used with a b2id://fileId, cancels a large file upload. Cannot be used once the file is finished. After finishing, - using ``delete-file-version`` to delete the large file. + use ``rm`` to delete the large file. + + When used with a b2://bucketName, lists all large files that + have been started but not finished and cancels them. Any parts + that have been uploaded will be deleted. Requires capability: + - **listFiles** (if canceling a bucket) - **writeFiles** """ - @classmethod - def _setup_parser(cls, parser): - parser.add_argument('fileId') - super()._setup_parser(parser) - def _run(self, args): - self.api.cancel_large_file(args.fileId) - self._print(args.fileId, 'canceled') + b2_uri = self.get_b2_uri_from_arg(args) + if isinstance(b2_uri, B2FileIdURI): + self.api.cancel_large_file(b2_uri.file_id) + self._print(b2_uri.file_id, 'canceled') + elif isinstance(b2_uri, B2URI): + bucket = self.api.get_bucket_by_name(b2_uri.bucket_name) + for file_version in bucket.list_unfinished_large_files(): + bucket.cancel_large_file(file_version.file_id) + self._print(file_version.file_id, 'canceled') return 0 @@ -2257,7 +2238,7 @@ def timestamp_display(self, timestamp_or_none): return dt.strftime('%Y-%m-%d'), dt.strftime('%H:%M:%S') -class ListParts(Command): +class FileLargePartsBase(Command): """ Lists all of the parts that have been uploaded for the given large file, which must be a file that was started but not @@ -2268,18 +2249,14 @@ class ListParts(Command): - **writeFiles** """ - @classmethod - def _setup_parser(cls, parser): - parser.add_argument('largeFileId') - super()._setup_parser(parser) - def _run(self, args): - for part in self.api.list_parts(args.largeFileId): + b2_uri = self.get_b2_uri_from_arg(args) + for part in self.api.list_parts(b2_uri.file_id): self._print('%5d %9d %s' % (part.part_number, part.content_length, part.content_sha1)) return 0 -class ListUnfinishedLargeFiles(Command): +class FileLargeUnfinishedListBase(Command): """ Lists all of the large files in the bucket that were started, but not finished or canceled. @@ -2289,13 +2266,9 @@ class ListUnfinishedLargeFiles(Command): - **listFiles** """ - @classmethod - def _setup_parser(cls, parser): - add_bucket_name_argument(parser) - super()._setup_parser(parser) - def _run(self, args): - bucket = self.api.get_bucket_by_name(args.bucketName) + b2_uri = self.get_b2_uri_from_arg(args) + bucket = self.api.get_bucket_by_name(b2_uri.bucket_name) for unfinished in bucket.list_unfinished_large_files(): file_info_text = ' '.join( f'{k}={unfinished.file_info[k]}' for k in sorted(unfinished.file_info) @@ -5121,6 +5094,102 @@ class DeleteFileVersion(CmdReplacedByMixin, DeleteFileVersionBase): replaced_by_cmd = Rm +@File.subcommands_registry.register +class FileLarge(Command): + """ + Large file uploads management subcommands. + + For more information on each subcommand, use ``{NAME} file large SUBCOMMAND --help``. + + Examples: + + .. code-block:: + + {NAME} file large parts + {NAME} file large unfinished + """ + COMMAND_NAME = 'large' + subcommands_registry = ClassRegistry(attr_name='COMMAND_NAME') + + +@FileLarge.subcommands_registry.register +class FileLargeParts(FileLargePartsBase): + __doc__ = FileLargePartsBase.__doc__ + COMMAND_NAME = 'parts' + + +@FileLarge.subcommands_registry.register +class FileLargeUnfinished(Command): + """ + Large file unfinished uploads management subcommands. + + For more information on each subcommand, use ``{NAME} file large unfinished SUBCOMMAND --help``. + + Examples: + + .. code-block:: + + {NAME} file large unfinished list + {NAME} file large unfinished cancel + """ + COMMAND_NAME = 'unfinished' + subcommands_registry = ClassRegistry(attr_name='COMMAND_NAME') + + +@FileLargeUnfinished.subcommands_registry.register +class FileLargeUnfinishedList(FileLargeUnfinishedListBase): + __doc__ = FileLargePartsBase.__doc__ + COMMAND_NAME = 'list' + + +@FileLargeUnfinished.subcommands_registry.register +class FileLargeUnfinishedCancel(FileLargeUnfinishedCancelBase): + __doc__ = FileLargeUnfinishedCancelBase.__doc__ + COMMAND_NAME = 'cancel' + + +class ListParts(CmdReplacedByMixin, B2URIFileIDArgMixin, FileLargePartsBase): + __doc__ = FileLargePartsBase.__doc__ + replaced_by_cmd = (File, FileLarge, FileLargeParts) + + +class ListUnfinishedLargeFiles( + CmdReplacedByMixin, B2URIBucketArgMixin, FileLargeUnfinishedListBase +): + __doc__ = FileLargeUnfinishedListBase.__doc__ + replaced_by_cmd = (File, FileLarge, FileLargeUnfinished, FileLargeUnfinishedList) + + +class CancelAllUnfinishedLargeFiles( + CmdReplacedByMixin, B2URIBucketArgMixin, FileLargeUnfinishedCancelBase +): + """ + Lists all large files that have been started but not + finished and cancels them. Any parts that have been + uploaded will be deleted. + + Requires capability: + + - **listFiles** + - **writeFiles** + """ + replaced_by_cmd = (File, FileLarge, FileLargeUnfinished, FileLargeUnfinishedCancel) + + +class CancelLargeFile(CmdReplacedByMixin, B2URIFileIDArgMixin, FileLargeUnfinishedCancelBase): + """ + Cancels a large file upload. Used to undo a ``start-large-file``. + + Cannot be used once the file is finished. After finishing, + using ``delete-file-version`` to delete the large file. + + Requires capability: + + - **writeFiles** + """ + replaced_by_cmd = (File, FileLarge, FileLargeUnfinished, FileLargeUnfinishedCancel) + + class ConsoleTool: """ Implements the commands available in the B2 command-line tool diff --git a/changelog.d/+command-file-large.added.md b/changelog.d/+command-file-large.added.md new file mode 100644 index 00000000..d736529b --- /dev/null +++ b/changelog.d/+command-file-large.added.md @@ -0,0 +1 @@ +Add `file large {parts|unfinished list|unfinished cancel}` commands. \ No newline at end of file diff --git a/changelog.d/+command-file-large.deprecated.md b/changelog.d/+command-file-large.deprecated.md new file mode 100644 index 00000000..dd7a7c04 --- /dev/null +++ b/changelog.d/+command-file-large.deprecated.md @@ -0,0 +1,3 @@ +Deprecated `list-parts`, use `file large parts` instead. +Deprecated `list-unfinished-large-files`, use `file large unfinished list` instead. +Deprecated `cancel-large-file` amd `cancel-all-unfinished-large-files`, use `file large unfinished cancel` instead. \ No newline at end of file