diff --git a/b2sdk/__init__.py b/b2sdk/__init__.py index 7912c1f40..3edaab638 100644 --- a/b2sdk/__init__.py +++ b/b2sdk/__init__.py @@ -9,19 +9,6 @@ ###################################################################### from __future__ import annotations -# Set default logging handler to avoid "No handler found" warnings. -import logging - -logging.getLogger(__name__).addHandler(logging.NullHandler()) - - -class UrllibWarningFilter: - def filter(self, record): - return record.msg != "Connection pool is full, discarding connection: %s" - - -logging.getLogger('urllib3.connectionpool').addFilter(UrllibWarningFilter()) - import b2sdk.version # noqa: E402 __version__ = b2sdk.version.VERSION assert __version__ # PEP-0396 diff --git a/b2sdk/account_info/__init__.py b/b2sdk/_internal/account_info/__init__.py similarity index 88% rename from b2sdk/account_info/__init__.py rename to b2sdk/_internal/account_info/__init__.py index 1b317b7f8..a3d4f9b58 100644 --- a/b2sdk/account_info/__init__.py +++ b/b2sdk/_internal/account_info/__init__.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/account_info/__init__.py +# File: b2sdk/_internal/account_info/__init__.py # # Copyright 2019 Backblaze Inc. All Rights Reserved. # diff --git a/b2sdk/account_info/abstract.py b/b2sdk/_internal/account_info/abstract.py similarity index 98% rename from b2sdk/account_info/abstract.py rename to b2sdk/_internal/account_info/abstract.py index 5a6582dcc..e48201844 100644 --- a/b2sdk/account_info/abstract.py +++ b/b2sdk/_internal/account_info/abstract.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/account_info/abstract.py +# File: b2sdk/_internal/account_info/abstract.py # # Copyright 2019 Backblaze Inc. All Rights Reserved. # @@ -11,9 +11,9 @@ from abc import abstractmethod -from b2sdk.account_info import exception -from b2sdk.raw_api import ALL_CAPABILITIES -from b2sdk.utils import B2TraceMetaAbstract, limit_trace_arguments +from b2sdk._internal.account_info import exception +from b2sdk._internal.raw_api import ALL_CAPABILITIES +from b2sdk._internal.utils import B2TraceMetaAbstract, limit_trace_arguments class AbstractAccountInfo(metaclass=B2TraceMetaAbstract): diff --git a/b2sdk/account_info/exception.py b/b2sdk/_internal/account_info/exception.py similarity index 96% rename from b2sdk/account_info/exception.py rename to b2sdk/_internal/account_info/exception.py index 6f7fd081d..bda210502 100644 --- a/b2sdk/account_info/exception.py +++ b/b2sdk/_internal/account_info/exception.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/account_info/exception.py +# File: b2sdk/_internal/account_info/exception.py # # Copyright 2019 Backblaze Inc. All Rights Reserved. # diff --git a/b2sdk/account_info/in_memory.py b/b2sdk/_internal/account_info/in_memory.py similarity index 98% rename from b2sdk/account_info/in_memory.py rename to b2sdk/_internal/account_info/in_memory.py index 63727ad28..d30e0114c 100644 --- a/b2sdk/account_info/in_memory.py +++ b/b2sdk/_internal/account_info/in_memory.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/account_info/in_memory.py +# File: b2sdk/_internal/account_info/in_memory.py # # Copyright 2019 Backblaze Inc. All Rights Reserved. # diff --git a/b2sdk/account_info/sqlite_account_info.py b/b2sdk/_internal/account_info/sqlite_account_info.py similarity index 99% rename from b2sdk/account_info/sqlite_account_info.py rename to b2sdk/_internal/account_info/sqlite_account_info.py index d7372412a..8f1d558e4 100644 --- a/b2sdk/account_info/sqlite_account_info.py +++ b/b2sdk/_internal/account_info/sqlite_account_info.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/account_info/sqlite_account_info.py +# File: b2sdk/_internal/account_info/sqlite_account_info.py # # Copyright 2019 Backblaze Inc. All Rights Reserved. # diff --git a/b2sdk/account_info/stub.py b/b2sdk/_internal/account_info/stub.py similarity index 98% rename from b2sdk/account_info/stub.py rename to b2sdk/_internal/account_info/stub.py index 0e1db8ce6..925f05ec3 100644 --- a/b2sdk/account_info/stub.py +++ b/b2sdk/_internal/account_info/stub.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/account_info/stub.py +# File: b2sdk/_internal/account_info/stub.py # # Copyright 2019 Backblaze Inc. All Rights Reserved. # diff --git a/b2sdk/account_info/upload_url_pool.py b/b2sdk/_internal/account_info/upload_url_pool.py similarity index 98% rename from b2sdk/account_info/upload_url_pool.py rename to b2sdk/_internal/account_info/upload_url_pool.py index 34bda735a..d409d4184 100644 --- a/b2sdk/account_info/upload_url_pool.py +++ b/b2sdk/_internal/account_info/upload_url_pool.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/account_info/upload_url_pool.py +# File: b2sdk/_internal/account_info/upload_url_pool.py # # Copyright 2019 Backblaze Inc. All Rights Reserved. # diff --git a/b2sdk/api.py b/b2sdk/_internal/api.py similarity index 98% rename from b2sdk/api.py rename to b2sdk/_internal/api.py index c49ee4a8f..cbc1b792e 100644 --- a/b2sdk/api.py +++ b/b2sdk/_internal/api.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/api.py +# File: b2sdk/_internal/api.py # # Copyright 2019 Backblaze Inc. All Rights Reserved. # @@ -160,7 +160,7 @@ def __init__( :class:`~b2sdk.v2.SqliteAccountInfo` :param cache: It is used by B2Api to cache the mapping between bucket name and bucket ids. - default is :class:`~b2sdk.cache.DummyCache` + default is :class:`~b2sdk._internal.cache.DummyCache` :param max_upload_workers: a number of upload threads :param max_copy_workers: a number of copy threads @@ -198,8 +198,10 @@ def cache(self): def raw_api(self): """ .. warning:: - :class:`~b2sdk.raw_api.B2RawHTTPApi` attribute is deprecated. - :class:`~b2sdk.session.B2Session` expose all :class:`~b2sdk.raw_api.B2RawHTTPApi` methods now.""" + :class:`~b2sdk._internal.raw_api.B2RawHTTPApi` attribute is deprecated. + :class:`~b2sdk._internal.session.B2Session` expose all + :class:`~b2sdk._internal.raw_api.B2RawHTTPApi` methods now. + """ return self.session.raw_api def authorize_automatically(self): diff --git a/b2sdk/api_config.py b/b2sdk/_internal/api_config.py similarity index 97% rename from b2sdk/api_config.py rename to b2sdk/_internal/api_config.py index 1dd10d314..47781a213 100644 --- a/b2sdk/api_config.py +++ b/b2sdk/_internal/api_config.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/api_config.py +# File: b2sdk/_internal/api_config.py # # Copyright 2021 Backblaze Inc. All Rights Reserved. # diff --git a/b2sdk/application_key.py b/b2sdk/_internal/application_key.py similarity index 99% rename from b2sdk/application_key.py rename to b2sdk/_internal/application_key.py index d2cb68924..4dc3a8487 100644 --- a/b2sdk/application_key.py +++ b/b2sdk/_internal/application_key.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/application_key.py +# File: b2sdk/_internal/application_key.py # # Copyright 2021 Backblaze Inc. All Rights Reserved. # diff --git a/b2sdk/b2http.py b/b2sdk/_internal/b2http.py similarity index 99% rename from b2sdk/b2http.py rename to b2sdk/_internal/b2http.py index 740a98298..8deb3fc0f 100644 --- a/b2sdk/b2http.py +++ b/b2sdk/_internal/b2http.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/b2http.py +# File: b2sdk/_internal/b2http.py # # Copyright 2019 Backblaze Inc. All Rights Reserved. # @@ -29,6 +29,8 @@ import requests from requests.adapters import HTTPAdapter +from b2sdk.version import USER_AGENT + from .api_config import DEFAULT_HTTP_API_CONFIG, B2HttpApiConfig from .exception import ( B2ConnectionError, @@ -46,7 +48,6 @@ ) from .requests import NotDecompressingResponse from .utils.typing import JSON -from .version import USER_AGENT LOCALE_LOCK = threading.Lock() logger = logging.getLogger(__name__) @@ -616,7 +617,7 @@ def _translate_and_retry( class NotDecompressingHTTPAdapter(HTTPAdapter): """ - HTTP adapter that uses :class:`b2sdk.requests.NotDecompressingResponse` instead of the default + HTTP adapter that uses :class:`b2sdk._internal.requests.NotDecompressingResponse` instead of the default :code:`requests.Response` class. """ diff --git a/b2sdk/bounded_queue_executor.py b/b2sdk/_internal/bounded_queue_executor.py similarity index 97% rename from b2sdk/bounded_queue_executor.py rename to b2sdk/_internal/bounded_queue_executor.py index 0ee25599c..16c17d05b 100644 --- a/b2sdk/bounded_queue_executor.py +++ b/b2sdk/_internal/bounded_queue_executor.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/bounded_queue_executor.py +# File: b2sdk/_internal/bounded_queue_executor.py # # Copyright 2019 Backblaze Inc. All Rights Reserved. # diff --git a/b2sdk/bucket.py b/b2sdk/_internal/bucket.py similarity index 99% rename from b2sdk/bucket.py rename to b2sdk/_internal/bucket.py index 6b729f457..d26738ec6 100644 --- a/b2sdk/bucket.py +++ b/b2sdk/_internal/bucket.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/bucket.py +# File: b2sdk/_internal/bucket.py # # Copyright 2019 Backblaze Inc. All Rights Reserved. # diff --git a/b2sdk/cache.py b/b2sdk/_internal/cache.py similarity index 97% rename from b2sdk/cache.py rename to b2sdk/_internal/cache.py index 0a81f7ea8..b87c0032a 100644 --- a/b2sdk/cache.py +++ b/b2sdk/_internal/cache.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/cache.py +# File: b2sdk/_internal/cache.py # # Copyright 2019 Backblaze Inc. All Rights Reserved. # @@ -13,7 +13,7 @@ from typing import TYPE_CHECKING if TYPE_CHECKING: - from b2sdk.account_info.abstract import AbstractAccountInfo + from b2sdk._internal.account_info.abstract import AbstractAccountInfo class AbstractCache(metaclass=ABCMeta): diff --git a/b2sdk/encryption/__init__.py b/b2sdk/_internal/encryption/__init__.py similarity index 86% rename from b2sdk/encryption/__init__.py rename to b2sdk/_internal/encryption/__init__.py index 3cff053a8..51b4e46ea 100644 --- a/b2sdk/encryption/__init__.py +++ b/b2sdk/_internal/encryption/__init__.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/encryption/__init__.py +# File: b2sdk/_internal/encryption/__init__.py # # Copyright 2021 Backblaze Inc. All Rights Reserved. # diff --git a/b2sdk/encryption/setting.py b/b2sdk/_internal/encryption/setting.py similarity index 99% rename from b2sdk/encryption/setting.py rename to b2sdk/_internal/encryption/setting.py index c2bcd0938..e072b6cb7 100644 --- a/b2sdk/encryption/setting.py +++ b/b2sdk/_internal/encryption/setting.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/encryption/setting.py +# File: b2sdk/_internal/encryption/setting.py # # Copyright 2021 Backblaze Inc. All Rights Reserved. # diff --git a/b2sdk/encryption/types.py b/b2sdk/_internal/encryption/types.py similarity index 96% rename from b2sdk/encryption/types.py rename to b2sdk/_internal/encryption/types.py index a0859e517..d095a22a2 100644 --- a/b2sdk/encryption/types.py +++ b/b2sdk/_internal/encryption/types.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/encryption/types.py +# File: b2sdk/_internal/encryption/types.py # # Copyright 2021 Backblaze Inc. All Rights Reserved. # diff --git a/b2sdk/exception.py b/b2sdk/_internal/exception.py similarity index 99% rename from b2sdk/exception.py rename to b2sdk/_internal/exception.py index e1b66b9f5..f87f5416c 100644 --- a/b2sdk/exception.py +++ b/b2sdk/_internal/exception.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/exception.py +# File: b2sdk/_internal/exception.py # # Copyright 2019 Backblaze Inc. All Rights Reserved. # diff --git a/b2sdk/file_lock.py b/b2sdk/_internal/file_lock.py similarity index 99% rename from b2sdk/file_lock.py rename to b2sdk/_internal/file_lock.py index ea90b23ef..7d09177de 100644 --- a/b2sdk/file_lock.py +++ b/b2sdk/_internal/file_lock.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/file_lock.py +# File: b2sdk/_internal/file_lock.py # # Copyright 2021 Backblaze Inc. All Rights Reserved. # diff --git a/b2sdk/file_version.py b/b2sdk/_internal/file_version.py similarity index 99% rename from b2sdk/file_version.py rename to b2sdk/_internal/file_version.py index dc2ca9728..6d6f586f4 100644 --- a/b2sdk/file_version.py +++ b/b2sdk/_internal/file_version.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/file_version.py +# File: b2sdk/_internal/file_version.py # # Copyright 2019 Backblaze Inc. All Rights Reserved. # diff --git a/b2sdk/filter.py b/b2sdk/_internal/filter.py similarity index 98% rename from b2sdk/filter.py rename to b2sdk/_internal/filter.py index 8b5209453..0fc5a2eaf 100644 --- a/b2sdk/filter.py +++ b/b2sdk/_internal/filter.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/filter.py +# File: b2sdk/_internal/filter.py # # Copyright 2024 Backblaze Inc. All Rights Reserved. # diff --git a/b2sdk/http_constants.py b/b2sdk/_internal/http_constants.py similarity index 97% rename from b2sdk/http_constants.py rename to b2sdk/_internal/http_constants.py index ead34b456..81e3e858f 100644 --- a/b2sdk/http_constants.py +++ b/b2sdk/_internal/http_constants.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/http_constants.py +# File: b2sdk/_internal/http_constants.py # # Copyright 2021 Backblaze Inc. All Rights Reserved. # diff --git a/b2sdk/included_sources.py b/b2sdk/_internal/included_sources.py similarity index 94% rename from b2sdk/included_sources.py rename to b2sdk/_internal/included_sources.py index ba2234185..dcf7452f7 100644 --- a/b2sdk/included_sources.py +++ b/b2sdk/_internal/included_sources.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/included_sources.py +# File: b2sdk/_internal/included_sources.py # # Copyright 2021 Backblaze Inc. All Rights Reserved. # diff --git a/b2sdk/transfer/emerge/__init__.py b/b2sdk/_internal/large_file/__init__.py similarity index 86% rename from b2sdk/transfer/emerge/__init__.py rename to b2sdk/_internal/large_file/__init__.py index ab5a6edbe..5db14982c 100644 --- a/b2sdk/transfer/emerge/__init__.py +++ b/b2sdk/_internal/large_file/__init__.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/transfer/emerge/__init__.py +# File: b2sdk/_internal/large_file/__init__.py # # Copyright 2020 Backblaze Inc. All Rights Reserved. # diff --git a/b2sdk/large_file/part.py b/b2sdk/_internal/large_file/part.py similarity index 97% rename from b2sdk/large_file/part.py rename to b2sdk/_internal/large_file/part.py index ed1fd06a7..c18beb927 100644 --- a/b2sdk/large_file/part.py +++ b/b2sdk/_internal/large_file/part.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/large_file/part.py +# File: b2sdk/_internal/large_file/part.py # # Copyright 2020 Backblaze Inc. All Rights Reserved. # diff --git a/b2sdk/large_file/services.py b/b2sdk/_internal/large_file/services.py similarity index 92% rename from b2sdk/large_file/services.py rename to b2sdk/_internal/large_file/services.py index e2be897d2..a7ff0666a 100644 --- a/b2sdk/large_file/services.py +++ b/b2sdk/_internal/large_file/services.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/large_file/services.py +# File: b2sdk/_internal/large_file/services.py # # Copyright 2021 Backblaze Inc. All Rights Reserved. # @@ -9,11 +9,11 @@ ###################################################################### from __future__ import annotations -from b2sdk.encryption.setting import EncryptionSetting -from b2sdk.file_lock import FileRetentionSetting, LegalHold -from b2sdk.file_version import FileIdAndName -from b2sdk.large_file.part import PartFactory -from b2sdk.large_file.unfinished_large_file import UnfinishedLargeFile +from b2sdk._internal.encryption.setting import EncryptionSetting +from b2sdk._internal.file_lock import FileRetentionSetting, LegalHold +from b2sdk._internal.file_version import FileIdAndName +from b2sdk._internal.large_file.part import PartFactory +from b2sdk._internal.large_file.unfinished_large_file import UnfinishedLargeFile class LargeFileServices: diff --git a/b2sdk/large_file/unfinished_large_file.py b/b2sdk/_internal/large_file/unfinished_large_file.py similarity index 91% rename from b2sdk/large_file/unfinished_large_file.py rename to b2sdk/_internal/large_file/unfinished_large_file.py index acb503357..4bfe3e7b2 100644 --- a/b2sdk/large_file/unfinished_large_file.py +++ b/b2sdk/_internal/large_file/unfinished_large_file.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/large_file/unfinished_large_file.py +# File: b2sdk/_internal/large_file/unfinished_large_file.py # # Copyright 2021 Backblaze Inc. All Rights Reserved. # @@ -11,9 +11,9 @@ import datetime as dt -from b2sdk.encryption.setting import EncryptionSettingFactory -from b2sdk.file_lock import FileRetentionSetting, LegalHold -from b2sdk.utils.http_date import parse_http_date +from b2sdk._internal.encryption.setting import EncryptionSettingFactory +from b2sdk._internal.file_lock import FileRetentionSetting, LegalHold +from b2sdk._internal.utils.http_date import parse_http_date class UnfinishedLargeFile: diff --git a/b2sdk/progress.py b/b2sdk/_internal/progress.py similarity index 95% rename from b2sdk/progress.py rename to b2sdk/_internal/progress.py index 504b1f3cd..43ed4fbba 100644 --- a/b2sdk/progress.py +++ b/b2sdk/_internal/progress.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/progress.py +# File: b2sdk/_internal/progress.py # # Copyright 2019 Backblaze Inc. All Rights Reserved. # @@ -104,9 +104,13 @@ def __exit__(self, exc_type, exc_val, exc_tb): class TqdmProgressListener(AbstractProgressListener): """ Progress listener based on tqdm library. + + This listener displays a nice progress bar, but requires `tqdm` package to be installed. """ def __init__(self, *args, **kwargs): + if tqdm is None: + raise ModuleNotFoundError("No module named 'tqdm' found") self.tqdm = None # set in set_total_bytes() self.prev_value = 0 super().__init__(*args, **kwargs) @@ -212,7 +216,7 @@ def get_calls(self) -> list[str]: def make_progress_listener(description: str, quiet: bool) -> AbstractProgressListener: """ - Return a progress listener object depending on some conditions. + Produce the best progress listener available for the given parameters. :param description: listener description :param quiet: if ``True``, do not output anything diff --git a/b2sdk/raw_api.py b/b2sdk/_internal/raw_api.py similarity index 99% rename from b2sdk/raw_api.py rename to b2sdk/_internal/raw_api.py index 403415573..c76cc25c6 100644 --- a/b2sdk/raw_api.py +++ b/b2sdk/_internal/raw_api.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/raw_api.py +# File: b2sdk/_internal/raw_api.py # # Copyright 2021 Backblaze Inc. All Rights Reserved. # @@ -23,9 +23,6 @@ except ImportError: from typing import NotRequired, TypedDict -from b2sdk.http_constants import FILE_INFO_HEADER_PREFIX -from b2sdk.utils.docs import ensure_b2sdk_doc_urls - from .encryption.setting import EncryptionMode, EncryptionSetting from .exception import ( AccessDenied, @@ -38,8 +35,10 @@ WrongEncryptionModeForBucketDefault, ) from .file_lock import BucketRetentionSetting, FileRetentionSetting, LegalHold +from .http_constants import FILE_INFO_HEADER_PREFIX from .replication.setting import ReplicationConfiguration from .utils import b2_url_encode +from .utils.docs import ensure_b2sdk_doc_urls # All supported realms REALM_URLS = { diff --git a/b2sdk/raw_simulator.py b/b2sdk/_internal/raw_simulator.py similarity index 99% rename from b2sdk/raw_simulator.py rename to b2sdk/_internal/raw_simulator.py index 2a4cfbdf1..41f4ce95a 100644 --- a/b2sdk/raw_simulator.py +++ b/b2sdk/_internal/raw_simulator.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/raw_simulator.py +# File: b2sdk/_internal/raw_simulator.py # # Copyright 2021 Backblaze Inc. All Rights Reserved. # @@ -20,9 +20,6 @@ from requests.structures import CaseInsensitiveDict -from b2sdk.http_constants import FILE_INFO_HEADER_PREFIX, HEX_DIGITS_AT_END -from b2sdk.replication.setting import ReplicationConfiguration - from .b2http import ResponseContextManager from .encryption.setting import EncryptionMode, EncryptionSetting from .exception import ( @@ -55,7 +52,9 @@ RetentionMode, ) from .file_version import UNVERIFIED_CHECKSUM_PREFIX +from .http_constants import FILE_INFO_HEADER_PREFIX, HEX_DIGITS_AT_END from .raw_api import ALL_CAPABILITIES, AbstractRawApi, LifecycleRule, MetadataDirectiveMode +from .replication.setting import ReplicationConfiguration from .replication.types import ReplicationStatus from .stream.hashing import StreamWithHash from .utils import ConcurrentUsedAuthTokenGuard, b2_url_decode, b2_url_encode, hex_sha1_of_bytes diff --git a/b2sdk/replication/__init__.py b/b2sdk/_internal/replication/__init__.py similarity index 85% rename from b2sdk/replication/__init__.py rename to b2sdk/_internal/replication/__init__.py index d225ca14a..94d4e49e4 100644 --- a/b2sdk/replication/__init__.py +++ b/b2sdk/_internal/replication/__init__.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/replication/__init__.py +# File: b2sdk/_internal/replication/__init__.py # # Copyright 2022 Backblaze Inc. All Rights Reserved. # diff --git a/b2sdk/replication/monitoring.py b/b2sdk/_internal/replication/monitoring.py similarity index 99% rename from b2sdk/replication/monitoring.py rename to b2sdk/_internal/replication/monitoring.py index dd43adef5..2f6446a16 100644 --- a/b2sdk/replication/monitoring.py +++ b/b2sdk/_internal/replication/monitoring.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/replication/monitoring.py +# File: b2sdk/_internal/replication/monitoring.py # # Copyright 2022 Backblaze Inc. All Rights Reserved. # diff --git a/b2sdk/replication/setting.py b/b2sdk/_internal/replication/setting.py similarity index 99% rename from b2sdk/replication/setting.py rename to b2sdk/_internal/replication/setting.py index 08703ae30..489b2a394 100644 --- a/b2sdk/replication/setting.py +++ b/b2sdk/_internal/replication/setting.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/replication/setting.py +# File: b2sdk/_internal/replication/setting.py # # Copyright 2022 Backblaze Inc. All Rights Reserved. # diff --git a/b2sdk/replication/setup.py b/b2sdk/_internal/replication/setup.py similarity index 97% rename from b2sdk/replication/setup.py rename to b2sdk/_internal/replication/setup.py index 0df3c8d46..cb58a7872 100644 --- a/b2sdk/replication/setup.py +++ b/b2sdk/_internal/replication/setup.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/replication/setup.py +# File: b2sdk/_internal/replication/setup.py # # Copyright 2022 Backblaze Inc. All Rights Reserved. # @@ -22,11 +22,11 @@ from collections.abc import Iterable from typing import ClassVar -from b2sdk.api import B2Api -from b2sdk.application_key import ApplicationKey -from b2sdk.bucket import Bucket -from b2sdk.replication.setting import ReplicationConfiguration, ReplicationRule -from b2sdk.utils import B2TraceMeta +from b2sdk._internal.api import B2Api +from b2sdk._internal.application_key import ApplicationKey +from b2sdk._internal.bucket import Bucket +from b2sdk._internal.replication.setting import ReplicationConfiguration, ReplicationRule +from b2sdk._internal.utils import B2TraceMeta logger = logging.getLogger(__name__) diff --git a/b2sdk/replication/types.py b/b2sdk/_internal/replication/types.py similarity index 93% rename from b2sdk/replication/types.py rename to b2sdk/_internal/replication/types.py index 8a7f36ec8..af9cf132a 100644 --- a/b2sdk/replication/types.py +++ b/b2sdk/_internal/replication/types.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/replication/types.py +# File: b2sdk/_internal/replication/types.py # # Copyright 2022 Backblaze Inc. All Rights Reserved. # diff --git a/b2sdk/requests/LICENSE b/b2sdk/_internal/requests/LICENSE similarity index 100% rename from b2sdk/requests/LICENSE rename to b2sdk/_internal/requests/LICENSE diff --git a/b2sdk/requests/NOTICE b/b2sdk/_internal/requests/NOTICE similarity index 100% rename from b2sdk/requests/NOTICE rename to b2sdk/_internal/requests/NOTICE diff --git a/b2sdk/requests/README.md b/b2sdk/_internal/requests/README.md similarity index 100% rename from b2sdk/requests/README.md rename to b2sdk/_internal/requests/README.md diff --git a/b2sdk/requests/__init__.py b/b2sdk/_internal/requests/__init__.py similarity index 94% rename from b2sdk/requests/__init__.py rename to b2sdk/_internal/requests/__init__.py index d1b657bd4..b9a71580f 100644 --- a/b2sdk/requests/__init__.py +++ b/b2sdk/_internal/requests/__init__.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/requests/__init__.py +# File: b2sdk/_internal/requests/__init__.py # # Copyright 2021 Backblaze Inc. All Rights Reserved. # Copyright 2019 Kenneth Reitz @@ -68,7 +68,7 @@ def generate(): @classmethod def from_builtin_response(cls, response: Response): """ - Create a :class:`b2sdk.requests.NotDecompressingResponse` object from a :class:`requests.Response` object. + Create a :class:`b2sdk._internal.requests.NotDecompressingResponse` object from a :class:`requests.Response` object. Don't use :code:`Response.__getstate__` and :code:`Response.__setstate__` because these assume that the content has been consumed, which will never be true in our case. """ diff --git a/b2sdk/requests/included_source_meta.py b/b2sdk/_internal/requests/included_source_meta.py similarity index 83% rename from b2sdk/requests/included_source_meta.py rename to b2sdk/_internal/requests/included_source_meta.py index 40bfcbe2d..9c48a9fb0 100644 --- a/b2sdk/requests/included_source_meta.py +++ b/b2sdk/_internal/requests/included_source_meta.py @@ -1,13 +1,13 @@ ###################################################################### # -# File: b2sdk/requests/included_source_meta.py +# File: b2sdk/_internal/requests/included_source_meta.py # # Copyright 2022 Backblaze Inc. All Rights Reserved. # # License https://www.backblaze.com/using_b2_code.html # ###################################################################### -from b2sdk.included_sources import IncludedSourceMeta, add_included_source +from b2sdk._internal.included_sources import IncludedSourceMeta, add_included_source included_source_meta = IncludedSourceMeta( 'requests', 'Included in a revised form', { diff --git a/b2sdk/scan/__init__.py b/b2sdk/_internal/scan/__init__.py similarity index 87% rename from b2sdk/scan/__init__.py rename to b2sdk/_internal/scan/__init__.py index 3f41e7c93..6a23d8cc9 100644 --- a/b2sdk/scan/__init__.py +++ b/b2sdk/_internal/scan/__init__.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/scan/__init__.py +# File: b2sdk/_internal/scan/__init__.py # # Copyright 2022 Backblaze Inc. All Rights Reserved. # diff --git a/b2sdk/scan/exception.py b/b2sdk/_internal/scan/exception.py similarity index 98% rename from b2sdk/scan/exception.py rename to b2sdk/_internal/scan/exception.py index 16e17495f..ff000f8c4 100644 --- a/b2sdk/scan/exception.py +++ b/b2sdk/_internal/scan/exception.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/scan/exception.py +# File: b2sdk/_internal/scan/exception.py # # Copyright 2022 Backblaze Inc. All Rights Reserved. # diff --git a/b2sdk/scan/folder.py b/b2sdk/_internal/scan/folder.py similarity index 99% rename from b2sdk/scan/folder.py rename to b2sdk/_internal/scan/folder.py index 562b38f46..1ae666680 100644 --- a/b2sdk/scan/folder.py +++ b/b2sdk/_internal/scan/folder.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/scan/folder.py +# File: b2sdk/_internal/scan/folder.py # # Copyright 2019 Backblaze Inc. All Rights Reserved. # @@ -344,7 +344,7 @@ def __init__(self, bucket_name, folder_name, api): :param folder_name: a folder name :type folder_name: str :param api: an API object - :type api: b2sdk.api.B2Api + :type api: b2sdk._internal.api.B2Api """ self.bucket_name = bucket_name self.folder_name = folder_name diff --git a/b2sdk/scan/folder_parser.py b/b2sdk/_internal/scan/folder_parser.py similarity index 97% rename from b2sdk/scan/folder_parser.py rename to b2sdk/_internal/scan/folder_parser.py index d641e8236..ac037bfc8 100644 --- a/b2sdk/scan/folder_parser.py +++ b/b2sdk/_internal/scan/folder_parser.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/scan/folder_parser.py +# File: b2sdk/_internal/scan/folder_parser.py # # Copyright 2019 Backblaze Inc. All Rights Reserved. # diff --git a/b2sdk/scan/path.py b/b2sdk/_internal/scan/path.py similarity index 98% rename from b2sdk/scan/path.py rename to b2sdk/_internal/scan/path.py index 26948e098..58a9d0395 100644 --- a/b2sdk/scan/path.py +++ b/b2sdk/_internal/scan/path.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/scan/path.py +# File: b2sdk/_internal/scan/path.py # # Copyright 2021 Backblaze Inc. All Rights Reserved. # diff --git a/b2sdk/scan/policies.py b/b2sdk/_internal/scan/policies.py similarity index 99% rename from b2sdk/scan/policies.py rename to b2sdk/_internal/scan/policies.py index 349a76fda..6befa8575 100644 --- a/b2sdk/scan/policies.py +++ b/b2sdk/_internal/scan/policies.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/scan/policies.py +# File: b2sdk/_internal/scan/policies.py # # Copyright 2019 Backblaze Inc. All Rights Reserved. # diff --git a/b2sdk/scan/report.py b/b2sdk/_internal/scan/report.py similarity index 99% rename from b2sdk/scan/report.py rename to b2sdk/_internal/scan/report.py index 684118155..4518d43d0 100644 --- a/b2sdk/scan/report.py +++ b/b2sdk/_internal/scan/report.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/scan/report.py +# File: b2sdk/_internal/scan/report.py # # Copyright 2022 Backblaze Inc. All Rights Reserved. # diff --git a/b2sdk/scan/scan.py b/b2sdk/_internal/scan/scan.py similarity index 94% rename from b2sdk/scan/scan.py rename to b2sdk/_internal/scan/scan.py index 442445851..342a2ae5b 100644 --- a/b2sdk/scan/scan.py +++ b/b2sdk/_internal/scan/scan.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/scan/scan.py +# File: b2sdk/_internal/scan/scan.py # # Copyright 2022 Backblaze Inc. All Rights Reserved. # @@ -35,8 +35,8 @@ def zip_folders( in both folders. Either file (but not both) will be None if the file is in only one folder. - :param b2sdk.scan.folder.AbstractFolder folder_a: first folder object. - :param b2sdk.scan.folder.AbstractFolder folder_b: second folder object. + :param b2sdk._internal.scan.folder.AbstractFolder folder_a: first folder object. + :param b2sdk._internal.scan.folder.AbstractFolder folder_b: second folder object. :param reporter: reporter object :param policies_manager: policies manager object :return: yields two element tuples diff --git a/b2sdk/session.py b/b2sdk/_internal/session.py similarity index 94% rename from b2sdk/session.py rename to b2sdk/_internal/session.py index 5ed9d4ce3..e288fe54a 100644 --- a/b2sdk/session.py +++ b/b2sdk/_internal/session.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/session.py +# File: b2sdk/_internal/session.py # # Copyright 2019 Backblaze Inc. All Rights Reserved. # @@ -14,17 +14,17 @@ from functools import partial from typing import Any -from b2sdk.account_info.abstract import AbstractAccountInfo -from b2sdk.account_info.exception import MissingAccountData -from b2sdk.account_info.sqlite_account_info import SqliteAccountInfo -from b2sdk.api_config import DEFAULT_HTTP_API_CONFIG, B2HttpApiConfig -from b2sdk.b2http import B2Http -from b2sdk.cache import AbstractCache, AuthInfoCache, DummyCache -from b2sdk.encryption.setting import EncryptionSetting -from b2sdk.exception import InvalidAuthToken, Unauthorized -from b2sdk.file_lock import BucketRetentionSetting, FileRetentionSetting, LegalHold -from b2sdk.raw_api import ALL_CAPABILITIES, REALM_URLS, LifecycleRule -from b2sdk.replication.setting import ReplicationConfiguration +from b2sdk._internal.account_info.abstract import AbstractAccountInfo +from b2sdk._internal.account_info.exception import MissingAccountData +from b2sdk._internal.account_info.sqlite_account_info import SqliteAccountInfo +from b2sdk._internal.api_config import DEFAULT_HTTP_API_CONFIG, B2HttpApiConfig +from b2sdk._internal.b2http import B2Http +from b2sdk._internal.cache import AbstractCache, AuthInfoCache, DummyCache +from b2sdk._internal.encryption.setting import EncryptionSetting +from b2sdk._internal.exception import InvalidAuthToken, Unauthorized +from b2sdk._internal.file_lock import BucketRetentionSetting, FileRetentionSetting, LegalHold +from b2sdk._internal.raw_api import ALL_CAPABILITIES, REALM_URLS, LifecycleRule +from b2sdk._internal.replication.setting import ReplicationConfiguration logger = logging.getLogger(__name__) @@ -61,11 +61,11 @@ def __init__( :class:`~b2sdk.v2.SqliteAccountInfo` :param cache: an instance of the one of the following classes: - :class:`~b2sdk.cache.DummyCache`, :class:`~b2sdk.cache.InMemoryCache`, - :class:`~b2sdk.cache.AuthInfoCache`, - or any custom class derived from :class:`~b2sdk.cache.AbstractCache` + :class:`~b2sdk._internal.cache.DummyCache`, :class:`~b2sdk._internal.cache.InMemoryCache`, + :class:`~b2sdk._internal.cache.AuthInfoCache`, + or any custom class derived from :class:`~b2sdk._internal.cache.AbstractCache` It is used by B2Api to cache the mapping between bucket name and bucket ids. - default is :class:`~b2sdk.cache.DummyCache` + default is :class:`~b2sdk._internal.cache.DummyCache` :param api_config """ diff --git a/b2sdk/stream/__init__.py b/b2sdk/_internal/stream/__init__.py similarity index 93% rename from b2sdk/stream/__init__.py rename to b2sdk/_internal/stream/__init__.py index 02f0d4fc6..f3b19d5a6 100644 --- a/b2sdk/stream/__init__.py +++ b/b2sdk/_internal/stream/__init__.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/stream/__init__.py +# File: b2sdk/_internal/stream/__init__.py # # Copyright 2020 Backblaze Inc. All Rights Reserved. # diff --git a/b2sdk/stream/base.py b/b2sdk/_internal/stream/base.py similarity index 92% rename from b2sdk/stream/base.py rename to b2sdk/_internal/stream/base.py index a525d6375..e3767e1e8 100644 --- a/b2sdk/stream/base.py +++ b/b2sdk/_internal/stream/base.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/stream/base.py +# File: b2sdk/_internal/stream/base.py # # Copyright 2020 Backblaze Inc. All Rights Reserved. # diff --git a/b2sdk/stream/chained.py b/b2sdk/_internal/stream/chained.py similarity index 98% rename from b2sdk/stream/chained.py rename to b2sdk/_internal/stream/chained.py index c512576e0..796cf362c 100644 --- a/b2sdk/stream/chained.py +++ b/b2sdk/_internal/stream/chained.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/stream/chained.py +# File: b2sdk/_internal/stream/chained.py # # Copyright 2020 Backblaze Inc. All Rights Reserved. # @@ -12,7 +12,7 @@ import io from abc import ABCMeta, abstractmethod -from b2sdk.stream.base import ReadOnlyStreamMixin +from b2sdk._internal.stream.base import ReadOnlyStreamMixin class ChainedStream(ReadOnlyStreamMixin, io.IOBase): diff --git a/b2sdk/stream/hashing.py b/b2sdk/_internal/stream/hashing.py similarity index 92% rename from b2sdk/stream/hashing.py rename to b2sdk/_internal/stream/hashing.py index 36c9b95a3..d62c8df63 100644 --- a/b2sdk/stream/hashing.py +++ b/b2sdk/_internal/stream/hashing.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/stream/hashing.py +# File: b2sdk/_internal/stream/hashing.py # # Copyright 2020 Backblaze Inc. All Rights Reserved. # @@ -12,8 +12,8 @@ import hashlib import io -from b2sdk.stream.base import ReadOnlyStreamMixin -from b2sdk.stream.wrapper import StreamWithLengthWrapper +from b2sdk._internal.stream.base import ReadOnlyStreamMixin +from b2sdk._internal.stream.wrapper import StreamWithLengthWrapper class StreamWithHash(ReadOnlyStreamMixin, StreamWithLengthWrapper): diff --git a/b2sdk/stream/progress.py b/b2sdk/_internal/stream/progress.py similarity index 96% rename from b2sdk/stream/progress.py rename to b2sdk/_internal/stream/progress.py index 6120b5db8..f984339f3 100644 --- a/b2sdk/stream/progress.py +++ b/b2sdk/_internal/stream/progress.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/stream/progress.py +# File: b2sdk/_internal/stream/progress.py # # Copyright 2020 Backblaze Inc. All Rights Reserved. # @@ -9,7 +9,7 @@ ###################################################################### from __future__ import annotations -from b2sdk.stream.wrapper import StreamWrapper +from b2sdk._internal.stream.wrapper import StreamWrapper class AbstractStreamWithProgress(StreamWrapper): diff --git a/b2sdk/stream/range.py b/b2sdk/_internal/stream/range.py similarity index 93% rename from b2sdk/stream/range.py rename to b2sdk/_internal/stream/range.py index d73140f4d..cdc891ed8 100644 --- a/b2sdk/stream/range.py +++ b/b2sdk/_internal/stream/range.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/stream/range.py +# File: b2sdk/_internal/stream/range.py # # Copyright 2020 Backblaze Inc. All Rights Reserved. # @@ -11,8 +11,8 @@ import io -from b2sdk.stream.base import ReadOnlyStreamMixin -from b2sdk.stream.wrapper import StreamWithLengthWrapper +from b2sdk._internal.stream.base import ReadOnlyStreamMixin +from b2sdk._internal.stream.wrapper import StreamWithLengthWrapper class RangeOfInputStream(ReadOnlyStreamMixin, StreamWithLengthWrapper): diff --git a/b2sdk/stream/wrapper.py b/b2sdk/_internal/stream/wrapper.py similarity index 98% rename from b2sdk/stream/wrapper.py rename to b2sdk/_internal/stream/wrapper.py index 25bd98ec6..1a9dd4132 100644 --- a/b2sdk/stream/wrapper.py +++ b/b2sdk/_internal/stream/wrapper.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/stream/wrapper.py +# File: b2sdk/_internal/stream/wrapper.py # # Copyright 2020 Backblaze Inc. All Rights Reserved. # diff --git a/b2sdk/sync/__init__.py b/b2sdk/_internal/sync/__init__.py similarity index 87% rename from b2sdk/sync/__init__.py rename to b2sdk/_internal/sync/__init__.py index 15a7593b3..de4c169ed 100644 --- a/b2sdk/sync/__init__.py +++ b/b2sdk/_internal/sync/__init__.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/sync/__init__.py +# File: b2sdk/_internal/sync/__init__.py # # Copyright 2019 Backblaze Inc. All Rights Reserved. # diff --git a/b2sdk/sync/action.py b/b2sdk/_internal/sync/action.py similarity index 99% rename from b2sdk/sync/action.py rename to b2sdk/_internal/sync/action.py index 306640351..98945324d 100644 --- a/b2sdk/sync/action.py +++ b/b2sdk/_internal/sync/action.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/sync/action.py +# File: b2sdk/_internal/sync/action.py # # Copyright 2019 Backblaze Inc. All Rights Reserved. # @@ -45,7 +45,7 @@ def run(self, bucket: Bucket, reporter: ProgressReport, dry_run: bool = False): Main action routine. :param bucket: a Bucket object - :type bucket: b2sdk.bucket.Bucket + :type bucket: b2sdk._internal.bucket.Bucket :param reporter: a place to report errors :param dry_run: if True, perform a dry run :type dry_run: bool diff --git a/b2sdk/sync/encryption_provider.py b/b2sdk/_internal/sync/encryption_provider.py similarity index 98% rename from b2sdk/sync/encryption_provider.py rename to b2sdk/_internal/sync/encryption_provider.py index c45042aa7..0304da46b 100644 --- a/b2sdk/sync/encryption_provider.py +++ b/b2sdk/_internal/sync/encryption_provider.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/sync/encryption_provider.py +# File: b2sdk/_internal/sync/encryption_provider.py # # Copyright 2021 Backblaze Inc. All Rights Reserved. # diff --git a/b2sdk/sync/exception.py b/b2sdk/_internal/sync/exception.py similarity index 90% rename from b2sdk/sync/exception.py rename to b2sdk/_internal/sync/exception.py index 8a1426df8..71f36d559 100644 --- a/b2sdk/sync/exception.py +++ b/b2sdk/_internal/sync/exception.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/sync/exception.py +# File: b2sdk/_internal/sync/exception.py # # Copyright 2019 Backblaze Inc. All Rights Reserved. # diff --git a/b2sdk/sync/policy.py b/b2sdk/_internal/sync/policy.py similarity index 99% rename from b2sdk/sync/policy.py rename to b2sdk/_internal/sync/policy.py index f0843de00..93b1263bb 100644 --- a/b2sdk/sync/policy.py +++ b/b2sdk/_internal/sync/policy.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/sync/policy.py +# File: b2sdk/_internal/sync/policy.py # # Copyright 2019 Backblaze Inc. All Rights Reserved. # diff --git a/b2sdk/sync/policy_manager.py b/b2sdk/_internal/sync/policy_manager.py similarity index 98% rename from b2sdk/sync/policy_manager.py rename to b2sdk/_internal/sync/policy_manager.py index 9b15dc557..d238a4b11 100644 --- a/b2sdk/sync/policy_manager.py +++ b/b2sdk/_internal/sync/policy_manager.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/sync/policy_manager.py +# File: b2sdk/_internal/sync/policy_manager.py # # Copyright 2019 Backblaze Inc. All Rights Reserved. # diff --git a/b2sdk/sync/report.py b/b2sdk/_internal/sync/report.py similarity index 99% rename from b2sdk/sync/report.py rename to b2sdk/_internal/sync/report.py index 5ce15d586..54433430b 100644 --- a/b2sdk/sync/report.py +++ b/b2sdk/_internal/sync/report.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/sync/report.py +# File: b2sdk/_internal/sync/report.py # # Copyright 2019 Backblaze Inc. All Rights Reserved. # diff --git a/b2sdk/sync/sync.py b/b2sdk/_internal/sync/sync.py similarity index 99% rename from b2sdk/sync/sync.py rename to b2sdk/_internal/sync/sync.py index 8dd129431..553d6dfc9 100644 --- a/b2sdk/sync/sync.py +++ b/b2sdk/_internal/sync/sync.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/sync/sync.py +# File: b2sdk/_internal/sync/sync.py # # Copyright 2019 Backblaze Inc. All Rights Reserved. # @@ -37,7 +37,7 @@ def count_files(local_folder, reporter, policies_manager): """ Count all of the files in a local folder. - :param b2sdk.scan.folder.AbstractFolder local_folder: a folder object. + :param b2sdk._internal.scan.folder.AbstractFolder local_folder: a folder object. :param reporter: reporter object """ # Don't pass in a reporter to all_files. Broken symlinks will be reported diff --git a/b2sdk/transfer/__init__.py b/b2sdk/_internal/transfer/__init__.py similarity index 92% rename from b2sdk/transfer/__init__.py rename to b2sdk/_internal/transfer/__init__.py index 293cdddd8..f45173746 100644 --- a/b2sdk/transfer/__init__.py +++ b/b2sdk/_internal/transfer/__init__.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/transfer/__init__.py +# File: b2sdk/_internal/transfer/__init__.py # # Copyright 2020 Backblaze Inc. All Rights Reserved. # diff --git a/b2sdk/large_file/__init__.py b/b2sdk/_internal/transfer/emerge/__init__.py similarity index 84% rename from b2sdk/large_file/__init__.py rename to b2sdk/_internal/transfer/emerge/__init__.py index e74f66488..22c12cc58 100644 --- a/b2sdk/large_file/__init__.py +++ b/b2sdk/_internal/transfer/emerge/__init__.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/large_file/__init__.py +# File: b2sdk/_internal/transfer/emerge/__init__.py # # Copyright 2020 Backblaze Inc. All Rights Reserved. # diff --git a/b2sdk/transfer/emerge/emerger.py b/b2sdk/_internal/transfer/emerge/emerger.py similarity index 94% rename from b2sdk/transfer/emerge/emerger.py rename to b2sdk/_internal/transfer/emerge/emerger.py index 1b692f155..567e98e4d 100644 --- a/b2sdk/transfer/emerge/emerger.py +++ b/b2sdk/_internal/transfer/emerge/emerger.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/transfer/emerge/emerger.py +# File: b2sdk/_internal/transfer/emerge/emerger.py # # Copyright 2020 Backblaze Inc. All Rights Reserved. # @@ -12,14 +12,14 @@ import logging from typing import Iterator -from b2sdk.encryption.setting import EncryptionSetting -from b2sdk.file_lock import FileRetentionSetting, LegalHold -from b2sdk.http_constants import LARGE_FILE_SHA1 -from b2sdk.progress import AbstractProgressListener -from b2sdk.transfer.emerge.executor import EmergeExecutor -from b2sdk.transfer.emerge.planner.planner import EmergePlan, EmergePlanner -from b2sdk.transfer.emerge.write_intent import WriteIntent -from b2sdk.utils import B2TraceMetaAbstract, Sha1HexDigest, iterator_peek +from b2sdk._internal.encryption.setting import EncryptionSetting +from b2sdk._internal.file_lock import FileRetentionSetting, LegalHold +from b2sdk._internal.http_constants import LARGE_FILE_SHA1 +from b2sdk._internal.progress import AbstractProgressListener +from b2sdk._internal.transfer.emerge.executor import EmergeExecutor +from b2sdk._internal.transfer.emerge.planner.planner import EmergePlan, EmergePlanner +from b2sdk._internal.transfer.emerge.write_intent import WriteIntent +from b2sdk._internal.utils import B2TraceMetaAbstract, Sha1HexDigest, iterator_peek logger = logging.getLogger(__name__) @@ -31,8 +31,8 @@ class Emerger(metaclass=B2TraceMetaAbstract): This class can be used to build advanced copy workflows like incremental upload. It creates a emerge plan and pass it to emerge executor - all complex logic - is actually implemented in :class:`b2sdk.transfer.emerge.planner.planner.EmergePlanner` - and :class:`b2sdk.transfer.emerge.executor.EmergeExecutor` + is actually implemented in :class:`b2sdk._internal.transfer.emerge.planner.planner.EmergePlanner` + and :class:`b2sdk._internal.transfer.emerge.executor.EmergeExecutor` """ DEFAULT_STREAMING_MAX_QUEUE_SIZE = 100 diff --git a/b2sdk/transfer/emerge/exception.py b/b2sdk/_internal/transfer/emerge/exception.py similarity index 81% rename from b2sdk/transfer/emerge/exception.py rename to b2sdk/_internal/transfer/emerge/exception.py index 02d8361b4..29728024c 100644 --- a/b2sdk/transfer/emerge/exception.py +++ b/b2sdk/_internal/transfer/emerge/exception.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/transfer/emerge/exception.py +# File: b2sdk/_internal/transfer/emerge/exception.py # # Copyright 2022 Backblaze Inc. All Rights Reserved. # @@ -9,7 +9,7 @@ ###################################################################### from __future__ import annotations -from b2sdk.exception import B2SimpleError +from b2sdk._internal.exception import B2SimpleError class UnboundStreamBufferTimeout(B2SimpleError): diff --git a/b2sdk/transfer/emerge/executor.py b/b2sdk/_internal/transfer/emerge/executor.py similarity index 97% rename from b2sdk/transfer/emerge/executor.py rename to b2sdk/_internal/transfer/emerge/executor.py index 7654076d1..f1b24516f 100644 --- a/b2sdk/transfer/emerge/executor.py +++ b/b2sdk/_internal/transfer/emerge/executor.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/transfer/emerge/executor.py +# File: b2sdk/_internal/transfer/emerge/executor.py # # Copyright 2020 Backblaze Inc. All Rights Reserved. # @@ -14,20 +14,20 @@ from abc import ABCMeta, abstractmethod from typing import TYPE_CHECKING -from b2sdk.encryption.setting import EncryptionSetting -from b2sdk.exception import MaxFileSizeExceeded -from b2sdk.file_lock import NO_RETENTION_FILE_SETTING, FileRetentionSetting, LegalHold -from b2sdk.http_constants import LARGE_FILE_SHA1 -from b2sdk.transfer.outbound.large_file_upload_state import LargeFileUploadState -from b2sdk.transfer.outbound.upload_source import UploadSourceStream +from b2sdk._internal.encryption.setting import EncryptionSetting +from b2sdk._internal.exception import MaxFileSizeExceeded +from b2sdk._internal.file_lock import NO_RETENTION_FILE_SETTING, FileRetentionSetting, LegalHold +from b2sdk._internal.http_constants import LARGE_FILE_SHA1 +from b2sdk._internal.transfer.outbound.large_file_upload_state import LargeFileUploadState +from b2sdk._internal.transfer.outbound.upload_source import UploadSourceStream AUTO_CONTENT_TYPE = 'b2/x-auto' logger = logging.getLogger(__name__) if TYPE_CHECKING: - from b2sdk.transfer.emerge.planner.part_definition import UploadEmergePartDefinition - from b2sdk.transfer.emerge.planner.planner import StreamingEmergePlan + from b2sdk._internal.transfer.emerge.planner.part_definition import UploadEmergePartDefinition + from b2sdk._internal.transfer.emerge.planner.planner import StreamingEmergePlan class EmergeExecutor: diff --git a/b2sdk/_internal/transfer/emerge/planner/__init__.py b/b2sdk/_internal/transfer/emerge/planner/__init__.py new file mode 100644 index 000000000..dc68d137c --- /dev/null +++ b/b2sdk/_internal/transfer/emerge/planner/__init__.py @@ -0,0 +1,10 @@ +###################################################################### +# +# File: b2sdk/_internal/transfer/emerge/planner/__init__.py +# +# Copyright 2020 Backblaze Inc. All Rights Reserved. +# +# License https://www.backblaze.com/using_b2_code.html +# +###################################################################### +from __future__ import annotations diff --git a/b2sdk/transfer/emerge/planner/part_definition.py b/b2sdk/_internal/transfer/emerge/planner/part_definition.py similarity index 93% rename from b2sdk/transfer/emerge/planner/part_definition.py rename to b2sdk/_internal/transfer/emerge/planner/part_definition.py index 8d060f551..9bef7faa6 100644 --- a/b2sdk/transfer/emerge/planner/part_definition.py +++ b/b2sdk/_internal/transfer/emerge/planner/part_definition.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/transfer/emerge/planner/part_definition.py +# File: b2sdk/_internal/transfer/emerge/planner/part_definition.py # # Copyright 2020 Backblaze Inc. All Rights Reserved. # @@ -13,12 +13,12 @@ from functools import partial from typing import TYPE_CHECKING -from b2sdk.stream.chained import ChainedStream -from b2sdk.stream.range import wrap_with_range -from b2sdk.utils import hex_sha1_of_unlimited_stream +from b2sdk._internal.stream.chained import ChainedStream +from b2sdk._internal.stream.range import wrap_with_range +from b2sdk._internal.utils import hex_sha1_of_unlimited_stream if TYPE_CHECKING: - from b2sdk.transfer.emerge.unbound_write_intent import UnboundSourceBytes + from b2sdk._internal.transfer.emerge.unbound_write_intent import UnboundSourceBytes class BaseEmergePartDefinition(metaclass=ABCMeta): diff --git a/b2sdk/transfer/emerge/planner/planner.py b/b2sdk/_internal/transfer/emerge/planner/planner.py similarity index 97% rename from b2sdk/transfer/emerge/planner/planner.py rename to b2sdk/_internal/transfer/emerge/planner/planner.py index 2b7edfc80..4282d9100 100644 --- a/b2sdk/transfer/emerge/planner/planner.py +++ b/b2sdk/_internal/transfer/emerge/planner/planner.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/transfer/emerge/planner/planner.py +# File: b2sdk/_internal/transfer/emerge/planner/planner.py # # Copyright 2020 Backblaze Inc. All Rights Reserved. # @@ -16,25 +16,25 @@ from collections import deque from math import ceil -from b2sdk.exception import InvalidUserInput -from b2sdk.http_constants import ( +from b2sdk._internal.exception import InvalidUserInput +from b2sdk._internal.http_constants import ( DEFAULT_MAX_PART_SIZE, DEFAULT_MIN_PART_SIZE, DEFAULT_RECOMMENDED_UPLOAD_PART_SIZE, ) -from b2sdk.transfer.emerge.planner.part_definition import ( +from b2sdk._internal.transfer.emerge.planner.part_definition import ( CopyEmergePartDefinition, UploadEmergePartDefinition, UploadSubpartsEmergePartDefinition, ) -from b2sdk.transfer.emerge.planner.upload_subpart import ( +from b2sdk._internal.transfer.emerge.planner.upload_subpart import ( LocalSourceUploadSubpart, RemoteSourceUploadSubpart, ) -from b2sdk.utils import iterator_peek +from b2sdk._internal.utils import iterator_peek if typing.TYPE_CHECKING: - from b2sdk.account_info.abstract import AbstractAccountInfo + from b2sdk._internal.account_info.abstract import AbstractAccountInfo class UploadBuffer: @@ -349,7 +349,7 @@ def _get_copy_parts(self, copy_intent, start_offset, end_offset): def _buff_split(self, upload_buffer): """ Split upload buffer to parts candidates - smaller upload buffers. - :rtype iterator[b2sdk.transfer.emerge.planner.planner.UploadBuffer]: + :rtype iterator[b2sdk._internal.transfer.emerge.planner.planner.UploadBuffer]: """ if upload_buffer.intent_count() == 0: return @@ -369,8 +369,8 @@ def _buff_partition(self, upload_buffer): In result left part cannot be split more, and nothing can be assumed about right part. - :rtype tuple(b2sdk.transfer.emerge.planner.planner.UploadBuffer, - b2sdk.transfer.emerge.planner.planner.UploadBuffer): + :rtype tuple(b2sdk._internal.transfer.emerge.planner.planner.UploadBuffer, + b2sdk._internal.transfer.emerge.planner.planner.UploadBuffer): """ left_buff = UploadBuffer(upload_buffer.start_offset) buff_start = upload_buffer.start_offset diff --git a/b2sdk/transfer/emerge/planner/upload_subpart.py b/b2sdk/_internal/transfer/emerge/planner/upload_subpart.py similarity index 93% rename from b2sdk/transfer/emerge/planner/upload_subpart.py rename to b2sdk/_internal/transfer/emerge/planner/upload_subpart.py index d51abb3fb..cc2bf534d 100644 --- a/b2sdk/transfer/emerge/planner/upload_subpart.py +++ b/b2sdk/_internal/transfer/emerge/planner/upload_subpart.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/transfer/emerge/planner/upload_subpart.py +# File: b2sdk/_internal/transfer/emerge/planner/upload_subpart.py # # Copyright 2020 Backblaze Inc. All Rights Reserved. # @@ -13,9 +13,9 @@ from abc import ABCMeta, abstractmethod from functools import partial -from b2sdk.stream.chained import StreamOpener -from b2sdk.stream.range import wrap_with_range -from b2sdk.utils import hex_sha1_of_unlimited_stream +from b2sdk._internal.stream.chained import StreamOpener +from b2sdk._internal.stream.range import wrap_with_range +from b2sdk._internal.utils import hex_sha1_of_unlimited_stream class BaseUploadSubpart(metaclass=ABCMeta): diff --git a/b2sdk/transfer/emerge/unbound_write_intent.py b/b2sdk/_internal/transfer/emerge/unbound_write_intent.py similarity index 96% rename from b2sdk/transfer/emerge/unbound_write_intent.py rename to b2sdk/_internal/transfer/emerge/unbound_write_intent.py index 2596d43f0..306202a6a 100644 --- a/b2sdk/transfer/emerge/unbound_write_intent.py +++ b/b2sdk/_internal/transfer/emerge/unbound_write_intent.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/transfer/emerge/unbound_write_intent.py +# File: b2sdk/_internal/transfer/emerge/unbound_write_intent.py # # Copyright 2022 Backblaze Inc. All Rights Reserved. # @@ -14,9 +14,9 @@ import queue from typing import Callable, Iterator -from b2sdk.transfer.emerge.exception import UnboundStreamBufferTimeout -from b2sdk.transfer.emerge.write_intent import WriteIntent -from b2sdk.transfer.outbound.upload_source import AbstractUploadSource +from b2sdk._internal.transfer.emerge.exception import UnboundStreamBufferTimeout +from b2sdk._internal.transfer.emerge.write_intent import WriteIntent +from b2sdk._internal.transfer.outbound.upload_source import AbstractUploadSource class IOWrapper(io.BytesIO): diff --git a/b2sdk/transfer/emerge/write_intent.py b/b2sdk/_internal/transfer/emerge/write_intent.py similarity index 96% rename from b2sdk/transfer/emerge/write_intent.py rename to b2sdk/_internal/transfer/emerge/write_intent.py index bc221dfb8..6d8d4835b 100644 --- a/b2sdk/transfer/emerge/write_intent.py +++ b/b2sdk/_internal/transfer/emerge/write_intent.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/transfer/emerge/write_intent.py +# File: b2sdk/_internal/transfer/emerge/write_intent.py # # Copyright 2020 Backblaze Inc. All Rights Reserved. # @@ -9,7 +9,7 @@ ###################################################################### from __future__ import annotations -from b2sdk.utils import Sha1HexDigest +from b2sdk._internal.utils import Sha1HexDigest class WriteIntent: diff --git a/b2sdk/transfer/emerge/planner/__init__.py b/b2sdk/_internal/transfer/inbound/__init__.py similarity index 84% rename from b2sdk/transfer/emerge/planner/__init__.py rename to b2sdk/_internal/transfer/inbound/__init__.py index 8fee2ae11..5e06207bb 100644 --- a/b2sdk/transfer/emerge/planner/__init__.py +++ b/b2sdk/_internal/transfer/inbound/__init__.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/transfer/emerge/planner/__init__.py +# File: b2sdk/_internal/transfer/inbound/__init__.py # # Copyright 2020 Backblaze Inc. All Rights Reserved. # diff --git a/b2sdk/transfer/inbound/download_manager.py b/b2sdk/_internal/transfer/inbound/download_manager.py similarity index 93% rename from b2sdk/transfer/inbound/download_manager.py rename to b2sdk/_internal/transfer/inbound/download_manager.py index 066927213..61b909372 100644 --- a/b2sdk/transfer/inbound/download_manager.py +++ b/b2sdk/_internal/transfer/inbound/download_manager.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/transfer/inbound/download_manager.py +# File: b2sdk/_internal/transfer/inbound/download_manager.py # # Copyright 2020 Backblaze Inc. All Rights Reserved. # @@ -11,12 +11,12 @@ import logging -from b2sdk.encryption.setting import EncryptionSetting -from b2sdk.exception import ( +from b2sdk._internal.encryption.setting import EncryptionSetting +from b2sdk._internal.exception import ( InvalidRange, ) -from b2sdk.progress import DoNothingProgressListener -from b2sdk.utils import B2TraceMetaAbstract +from b2sdk._internal.progress import DoNothingProgressListener +from b2sdk._internal.utils import B2TraceMetaAbstract from ...utils.thread_pool import ThreadPoolMixin from ..transfer_manager import TransferManager diff --git a/b2sdk/transfer/inbound/downloaded_file.py b/b2sdk/_internal/transfer/inbound/downloaded_file.py similarity index 98% rename from b2sdk/transfer/inbound/downloaded_file.py rename to b2sdk/_internal/transfer/inbound/downloaded_file.py index 14f252d81..ef7c05910 100644 --- a/b2sdk/transfer/inbound/downloaded_file.py +++ b/b2sdk/_internal/transfer/inbound/downloaded_file.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/transfer/inbound/downloaded_file.py +# File: b2sdk/_internal/transfer/inbound/downloaded_file.py # # Copyright 2021 Backblaze Inc. All Rights Reserved. # @@ -18,8 +18,7 @@ from requests.models import Response -from b2sdk._internal.utils.filesystem import _IS_WINDOWS, points_to_fifo, points_to_stdout -from b2sdk.exception import ( +from b2sdk._internal.exception import ( ChecksumMismatch, DestinationDirectoryDoesntAllowOperation, DestinationDirectoryDoesntExist, @@ -28,7 +27,8 @@ DestinationParentIsNotADirectory, TruncatedOutput, ) -from b2sdk.utils import set_file_mtime +from b2sdk._internal.utils import set_file_mtime +from b2sdk._internal.utils.filesystem import _IS_WINDOWS, points_to_fifo, points_to_stdout try: from typing_extensions import Literal diff --git a/b2sdk/_internal/transfer/inbound/downloader/__init__.py b/b2sdk/_internal/transfer/inbound/downloader/__init__.py new file mode 100644 index 000000000..5f2cb0a46 --- /dev/null +++ b/b2sdk/_internal/transfer/inbound/downloader/__init__.py @@ -0,0 +1,10 @@ +###################################################################### +# +# File: b2sdk/_internal/transfer/inbound/downloader/__init__.py +# +# Copyright 2020 Backblaze Inc. All Rights Reserved. +# +# License https://www.backblaze.com/using_b2_code.html +# +###################################################################### +from __future__ import annotations diff --git a/b2sdk/transfer/inbound/downloader/abstract.py b/b2sdk/_internal/transfer/inbound/downloader/abstract.py similarity index 91% rename from b2sdk/transfer/inbound/downloader/abstract.py rename to b2sdk/_internal/transfer/inbound/downloader/abstract.py index fdb9ad04b..6feb7f6d2 100644 --- a/b2sdk/transfer/inbound/downloader/abstract.py +++ b/b2sdk/_internal/transfer/inbound/downloader/abstract.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/transfer/inbound/downloader/abstract.py +# File: b2sdk/_internal/transfer/inbound/downloader/abstract.py # # Copyright 2020 Backblaze Inc. All Rights Reserved. # @@ -16,11 +16,11 @@ from requests.models import Response -from b2sdk.encryption.setting import EncryptionSetting -from b2sdk.file_version import DownloadVersion -from b2sdk.session import B2Session -from b2sdk.utils import B2TraceMetaAbstract -from b2sdk.utils.range_ import Range +from b2sdk._internal.encryption.setting import EncryptionSetting +from b2sdk._internal.file_version import DownloadVersion +from b2sdk._internal.session import B2Session +from b2sdk._internal.utils import B2TraceMetaAbstract +from b2sdk._internal.utils.range_ import Range class EmptyHasher: diff --git a/b2sdk/transfer/inbound/downloader/parallel.py b/b2sdk/_internal/transfer/inbound/downloader/parallel.py similarity index 98% rename from b2sdk/transfer/inbound/downloader/parallel.py rename to b2sdk/_internal/transfer/inbound/downloader/parallel.py index c5e70d509..d94686a7c 100644 --- a/b2sdk/transfer/inbound/downloader/parallel.py +++ b/b2sdk/_internal/transfer/inbound/downloader/parallel.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/transfer/inbound/downloader/parallel.py +# File: b2sdk/_internal/transfer/inbound/downloader/parallel.py # # Copyright 2020 Backblaze Inc. All Rights Reserved. # @@ -18,10 +18,10 @@ from requests.models import Response -from b2sdk.encryption.setting import EncryptionSetting -from b2sdk.file_version import DownloadVersion -from b2sdk.session import B2Session -from b2sdk.utils.range_ import Range +from b2sdk._internal.encryption.setting import EncryptionSetting +from b2sdk._internal.file_version import DownloadVersion +from b2sdk._internal.session import B2Session +from b2sdk._internal.utils.range_ import Range from .abstract import AbstractDownloader from .stats_collector import StatsCollector diff --git a/b2sdk/transfer/inbound/downloader/simple.py b/b2sdk/_internal/transfer/inbound/downloader/simple.py similarity index 93% rename from b2sdk/transfer/inbound/downloader/simple.py rename to b2sdk/_internal/transfer/inbound/downloader/simple.py index 03ef68792..8bab6f493 100644 --- a/b2sdk/transfer/inbound/downloader/simple.py +++ b/b2sdk/_internal/transfer/inbound/downloader/simple.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/transfer/inbound/downloader/simple.py +# File: b2sdk/_internal/transfer/inbound/downloader/simple.py # # Copyright 2020 Backblaze Inc. All Rights Reserved. # @@ -14,9 +14,9 @@ from requests.models import Response -from b2sdk.encryption.setting import EncryptionSetting -from b2sdk.file_version import DownloadVersion -from b2sdk.session import B2Session +from b2sdk._internal.encryption.setting import EncryptionSetting +from b2sdk._internal.file_version import DownloadVersion +from b2sdk._internal.session import B2Session from .abstract import AbstractDownloader diff --git a/b2sdk/transfer/inbound/downloader/stats_collector.py b/b2sdk/_internal/transfer/inbound/downloader/stats_collector.py similarity index 97% rename from b2sdk/transfer/inbound/downloader/stats_collector.py rename to b2sdk/_internal/transfer/inbound/downloader/stats_collector.py index a911d01c4..ba960d8de 100644 --- a/b2sdk/transfer/inbound/downloader/stats_collector.py +++ b/b2sdk/_internal/transfer/inbound/downloader/stats_collector.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/transfer/inbound/downloader/stats_collector.py +# File: b2sdk/_internal/transfer/inbound/downloader/stats_collector.py # # Copyright 2020 Backblaze Inc. All Rights Reserved. # diff --git a/b2sdk/transfer/inbound/__init__.py b/b2sdk/_internal/transfer/outbound/__init__.py similarity index 84% rename from b2sdk/transfer/inbound/__init__.py rename to b2sdk/_internal/transfer/outbound/__init__.py index ca57725b5..74dc65537 100644 --- a/b2sdk/transfer/inbound/__init__.py +++ b/b2sdk/_internal/transfer/outbound/__init__.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/transfer/inbound/__init__.py +# File: b2sdk/_internal/transfer/outbound/__init__.py # # Copyright 2020 Backblaze Inc. All Rights Reserved. # diff --git a/b2sdk/transfer/outbound/copy_manager.py b/b2sdk/_internal/transfer/outbound/copy_manager.py similarity index 93% rename from b2sdk/transfer/outbound/copy_manager.py rename to b2sdk/_internal/transfer/outbound/copy_manager.py index 0714ed805..b027b2b56 100644 --- a/b2sdk/transfer/outbound/copy_manager.py +++ b/b2sdk/_internal/transfer/outbound/copy_manager.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/transfer/outbound/copy_manager.py +# File: b2sdk/_internal/transfer/outbound/copy_manager.py # # Copyright 2020 Backblaze Inc. All Rights Reserved. # @@ -11,14 +11,14 @@ import logging -from b2sdk.encryption.setting import EncryptionMode, EncryptionSetting -from b2sdk.exception import AlreadyFailed, CopyArgumentsMismatch, SSECKeyIdMismatchInCopy -from b2sdk.file_lock import FileRetentionSetting, LegalHold -from b2sdk.http_constants import SSE_C_KEY_ID_FILE_INFO_KEY_NAME -from b2sdk.progress import AbstractProgressListener -from b2sdk.raw_api import MetadataDirectiveMode -from b2sdk.transfer.transfer_manager import TransferManager -from b2sdk.utils.thread_pool import ThreadPoolMixin +from b2sdk._internal.encryption.setting import EncryptionMode, EncryptionSetting +from b2sdk._internal.exception import AlreadyFailed, CopyArgumentsMismatch, SSECKeyIdMismatchInCopy +from b2sdk._internal.file_lock import FileRetentionSetting, LegalHold +from b2sdk._internal.http_constants import SSE_C_KEY_ID_FILE_INFO_KEY_NAME +from b2sdk._internal.progress import AbstractProgressListener +from b2sdk._internal.raw_api import MetadataDirectiveMode +from b2sdk._internal.transfer.transfer_manager import TransferManager +from b2sdk._internal.utils.thread_pool import ThreadPoolMixin logger = logging.getLogger(__name__) diff --git a/b2sdk/transfer/outbound/copy_source.py b/b2sdk/_internal/transfer/outbound/copy_source.py similarity index 91% rename from b2sdk/transfer/outbound/copy_source.py rename to b2sdk/_internal/transfer/outbound/copy_source.py index 0c66f89d9..9bf960c36 100644 --- a/b2sdk/transfer/outbound/copy_source.py +++ b/b2sdk/_internal/transfer/outbound/copy_source.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/transfer/outbound/copy_source.py +# File: b2sdk/_internal/transfer/outbound/copy_source.py # # Copyright 2020 Backblaze Inc. All Rights Reserved. # @@ -9,9 +9,9 @@ ###################################################################### from __future__ import annotations -from b2sdk.encryption.setting import EncryptionSetting -from b2sdk.http_constants import LARGE_FILE_SHA1 -from b2sdk.transfer.outbound.outbound_source import OutboundTransferSource +from b2sdk._internal.encryption.setting import EncryptionSetting +from b2sdk._internal.http_constants import LARGE_FILE_SHA1 +from b2sdk._internal.transfer.outbound.outbound_source import OutboundTransferSource class CopySource(OutboundTransferSource): diff --git a/b2sdk/transfer/outbound/large_file_upload_state.py b/b2sdk/_internal/transfer/outbound/large_file_upload_state.py similarity index 96% rename from b2sdk/transfer/outbound/large_file_upload_state.py rename to b2sdk/_internal/transfer/outbound/large_file_upload_state.py index 018434619..8c19b8014 100644 --- a/b2sdk/transfer/outbound/large_file_upload_state.py +++ b/b2sdk/_internal/transfer/outbound/large_file_upload_state.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/transfer/outbound/large_file_upload_state.py +# File: b2sdk/_internal/transfer/outbound/large_file_upload_state.py # # Copyright 2020 Backblaze Inc. All Rights Reserved. # diff --git a/b2sdk/transfer/outbound/outbound_source.py b/b2sdk/_internal/transfer/outbound/outbound_source.py similarity index 93% rename from b2sdk/transfer/outbound/outbound_source.py rename to b2sdk/_internal/transfer/outbound/outbound_source.py index ef69e9a11..bf4b5573d 100644 --- a/b2sdk/transfer/outbound/outbound_source.py +++ b/b2sdk/_internal/transfer/outbound/outbound_source.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/transfer/outbound/outbound_source.py +# File: b2sdk/_internal/transfer/outbound/outbound_source.py # # Copyright 2020 Backblaze Inc. All Rights Reserved. # @@ -11,7 +11,7 @@ from abc import ABCMeta, abstractmethod -from b2sdk.utils import Sha1HexDigest +from b2sdk._internal.utils import Sha1HexDigest class OutboundTransferSource(metaclass=ABCMeta): diff --git a/b2sdk/transfer/outbound/progress_reporter.py b/b2sdk/_internal/transfer/outbound/progress_reporter.py similarity index 66% rename from b2sdk/transfer/outbound/progress_reporter.py rename to b2sdk/_internal/transfer/outbound/progress_reporter.py index 0c12bdf02..9aacc8b03 100644 --- a/b2sdk/transfer/outbound/progress_reporter.py +++ b/b2sdk/_internal/transfer/outbound/progress_reporter.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/transfer/outbound/progress_reporter.py +# File: b2sdk/_internal/transfer/outbound/progress_reporter.py # # Copyright 2020 Backblaze Inc. All Rights Reserved. # @@ -9,23 +9,23 @@ ###################################################################### from __future__ import annotations -from b2sdk.progress import AbstractProgressListener +from b2sdk._internal.progress import AbstractProgressListener class PartProgressReporter(AbstractProgressListener): """ An adapter that listens to the progress of upload a part and - gives the information to a :py:class:`b2sdk.bucket.LargeFileUploadState`. + gives the information to a :py:class:`b2sdk._internal.transfer.outbound.large_file_upload_state.LargeFileUploadState`. Accepts absolute bytes_completed from the uploader, and reports - deltas to the :py:class:`b2sdk.bucket.LargeFileUploadState`. The bytes_completed for the + deltas to the :py:class:`b2sdk._internal.transfer.outbound.large_file_upload_state.LargeFileUploadState`. The bytes_completed for the part will drop back to 0 on a retry, which will result in a negative delta. """ def __init__(self, large_file_upload_state, *args, **kwargs): """ - :param b2sdk.bucket.LargeFileUploadState large_file_upload_state: object to relay the progress to + :param b2sdk._internal.transfer.outbound.large_file_upload_state.LargeFileUploadState large_file_upload_state: object to relay the progress to """ super().__init__(*args, **kwargs) self.large_file_upload_state = large_file_upload_state diff --git a/b2sdk/transfer/outbound/upload_manager.py b/b2sdk/_internal/transfer/outbound/upload_manager.py similarity index 94% rename from b2sdk/transfer/outbound/upload_manager.py rename to b2sdk/_internal/transfer/outbound/upload_manager.py index 617bf29c1..1005634e5 100644 --- a/b2sdk/transfer/outbound/upload_manager.py +++ b/b2sdk/_internal/transfer/outbound/upload_manager.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/transfer/outbound/upload_manager.py +# File: b2sdk/_internal/transfer/outbound/upload_manager.py # # Copyright 2020 Backblaze Inc. All Rights Reserved. # @@ -13,16 +13,16 @@ from contextlib import ExitStack from typing import TYPE_CHECKING, TypeVar -from b2sdk.encryption.setting import EncryptionMode, EncryptionSetting -from b2sdk.exception import ( +from b2sdk._internal.encryption.setting import EncryptionMode, EncryptionSetting +from b2sdk._internal.exception import ( AlreadyFailed, B2Error, MaxRetriesExceeded, ) -from b2sdk.file_lock import FileRetentionSetting, LegalHold -from b2sdk.http_constants import HEX_DIGITS_AT_END -from b2sdk.stream.hashing import StreamWithHash -from b2sdk.stream.progress import ReadingStreamWithProgress +from b2sdk._internal.file_lock import FileRetentionSetting, LegalHold +from b2sdk._internal.http_constants import HEX_DIGITS_AT_END +from b2sdk._internal.stream.hashing import StreamWithHash +from b2sdk._internal.stream.progress import ReadingStreamWithProgress from ...utils.thread_pool import ThreadPoolMixin from ..transfer_manager import TransferManager @@ -31,7 +31,7 @@ logger = logging.getLogger(__name__) if TYPE_CHECKING: - from b2sdk.transfer.outbound.upload_source import AbstractUploadSource + from b2sdk._internal.transfer.outbound.upload_source import AbstractUploadSource _TypeUploadSource = TypeVar("_TypeUploadSource", bound=AbstractUploadSource) diff --git a/b2sdk/transfer/outbound/upload_source.py b/b2sdk/_internal/transfer/outbound/upload_source.py similarity index 96% rename from b2sdk/transfer/outbound/upload_source.py rename to b2sdk/_internal/transfer/outbound/upload_source.py index 2510d37ab..c10a38fb1 100644 --- a/b2sdk/transfer/outbound/upload_source.py +++ b/b2sdk/_internal/transfer/outbound/upload_source.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/transfer/outbound/upload_source.py +# File: b2sdk/_internal/transfer/outbound/upload_source.py # # Copyright 2020 Backblaze Inc. All Rights Reserved. # @@ -17,13 +17,13 @@ from enum import Enum, auto, unique from typing import Callable -from b2sdk.exception import InvalidUploadSource -from b2sdk.file_version import BaseFileVersion -from b2sdk.http_constants import DEFAULT_MIN_PART_SIZE -from b2sdk.stream.range import RangeOfInputStream, wrap_with_range -from b2sdk.transfer.outbound.copy_source import CopySource -from b2sdk.transfer.outbound.outbound_source import OutboundTransferSource -from b2sdk.utils import ( +from b2sdk._internal.exception import InvalidUploadSource +from b2sdk._internal.file_version import BaseFileVersion +from b2sdk._internal.http_constants import DEFAULT_MIN_PART_SIZE +from b2sdk._internal.stream.range import RangeOfInputStream, wrap_with_range +from b2sdk._internal.transfer.outbound.copy_source import CopySource +from b2sdk._internal.transfer.outbound.outbound_source import OutboundTransferSource +from b2sdk._internal.utils import ( IncrementalHexDigester, Sha1HexDigest, hex_sha1_of_stream, diff --git a/b2sdk/transfer/transfer_manager.py b/b2sdk/_internal/transfer/transfer_manager.py similarity index 90% rename from b2sdk/transfer/transfer_manager.py rename to b2sdk/_internal/transfer/transfer_manager.py index 67199dc8f..6067af839 100644 --- a/b2sdk/transfer/transfer_manager.py +++ b/b2sdk/_internal/transfer/transfer_manager.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/transfer/transfer_manager.py +# File: b2sdk/_internal/transfer/transfer_manager.py # # Copyright 2022 Backblaze Inc. All Rights Reserved. # diff --git a/b2sdk/_internal/utils/__init__.py b/b2sdk/_internal/utils/__init__.py index e87ebe6e6..5fd7dd41c 100644 --- a/b2sdk/_internal/utils/__init__.py +++ b/b2sdk/_internal/utils/__init__.py @@ -2,8 +2,514 @@ # # File: b2sdk/_internal/utils/__init__.py # -# Copyright 2023 Backblaze Inc. All Rights Reserved. +# Copyright 2022 Backblaze Inc. All Rights Reserved. # # License https://www.backblaze.com/using_b2_code.html # ###################################################################### +from __future__ import annotations + +import base64 +import hashlib +import logging +import os +import pathlib +import platform +import re +import time +from dataclasses import dataclass, field +from decimal import Decimal +from itertools import chain +from typing import Any, Iterator, NewType, TypeVar +from urllib.parse import quote, unquote_plus + +from logfury.v1 import DefaultTraceAbstractMeta, DefaultTraceMeta, limit_trace_arguments, disable_trace, trace_call + +logger = logging.getLogger(__name__) + +Sha1HexDigest = NewType('Sha1HexDigest', str) +T = TypeVar('T') +# TODO: When we drop Python 3.7 support, this should be replaced +# with typing.Protocol that exposes read method. +ReadOnlyStream = Any + + +def b2_url_encode(s): + """ + URL-encode a unicode string to be sent to B2 in an HTTP header. + + :param s: a unicode string to encode + :type s: str + :return: URL-encoded string + :rtype: str + """ + return quote(s.encode('utf-8')) + + +def b2_url_decode(s): + """ + Decode a Unicode string returned from B2 in an HTTP header. + + :param s: a unicode string to decode + :type s: str + :return: a Python unicode string. + :rtype: str + """ + return unquote_plus(s) + + +def choose_part_ranges(content_length, minimum_part_size): + """ + Return a list of (offset, length) for the parts of a large file. + + :param content_length: content length value + :type content_length: int + :param minimum_part_size: a minimum file part size + :type minimum_part_size: int + :rtype: list + """ + + # If the file is at least twice the minimum part size, we are guaranteed + # to be able to break it into multiple parts that are all at least + # the minimum part size. + assert minimum_part_size * 2 <= content_length + + # How many parts can we make? + part_count = min(content_length // minimum_part_size, 10000) + assert 2 <= part_count + + # All of the parts, except the last, are the same size. The + # last one may be bigger. + part_size = content_length // part_count + last_part_size = content_length - (part_size * (part_count - 1)) + assert minimum_part_size <= last_part_size + + # Make all of the parts except the last + parts = [(i * part_size, part_size) for i in range(part_count - 1)] + + # Add the last part + start_of_last = (part_count - 1) * part_size + last_part = (start_of_last, content_length - start_of_last) + parts.append(last_part) + + return parts + + +def update_digest_from_stream(digest: T, input_stream: ReadOnlyStream, content_length: int) -> T: + """ + Update and return `digest` with data read from `input_stream` + + :param digest: a digest object, which exposes an `update(bytes)` method + :param input_stream: stream object, which exposes a `read(int|None)` method + :param content_length: expected length of the stream + :type content_length: int + """ + remaining = content_length + block_size = 1024 * 1024 + while remaining != 0: + to_read = min(remaining, block_size) + data = input_stream.read(to_read) + if len(data) != to_read: + raise ValueError( + 'content_length(%s) is more than the size of the file' % content_length + ) + digest.update(data) + remaining -= to_read + return digest + + +def hex_sha1_of_stream(input_stream: ReadOnlyStream, content_length: int) -> Sha1HexDigest: + """ + Return the 40-character hex SHA1 checksum of the first content_length + bytes in the input stream. + + :param input_stream: stream object, which exposes read(int|None) method + :param content_length: expected length of the stream + :type content_length: int + :rtype: str + """ + return Sha1HexDigest( + update_digest_from_stream( + hashlib.sha1(), + input_stream, + content_length, + ).hexdigest() + ) + + +@dataclass +class IncrementalHexDigester: + """ + Calculates digest of a stream or parts of it. + """ + stream: ReadOnlyStream + digest: 'hashlib._Hash' = field( # noqa (_Hash is a dynamic object) + default_factory=hashlib.sha1 + ) + read_bytes: int = 0 + block_size: int = 1024 * 1024 + + @property + def hex_digest(self) -> Sha1HexDigest: + return Sha1HexDigest(self.digest.hexdigest()) + + def update_from_stream( + self, + limit: int | None = None, + ) -> Sha1HexDigest: + """ + :param limit: How many new bytes try to read from the stream. Default None – read until nothing left. + """ + offset = 0 + + while True: + if limit is not None: + to_read = min(limit - offset, self.block_size) + else: + to_read = self.block_size + data = self.stream.read(to_read) + data_len = len(data) + if data_len > 0: + self.digest.update(data) + self.read_bytes += data_len + offset += data_len + if data_len < to_read or to_read == 0: + break + + return self.hex_digest + + +def hex_sha1_of_unlimited_stream( + input_stream: ReadOnlyStream, + limit: int | None = None, +) -> tuple[Sha1HexDigest, int]: + digester = IncrementalHexDigester(input_stream) + digester.update_from_stream(limit) + return digester.hex_digest, digester.read_bytes + + +def hex_sha1_of_file(path_) -> Sha1HexDigest: + with open(path_, 'rb') as file: + return hex_sha1_of_unlimited_stream(file)[0] + + +def hex_sha1_of_bytes(data: bytes) -> Sha1HexDigest: + """ + Return the 40-character hex SHA1 checksum of the data. + """ + return Sha1HexDigest(hashlib.sha1(data).hexdigest()) + + +def hex_md5_of_bytes(data: bytes) -> str: + """ + Return the 32-character hex MD5 checksum of the data. + """ + return hashlib.md5(data).hexdigest() + + +def md5_of_bytes(data: bytes) -> bytes: + """ + Return the 16-byte MD5 checksum of the data. + """ + return hashlib.md5(data).digest() + + +def b64_of_bytes(data: bytes) -> str: + """ + Return the base64 encoded represtantion of the data. + """ + return base64.b64encode(data).decode() + + +def validate_b2_file_name(name): + """ + Raise a ValueError if the name is not a valid B2 file name. + + :param name: a string to check + :type name: str + """ + if not isinstance(name, str): + raise ValueError('file name must be a string, not bytes') + name_utf8 = name.encode('utf-8') + if len(name_utf8) < 1: + raise ValueError('file name too short (0 utf-8 bytes)') + if 1000 < len(name_utf8): + raise ValueError('file name too long (more than 1000 utf-8 bytes)') + if name[0] == '/': + raise ValueError("file names must not start with '/'") + if name[-1] == '/': + raise ValueError("file names must not end with '/'") + if '\\' in name: + raise ValueError("file names must not contain '\\'") + if '//' in name: + raise ValueError("file names must not contain '//'") + if chr(127) in name: + raise ValueError("file names must not contain DEL") + if any(250 < len(segment) for segment in name_utf8.split(b'/')): + raise ValueError("file names segments (between '/') can be at most 250 utf-8 bytes") + + +def is_file_readable(local_path, reporter=None): + """ + Check if the local file has read permissions. + + :param local_path: a file path + :type local_path: str + :param reporter: reporter object to put errors on + :rtype: bool + """ + if not os.path.exists(local_path): + if reporter is not None: + reporter.local_access_error(local_path) + return False + elif not os.access(local_path, os.R_OK): + if reporter is not None: + reporter.local_permission_error(local_path) + return False + return True + + +def get_file_mtime(local_path): + """ + Get modification time of a file in milliseconds. + + :param local_path: a file path + :type local_path: str + :rtype: int + """ + mod_time = os.path.getmtime(local_path) * 1000 + return int(mod_time) + + +def is_special_file(path: str | pathlib.Path) -> bool: + """ + Is the path a special file, such as /dev/null or stdout? + + :param path: a "file" path + :return: True if the path is a special file + """ + path_str = str(path) + return ( + path == os.devnull or path_str.startswith('/dev/') or + platform.system() == 'Windows' and path_str.upper() in ('CON', 'NUL') + ) + + +def set_file_mtime(local_path: str | pathlib.Path, mod_time_millis: int) -> None: + """ + Set modification time of a file in milliseconds. + + :param local_path: a file path + :param mod_time_millis: time to be set + """ + mod_time = mod_time_millis / 1000.0 + + # We have to convert it this way to avoid differences when mtime + # is read from the local file in the next iterations, and time is fetched + # without rounding. + # This is caused by floating point arithmetic as POSIX systems + # represents mtime as floats and B2 as integers. + # E.g. for 1093258377393, it would be converted to 1093258377.393 + # which is actually represented by 1093258377.3929998874664306640625. + # When we save mtime and read it again, we will end up with 1093258377392. + # See #617 for details. + mod_time = float(Decimal('%.3f5' % mod_time)) + + try: + os.utime(local_path, (mod_time, mod_time)) + except OSError: + if not is_special_file(local_path): + raise + + +def fix_windows_path_limit(path): + """ + Prefix paths when running on Windows to overcome 260 character path length limit. + See https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx#maxpath + + :param path: a path to prefix + :type path: str + :return: a prefixed path + :rtype: str + """ + if platform.system() == 'Windows': + if path.startswith('\\\\'): + # UNC network path + return '\\\\?\\UNC\\' + path[2:] + elif os.path.isabs(path): + # local absolute path + return '\\\\?\\' + path + else: + # relative path, don't alter + return path + else: + return path + + +def _pick_scale_and_suffix(x): + # suffixes for different scales + suffixes = ' kMGTP' + + # We want to use the biggest suffix that makes sense. + ref_digits = str(int(x)) + index = (len(ref_digits) - 1) // 3 + suffix = suffixes[index] + if suffix == ' ': + suffix = '' + + scale = 1000**index + return (scale, suffix) + + +def format_and_scale_number(x, unit): + """ + Pick a good scale for representing a number and format it. + + :param x: a number + :type x: int + :param unit: an arbitrary unit name + :type unit: str + :return: scaled and formatted number + :rtype: str + """ + + # simple case for small numbers + if x < 1000: + return '%d %s' % (x, unit) + + # pick a scale + (scale, suffix) = _pick_scale_and_suffix(x) + + # decide how many digits after the decimal to display + scaled = x / scale + if scaled < 10.0: + fmt = '%1.2f %s%s' + elif scaled < 100.0: + fmt = '%1.1f %s%s' + else: + fmt = '%1.0f %s%s' + + # format it + return fmt % (scaled, suffix, unit) + + +def format_and_scale_fraction(numerator, denominator, unit): + """ + Pick a good scale for representing a fraction, and format it. + + :param numerator: a numerator of a fraction + :type numerator: int + :param denominator: a denominator of a fraction + :type denominator: int + :param unit: an arbitrary unit name + :type unit: str + :return: scaled and formatted fraction + :rtype: str + """ + + # simple case for small numbers + if denominator < 1000: + return '%d / %d %s' % (numerator, denominator, unit) + + # pick a scale + (scale, suffix) = _pick_scale_and_suffix(denominator) + + # decide how many digits after the decimal to display + scaled_denominator = denominator / scale + if scaled_denominator < 10.0: + fmt = '%1.2f / %1.2f %s%s' + elif scaled_denominator < 100.0: + fmt = '%1.1f / %1.1f %s%s' + else: + fmt = '%1.0f / %1.0f %s%s' + + # format it + scaled_numerator = numerator / scale + return fmt % (scaled_numerator, scaled_denominator, suffix, unit) + + +_CAMELCASE_TO_UNDERSCORE_RE = re.compile('((?<=[a-z0-9])[A-Z]|(?!^)[A-Z](?=[a-z]))') + + +def camelcase_to_underscore(input_): + """ + Convert a camel-cased string to a string with underscores. + + :param input_: an input string + :type input_: str + :return: string with underscores + :rtype: str + """ + return _CAMELCASE_TO_UNDERSCORE_RE.sub(r'_\1', input_).lower() + + +class B2TraceMeta(DefaultTraceMeta): + """ + Trace all public method calls, except for ones with names that begin with `get_`. + """ + pass + + +class B2TraceMetaAbstract(DefaultTraceAbstractMeta): + """ + Default class for tracers, to be set as + a metaclass for abstract base classes. + """ + pass + + +class ConcurrentUsedAuthTokenGuard: + """ + Context manager preventing two tokens being used simultaneously. + Throws UploadTokenUsedConcurrently when unable to acquire a lock + Sample usage: + + with ConcurrentUsedAuthTokenGuard(lock_for_token, token): + # code that uses the token exclusively + """ + + def __init__(self, lock, token): + self.lock = lock + self.token = token + + def __enter__(self): + if not self.lock.acquire(False): + from b2sdk._internal.exception import UploadTokenUsedConcurrently + raise UploadTokenUsedConcurrently(self.token) + + def __exit__(self, exc_type, exc_val, exc_tb): + try: + self.lock.release() + except RuntimeError: + # guard against releasing a non-acquired lock + pass + + +def current_time_millis(): + """ + File times are in integer milliseconds, to avoid roundoff errors. + """ + return int(round(time.time() * 1000)) + + +def iterator_peek(iterator: Iterator[T], count: int) -> tuple[list[T], Iterator[T]]: + """ + Get up to the `count` first elements yielded by `iterator`. + + The function will read `count` elements from `iterator` or less if the end is reached first. Returns a tuple + consisting of a list of retrieved elements and an iterator equivalent to the input iterator. + """ + + ret = [] + for _ in range(count): + try: + ret.append(next(iterator)) + except StopIteration: + break + + return ret, chain(ret, iterator) + + +assert disable_trace +assert limit_trace_arguments +assert trace_call diff --git a/b2sdk/utils/docs.py b/b2sdk/_internal/utils/docs.py similarity index 97% rename from b2sdk/utils/docs.py rename to b2sdk/_internal/utils/docs.py index 8e31217ad..d860d2eb4 100644 --- a/b2sdk/utils/docs.py +++ b/b2sdk/_internal/utils/docs.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/utils/docs.py +# File: b2sdk/_internal/utils/docs.py # # Copyright 2023 Backblaze Inc. All Rights Reserved. # diff --git a/b2sdk/utils/escape.py b/b2sdk/_internal/utils/escape.py similarity index 97% rename from b2sdk/utils/escape.py rename to b2sdk/_internal/utils/escape.py index 2f3a73ef3..b8280f29d 100644 --- a/b2sdk/utils/escape.py +++ b/b2sdk/_internal/utils/escape.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/utils/escape.py +# File: b2sdk/_internal/utils/escape.py # # Copyright 2023 Backblaze Inc. All Rights Reserved. # diff --git a/b2sdk/utils/http_date.py b/b2sdk/_internal/utils/http_date.py similarity index 96% rename from b2sdk/utils/http_date.py rename to b2sdk/_internal/utils/http_date.py index 64913f09e..96558780f 100644 --- a/b2sdk/utils/http_date.py +++ b/b2sdk/_internal/utils/http_date.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/utils/http_date.py +# File: b2sdk/_internal/utils/http_date.py # # Copyright 2019 Backblaze Inc. All Rights Reserved. # diff --git a/b2sdk/utils/range_.py b/b2sdk/_internal/utils/range_.py similarity index 97% rename from b2sdk/utils/range_.py rename to b2sdk/_internal/utils/range_.py index 3e3cfb680..65a355cd1 100644 --- a/b2sdk/utils/range_.py +++ b/b2sdk/_internal/utils/range_.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/utils/range_.py +# File: b2sdk/_internal/utils/range_.py # # Copyright 2020 Backblaze Inc. All Rights Reserved. # diff --git a/b2sdk/utils/thread_pool.py b/b2sdk/_internal/utils/thread_pool.py similarity index 97% rename from b2sdk/utils/thread_pool.py rename to b2sdk/_internal/utils/thread_pool.py index b9a190c89..d169eb7de 100644 --- a/b2sdk/utils/thread_pool.py +++ b/b2sdk/_internal/utils/thread_pool.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/utils/thread_pool.py +# File: b2sdk/_internal/utils/thread_pool.py # # Copyright 2022 Backblaze Inc. All Rights Reserved. # @@ -18,7 +18,7 @@ except ImportError: from typing import Protocol -from b2sdk.utils import B2TraceMetaAbstract +from b2sdk._internal.utils import B2TraceMetaAbstract class DynamicThreadPoolExecutorProtocol(Protocol): diff --git a/b2sdk/utils/typing.py b/b2sdk/_internal/utils/typing.py similarity index 92% rename from b2sdk/utils/typing.py rename to b2sdk/_internal/utils/typing.py index b34e53b86..252cb95a9 100644 --- a/b2sdk/utils/typing.py +++ b/b2sdk/_internal/utils/typing.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/utils/typing.py +# File: b2sdk/_internal/utils/typing.py # # Copyright 2023 Backblaze Inc. All Rights Reserved. # diff --git a/b2sdk/version_utils.py b/b2sdk/_internal/version_utils.py similarity index 84% rename from b2sdk/version_utils.py rename to b2sdk/_internal/version_utils.py index b67a0d06a..2147a3562 100644 --- a/b2sdk/version_utils.py +++ b/b2sdk/_internal/version_utils.py @@ -1,6 +1,6 @@ ###################################################################### # -# File: b2sdk/version_utils.py +# File: b2sdk/_internal/version_utils.py # # Copyright 2019 Backblaze Inc. All Rights Reserved. # @@ -10,15 +10,44 @@ from __future__ import annotations import inspect +import re import warnings from abc import ABCMeta, abstractmethod -from functools import wraps - -from packaging.version import parse +from functools import total_ordering, wraps from b2sdk.version import VERSION +@total_ordering +class _Version: + """ + Rudimentary semver version parser. + + It uses VERY naive parsing which is only supposed to produce a tuple, able to + compare major.minor.patch versions. + It does not support PEP 440 epoch, pre-releases, post-releases, local versions, etc. + """ + + def __init__(self, version: str): + self._raw = version + self._parsed = self._parse_version(version) + + def __str__(self): + return self._raw + + def __eq__(self, other): + return self._parsed == other._parsed + + def __lt__(self, other): + return self._parsed < other._parsed + + @classmethod + def _parse_version(cls, version: str) -> tuple[int, ...]: + if "!" in version: # strip PEP 440 epoch + version = version.split("!", 1)[1] + return tuple(map(int, re.findall(r'\d+', version))) + + class AbstractVersionDecorator(metaclass=ABCMeta): WHAT = NotImplemented # 'function', 'method', 'class' etc @@ -28,7 +57,7 @@ def __init__(self, changed_version, cutoff_version=None, reason='', current_vers """ if current_version is None: # this is for tests only current_version = VERSION # TODO autodetect by going up the qualname tree and trying getattr(part, '__version__') - self.current_version = parse(current_version) #: current version + self.current_version = _Version(current_version) #: current version self.reason = reason self.changed_version = self._parse_if_not_none( @@ -42,7 +71,7 @@ def __init__(self, changed_version, cutoff_version=None, reason='', current_vers def _parse_if_not_none(cls, version): if version is None: return None - return parse(version) + return _Version(version) @abstractmethod def __call__(self, func): diff --git a/b2sdk/_v3/__init__.py b/b2sdk/_v3/__init__.py index 697ecbdef..51c388c0a 100644 --- a/b2sdk/_v3/__init__.py +++ b/b2sdk/_v3/__init__.py @@ -9,48 +9,61 @@ ###################################################################### from __future__ import annotations +# Set default logging handler to avoid "No handler found" warnings. +import logging as _logging + +_logging.getLogger("b2sdk").addHandler(_logging.NullHandler()) + + +class UrllibWarningFilter: + def filter(self, record): + return record.msg != "Connection pool is full, discarding connection: %s" + + +_logging.getLogger('urllib3.connectionpool').addFilter(UrllibWarningFilter()) + # this file maps the external interface into internal interface # it will come handy if we ever need to move something # core -from b2sdk.api import B2Api -from b2sdk.api import Services -from b2sdk.bucket import Bucket -from b2sdk.bucket import BucketFactory -from b2sdk.raw_api import ALL_CAPABILITIES, REALM_URLS +from b2sdk._internal.api import B2Api +from b2sdk._internal.api import Services +from b2sdk._internal.bucket import Bucket +from b2sdk._internal.bucket import BucketFactory +from b2sdk._internal.raw_api import ALL_CAPABILITIES, REALM_URLS # encryption -from b2sdk.encryption.setting import EncryptionSetting -from b2sdk.encryption.setting import EncryptionSettingFactory -from b2sdk.encryption.setting import EncryptionKey -from b2sdk.encryption.setting import SSE_NONE, SSE_B2_AES, UNKNOWN_KEY_ID -from b2sdk.encryption.types import EncryptionAlgorithm -from b2sdk.encryption.types import EncryptionMode -from b2sdk.http_constants import SSE_C_KEY_ID_FILE_INFO_KEY_NAME +from b2sdk._internal.encryption.setting import EncryptionSetting +from b2sdk._internal.encryption.setting import EncryptionSettingFactory +from b2sdk._internal.encryption.setting import EncryptionKey +from b2sdk._internal.encryption.setting import SSE_NONE, SSE_B2_AES, UNKNOWN_KEY_ID +from b2sdk._internal.encryption.types import EncryptionAlgorithm +from b2sdk._internal.encryption.types import EncryptionMode +from b2sdk._internal.http_constants import SSE_C_KEY_ID_FILE_INFO_KEY_NAME # account info -from b2sdk.account_info.abstract import AbstractAccountInfo -from b2sdk.account_info.in_memory import InMemoryAccountInfo -from b2sdk.account_info.sqlite_account_info import SqliteAccountInfo -from b2sdk.account_info.sqlite_account_info import B2_ACCOUNT_INFO_ENV_VAR -from b2sdk.account_info.sqlite_account_info import B2_ACCOUNT_INFO_DEFAULT_FILE -from b2sdk.account_info.sqlite_account_info import B2_ACCOUNT_INFO_PROFILE_FILE -from b2sdk.account_info.sqlite_account_info import XDG_CONFIG_HOME_ENV_VAR -from b2sdk.account_info.stub import StubAccountInfo -from b2sdk.account_info.upload_url_pool import UploadUrlPool -from b2sdk.account_info.upload_url_pool import UrlPoolAccountInfo +from b2sdk._internal.account_info.abstract import AbstractAccountInfo +from b2sdk._internal.account_info.in_memory import InMemoryAccountInfo +from b2sdk._internal.account_info.sqlite_account_info import SqliteAccountInfo +from b2sdk._internal.account_info.sqlite_account_info import B2_ACCOUNT_INFO_ENV_VAR +from b2sdk._internal.account_info.sqlite_account_info import B2_ACCOUNT_INFO_DEFAULT_FILE +from b2sdk._internal.account_info.sqlite_account_info import B2_ACCOUNT_INFO_PROFILE_FILE +from b2sdk._internal.account_info.sqlite_account_info import XDG_CONFIG_HOME_ENV_VAR +from b2sdk._internal.account_info.stub import StubAccountInfo +from b2sdk._internal.account_info.upload_url_pool import UploadUrlPool +from b2sdk._internal.account_info.upload_url_pool import UrlPoolAccountInfo # version & version utils from b2sdk.version import VERSION, USER_AGENT -from b2sdk.version_utils import rename_argument, rename_function +from b2sdk._internal.version_utils import rename_argument, rename_function # utils -from b2sdk.utils import ( +from b2sdk._internal.utils import ( b2_url_encode, b2_url_decode, choose_part_ranges, @@ -69,182 +82,182 @@ points_to_stdout, STDOUT_FILEPATH, ) -from b2sdk.utils import trace_call -from b2sdk.utils.docs import get_b2sdk_doc_urls +from b2sdk._internal.utils import trace_call +from b2sdk._internal.utils.docs import get_b2sdk_doc_urls # data classes -from b2sdk.application_key import ApplicationKey -from b2sdk.application_key import BaseApplicationKey -from b2sdk.application_key import FullApplicationKey -from b2sdk.file_version import DownloadVersion -from b2sdk.file_version import DownloadVersionFactory -from b2sdk.file_version import FileIdAndName -from b2sdk.file_version import FileVersion -from b2sdk.file_version import FileVersionFactory -from b2sdk.large_file.part import Part -from b2sdk.large_file.unfinished_large_file import UnfinishedLargeFile -from b2sdk.large_file.services import LargeFileServices -from b2sdk.utils.range_ import Range +from b2sdk._internal.application_key import ApplicationKey +from b2sdk._internal.application_key import BaseApplicationKey +from b2sdk._internal.application_key import FullApplicationKey +from b2sdk._internal.file_version import DownloadVersion +from b2sdk._internal.file_version import DownloadVersionFactory +from b2sdk._internal.file_version import FileIdAndName +from b2sdk._internal.file_version import FileVersion +from b2sdk._internal.file_version import FileVersionFactory +from b2sdk._internal.large_file.part import Part +from b2sdk._internal.large_file.unfinished_large_file import UnfinishedLargeFile +from b2sdk._internal.large_file.services import LargeFileServices +from b2sdk._internal.utils.range_ import Range # file lock -from b2sdk.file_lock import BucketRetentionSetting -from b2sdk.file_lock import FileLockConfiguration -from b2sdk.file_lock import FileRetentionSetting -from b2sdk.file_lock import LegalHold -from b2sdk.file_lock import NO_RETENTION_BUCKET_SETTING -from b2sdk.file_lock import NO_RETENTION_FILE_SETTING -from b2sdk.file_lock import RetentionMode -from b2sdk.file_lock import RetentionPeriod -from b2sdk.file_lock import UNKNOWN_BUCKET_RETENTION -from b2sdk.file_lock import UNKNOWN_FILE_LOCK_CONFIGURATION -from b2sdk.file_lock import UNKNOWN_FILE_RETENTION_SETTING +from b2sdk._internal.file_lock import BucketRetentionSetting +from b2sdk._internal.file_lock import FileLockConfiguration +from b2sdk._internal.file_lock import FileRetentionSetting +from b2sdk._internal.file_lock import LegalHold +from b2sdk._internal.file_lock import NO_RETENTION_BUCKET_SETTING +from b2sdk._internal.file_lock import NO_RETENTION_FILE_SETTING +from b2sdk._internal.file_lock import RetentionMode +from b2sdk._internal.file_lock import RetentionPeriod +from b2sdk._internal.file_lock import UNKNOWN_BUCKET_RETENTION +from b2sdk._internal.file_lock import UNKNOWN_FILE_LOCK_CONFIGURATION +from b2sdk._internal.file_lock import UNKNOWN_FILE_RETENTION_SETTING # progress reporting -from b2sdk.progress import AbstractProgressListener -from b2sdk.progress import DoNothingProgressListener -from b2sdk.progress import ProgressListenerForTest -from b2sdk.progress import SimpleProgressListener -from b2sdk.progress import TqdmProgressListener -from b2sdk.progress import make_progress_listener +from b2sdk._internal.progress import AbstractProgressListener +from b2sdk._internal.progress import DoNothingProgressListener +from b2sdk._internal.progress import ProgressListenerForTest +from b2sdk._internal.progress import SimpleProgressListener +from b2sdk._internal.progress import TqdmProgressListener +from b2sdk._internal.progress import make_progress_listener # raw_simulator -from b2sdk.raw_simulator import BucketSimulator -from b2sdk.raw_simulator import FakeResponse -from b2sdk.raw_simulator import FileSimulator -from b2sdk.raw_simulator import KeySimulator -from b2sdk.raw_simulator import PartSimulator -from b2sdk.raw_simulator import RawSimulator +from b2sdk._internal.raw_simulator import BucketSimulator +from b2sdk._internal.raw_simulator import FakeResponse +from b2sdk._internal.raw_simulator import FileSimulator +from b2sdk._internal.raw_simulator import KeySimulator +from b2sdk._internal.raw_simulator import PartSimulator +from b2sdk._internal.raw_simulator import RawSimulator # raw_api -from b2sdk.raw_api import AbstractRawApi -from b2sdk.raw_api import B2RawHTTPApi -from b2sdk.raw_api import MetadataDirectiveMode -from b2sdk.raw_api import LifecycleRule +from b2sdk._internal.raw_api import AbstractRawApi +from b2sdk._internal.raw_api import B2RawHTTPApi +from b2sdk._internal.raw_api import MetadataDirectiveMode +from b2sdk._internal.raw_api import LifecycleRule # stream -from b2sdk.stream.chained import StreamOpener -from b2sdk.stream.progress import AbstractStreamWithProgress -from b2sdk.stream import RangeOfInputStream -from b2sdk.stream import ReadingStreamWithProgress -from b2sdk.stream import StreamWithHash -from b2sdk.stream import WritingStreamWithProgress +from b2sdk._internal.stream.chained import StreamOpener +from b2sdk._internal.stream.progress import AbstractStreamWithProgress +from b2sdk._internal.stream import RangeOfInputStream +from b2sdk._internal.stream import ReadingStreamWithProgress +from b2sdk._internal.stream import StreamWithHash +from b2sdk._internal.stream import WritingStreamWithProgress # source / destination -from b2sdk.transfer.inbound.downloaded_file import DownloadedFile -from b2sdk.transfer.inbound.downloaded_file import MtimeUpdatedFile -from b2sdk.transfer.inbound.download_manager import DownloadManager +from b2sdk._internal.transfer.inbound.downloaded_file import DownloadedFile +from b2sdk._internal.transfer.inbound.downloaded_file import MtimeUpdatedFile +from b2sdk._internal.transfer.inbound.download_manager import DownloadManager -from b2sdk.transfer.outbound.outbound_source import OutboundTransferSource -from b2sdk.transfer.outbound.copy_source import CopySource -from b2sdk.transfer.outbound.upload_source import AbstractUploadSource -from b2sdk.transfer.outbound.upload_source import UploadSourceBytes -from b2sdk.transfer.outbound.upload_source import UploadSourceLocalFile -from b2sdk.transfer.outbound.upload_source import UploadSourceLocalFileRange -from b2sdk.transfer.outbound.upload_source import UploadSourceStream -from b2sdk.transfer.outbound.upload_source import UploadSourceStreamRange -from b2sdk.transfer.outbound.upload_manager import UploadManager +from b2sdk._internal.transfer.outbound.outbound_source import OutboundTransferSource +from b2sdk._internal.transfer.outbound.copy_source import CopySource +from b2sdk._internal.transfer.outbound.upload_source import AbstractUploadSource +from b2sdk._internal.transfer.outbound.upload_source import UploadSourceBytes +from b2sdk._internal.transfer.outbound.upload_source import UploadSourceLocalFile +from b2sdk._internal.transfer.outbound.upload_source import UploadSourceLocalFileRange +from b2sdk._internal.transfer.outbound.upload_source import UploadSourceStream +from b2sdk._internal.transfer.outbound.upload_source import UploadSourceStreamRange +from b2sdk._internal.transfer.outbound.upload_manager import UploadManager -from b2sdk.transfer.emerge.planner.upload_subpart import CachedBytesStreamOpener -from b2sdk.transfer.emerge.write_intent import WriteIntent +from b2sdk._internal.transfer.emerge.planner.upload_subpart import CachedBytesStreamOpener +from b2sdk._internal.transfer.emerge.write_intent import WriteIntent # transfer -from b2sdk.transfer.inbound.downloader.abstract import AbstractDownloader -from b2sdk.transfer.outbound.large_file_upload_state import LargeFileUploadState -from b2sdk.transfer.inbound.downloader.parallel import ParallelDownloader -from b2sdk.transfer.inbound.downloader.parallel import PartToDownload -from b2sdk.transfer.inbound.downloader.parallel import WriterThread -from b2sdk.transfer.outbound.progress_reporter import PartProgressReporter -from b2sdk.transfer.inbound.downloader.simple import SimpleDownloader +from b2sdk._internal.transfer.inbound.downloader.abstract import AbstractDownloader +from b2sdk._internal.transfer.outbound.large_file_upload_state import LargeFileUploadState +from b2sdk._internal.transfer.inbound.downloader.parallel import ParallelDownloader +from b2sdk._internal.transfer.inbound.downloader.parallel import PartToDownload +from b2sdk._internal.transfer.inbound.downloader.parallel import WriterThread +from b2sdk._internal.transfer.outbound.progress_reporter import PartProgressReporter +from b2sdk._internal.transfer.inbound.downloader.simple import SimpleDownloader # sync -from b2sdk.sync.action import AbstractAction -from b2sdk.sync.action import B2CopyAction -from b2sdk.sync.action import B2DeleteAction -from b2sdk.sync.action import B2DownloadAction -from b2sdk.sync.action import B2HideAction -from b2sdk.sync.action import B2UploadAction -from b2sdk.sync.action import LocalDeleteAction -from b2sdk.sync.exception import IncompleteSync -from b2sdk.sync.policy import AbstractFileSyncPolicy -from b2sdk.sync.policy import CompareVersionMode -from b2sdk.sync.policy import NewerFileSyncMode -from b2sdk.sync.policy import DownAndDeletePolicy -from b2sdk.sync.policy import DownAndKeepDaysPolicy -from b2sdk.sync.policy import DownPolicy -from b2sdk.sync.policy import CopyPolicy -from b2sdk.sync.policy import CopyAndDeletePolicy -from b2sdk.sync.policy import CopyAndKeepDaysPolicy -from b2sdk.sync.policy import UpAndDeletePolicy -from b2sdk.sync.policy import UpAndKeepDaysPolicy -from b2sdk.sync.policy import UpPolicy -from b2sdk.sync.policy import make_b2_keep_days_actions -from b2sdk.sync.policy_manager import SyncPolicyManager -from b2sdk.sync.policy_manager import POLICY_MANAGER -from b2sdk.sync.report import SyncFileReporter -from b2sdk.sync.report import SyncReport -from b2sdk.sync.sync import KeepOrDeleteMode -from b2sdk.sync.sync import Synchronizer -from b2sdk.sync.sync import UploadMode -from b2sdk.sync.encryption_provider import AbstractSyncEncryptionSettingsProvider -from b2sdk.sync.encryption_provider import BasicSyncEncryptionSettingsProvider -from b2sdk.sync.encryption_provider import ServerDefaultSyncEncryptionSettingsProvider -from b2sdk.sync.encryption_provider import SERVER_DEFAULT_SYNC_ENCRYPTION_SETTINGS_PROVIDER +from b2sdk._internal.sync.action import AbstractAction +from b2sdk._internal.sync.action import B2CopyAction +from b2sdk._internal.sync.action import B2DeleteAction +from b2sdk._internal.sync.action import B2DownloadAction +from b2sdk._internal.sync.action import B2HideAction +from b2sdk._internal.sync.action import B2UploadAction +from b2sdk._internal.sync.action import LocalDeleteAction +from b2sdk._internal.sync.exception import IncompleteSync +from b2sdk._internal.sync.policy import AbstractFileSyncPolicy +from b2sdk._internal.sync.policy import CompareVersionMode +from b2sdk._internal.sync.policy import NewerFileSyncMode +from b2sdk._internal.sync.policy import DownAndDeletePolicy +from b2sdk._internal.sync.policy import DownAndKeepDaysPolicy +from b2sdk._internal.sync.policy import DownPolicy +from b2sdk._internal.sync.policy import CopyPolicy +from b2sdk._internal.sync.policy import CopyAndDeletePolicy +from b2sdk._internal.sync.policy import CopyAndKeepDaysPolicy +from b2sdk._internal.sync.policy import UpAndDeletePolicy +from b2sdk._internal.sync.policy import UpAndKeepDaysPolicy +from b2sdk._internal.sync.policy import UpPolicy +from b2sdk._internal.sync.policy import make_b2_keep_days_actions +from b2sdk._internal.sync.policy_manager import SyncPolicyManager +from b2sdk._internal.sync.policy_manager import POLICY_MANAGER +from b2sdk._internal.sync.report import SyncFileReporter +from b2sdk._internal.sync.report import SyncReport +from b2sdk._internal.sync.sync import KeepOrDeleteMode +from b2sdk._internal.sync.sync import Synchronizer +from b2sdk._internal.sync.sync import UploadMode +from b2sdk._internal.sync.encryption_provider import AbstractSyncEncryptionSettingsProvider +from b2sdk._internal.sync.encryption_provider import BasicSyncEncryptionSettingsProvider +from b2sdk._internal.sync.encryption_provider import ServerDefaultSyncEncryptionSettingsProvider +from b2sdk._internal.sync.encryption_provider import SERVER_DEFAULT_SYNC_ENCRYPTION_SETTINGS_PROVIDER # scan -from b2sdk.scan.exception import EnvironmentEncodingError -from b2sdk.scan.exception import InvalidArgument -from b2sdk.scan.folder import AbstractFolder -from b2sdk.scan.folder import B2Folder -from b2sdk.scan.folder import LocalFolder -from b2sdk.scan.folder_parser import parse_folder -from b2sdk.scan.path import AbstractPath, B2Path, LocalPath -from b2sdk.scan.policies import convert_dir_regex_to_dir_prefix_regex -from b2sdk.scan.policies import DEFAULT_SCAN_MANAGER -from b2sdk.scan.policies import IntegerRange -from b2sdk.scan.policies import RegexSet -from b2sdk.scan.policies import ScanPoliciesManager -from b2sdk.scan.report import ProgressReport -from b2sdk.scan.scan import zip_folders -from b2sdk.scan.scan import AbstractScanResult -from b2sdk.scan.scan import AbstractScanReport -from b2sdk.scan.scan import CountAndSampleScanReport +from b2sdk._internal.scan.exception import EnvironmentEncodingError +from b2sdk._internal.scan.exception import InvalidArgument +from b2sdk._internal.scan.folder import AbstractFolder +from b2sdk._internal.scan.folder import B2Folder +from b2sdk._internal.scan.folder import LocalFolder +from b2sdk._internal.scan.folder_parser import parse_folder +from b2sdk._internal.scan.path import AbstractPath, B2Path, LocalPath +from b2sdk._internal.scan.policies import convert_dir_regex_to_dir_prefix_regex +from b2sdk._internal.scan.policies import DEFAULT_SCAN_MANAGER +from b2sdk._internal.scan.policies import IntegerRange +from b2sdk._internal.scan.policies import RegexSet +from b2sdk._internal.scan.policies import ScanPoliciesManager +from b2sdk._internal.scan.report import ProgressReport +from b2sdk._internal.scan.scan import zip_folders +from b2sdk._internal.scan.scan import AbstractScanResult +from b2sdk._internal.scan.scan import AbstractScanReport +from b2sdk._internal.scan.scan import CountAndSampleScanReport # replication -from b2sdk.replication.setting import ReplicationConfigurationFactory -from b2sdk.replication.setting import ReplicationConfiguration -from b2sdk.replication.setting import ReplicationRule -from b2sdk.replication.types import ReplicationStatus -from b2sdk.replication.setup import ReplicationSetupHelper -from b2sdk.replication.monitoring import ReplicationScanResult -from b2sdk.replication.monitoring import ReplicationReport -from b2sdk.replication.monitoring import ReplicationMonitor +from b2sdk._internal.replication.setting import ReplicationConfigurationFactory +from b2sdk._internal.replication.setting import ReplicationConfiguration +from b2sdk._internal.replication.setting import ReplicationRule +from b2sdk._internal.replication.types import ReplicationStatus +from b2sdk._internal.replication.setup import ReplicationSetupHelper +from b2sdk._internal.replication.monitoring import ReplicationScanResult +from b2sdk._internal.replication.monitoring import ReplicationReport +from b2sdk._internal.replication.monitoring import ReplicationMonitor # other -from b2sdk.included_sources import get_included_sources -from b2sdk.b2http import B2Http -from b2sdk.api_config import B2HttpApiConfig -from b2sdk.api_config import DEFAULT_HTTP_API_CONFIG -from b2sdk.b2http import ClockSkewHook -from b2sdk.b2http import HttpCallback -from b2sdk.b2http import ResponseContextManager -from b2sdk.bounded_queue_executor import BoundedQueueExecutor -from b2sdk.cache import AbstractCache -from b2sdk.cache import AuthInfoCache -from b2sdk.cache import DummyCache -from b2sdk.cache import InMemoryCache -from b2sdk.http_constants import ( +from b2sdk._internal.included_sources import get_included_sources +from b2sdk._internal.b2http import B2Http +from b2sdk._internal.api_config import B2HttpApiConfig +from b2sdk._internal.api_config import DEFAULT_HTTP_API_CONFIG +from b2sdk._internal.b2http import ClockSkewHook +from b2sdk._internal.b2http import HttpCallback +from b2sdk._internal.b2http import ResponseContextManager +from b2sdk._internal.bounded_queue_executor import BoundedQueueExecutor +from b2sdk._internal.cache import AbstractCache +from b2sdk._internal.cache import AuthInfoCache +from b2sdk._internal.cache import DummyCache +from b2sdk._internal.cache import InMemoryCache +from b2sdk._internal.http_constants import ( BUCKET_NAME_CHARS, BUCKET_NAME_CHARS_UNIQ, BUCKET_NAME_LENGTH_RANGE, @@ -255,12 +268,12 @@ LIST_FILE_NAMES_MAX_LIMIT, SRC_LAST_MODIFIED_MILLIS, ) -from b2sdk.session import B2Session -from b2sdk.utils.thread_pool import ThreadPoolMixin -from b2sdk.utils.escape import unprintable_to_hex, escape_control_chars, substitute_control_chars +from b2sdk._internal.session import B2Session +from b2sdk._internal.utils.thread_pool import ThreadPoolMixin +from b2sdk._internal.utils.escape import unprintable_to_hex, escape_control_chars, substitute_control_chars # filter -from b2sdk.filter import FilterType, Filter +from b2sdk._internal.filter import FilterType, Filter # typing -from b2sdk.utils.typing import JSON +from b2sdk._internal.utils.typing import JSON diff --git a/b2sdk/_v3/exception.py b/b2sdk/_v3/exception.py index e48f1879d..ef63fcd63 100644 --- a/b2sdk/_v3/exception.py +++ b/b2sdk/_v3/exception.py @@ -9,86 +9,86 @@ ###################################################################### from __future__ import annotations -from b2sdk.account_info.exception import AccountInfoError -from b2sdk.account_info.exception import CorruptAccountInfo -from b2sdk.account_info.exception import MissingAccountData -from b2sdk.exception import AccessDenied -from b2sdk.exception import AlreadyFailed -from b2sdk.exception import B2ConnectionError -from b2sdk.exception import B2Error -from b2sdk.exception import B2HttpCallbackException -from b2sdk.exception import B2HttpCallbackPostRequestException -from b2sdk.exception import B2HttpCallbackPreRequestException -from b2sdk.exception import B2RequestTimeout -from b2sdk.exception import B2RequestTimeoutDuringUpload -from b2sdk.exception import B2SimpleError -from b2sdk.exception import BadDateFormat -from b2sdk.exception import BadFileInfo -from b2sdk.exception import BadJson -from b2sdk.exception import BadRequest -from b2sdk.exception import BadUploadUrl -from b2sdk.exception import BrokenPipe -from b2sdk.exception import BucketIdNotFound -from b2sdk.exception import BucketNotAllowed -from b2sdk.exception import CapExceeded -from b2sdk.exception import CapabilityNotAllowed -from b2sdk.exception import ChecksumMismatch -from b2sdk.exception import ClockSkew -from b2sdk.exception import Conflict -from b2sdk.exception import ConnectionReset -from b2sdk.exception import CopyArgumentsMismatch -from b2sdk.exception import DestFileNewer -from b2sdk.exception import DestinationDirectoryDoesntAllowOperation -from b2sdk.exception import DestinationDirectoryDoesntExist -from b2sdk.exception import DestinationIsADirectory -from b2sdk.exception import DestinationParentIsNotADirectory -from b2sdk.exception import DisablingFileLockNotSupported -from b2sdk.exception import DuplicateBucketName -from b2sdk.exception import FileAlreadyHidden -from b2sdk.exception import FileNameNotAllowed -from b2sdk.exception import FileNotPresent -from b2sdk.exception import FileSha1Mismatch -from b2sdk.exception import InvalidAuthToken -from b2sdk.exception import InvalidJsonResponse -from b2sdk.exception import InvalidMetadataDirective -from b2sdk.exception import InvalidRange -from b2sdk.exception import InvalidUploadSource -from b2sdk.exception import MaxFileSizeExceeded -from b2sdk.exception import MaxRetriesExceeded -from b2sdk.exception import MissingPart -from b2sdk.exception import NonExistentBucket -from b2sdk.exception import NotAllowedByAppKeyError -from b2sdk.exception import PartSha1Mismatch -from b2sdk.exception import PotentialS3EndpointPassedAsRealm -from b2sdk.exception import RestrictedBucket -from b2sdk.exception import RestrictedBucketMissing -from b2sdk.exception import RetentionWriteError -from b2sdk.exception import SSECKeyError -from b2sdk.exception import SSECKeyIdMismatchInCopy -from b2sdk.exception import ServiceError -from b2sdk.exception import SourceReplicationConflict -from b2sdk.exception import StorageCapExceeded -from b2sdk.exception import TooManyRequests -from b2sdk.exception import TransactionCapExceeded -from b2sdk.exception import TransientErrorMixin -from b2sdk.exception import TruncatedOutput -from b2sdk.exception import Unauthorized -from b2sdk.exception import UnexpectedCloudBehaviour -from b2sdk.exception import UnknownError -from b2sdk.exception import UnknownHost -from b2sdk.exception import UnrecognizedBucketType -from b2sdk.exception import UnsatisfiableRange -from b2sdk.exception import UnusableFileName -from b2sdk.exception import WrongEncryptionModeForBucketDefault -from b2sdk.exception import interpret_b2_error -from b2sdk.sync.exception import IncompleteSync -from b2sdk.scan.exception import UnableToCreateDirectory -from b2sdk.scan.exception import EmptyDirectory -from b2sdk.scan.exception import EnvironmentEncodingError -from b2sdk.scan.exception import InvalidArgument -from b2sdk.scan.exception import NotADirectory -from b2sdk.scan.exception import UnsupportedFilename -from b2sdk.scan.exception import check_invalid_argument +from b2sdk._internal.account_info.exception import AccountInfoError +from b2sdk._internal.account_info.exception import CorruptAccountInfo +from b2sdk._internal.account_info.exception import MissingAccountData +from b2sdk._internal.exception import AccessDenied +from b2sdk._internal.exception import AlreadyFailed +from b2sdk._internal.exception import B2ConnectionError +from b2sdk._internal.exception import B2Error +from b2sdk._internal.exception import B2HttpCallbackException +from b2sdk._internal.exception import B2HttpCallbackPostRequestException +from b2sdk._internal.exception import B2HttpCallbackPreRequestException +from b2sdk._internal.exception import B2RequestTimeout +from b2sdk._internal.exception import B2RequestTimeoutDuringUpload +from b2sdk._internal.exception import B2SimpleError +from b2sdk._internal.exception import BadDateFormat +from b2sdk._internal.exception import BadFileInfo +from b2sdk._internal.exception import BadJson +from b2sdk._internal.exception import BadRequest +from b2sdk._internal.exception import BadUploadUrl +from b2sdk._internal.exception import BrokenPipe +from b2sdk._internal.exception import BucketIdNotFound +from b2sdk._internal.exception import BucketNotAllowed +from b2sdk._internal.exception import CapExceeded +from b2sdk._internal.exception import CapabilityNotAllowed +from b2sdk._internal.exception import ChecksumMismatch +from b2sdk._internal.exception import ClockSkew +from b2sdk._internal.exception import Conflict +from b2sdk._internal.exception import ConnectionReset +from b2sdk._internal.exception import CopyArgumentsMismatch +from b2sdk._internal.exception import DestFileNewer +from b2sdk._internal.exception import DestinationDirectoryDoesntAllowOperation +from b2sdk._internal.exception import DestinationDirectoryDoesntExist +from b2sdk._internal.exception import DestinationIsADirectory +from b2sdk._internal.exception import DestinationParentIsNotADirectory +from b2sdk._internal.exception import DisablingFileLockNotSupported +from b2sdk._internal.exception import DuplicateBucketName +from b2sdk._internal.exception import FileAlreadyHidden +from b2sdk._internal.exception import FileNameNotAllowed +from b2sdk._internal.exception import FileNotPresent +from b2sdk._internal.exception import FileSha1Mismatch +from b2sdk._internal.exception import InvalidAuthToken +from b2sdk._internal.exception import InvalidJsonResponse +from b2sdk._internal.exception import InvalidMetadataDirective +from b2sdk._internal.exception import InvalidRange +from b2sdk._internal.exception import InvalidUploadSource +from b2sdk._internal.exception import MaxFileSizeExceeded +from b2sdk._internal.exception import MaxRetriesExceeded +from b2sdk._internal.exception import MissingPart +from b2sdk._internal.exception import NonExistentBucket +from b2sdk._internal.exception import NotAllowedByAppKeyError +from b2sdk._internal.exception import PartSha1Mismatch +from b2sdk._internal.exception import PotentialS3EndpointPassedAsRealm +from b2sdk._internal.exception import RestrictedBucket +from b2sdk._internal.exception import RestrictedBucketMissing +from b2sdk._internal.exception import RetentionWriteError +from b2sdk._internal.exception import SSECKeyError +from b2sdk._internal.exception import SSECKeyIdMismatchInCopy +from b2sdk._internal.exception import ServiceError +from b2sdk._internal.exception import SourceReplicationConflict +from b2sdk._internal.exception import StorageCapExceeded +from b2sdk._internal.exception import TooManyRequests +from b2sdk._internal.exception import TransactionCapExceeded +from b2sdk._internal.exception import TransientErrorMixin +from b2sdk._internal.exception import TruncatedOutput +from b2sdk._internal.exception import Unauthorized +from b2sdk._internal.exception import UnexpectedCloudBehaviour +from b2sdk._internal.exception import UnknownError +from b2sdk._internal.exception import UnknownHost +from b2sdk._internal.exception import UnrecognizedBucketType +from b2sdk._internal.exception import UnsatisfiableRange +from b2sdk._internal.exception import UnusableFileName +from b2sdk._internal.exception import WrongEncryptionModeForBucketDefault +from b2sdk._internal.exception import interpret_b2_error +from b2sdk._internal.sync.exception import IncompleteSync +from b2sdk._internal.scan.exception import UnableToCreateDirectory +from b2sdk._internal.scan.exception import EmptyDirectory +from b2sdk._internal.scan.exception import EnvironmentEncodingError +from b2sdk._internal.scan.exception import InvalidArgument +from b2sdk._internal.scan.exception import NotADirectory +from b2sdk._internal.scan.exception import UnsupportedFilename +from b2sdk._internal.scan.exception import check_invalid_argument __all__ = ( 'AccessDenied', diff --git a/b2sdk/transfer/inbound/downloader/__init__.py b/b2sdk/transfer/inbound/downloader/__init__.py deleted file mode 100644 index 4079b3c34..000000000 --- a/b2sdk/transfer/inbound/downloader/__init__.py +++ /dev/null @@ -1,10 +0,0 @@ -###################################################################### -# -# File: b2sdk/transfer/inbound/downloader/__init__.py -# -# Copyright 2020 Backblaze Inc. All Rights Reserved. -# -# License https://www.backblaze.com/using_b2_code.html -# -###################################################################### -from __future__ import annotations diff --git a/b2sdk/transfer/outbound/__init__.py b/b2sdk/transfer/outbound/__init__.py deleted file mode 100644 index 9df42b4bb..000000000 --- a/b2sdk/transfer/outbound/__init__.py +++ /dev/null @@ -1,10 +0,0 @@ -###################################################################### -# -# File: b2sdk/transfer/outbound/__init__.py -# -# Copyright 2020 Backblaze Inc. All Rights Reserved. -# -# License https://www.backblaze.com/using_b2_code.html -# -###################################################################### -from __future__ import annotations diff --git a/b2sdk/utils/__init__.py b/b2sdk/utils/__init__.py deleted file mode 100644 index cac740cc5..000000000 --- a/b2sdk/utils/__init__.py +++ /dev/null @@ -1,515 +0,0 @@ -###################################################################### -# -# File: b2sdk/utils/__init__.py -# -# Copyright 2022 Backblaze Inc. All Rights Reserved. -# -# License https://www.backblaze.com/using_b2_code.html -# -###################################################################### -from __future__ import annotations - -import base64 -import hashlib -import logging -import os -import pathlib -import platform -import re -import time -from dataclasses import dataclass, field -from decimal import Decimal -from itertools import chain -from typing import Any, Iterator, NewType, TypeVar -from urllib.parse import quote, unquote_plus - -from logfury.v1 import DefaultTraceAbstractMeta, DefaultTraceMeta, limit_trace_arguments, disable_trace, trace_call - -logger = logging.getLogger(__name__) - -Sha1HexDigest = NewType('Sha1HexDigest', str) -T = TypeVar('T') -# TODO: When we drop Python 3.7 support, this should be replaced -# with typing.Protocol that exposes read method. -ReadOnlyStream = Any - - -def b2_url_encode(s): - """ - URL-encode a unicode string to be sent to B2 in an HTTP header. - - :param s: a unicode string to encode - :type s: str - :return: URL-encoded string - :rtype: str - """ - return quote(s.encode('utf-8')) - - -def b2_url_decode(s): - """ - Decode a Unicode string returned from B2 in an HTTP header. - - :param s: a unicode string to decode - :type s: str - :return: a Python unicode string. - :rtype: str - """ - return unquote_plus(s) - - -def choose_part_ranges(content_length, minimum_part_size): - """ - Return a list of (offset, length) for the parts of a large file. - - :param content_length: content length value - :type content_length: int - :param minimum_part_size: a minimum file part size - :type minimum_part_size: int - :rtype: list - """ - - # If the file is at least twice the minimum part size, we are guaranteed - # to be able to break it into multiple parts that are all at least - # the minimum part size. - assert minimum_part_size * 2 <= content_length - - # How many parts can we make? - part_count = min(content_length // minimum_part_size, 10000) - assert 2 <= part_count - - # All of the parts, except the last, are the same size. The - # last one may be bigger. - part_size = content_length // part_count - last_part_size = content_length - (part_size * (part_count - 1)) - assert minimum_part_size <= last_part_size - - # Make all of the parts except the last - parts = [(i * part_size, part_size) for i in range(part_count - 1)] - - # Add the last part - start_of_last = (part_count - 1) * part_size - last_part = (start_of_last, content_length - start_of_last) - parts.append(last_part) - - return parts - - -def update_digest_from_stream(digest: T, input_stream: ReadOnlyStream, content_length: int) -> T: - """ - Update and return `digest` with data read from `input_stream` - - :param digest: a digest object, which exposes an `update(bytes)` method - :param input_stream: stream object, which exposes a `read(int|None)` method - :param content_length: expected length of the stream - :type content_length: int - """ - remaining = content_length - block_size = 1024 * 1024 - while remaining != 0: - to_read = min(remaining, block_size) - data = input_stream.read(to_read) - if len(data) != to_read: - raise ValueError( - 'content_length(%s) is more than the size of the file' % content_length - ) - digest.update(data) - remaining -= to_read - return digest - - -def hex_sha1_of_stream(input_stream: ReadOnlyStream, content_length: int) -> Sha1HexDigest: - """ - Return the 40-character hex SHA1 checksum of the first content_length - bytes in the input stream. - - :param input_stream: stream object, which exposes read(int|None) method - :param content_length: expected length of the stream - :type content_length: int - :rtype: str - """ - return Sha1HexDigest( - update_digest_from_stream( - hashlib.sha1(), - input_stream, - content_length, - ).hexdigest() - ) - - -@dataclass -class IncrementalHexDigester: - """ - Calculates digest of a stream or parts of it. - """ - stream: ReadOnlyStream - digest: 'hashlib._Hash' = field( # noqa (_Hash is a dynamic object) - default_factory=hashlib.sha1 - ) - read_bytes: int = 0 - block_size: int = 1024 * 1024 - - @property - def hex_digest(self) -> Sha1HexDigest: - return Sha1HexDigest(self.digest.hexdigest()) - - def update_from_stream( - self, - limit: int | None = None, - ) -> Sha1HexDigest: - """ - :param limit: How many new bytes try to read from the stream. Default None – read until nothing left. - """ - offset = 0 - - while True: - if limit is not None: - to_read = min(limit - offset, self.block_size) - else: - to_read = self.block_size - data = self.stream.read(to_read) - data_len = len(data) - if data_len > 0: - self.digest.update(data) - self.read_bytes += data_len - offset += data_len - if data_len < to_read or to_read == 0: - break - - return self.hex_digest - - -def hex_sha1_of_unlimited_stream( - input_stream: ReadOnlyStream, - limit: int | None = None, -) -> tuple[Sha1HexDigest, int]: - digester = IncrementalHexDigester(input_stream) - digester.update_from_stream(limit) - return digester.hex_digest, digester.read_bytes - - -def hex_sha1_of_file(path_) -> Sha1HexDigest: - with open(path_, 'rb') as file: - return hex_sha1_of_unlimited_stream(file)[0] - - -def hex_sha1_of_bytes(data: bytes) -> Sha1HexDigest: - """ - Return the 40-character hex SHA1 checksum of the data. - """ - return Sha1HexDigest(hashlib.sha1(data).hexdigest()) - - -def hex_md5_of_bytes(data: bytes) -> str: - """ - Return the 32-character hex MD5 checksum of the data. - """ - return hashlib.md5(data).hexdigest() - - -def md5_of_bytes(data: bytes) -> bytes: - """ - Return the 16-byte MD5 checksum of the data. - """ - return hashlib.md5(data).digest() - - -def b64_of_bytes(data: bytes) -> str: - """ - Return the base64 encoded represtantion of the data. - """ - return base64.b64encode(data).decode() - - -def validate_b2_file_name(name): - """ - Raise a ValueError if the name is not a valid B2 file name. - - :param name: a string to check - :type name: str - """ - if not isinstance(name, str): - raise ValueError('file name must be a string, not bytes') - name_utf8 = name.encode('utf-8') - if len(name_utf8) < 1: - raise ValueError('file name too short (0 utf-8 bytes)') - if 1000 < len(name_utf8): - raise ValueError('file name too long (more than 1000 utf-8 bytes)') - if name[0] == '/': - raise ValueError("file names must not start with '/'") - if name[-1] == '/': - raise ValueError("file names must not end with '/'") - if '\\' in name: - raise ValueError("file names must not contain '\\'") - if '//' in name: - raise ValueError("file names must not contain '//'") - if chr(127) in name: - raise ValueError("file names must not contain DEL") - if any(250 < len(segment) for segment in name_utf8.split(b'/')): - raise ValueError("file names segments (between '/') can be at most 250 utf-8 bytes") - - -def is_file_readable(local_path, reporter=None): - """ - Check if the local file has read permissions. - - :param local_path: a file path - :type local_path: str - :param reporter: reporter object to put errors on - :rtype: bool - """ - if not os.path.exists(local_path): - if reporter is not None: - reporter.local_access_error(local_path) - return False - elif not os.access(local_path, os.R_OK): - if reporter is not None: - reporter.local_permission_error(local_path) - return False - return True - - -def get_file_mtime(local_path): - """ - Get modification time of a file in milliseconds. - - :param local_path: a file path - :type local_path: str - :rtype: int - """ - mod_time = os.path.getmtime(local_path) * 1000 - return int(mod_time) - - -def is_special_file(path: str | pathlib.Path) -> bool: - """ - Is the path a special file, such as /dev/null or stdout? - - :param path: a "file" path - :return: True if the path is a special file - """ - path_str = str(path) - return ( - path == os.devnull or path_str.startswith('/dev/') or - platform.system() == 'Windows' and path_str.upper() in ('CON', 'NUL') - ) - - -def set_file_mtime(local_path: str | pathlib.Path, mod_time_millis: int) -> None: - """ - Set modification time of a file in milliseconds. - - :param local_path: a file path - :param mod_time_millis: time to be set - """ - mod_time = mod_time_millis / 1000.0 - - # We have to convert it this way to avoid differences when mtime - # is read from the local file in the next iterations, and time is fetched - # without rounding. - # This is caused by floating point arithmetic as POSIX systems - # represents mtime as floats and B2 as integers. - # E.g. for 1093258377393, it would be converted to 1093258377.393 - # which is actually represented by 1093258377.3929998874664306640625. - # When we save mtime and read it again, we will end up with 1093258377392. - # See #617 for details. - mod_time = float(Decimal('%.3f5' % mod_time)) - - try: - os.utime(local_path, (mod_time, mod_time)) - except OSError: - if not is_special_file(local_path): - raise - - -def fix_windows_path_limit(path): - """ - Prefix paths when running on Windows to overcome 260 character path length limit. - See https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx#maxpath - - :param path: a path to prefix - :type path: str - :return: a prefixed path - :rtype: str - """ - if platform.system() == 'Windows': - if path.startswith('\\\\'): - # UNC network path - return '\\\\?\\UNC\\' + path[2:] - elif os.path.isabs(path): - # local absolute path - return '\\\\?\\' + path - else: - # relative path, don't alter - return path - else: - return path - - -def _pick_scale_and_suffix(x): - # suffixes for different scales - suffixes = ' kMGTP' - - # We want to use the biggest suffix that makes sense. - ref_digits = str(int(x)) - index = (len(ref_digits) - 1) // 3 - suffix = suffixes[index] - if suffix == ' ': - suffix = '' - - scale = 1000**index - return (scale, suffix) - - -def format_and_scale_number(x, unit): - """ - Pick a good scale for representing a number and format it. - - :param x: a number - :type x: int - :param unit: an arbitrary unit name - :type unit: str - :return: scaled and formatted number - :rtype: str - """ - - # simple case for small numbers - if x < 1000: - return '%d %s' % (x, unit) - - # pick a scale - (scale, suffix) = _pick_scale_and_suffix(x) - - # decide how many digits after the decimal to display - scaled = x / scale - if scaled < 10.0: - fmt = '%1.2f %s%s' - elif scaled < 100.0: - fmt = '%1.1f %s%s' - else: - fmt = '%1.0f %s%s' - - # format it - return fmt % (scaled, suffix, unit) - - -def format_and_scale_fraction(numerator, denominator, unit): - """ - Pick a good scale for representing a fraction, and format it. - - :param numerator: a numerator of a fraction - :type numerator: int - :param denominator: a denominator of a fraction - :type denominator: int - :param unit: an arbitrary unit name - :type unit: str - :return: scaled and formatted fraction - :rtype: str - """ - - # simple case for small numbers - if denominator < 1000: - return '%d / %d %s' % (numerator, denominator, unit) - - # pick a scale - (scale, suffix) = _pick_scale_and_suffix(denominator) - - # decide how many digits after the decimal to display - scaled_denominator = denominator / scale - if scaled_denominator < 10.0: - fmt = '%1.2f / %1.2f %s%s' - elif scaled_denominator < 100.0: - fmt = '%1.1f / %1.1f %s%s' - else: - fmt = '%1.0f / %1.0f %s%s' - - # format it - scaled_numerator = numerator / scale - return fmt % (scaled_numerator, scaled_denominator, suffix, unit) - - -_CAMELCASE_TO_UNDERSCORE_RE = re.compile('((?<=[a-z0-9])[A-Z]|(?!^)[A-Z](?=[a-z]))') - - -def camelcase_to_underscore(input_): - """ - Convert a camel-cased string to a string with underscores. - - :param input_: an input string - :type input_: str - :return: string with underscores - :rtype: str - """ - return _CAMELCASE_TO_UNDERSCORE_RE.sub(r'_\1', input_).lower() - - -class B2TraceMeta(DefaultTraceMeta): - """ - Trace all public method calls, except for ones with names that begin with `get_`. - """ - pass - - -class B2TraceMetaAbstract(DefaultTraceAbstractMeta): - """ - Default class for tracers, to be set as - a metaclass for abstract base classes. - """ - pass - - -class ConcurrentUsedAuthTokenGuard: - """ - Context manager preventing two tokens being used simultaneously. - Throws UploadTokenUsedConcurrently when unable to acquire a lock - Sample usage: - - with ConcurrentUsedAuthTokenGuard(lock_for_token, token): - # code that uses the token exclusively - """ - - def __init__(self, lock, token): - self.lock = lock - self.token = token - - def __enter__(self): - if not self.lock.acquire(False): - from b2sdk.exception import UploadTokenUsedConcurrently - raise UploadTokenUsedConcurrently(self.token) - - def __exit__(self, exc_type, exc_val, exc_tb): - try: - self.lock.release() - except RuntimeError: - # guard against releasing a non-acquired lock - pass - - -def current_time_millis(): - """ - File times are in integer milliseconds, to avoid roundoff errors. - """ - return int(round(time.time() * 1000)) - - -def iterator_peek(iterator: Iterator[T], count: int) -> tuple[list[T], Iterator[T]]: - """ - Get up to the `count` first elements yielded by `iterator`. - - The function will read `count` elements from `iterator` or less if the end is reached first. Returns a tuple - consisting of a list of retrieved elements and an iterator equivalent to the input iterator. - """ - - ret = [] - for _ in range(count): - try: - ret.append(next(iterator)) - except StopIteration: - break - - return ret, chain(ret, iterator) - - -assert disable_trace -assert limit_trace_arguments -assert trace_call diff --git a/b2sdk/v0/account_info.py b/b2sdk/v0/account_info.py index dbf103481..42c77effc 100644 --- a/b2sdk/v0/account_info.py +++ b/b2sdk/v0/account_info.py @@ -9,7 +9,7 @@ ###################################################################### from __future__ import annotations -from b2sdk import version_utils +from b2sdk._internal import version_utils from b2sdk import v1 diff --git a/b2sdk/v0/sync.py b/b2sdk/v0/sync.py index 0fec847f5..1fcf806f3 100644 --- a/b2sdk/v0/sync.py +++ b/b2sdk/v0/sync.py @@ -122,9 +122,9 @@ def make_folder_sync_actions( folder to the source folder. :param source_folder: source folder object - :type source_folder: b2sdk.scan.folder.AbstractFolder + :type source_folder: b2sdk._internal.scan.folder.AbstractFolder :param dest_folder: destination folder object - :type dest_folder: b2sdk.scan.folder.AbstractFolder + :type dest_folder: b2sdk._internal.scan.folder.AbstractFolder :param args: an object which holds command line arguments :param now_millis: current time in milliseconds :type now_millis: int @@ -175,9 +175,9 @@ def sync_folders( in the destination older than history_days. :param source_folder: source folder object - :type source_folder: b2sdk.scan.folder.AbstractFolder + :type source_folder: b2sdk._internal.scan.folder.AbstractFolder :param dest_folder: destination folder object - :type dest_folder: b2sdk.scan.folder.AbstractFolder + :type dest_folder: b2sdk._internal.scan.folder.AbstractFolder :param args: an object which holds command line arguments :param now_millis: current time in milliseconds :type now_millis: int diff --git a/b2sdk/v1/account_info.py b/b2sdk/v1/account_info.py index a93adb571..54a98a741 100644 --- a/b2sdk/v1/account_info.py +++ b/b2sdk/v1/account_info.py @@ -15,8 +15,8 @@ import os from b2sdk import v2 -from b2sdk.account_info.sqlite_account_info import DEFAULT_ABSOLUTE_MINIMUM_PART_SIZE -from b2sdk.utils import limit_trace_arguments +from b2sdk._internal.account_info.sqlite_account_info import DEFAULT_ABSOLUTE_MINIMUM_PART_SIZE +from b2sdk._internal.utils import limit_trace_arguments logger = logging.getLogger(__name__) diff --git a/b2sdk/v1/api.py b/b2sdk/v1/api.py index fd229e070..13feef019 100644 --- a/b2sdk/v1/api.py +++ b/b2sdk/v1/api.py @@ -13,7 +13,7 @@ from .download_dest import AbstractDownloadDestination from b2sdk import v2 -from b2sdk.api import Services +from b2sdk._internal.api import Services from .account_info import AbstractAccountInfo from .bucket import Bucket, BucketFactory, download_file_and_return_info_dict from .cache import AbstractCache @@ -51,7 +51,7 @@ def __init__( :class:`~b2sdk.v1.SqliteAccountInfo` :param cache: It is used by B2Api to cache the mapping between bucket name and bucket ids. - default is :class:`~b2sdk.cache.DummyCache` + default is :class:`~b2sdk._internal.cache.DummyCache` :param max_upload_workers: a number of upload threads :param max_copy_workers: a number of copy threads diff --git a/b2sdk/v1/bucket.py b/b2sdk/v1/bucket.py index f27c31cf0..e6d1a4b61 100644 --- a/b2sdk/v1/bucket.py +++ b/b2sdk/v1/bucket.py @@ -16,8 +16,8 @@ from .file_metadata import FileMetadata from .file_version import FileVersionInfo, FileVersionInfoFactory, file_version_info_from_download_version from b2sdk import v2 -from b2sdk.utils import validate_b2_file_name -from ..raw_api import LifecycleRule +from b2sdk._internal.utils import validate_b2_file_name +from b2sdk._internal.raw_api import LifecycleRule # Overridden to retain the obsolete copy_file and start_large_file methods diff --git a/b2sdk/v1/download_dest.py b/b2sdk/v1/download_dest.py index 4aeb43e1a..cd78db94e 100644 --- a/b2sdk/v1/download_dest.py +++ b/b2sdk/v1/download_dest.py @@ -14,9 +14,9 @@ from abc import abstractmethod from contextlib import contextmanager -from b2sdk.stream.progress import WritingStreamWithProgress +from b2sdk._internal.stream.progress import WritingStreamWithProgress -from ..utils import B2TraceMetaAbstract, limit_trace_arguments, set_file_mtime +from b2sdk._internal.utils import B2TraceMetaAbstract, limit_trace_arguments, set_file_mtime class AbstractDownloadDestination(metaclass=B2TraceMetaAbstract): diff --git a/b2sdk/v1/sync/file.py b/b2sdk/v1/sync/file.py index 842287680..d991cddb6 100644 --- a/b2sdk/v1/sync/file.py +++ b/b2sdk/v1/sync/file.py @@ -10,7 +10,7 @@ from __future__ import annotations from b2sdk.v1 import FileVersionInfo -from b2sdk.http_constants import SRC_LAST_MODIFIED_MILLIS +from b2sdk._internal.http_constants import SRC_LAST_MODIFIED_MILLIS # This whole module is here to retain legacy classes so they can be used in retained legacy exception diff --git a/b2sdk/v2/__init__.py b/b2sdk/v2/__init__.py index 6bf066e13..ecedf98df 100644 --- a/b2sdk/v2/__init__.py +++ b/b2sdk/v2/__init__.py @@ -13,7 +13,7 @@ from b2sdk._v3 import parse_folder as parse_sync_folder from b2sdk._v3 import AbstractPath as AbstractSyncPath from b2sdk._v3 import LocalPath as LocalSyncPath -from b2sdk.utils.escape import unprintable_to_hex, escape_control_chars, substitute_control_chars +from b2sdk._internal.utils.escape import unprintable_to_hex, escape_control_chars, substitute_control_chars from .account_info import AbstractAccountInfo from .api import B2Api diff --git a/b2sdk/v2/_compat.py b/b2sdk/v2/_compat.py index 00488ba18..501ba0bb6 100644 --- a/b2sdk/v2/_compat.py +++ b/b2sdk/v2/_compat.py @@ -8,6 +8,6 @@ # ###################################################################### from __future__ import annotations -from b2sdk import version_utils +from b2sdk._internal import version_utils _file_infos_rename = version_utils.rename_argument('file_infos', 'file_info', None, 'v3') diff --git a/b2sdk/v2/bucket.py b/b2sdk/v2/bucket.py index ed0fbf339..f2edc71bd 100644 --- a/b2sdk/v2/bucket.py +++ b/b2sdk/v2/bucket.py @@ -18,7 +18,7 @@ from .file_version import FileVersionFactory if typing.TYPE_CHECKING: - from b2sdk.utils import Sha1HexDigest + from b2sdk._internal.utils import Sha1HexDigest # Overridden to raise old style BucketIdNotFound exception diff --git a/b2sdk/v2/transfer.py b/b2sdk/v2/transfer.py index 151f5ff1c..1ad2d5bfa 100644 --- a/b2sdk/v2/transfer.py +++ b/b2sdk/v2/transfer.py @@ -10,7 +10,7 @@ from __future__ import annotations from b2sdk import _v3 as v3 -from b2sdk.utils.thread_pool import LazyThreadPool # noqa: F401 +from b2sdk._internal.utils.thread_pool import LazyThreadPool # noqa: F401 class ThreadPoolMixin(v3.ThreadPoolMixin): diff --git a/b2sdk/version.py b/b2sdk/version.py index a2506368f..8ce1c4347 100644 --- a/b2sdk/version.py +++ b/b2sdk/version.py @@ -9,15 +9,21 @@ ###################################################################### from __future__ import annotations -import sys +from sys import version_info as _version_info try: - from importlib.metadata import version -except ModuleNotFoundError: - from importlib_metadata import version # for python 3.7 + from importlib.metadata import version as _version +except ModuleNotFoundError: # python 3.7 + from importlib_metadata import version as _version -VERSION = version('b2sdk') +__all__ = [ + "VERSION", + "PYTHON_VERSION", + "USER_AGENT", +] -PYTHON_VERSION = '.'.join(map(str, sys.version_info[:3])) # something like: 3.9.1 +VERSION = _version("b2sdk") -USER_AGENT = f'backblaze-b2/{VERSION} python/{PYTHON_VERSION}' +PYTHON_VERSION = ".".join(map(str, _version_info[:3])) # something like: 3.9.1 + +USER_AGENT = f"backblaze-b2/{VERSION} python/{PYTHON_VERSION}" diff --git a/changelog.d/+internal.changed.md b/changelog.d/+internal.changed.md new file mode 100644 index 000000000..b432c6975 --- /dev/null +++ b/changelog.d/+internal.changed.md @@ -0,0 +1 @@ +Move non-apiver packages (e.g. packages other than `b2sdk.v1`, `b2sdk.v2`, ...) to `b2sdk._internal` to further discourage use of non-public internals. diff --git a/changelog.d/+logging.changed.md b/changelog.d/+logging.changed.md new file mode 100644 index 000000000..804f5b3a5 --- /dev/null +++ b/changelog.d/+logging.changed.md @@ -0,0 +1,2 @@ +Move logging setup and `UrllibWarningFilter` class from `b2sdk.__init__.py` to `b2sdk._v3` (and thus `b2sdk.v2` & `b2sdk.v1`). +This will allow us to remove/change it in new apiver releases without the need to change the major semver version. diff --git a/changelog.d/+move_doc_extras_to_dev.removed.md b/changelog.d/+move_doc_extras_to_dev.removed.md new file mode 100644 index 000000000..917a375ef --- /dev/null +++ b/changelog.d/+move_doc_extras_to_dev.removed.md @@ -0,0 +1 @@ +Removed `[doc]` extras dependency group (moved it to dev dependencies). diff --git a/changelog.d/+remove_packaging_dep.fixed.md b/changelog.d/+remove_packaging_dep.fixed.md new file mode 100644 index 000000000..04635a910 --- /dev/null +++ b/changelog.d/+remove_packaging_dep.fixed.md @@ -0,0 +1 @@ +Remove unnecessary `packaging` package dependency. diff --git a/changelog.d/+tqdm_removal.removed.md b/changelog.d/+tqdm_removal.removed.md new file mode 100644 index 000000000..c447fd08f --- /dev/null +++ b/changelog.d/+tqdm_removal.removed.md @@ -0,0 +1 @@ +Remove `tqdm` dependency. Now `tqdm` has to be explicitly installed to use `TqdmProgressListener` class. diff --git a/doc/markup-test.rst b/doc/markup-test.rst index 4ab8d5365..7548c772b 100644 --- a/doc/markup-test.rst +++ b/doc/markup-test.rst @@ -89,10 +89,10 @@ Public interface consists of *public* members of the following modules: * b2sdk.sync.exception and some of their dependencies: -* b2sdk.account_info.InMemoryAccountInfo -* b2sdk.account_info.SqliteAccountInfo +* b2sdk._internal.account_info.InMemoryAccountInfo +* b2sdk._internal.account_info.SqliteAccountInfo * b2sdk.transferer -* b2sdk.utils +* b2sdk._internal.utils Those will not change in a backwards-incompatible way between non-major versions. In other words, if you pin your dependencies to `>=x.0.0;>> file_info = {'how': 'good-file'} >>> bucket.concatenate(input_sources, remote_name, file_info) - + If one of remote source has length smaller than :term:`absoluteMinimumPartSize` then it cannot be copied into large file part. Such remote source would be downloaded and concatenated locally with local source or with other downloaded remote source. @@ -99,7 +99,7 @@ Concatenate files of known size (streamed version) ... ] >>> file_info = {'how': 'good-file'} >>> bucket.concatenate_stream(input_sources, remote_name, file_info) - + @@ -148,7 +148,7 @@ The assumption here is that the file has been appended to since it was last uplo ... ] >>> file_info = {'how': 'good-file'} >>> bucket.create_file(input_sources, remote_name, file_info) - + `LocalUploadSource` has the size determined automatically in this case. This is more efficient than :meth:`b2sdk.v2.Bucket.concatenate`, as it can use the overlapping ranges when a remote part is smaller than :term:`absoluteMinimumPartSize` to prevent downloading a range (when concatenating, local source would have destination offset at the end of remote source) @@ -177,7 +177,7 @@ Change the middle of the remote file ... ] >>> file_info = {'how': 'good-file'} >>> bucket.create_file(input_sources, remote_name, file_info) - + `LocalUploadSource` has the size determined automatically in this case. This is more efficient than :meth:`b2sdk.v2.Bucket.concatenate`, as it can use the overlapping ranges when a remote part is smaller than :term:`absoluteMinimumPartSize` to prevent downloading a range. @@ -236,7 +236,7 @@ Scenarios such as below are then possible: ... >>> file_info = {'how': 'good-file'} >>> bucket.create_file(generate_input(), remote_name, file_info) - + In such case, if the sizes allow for it (there would be no parts smaller than :term:`absoluteMinimumPartSize`), the only uploaded part will be `C-D`. Otherwise, more data will be uploaded, but the data transfer will be reduced in most cases. :meth:`b2sdk.v2.Bucket.create_file` does not guarantee that outbound transfer usage would be optimal, it uses a simple greedy algorithm with as small look-aheads as possible. diff --git a/doc/source/api/account_info.rst b/doc/source/api/account_info.rst index ce0b998a2..9a56a2d44 100644 --- a/doc/source/api/account_info.rst +++ b/doc/source/api/account_info.rst @@ -107,7 +107,7 @@ AccountInfo helper classes .. caution:: This class is not part of the public interface. To find out how to safely use it, read :ref:`this `. -.. autoclass:: b2sdk.account_info.upload_url_pool.UploadUrlPool() +.. autoclass:: b2sdk._internal.account_info.upload_url_pool.UploadUrlPool() :inherited-members: :private-members: diff --git a/doc/source/api/api.rst b/doc/source/api/api.rst index 504b28dd5..c6fc51b87 100644 --- a/doc/source/api/api.rst +++ b/doc/source/api/api.rst @@ -1,5 +1,5 @@ B2 Api client -=============================================== +============= .. autoclass:: b2sdk.v2.B2Api() :inherited-members: diff --git a/doc/source/api/bucket.rst b/doc/source/api/bucket.rst index 0d6110542..3900bf79a 100644 --- a/doc/source/api/bucket.rst +++ b/doc/source/api/bucket.rst @@ -1,5 +1,5 @@ B2 Bucket -=============================================== +========= .. autoclass:: b2sdk.v2.Bucket() :inherited-members: diff --git a/doc/source/api/cache.rst b/doc/source/api/cache.rst index dd2cb0ee7..e000e9071 100644 --- a/doc/source/api/cache.rst +++ b/doc/source/api/cache.rst @@ -1,5 +1,5 @@ Cache -=============================================== +===== **b2sdk** caches the mapping between bucket name and bucket id, so that the user of the library does not need to maintain diff --git a/doc/source/api/data_classes.rst b/doc/source/api/data_classes.rst index 532b6bb9b..1ecd7ee5c 100644 --- a/doc/source/api/data_classes.rst +++ b/doc/source/api/data_classes.rst @@ -1,5 +1,5 @@ Data classes -=============================================== +============ .. autoclass:: b2sdk.v2.FileVersion :inherited-members: diff --git a/doc/source/api/downloaded_file.rst b/doc/source/api/downloaded_file.rst index bb91b43cf..e83c317a4 100644 --- a/doc/source/api/downloaded_file.rst +++ b/doc/source/api/downloaded_file.rst @@ -4,4 +4,3 @@ Downloaded File .. autoclass:: b2sdk.v2.DownloadedFile .. autoclass:: b2sdk.v2.MtimeUpdatedFile - diff --git a/doc/source/api/encryption/types.rst b/doc/source/api/encryption/types.rst index 910cc1c03..76aa46519 100644 --- a/doc/source/api/encryption/types.rst +++ b/doc/source/api/encryption/types.rst @@ -3,4 +3,4 @@ Encryption Types ================ -.. automodule:: b2sdk.encryption.types +.. automodule:: b2sdk._internal.encryption.types diff --git a/doc/source/api/enums.rst b/doc/source/api/enums.rst index ec55327e6..a453f30bf 100644 --- a/doc/source/api/enums.rst +++ b/doc/source/api/enums.rst @@ -1,5 +1,5 @@ Enums -=============================================== +===== .. autoclass:: b2sdk.v2.MetadataDirectiveMode :inherited-members: @@ -12,4 +12,3 @@ Enums .. autoclass:: b2sdk.v2.KeepOrDeleteMode :inherited-members: - diff --git a/doc/source/api/exception.rst b/doc/source/api/exception.rst index 68fba2343..69e38ec0b 100644 --- a/doc/source/api/exception.rst +++ b/doc/source/api/exception.rst @@ -1,5 +1,5 @@ Exceptions -==================================== +========== .. todo:: improve documentation of exceptions, automodule -> autoclass? diff --git a/doc/source/api/file_lock.rst b/doc/source/api/file_lock.rst index 4836ed115..a2c4b1ea1 100644 --- a/doc/source/api/file_lock.rst +++ b/doc/source/api/file_lock.rst @@ -34,4 +34,3 @@ File locks .. autoclass:: b2sdk.v2.NO_RETENTION_FILE_SETTING() .. autoclass:: b2sdk.v2.UNKNOWN_FILE_RETENTION_SETTING() - diff --git a/doc/source/api/internal/b2http.rst b/doc/source/api/internal/b2http.rst index bd8c2eb38..17b533e71 100644 --- a/doc/source/api/internal/b2http.rst +++ b/doc/source/api/internal/b2http.rst @@ -1,4 +1,4 @@ -:mod:`b2sdk.b2http` -- thin http client wrapper -=============================================== +:mod:`b2sdk._internal.b2http` -- thin http client wrapper +========================================================= -.. automodule:: b2sdk.b2http +.. automodule:: b2sdk._internal.b2http diff --git a/doc/source/api/internal/cache.rst b/doc/source/api/internal/cache.rst index 6e66b8f51..70ab71ba3 100644 --- a/doc/source/api/internal/cache.rst +++ b/doc/source/api/internal/cache.rst @@ -1,7 +1,7 @@ -:mod:`b2sdk.cache` -=========================== +:mod:`b2sdk._internal.cache` +============================ -.. automodule:: b2sdk.cache +.. automodule:: b2sdk._internal.cache :members: :undoc-members: :show-inheritance: diff --git a/doc/source/api/internal/raw_api.rst b/doc/source/api/internal/raw_api.rst index ffe3333a6..25daf2259 100644 --- a/doc/source/api/internal/raw_api.rst +++ b/doc/source/api/internal/raw_api.rst @@ -1,7 +1,7 @@ -:mod:`b2sdk.raw_api` -- B2 raw api wrapper -============================================= +:mod:`b2sdk._internal.raw_api` -- B2 raw api wrapper +==================================================== -.. automodule:: b2sdk.raw_api +.. automodule:: b2sdk._internal.raw_api :members: :undoc-members: :show-inheritance: diff --git a/doc/source/api/internal/raw_simulator.rst b/doc/source/api/internal/raw_simulator.rst index 379542266..e54b98856 100644 --- a/doc/source/api/internal/raw_simulator.rst +++ b/doc/source/api/internal/raw_simulator.rst @@ -1,7 +1,7 @@ -:mod:`b2sdk.raw_simulator` -- B2 raw api simulator -================================================== +:mod:`b2sdk._internal.raw_simulator` -- B2 raw api simulator +============================================================ -.. automodule:: b2sdk.raw_simulator +.. automodule:: b2sdk._internal.raw_simulator :members: :undoc-members: :show-inheritance: diff --git a/doc/source/api/internal/requests.rst b/doc/source/api/internal/requests.rst index 6698196ee..379cd884d 100644 --- a/doc/source/api/internal/requests.rst +++ b/doc/source/api/internal/requests.rst @@ -1,4 +1,4 @@ -:mod:`b2sdk.requests` -- modified requests.models.Response class -================================================================ +:mod:`b2sdk._internal.requests` -- modified requests.models.Response class +========================================================================== -.. automodule:: b2sdk.requests +.. automodule:: b2sdk._internal.requests diff --git a/doc/source/api/internal/scan/folder.rst b/doc/source/api/internal/scan/folder.rst index 30bcc35fb..cf27a007f 100644 --- a/doc/source/api/internal/scan/folder.rst +++ b/doc/source/api/internal/scan/folder.rst @@ -1,7 +1,7 @@ -:mod:`b2sdk.scan.folder` +:mod:`b2sdk._internal.scan.folder` ================================== -.. automodule:: b2sdk.scan.folder +.. automodule:: b2sdk._internal.scan.folder :members: :undoc-members: :show-inheritance: diff --git a/doc/source/api/internal/scan/folder_parser.rst b/doc/source/api/internal/scan/folder_parser.rst index 7bf5001b8..3040d6aa9 100644 --- a/doc/source/api/internal/scan/folder_parser.rst +++ b/doc/source/api/internal/scan/folder_parser.rst @@ -1,7 +1,7 @@ -:mod:`b2sdk.scan.folder_parser` -================================================ +:mod:`b2sdk._internal.scan.folder_parser` +========================================= -.. automodule:: b2sdk.scan.folder_parser +.. automodule:: b2sdk._internal.scan.folder_parser :members: :undoc-members: :show-inheritance: diff --git a/doc/source/api/internal/scan/path.rst b/doc/source/api/internal/scan/path.rst index 707a888d1..dbb7601d6 100644 --- a/doc/source/api/internal/scan/path.rst +++ b/doc/source/api/internal/scan/path.rst @@ -1,7 +1,7 @@ -:mod:`b2sdk.scan.path` -============================== +:mod:`b2sdk._internal.scan.path` +================================ -.. automodule:: b2sdk.scan.path +.. automodule:: b2sdk._internal.scan.path :members: :undoc-members: :show-inheritance: diff --git a/doc/source/api/internal/scan/policies.rst b/doc/source/api/internal/scan/policies.rst index d262132b4..d9fedd58f 100644 --- a/doc/source/api/internal/scan/policies.rst +++ b/doc/source/api/internal/scan/policies.rst @@ -1,7 +1,7 @@ -:mod:`b2sdk.scan.policies` -================================================ +:mod:`b2sdk._internal.scan.policies` +==================================== -.. automodule:: b2sdk.scan.policies +.. automodule:: b2sdk._internal.scan.policies :members: :undoc-members: :show-inheritance: diff --git a/doc/source/api/internal/scan/scan.rst b/doc/source/api/internal/scan/scan.rst index e0d4a44a3..09d74c2d4 100644 --- a/doc/source/api/internal/scan/scan.rst +++ b/doc/source/api/internal/scan/scan.rst @@ -1,7 +1,7 @@ -:mod:`b2sdk.scan.scan` -================================================ +:mod:`b2sdk._internal.scan.scan` +================================ -.. automodule:: b2sdk.scan.scan +.. automodule:: b2sdk._internal.scan.scan :members: :undoc-members: :show-inheritance: diff --git a/doc/source/api/internal/session.rst b/doc/source/api/internal/session.rst index b0d2afb32..780a15e56 100644 --- a/doc/source/api/internal/session.rst +++ b/doc/source/api/internal/session.rst @@ -1,7 +1,7 @@ -:mod:`b2sdk.session` -- B2 Session -============================================= +:mod:`b2sdk._internal.session` -- B2 Session +============================================ -.. automodule:: b2sdk.session +.. automodule:: b2sdk._internal.session :members: :undoc-members: :show-inheritance: diff --git a/doc/source/api/internal/stream/chained.rst b/doc/source/api/internal/stream/chained.rst index 2f5c966c6..b561c6099 100644 --- a/doc/source/api/internal/stream/chained.rst +++ b/doc/source/api/internal/stream/chained.rst @@ -1,7 +1,7 @@ -:mod:`b2sdk.stream.chained` ChainedStream -============================================ +:mod:`b2sdk._internal.stream.chained` ChainedStream +=================================================== -.. automodule:: b2sdk.stream.chained +.. automodule:: b2sdk._internal.stream.chained :members: :undoc-members: :show-inheritance: diff --git a/doc/source/api/internal/stream/hashing.rst b/doc/source/api/internal/stream/hashing.rst index 9eab9ba28..0b12e34df 100644 --- a/doc/source/api/internal/stream/hashing.rst +++ b/doc/source/api/internal/stream/hashing.rst @@ -1,7 +1,7 @@ -:mod:`b2sdk.stream.hashing` StreamWithHash -============================================ +:mod:`b2sdk._internal.stream.hashing` StreamWithHash +==================================================== -.. automodule:: b2sdk.stream.hashing +.. automodule:: b2sdk._internal.stream.hashing :members: :undoc-members: :show-inheritance: diff --git a/doc/source/api/internal/stream/progress.rst b/doc/source/api/internal/stream/progress.rst index f1c972b93..2ac00e5cf 100644 --- a/doc/source/api/internal/stream/progress.rst +++ b/doc/source/api/internal/stream/progress.rst @@ -1,7 +1,7 @@ -:mod:`b2sdk.stream.progress` Streams with progress reporting -============================================================ +:mod:`b2sdk._internal.stream.progress` Streams with progress reporting +====================================================================== -.. automodule:: b2sdk.stream.progress +.. automodule:: b2sdk._internal.stream.progress :members: :undoc-members: :show-inheritance: diff --git a/doc/source/api/internal/stream/range.rst b/doc/source/api/internal/stream/range.rst index eb8c2df1e..a8a48b33d 100644 --- a/doc/source/api/internal/stream/range.rst +++ b/doc/source/api/internal/stream/range.rst @@ -1,7 +1,7 @@ -:mod:`b2sdk.stream.range` RangeOfInputStream -============================================= +:mod:`b2sdk._internal.stream.range` RangeOfInputStream +====================================================== -.. automodule:: b2sdk.stream.range +.. automodule:: b2sdk._internal.stream.range :members: :undoc-members: :show-inheritance: diff --git a/doc/source/api/internal/stream/wrapper.rst b/doc/source/api/internal/stream/wrapper.rst index ed702ccf8..0874660f0 100644 --- a/doc/source/api/internal/stream/wrapper.rst +++ b/doc/source/api/internal/stream/wrapper.rst @@ -1,7 +1,7 @@ -:mod:`b2sdk.stream.wrapper` StreamWrapper -========================================= +:mod:`b2sdk._internal.stream.wrapper` StreamWrapper +=================================================== -.. automodule:: b2sdk.stream.wrapper +.. automodule:: b2sdk._internal.stream.wrapper :members: :undoc-members: :show-inheritance: diff --git a/doc/source/api/internal/sync/action.rst b/doc/source/api/internal/sync/action.rst index 0d097f975..35ca74323 100644 --- a/doc/source/api/internal/sync/action.rst +++ b/doc/source/api/internal/sync/action.rst @@ -1,7 +1,7 @@ -:mod:`b2sdk.sync.action` -======================================= +:mod:`b2sdk._internal.sync.action` +================================== -.. automodule:: b2sdk.sync.action +.. automodule:: b2sdk._internal.sync.action :members: :undoc-members: :show-inheritance: diff --git a/doc/source/api/internal/sync/exception.rst b/doc/source/api/internal/sync/exception.rst index 9427225cc..5f892fa8c 100644 --- a/doc/source/api/internal/sync/exception.rst +++ b/doc/source/api/internal/sync/exception.rst @@ -1,7 +1,7 @@ -:mod:`b2sdk.sync.exception` -============================================== +:mod:`b2sdk._internal.sync.exception` +===================================== -.. automodule:: b2sdk.sync.exception +.. automodule:: b2sdk._internal.sync.exception :members: :undoc-members: :show-inheritance: diff --git a/doc/source/api/internal/sync/policy.rst b/doc/source/api/internal/sync/policy.rst index fd01384df..39dbbc0df 100644 --- a/doc/source/api/internal/sync/policy.rst +++ b/doc/source/api/internal/sync/policy.rst @@ -1,7 +1,7 @@ -:mod:`b2sdk.sync.policy` +:mod:`b2sdk._internal.sync.policy` ================================== -.. automodule:: b2sdk.sync.policy +.. automodule:: b2sdk._internal.sync.policy :members: :undoc-members: :show-inheritance: diff --git a/doc/source/api/internal/sync/policy_manager.rst b/doc/source/api/internal/sync/policy_manager.rst index d1e8aa9ae..608aab025 100644 --- a/doc/source/api/internal/sync/policy_manager.rst +++ b/doc/source/api/internal/sync/policy_manager.rst @@ -1,7 +1,7 @@ -:mod:`b2sdk.sync.policy_manager` -================================================== +:mod:`b2sdk._internal.sync.policy_manager` +========================================== -.. automodule:: b2sdk.sync.policy_manager +.. automodule:: b2sdk._internal.sync.policy_manager :members: :undoc-members: :show-inheritance: diff --git a/doc/source/api/internal/sync/sync.rst b/doc/source/api/internal/sync/sync.rst index 8cdc82bb4..b63766840 100644 --- a/doc/source/api/internal/sync/sync.rst +++ b/doc/source/api/internal/sync/sync.rst @@ -1,7 +1,7 @@ -:mod:`b2sdk.sync.sync` -============================== +:mod:`b2sdk._internal.sync.sync` +================================ -.. automodule:: b2sdk.sync.sync +.. automodule:: b2sdk._internal.sync.sync :members: :undoc-members: :show-inheritance: diff --git a/doc/source/api/internal/transfer/inbound/download_manager.rst b/doc/source/api/internal/transfer/inbound/download_manager.rst index b5ca47bb1..d93f97cae 100644 --- a/doc/source/api/internal/transfer/inbound/download_manager.rst +++ b/doc/source/api/internal/transfer/inbound/download_manager.rst @@ -1,7 +1,7 @@ -:mod:`b2sdk.transfer.inbound.download_manager` -- Manager of downloaders -======================================================================== +:mod:`b2sdk._internal.transfer.inbound.download_manager` -- Manager of downloaders +================================================================================== -.. automodule:: b2sdk.transfer.inbound.download_manager +.. automodule:: b2sdk._internal.transfer.inbound.download_manager :members: :undoc-members: :show-inheritance: diff --git a/doc/source/api/internal/transfer/inbound/downloader/abstract.rst b/doc/source/api/internal/transfer/inbound/downloader/abstract.rst index 68ef282b6..e32643b8f 100644 --- a/doc/source/api/internal/transfer/inbound/downloader/abstract.rst +++ b/doc/source/api/internal/transfer/inbound/downloader/abstract.rst @@ -1,7 +1,7 @@ -:mod:`b2sdk.transfer.inbound.downloader.abstract` -- Downloader base class -========================================================================== +:mod:`b2sdk._internal.transfer.inbound.downloader.abstract` -- Downloader base class +==================================================================================== -.. automodule:: b2sdk.transfer.inbound.downloader.abstract +.. automodule:: b2sdk._internal.transfer.inbound.downloader.abstract :members: :undoc-members: :show-inheritance: diff --git a/doc/source/api/internal/transfer/inbound/downloader/parallel.rst b/doc/source/api/internal/transfer/inbound/downloader/parallel.rst index 8e78f3668..6d82f01ac 100644 --- a/doc/source/api/internal/transfer/inbound/downloader/parallel.rst +++ b/doc/source/api/internal/transfer/inbound/downloader/parallel.rst @@ -1,7 +1,7 @@ -:mod:`b2sdk.transfer.inbound.downloader.parallel` -- ParallelTransferer -======================================================================= +:mod:`b2sdk._internal.transfer.inbound.downloader.parallel` -- ParallelTransferer +================================================================================= -.. automodule:: b2sdk.transfer.inbound.downloader.parallel +.. automodule:: b2sdk._internal.transfer.inbound.downloader.parallel :members: :undoc-members: :show-inheritance: diff --git a/doc/source/api/internal/transfer/inbound/downloader/simple.rst b/doc/source/api/internal/transfer/inbound/downloader/simple.rst index dbddfa9cb..bd440e085 100644 --- a/doc/source/api/internal/transfer/inbound/downloader/simple.rst +++ b/doc/source/api/internal/transfer/inbound/downloader/simple.rst @@ -1,7 +1,7 @@ -:mod:`b2sdk.transfer.inbound.downloader.simple` -- SimpleDownloader -=================================================================== +:mod:`b2sdk._internal.transfer.inbound.downloader.simple` -- SimpleDownloader +============================================================================= -.. automodule:: b2sdk.transfer.inbound.downloader.simple +.. automodule:: b2sdk._internal.transfer.inbound.downloader.simple :members: :undoc-members: :show-inheritance: diff --git a/doc/source/api/internal/transfer/outbound/upload_source.rst b/doc/source/api/internal/transfer/outbound/upload_source.rst index dac6b0471..8351403ce 100644 --- a/doc/source/api/internal/transfer/outbound/upload_source.rst +++ b/doc/source/api/internal/transfer/outbound/upload_source.rst @@ -1,7 +1,7 @@ -:mod:`b2sdk.transfer.outbound.upload_source` -============================================ +:mod:`b2sdk._internal.transfer.outbound.upload_source` +====================================================== -.. automodule:: b2sdk.transfer.outbound.upload_source +.. automodule:: b2sdk._internal.transfer.outbound.upload_source :members: :undoc-members: :show-inheritance: diff --git a/doc/source/api/internal/utils.rst b/doc/source/api/internal/utils.rst index 3465937b7..163b4828f 100644 --- a/doc/source/api/internal/utils.rst +++ b/doc/source/api/internal/utils.rst @@ -1,7 +1,7 @@ -:mod:`b2sdk.utils` -======================================== +:mod:`b2sdk._internal.utils` +============================ -.. automodule:: b2sdk.utils +.. automodule:: b2sdk._internal.utils :members: :undoc-members: :show-inheritance: diff --git a/doc/source/api/progress.rst b/doc/source/api/progress.rst index 5362d2264..94ccc2062 100644 --- a/doc/source/api/progress.rst +++ b/doc/source/api/progress.rst @@ -1,5 +1,5 @@ Progress reporters -========================================== +================== .. note:: Concrete classes described in this chapter implement methods defined in ``AbstractProgressListener`` @@ -26,4 +26,3 @@ Progress reporters :no-members: .. autofunction:: b2sdk.v2.make_progress_listener - diff --git a/doc/source/api/transfer/emerge/write_intent.rst b/doc/source/api/transfer/emerge/write_intent.rst index 29ebf95f6..bed93e218 100644 --- a/doc/source/api/transfer/emerge/write_intent.rst +++ b/doc/source/api/transfer/emerge/write_intent.rst @@ -1,5 +1,5 @@ Write intent -=============================================== +============ .. autoclass:: b2sdk.v2.WriteIntent() :inherited-members: diff --git a/doc/source/api/transfer/outbound/outbound_source.rst b/doc/source/api/transfer/outbound/outbound_source.rst index bd18d7bef..67809ba83 100644 --- a/doc/source/api/transfer/outbound/outbound_source.rst +++ b/doc/source/api/transfer/outbound/outbound_source.rst @@ -1,5 +1,5 @@ Outbound Transfer Source -=============================================== +======================== .. autoclass:: b2sdk.v2.OutboundTransferSource() :inherited-members: diff --git a/doc/source/api/utils.rst b/doc/source/api/utils.rst index 17e658d39..1bfebec94 100644 --- a/doc/source/api/utils.rst +++ b/doc/source/api/utils.rst @@ -13,4 +13,3 @@ B2 Utility functions .. autoclass:: b2sdk.v2.TempDir() :inherited-members: :special-members: __enter__, __exit__ - diff --git a/doc/source/quick_start.rst b/doc/source/quick_start.rst index f3ec811dc..b3b296dbd 100644 --- a/doc/source/quick_start.rst +++ b/doc/source/quick_start.rst @@ -178,7 +178,7 @@ Upload file file_name=b2_file_name, file_infos=file_info, ) - + This will work regardless of the size of the file - ``upload_local_file`` automatically uses large file upload API when necessary. diff --git a/doc/sqlite_account_info_schema.py b/doc/sqlite_account_info_schema.py index d2d2ff5b1..edfdbd532 100755 --- a/doc/sqlite_account_info_schema.py +++ b/doc/sqlite_account_info_schema.py @@ -16,7 +16,7 @@ from sadisplay import describe, render from sqlalchemy import create_engine, MetaData -from b2sdk.account_info.sqlite_account_info import SqliteAccountInfo +from b2sdk._internal.account_info.sqlite_account_info import SqliteAccountInfo def main(): diff --git a/noxfile.py b/noxfile.py index fa9b40eb7..770e362b4 100644 --- a/noxfile.py +++ b/noxfile.py @@ -185,7 +185,7 @@ def build(session): @nox.session(python=PYTHON_DEFAULT_VERSION) def doc(session): """Build the documentation.""" - pdm_install(session, 'doc', dev=False) + pdm_install(session, 'doc') session.cd('doc') sphinx_args = ['-b', 'html', '-T', '-W', 'source', 'build/html'] session.run('rm', '-rf', 'build', external=True) @@ -203,7 +203,7 @@ def doc(session): @nox.session def doc_cover(session): """Perform coverage analysis for the documentation.""" - pdm_install(session, 'doc', dev=False) + pdm_install(session, 'doc') session.cd('doc') sphinx_args = ['-b', 'coverage', '-T', '-W', 'source', 'build/coverage'] report_file = 'build/coverage/python.txt' diff --git a/pdm.lock b/pdm.lock index 9abaf0eca..af602e006 100644 --- a/pdm.lock +++ b/pdm.lock @@ -5,7 +5,7 @@ groups = ["default", "doc", "format", "lint", "release", "test"] strategy = ["cross_platform", "inherit_metadata"] lock_version = "4.4.1" -content_hash = "sha256:5cd425d64818d99f7f48a8198c1f6b43453a9360d9d6a4ef262850f501d54b8d" +content_hash = "sha256:10acaf36178d2fa68d0b3eb3af65f8844349a6d9a42416258f6f133640f03528" [[package]] name = "alabaster" @@ -187,7 +187,7 @@ name = "colorama" version = "0.4.6" requires_python = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" summary = "Cross-platform colored terminal text." -groups = ["default", "doc", "lint", "release", "test"] +groups = ["doc", "lint", "release", "test"] files = [ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, @@ -628,7 +628,7 @@ name = "packaging" version = "23.2" requires_python = ">=3.7" summary = "Core utilities for Python packages" -groups = ["default", "doc", "lint", "test"] +groups = ["doc", "lint", "test"] files = [ {file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"}, {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, @@ -862,7 +862,7 @@ name = "setuptools" version = "68.0.0" requires_python = ">=3.7" summary = "Easily download, build, install, upgrade, and uninstall Python packages" -groups = ["default"] +groups = ["lint"] files = [ {file = "setuptools-68.0.0-py3-none-any.whl", hash = "sha256:11e52c67415a381d10d6b462ced9cfb97066179f0e871399e006c4ab101fc85f"}, {file = "setuptools-68.0.0.tar.gz", hash = "sha256:baf1fdb41c6da4cd2eae722e135500da913332ab3f2f5c7d33af9b492acb5235"}, @@ -1188,7 +1188,7 @@ name = "tqdm" version = "4.66.1" requires_python = ">=3.7" summary = "Fast, Extensible Progress Meter" -groups = ["default"] +groups = ["test"] dependencies = [ "colorama; platform_system == \"Windows\"", ] diff --git a/pyproject.toml b/pyproject.toml index a1300d631..34ac0cccf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,9 +9,7 @@ dependencies = [ "importlib-metadata>=3.3.0; python_version < '3.8'", "logfury<2.0.0,>=1.0.1", "requests<3.0.0,>=2.9.1", - "tqdm<5.0.0,>=4.5.0", "typing-extensions>=4.7.1; python_version < '3.12'", - "packaging>=21.0", ] requires-python = ">=3.7" readme = "README.md" @@ -31,19 +29,6 @@ classifiers = [ "Programming Language :: Python :: 3.12", ] -[project.optional-dependencies] -# doc group should be moved to dev dependencies when we release -# a new major version. -doc = [ - "sadisplay>=0.4.9", - "sphinx>=5.3.0, <6", - "sphinx-autobuild>=2021.3.14", - "sphinx-rtd-theme>=2.0.0", - "sphinx-autodoc-typehints>=1.23.0", - "sphinxcontrib-plantuml>=0.27", - "tornado>=6.3.3; python_version>='3.8'", -] - [project.urls] Homepage = "https://github.com/Backblaze/b2-sdk-python" @@ -104,6 +89,7 @@ target-version = "py37" [tool.ruff.per-file-ignores] "__init__.py" = ["I", "F401"] +"b2sdk/_v3/__init__.py" = ["E402"] "b2sdk/v*/**" = ["I", "F403", "F405"] "b2sdk/_v*/**" = ["I", "F403", "F405"] "test/**" = ["D", "F403", "F405"] @@ -180,7 +166,17 @@ test = [ "pytest-lazy-fixture==0.6.3", "pytest-xdist==2.5.0", "pytest-timeout==2.1.0", + "tqdm<5.0.0,>=4.5.0", ] release = [ "towncrier==23.11.0; python_version>='3.8'", ] +doc = [ + "sadisplay>=0.4.9", + "sphinx>=5.3.0, <6", + "sphinx-autobuild>=2021.3.14", + "sphinx-rtd-theme>=2.0.0", + "sphinx-autodoc-typehints>=1.23.0", + "sphinxcontrib-plantuml>=0.27", + "tornado>=6.3.3; python_version>='3.8'", +] diff --git a/test/integration/conftest.py b/test/integration/conftest.py index cf96039ef..630748307 100644 --- a/test/integration/conftest.py +++ b/test/integration/conftest.py @@ -23,7 +23,7 @@ import pytest -from b2sdk.utils import current_time_millis +from b2sdk._internal.utils import current_time_millis def pytest_addoption(parser): diff --git a/test/integration/test_download.py b/test/integration/test_download.py index a7faf772c..ff1b5779f 100644 --- a/test/integration/test_download.py +++ b/test/integration/test_download.py @@ -20,8 +20,8 @@ import pytest +from b2sdk._internal.utils import Sha1HexDigest from b2sdk._internal.utils.filesystem import _IS_WINDOWS -from b2sdk.utils import Sha1HexDigest from b2sdk.v2 import * from .base import IntegrationTestBase diff --git a/test/integration/test_raw_api.py b/test/integration/test_raw_api.py index e0cef927f..cbc83a3d5 100644 --- a/test/integration/test_raw_api.py +++ b/test/integration/test_raw_api.py @@ -19,20 +19,24 @@ import pytest -from b2sdk.b2http import B2Http -from b2sdk.encryption.setting import EncryptionAlgorithm, EncryptionMode, EncryptionSetting -from b2sdk.exception import DisablingFileLockNotSupported, Unauthorized -from b2sdk.file_lock import ( +from b2sdk._internal.b2http import B2Http +from b2sdk._internal.encryption.setting import ( + EncryptionAlgorithm, + EncryptionMode, + EncryptionSetting, +) +from b2sdk._internal.exception import DisablingFileLockNotSupported, Unauthorized +from b2sdk._internal.file_lock import ( NO_RETENTION_FILE_SETTING, BucketRetentionSetting, FileRetentionSetting, RetentionMode, RetentionPeriod, ) -from b2sdk.raw_api import ALL_CAPABILITIES, REALM_URLS, B2RawHTTPApi -from b2sdk.replication.setting import ReplicationConfiguration, ReplicationRule -from b2sdk.replication.types import ReplicationStatus -from b2sdk.utils import hex_sha1_of_stream +from b2sdk._internal.raw_api import ALL_CAPABILITIES, REALM_URLS, B2RawHTTPApi +from b2sdk._internal.replication.setting import ReplicationConfiguration, ReplicationRule +from b2sdk._internal.replication.types import ReplicationStatus +from b2sdk._internal.utils import hex_sha1_of_stream # TODO: rewrite to separate test cases diff --git a/test/integration/test_upload.py b/test/integration/test_upload.py index b3d79939b..1dba4986b 100644 --- a/test/integration/test_upload.py +++ b/test/integration/test_upload.py @@ -11,9 +11,9 @@ import io -from b2sdk.b2http import B2Http -from b2sdk.encryption.setting import EncryptionKey, EncryptionSetting -from b2sdk.encryption.types import EncryptionAlgorithm, EncryptionMode +from b2sdk._internal.b2http import B2Http +from b2sdk._internal.encryption.setting import EncryptionKey, EncryptionSetting +from b2sdk._internal.encryption.types import EncryptionAlgorithm, EncryptionMode from b2sdk.v2 import B2RawHTTPApi from .base import IntegrationTestBase diff --git a/test/unit/b2http/test_b2http.py b/test/unit/b2http/test_b2http.py index bf29e3039..789d04263 100644 --- a/test/unit/b2http/test_b2http.py +++ b/test/unit/b2http/test_b2http.py @@ -33,7 +33,7 @@ UnknownHost, ) -from b2sdk.b2http import setlocale +from b2sdk._internal.b2http import setlocale from ..test_base import TestBase diff --git a/test/unit/bucket/test_bucket.py b/test/unit/bucket/test_bucket.py index 8521a250b..6df52191e 100644 --- a/test/unit/bucket/test_bucket.py +++ b/test/unit/bucket/test_bucket.py @@ -2783,7 +2783,7 @@ def test_get_chunk_size_alignment(self): def test_buffering_in_save_to(self): with tempfile.TemporaryDirectory() as d: path = pathlib.Path(d) / 'file2' - with mock.patch('b2sdk.transfer.inbound.downloaded_file.open') as mock_open: + with mock.patch('b2sdk._internal.transfer.inbound.downloaded_file.open') as mock_open: mock_open.side_effect = open self.bucket.download_file_by_id(self.file_version.id_).save_to(path) mock_open.assert_called_once_with(path, mock.ANY, buffering=self.ALIGN_FACTOR) diff --git a/test/unit/filter/test_filter.py b/test/unit/filter/test_filter.py index 44dfb1652..42b2c4d70 100644 --- a/test/unit/filter/test_filter.py +++ b/test/unit/filter/test_filter.py @@ -12,7 +12,7 @@ import pytest from apiver_deps import Filter -from b2sdk.filter import FilterMatcher +from b2sdk._internal.filter import FilterMatcher @pytest.mark.parametrize( diff --git a/test/unit/internal/test_emerge_planner.py b/test/unit/internal/test_emerge_planner.py index d5810ba79..1510d5e4c 100644 --- a/test/unit/internal/test_emerge_planner.py +++ b/test/unit/internal/test_emerge_planner.py @@ -13,27 +13,27 @@ import pytest -from b2sdk.account_info.abstract import AbstractAccountInfo -from b2sdk.http_constants import ( +from b2sdk._internal.account_info.abstract import AbstractAccountInfo +from b2sdk._internal.http_constants import ( DEFAULT_MAX_PART_SIZE, DEFAULT_MIN_PART_SIZE, DEFAULT_RECOMMENDED_UPLOAD_PART_SIZE, GIGABYTE, MEGABYTE, ) -from b2sdk.transfer.emerge.planner.part_definition import ( +from b2sdk._internal.transfer.emerge.planner.part_definition import ( CopyEmergePartDefinition, UploadEmergePartDefinition, UploadSubpartsEmergePartDefinition, ) -from b2sdk.transfer.emerge.planner.planner import EmergePlanner -from b2sdk.transfer.emerge.planner.upload_subpart import ( +from b2sdk._internal.transfer.emerge.planner.planner import EmergePlanner +from b2sdk._internal.transfer.emerge.planner.upload_subpart import ( LocalSourceUploadSubpart, RemoteSourceUploadSubpart, ) -from b2sdk.transfer.emerge.write_intent import WriteIntent -from b2sdk.transfer.outbound.copy_source import CopySource as OrigCopySource -from b2sdk.transfer.outbound.upload_source import UploadSourceStream +from b2sdk._internal.transfer.emerge.write_intent import WriteIntent +from b2sdk._internal.transfer.outbound.copy_source import CopySource as OrigCopySource +from b2sdk._internal.transfer.outbound.upload_source import UploadSourceStream from ..test_base import TestBase diff --git a/test/unit/internal/test_unbound_write_intent.py b/test/unit/internal/test_unbound_write_intent.py index 2426457e3..6ecc0035f 100644 --- a/test/unit/internal/test_unbound_write_intent.py +++ b/test/unit/internal/test_unbound_write_intent.py @@ -13,14 +13,14 @@ import string from unittest.mock import MagicMock -from b2sdk.transfer.emerge.unbound_write_intent import ( +from b2sdk._internal.transfer.emerge.unbound_write_intent import ( IOWrapper, UnboundSourceBytes, UnboundStreamBufferTimeout, UnboundWriteIntentGenerator, ) -from b2sdk.transfer.emerge.write_intent import WriteIntent -from b2sdk.utils import hex_sha1_of_bytes +from b2sdk._internal.transfer.emerge.write_intent import WriteIntent +from b2sdk._internal.utils import hex_sha1_of_bytes from ..test_base import TestBase diff --git a/test/unit/scan/test_folder_traversal.py b/test/unit/scan/test_folder_traversal.py index fe5437165..090321762 100644 --- a/test/unit/scan/test_folder_traversal.py +++ b/test/unit/scan/test_folder_traversal.py @@ -14,9 +14,9 @@ import pytest -from b2sdk.scan.folder import LocalFolder -from b2sdk.scan.policies import ScanPoliciesManager -from b2sdk.utils import fix_windows_path_limit +from b2sdk._internal.scan.folder import LocalFolder +from b2sdk._internal.scan.policies import ScanPoliciesManager +from b2sdk._internal.utils import fix_windows_path_limit class TestFolderTraversal: diff --git a/test/unit/test_exception.py b/test/unit/test_exception.py index 1766623b4..34c65a868 100644 --- a/test/unit/test_exception.py +++ b/test/unit/test_exception.py @@ -33,7 +33,7 @@ interpret_b2_error, ) -from b2sdk.exception import ResourceNotFound +from b2sdk._internal.exception import ResourceNotFound class TestB2Error: diff --git a/test/unit/test_included_modules.py b/test/unit/test_included_modules.py index f55d827e7..094bdeba1 100644 --- a/test/unit/test_included_modules.py +++ b/test/unit/test_included_modules.py @@ -11,8 +11,8 @@ import pathlib -from b2sdk import requests -from b2sdk.requests.included_source_meta import included_source_meta +from b2sdk._internal import requests +from b2sdk._internal.requests.included_source_meta import included_source_meta def test_requests_notice_file(): diff --git a/test/unit/test_progress.py b/test/unit/test_progress.py new file mode 100644 index 000000000..5cf293265 --- /dev/null +++ b/test/unit/test_progress.py @@ -0,0 +1,33 @@ +###################################################################### +# +# File: test/unit/test_progress.py +# +# Copyright 2024 Backblaze Inc. All Rights Reserved. +# +# License https://www.backblaze.com/using_b2_code.html +# +###################################################################### +import pytest +from apiver_deps import TqdmProgressListener, make_progress_listener + + +@pytest.mark.parametrize( + "tqdm_available, quiet, expected_listener", + [ + (True, False, "TqdmProgressListener"), + (False, False, "SimpleProgressListener"), + (False, True, "DoNothingProgressListener"), + ], +) +def test_make_progress_listener(tqdm_available, quiet, expected_listener, monkeypatch): + if not tqdm_available: + monkeypatch.setattr("b2sdk._internal.progress.tqdm", None) + + assert make_progress_listener("description", quiet).__class__.__name__ == expected_listener + + +def test_tqdm_progress_listener__without_tqdm_module(monkeypatch): + monkeypatch.setattr("b2sdk._internal.progress.tqdm", None) + + with pytest.raises(ModuleNotFoundError): + TqdmProgressListener("description") diff --git a/test/unit/utils/test_docs.py b/test/unit/utils/test_docs.py index c7a1e086a..ce26ee468 100644 --- a/test/unit/utils/test_docs.py +++ b/test/unit/utils/test_docs.py @@ -11,8 +11,8 @@ import pytest -from b2sdk.raw_api import AbstractRawApi, LifecycleRule -from b2sdk.utils.docs import MissingDocURL, ensure_b2sdk_doc_urls, get_b2sdk_doc_urls +from b2sdk._internal.raw_api import AbstractRawApi, LifecycleRule +from b2sdk._internal.utils.docs import MissingDocURL, ensure_b2sdk_doc_urls, get_b2sdk_doc_urls def test_b2sdk_doc_urls(): diff --git a/test/unit/utils/test_escape.py b/test/unit/utils/test_escape.py index 2c505f6a9..dc1ebd679 100644 --- a/test/unit/utils/test_escape.py +++ b/test/unit/utils/test_escape.py @@ -8,7 +8,11 @@ # ###################################################################### -from b2sdk.utils.escape import escape_control_chars, substitute_control_chars, unprintable_to_hex +from b2sdk._internal.utils.escape import ( + escape_control_chars, + substitute_control_chars, + unprintable_to_hex, +) def test_unprintable_to_hex(): diff --git a/test/unit/utils/test_incremental_hex_digester.py b/test/unit/utils/test_incremental_hex_digester.py index 96cc1e06d..7635733e6 100644 --- a/test/unit/utils/test_incremental_hex_digester.py +++ b/test/unit/utils/test_incremental_hex_digester.py @@ -13,7 +13,7 @@ import io from test.unit.test_base import TestBase -from b2sdk.utils import ( +from b2sdk._internal.utils import ( IncrementalHexDigester, Sha1HexDigest, ) diff --git a/test/unit/utils/test_thread_pool.py b/test/unit/utils/test_thread_pool.py index 5742d3e35..82a3c4af0 100644 --- a/test/unit/utils/test_thread_pool.py +++ b/test/unit/utils/test_thread_pool.py @@ -11,7 +11,7 @@ import pytest -from b2sdk.utils.thread_pool import LazyThreadPool +from b2sdk._internal.utils.thread_pool import LazyThreadPool class TestLazyThreadPool: diff --git a/test/unit/v0/test_copy_manager.py b/test/unit/v0/test_copy_manager.py index 76765c00d..082c6e98f 100644 --- a/test/unit/v0/test_copy_manager.py +++ b/test/unit/v0/test_copy_manager.py @@ -9,8 +9,8 @@ ###################################################################### from __future__ import annotations -from b2sdk.http_constants import SSE_C_KEY_ID_FILE_INFO_KEY_NAME -from b2sdk.transfer.outbound.copy_manager import CopyManager +from b2sdk._internal.http_constants import SSE_C_KEY_ID_FILE_INFO_KEY_NAME +from b2sdk._internal.transfer.outbound.copy_manager import CopyManager from ..test_base import TestBase from .deps import ( diff --git a/test/unit/v1/test_copy_manager.py b/test/unit/v1/test_copy_manager.py index 3a9e5b9a3..c6ee6d8c5 100644 --- a/test/unit/v1/test_copy_manager.py +++ b/test/unit/v1/test_copy_manager.py @@ -9,8 +9,8 @@ ###################################################################### from __future__ import annotations -from b2sdk.http_constants import SSE_C_KEY_ID_FILE_INFO_KEY_NAME -from b2sdk.transfer.outbound.copy_manager import CopyManager +from b2sdk._internal.http_constants import SSE_C_KEY_ID_FILE_INFO_KEY_NAME +from b2sdk._internal.transfer.outbound.copy_manager import CopyManager from ..test_base import TestBase from .deps import (