Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion b2sdk/_internal/raw_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -553,7 +553,7 @@ def _post_json(self, base_url: str, endpoint: str, auth: str, **params) -> JSON:
:param args: the rest of the parameters are passed to b2
:return: the decoded JSON response
"""
url = f'{base_url}/b2api/{API_VERSION}/{endpoint}'
url = f'{base_url}/b2api/{self.API_VERSION}/{endpoint}'
headers = {'Authorization': auth}
return self.b2_http.post_json_return_json(url, headers, params)

Expand Down
29 changes: 25 additions & 4 deletions b2sdk/v2/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
from .file_version import FileVersionFactory
from .large_file import LargeFileServices
from .application_key import FullApplicationKey, ApplicationKey, BaseApplicationKey
from .account_info import AbstractAccountInfo
from .api_config import DEFAULT_HTTP_API_CONFIG, B2HttpApiConfig


class Services(v3.Services):
Expand All @@ -48,10 +50,29 @@ class B2Api(v3.B2Api):
API_VERSION = RAW_API_VERSION

# Legacy init in case something depends on max_workers defaults = 10
def __init__(self, *args, **kwargs):
kwargs.setdefault('max_upload_workers', 10)
kwargs.setdefault('max_copy_workers', 10)
super().__init__(*args, **kwargs)
def __init__(
self,
account_info: AbstractAccountInfo | None = None,
cache: v3.AbstractCache | None = None,
max_upload_workers: int | None = 10,
max_copy_workers: int | None = 10,
api_config: B2HttpApiConfig = DEFAULT_HTTP_API_CONFIG,
max_download_workers: int | None = None,
save_to_buffer_size: int | None = None,
check_download_hash: bool = True,
max_download_streams_per_file: int | None = None,
):
super().__init__(
account_info=account_info,
cache=cache,
max_upload_workers=max_upload_workers,
max_copy_workers=max_copy_workers,
api_config=api_config,
max_download_workers=max_download_workers,
save_to_buffer_size=save_to_buffer_size,
check_download_hash=check_download_hash,
max_download_streams_per_file=max_download_streams_per_file,
)

def get_bucket_by_id(self, bucket_id: str) -> v3.Bucket:
try:
Expand Down
18 changes: 18 additions & 0 deletions b2sdk/v2/api_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
######################################################################
#
# File: b2sdk/v2/api_config.py
#
# Copyright 2025 Backblaze Inc. All Rights Reserved.
#
# License https://www.backblaze.com/using_b2_code.html
#
######################################################################
from b2sdk import v3
from .raw_api import B2RawHTTPApi


class B2HttpApiConfig(v3.B2HttpApiConfig):
DEFAULT_RAW_API_CLASS = B2RawHTTPApi


DEFAULT_HTTP_API_CONFIG = B2HttpApiConfig()
5 changes: 4 additions & 1 deletion b2sdk/v2/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,16 @@
from b2sdk import v3
from .b2http import B2Http

from .account_info import SqliteAccountInfo
from ._compat import _file_infos_rename
from .._internal import api_config as _api_config
from . import api_config as _api_config
from .._internal import cache as _cache
from .._internal.account_info import abstract as _abstract


# Override to use legacy B2Http
class B2Session(v3.B2Session):
SQLITE_ACCOUNT_INFO_CLASS = staticmethod(SqliteAccountInfo)
B2HTTP_CLASS = staticmethod(B2Http)

def __init__(
Expand All @@ -31,6 +33,7 @@ def __init__(
if account_info is not None and cache is None:
# preserve legacy behavior https://github.com/Backblaze/b2-sdk-python/issues/497#issuecomment-2147461352
cache = _cache.DummyCache()

super().__init__(account_info, cache, api_config)

def create_key(
Expand Down
1 change: 1 addition & 0 deletions changelog.d/540.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix incorrect reliance on v3 abstractions in apiver v2.
14 changes: 13 additions & 1 deletion test/unit/v2/test_session.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from apiver_deps_exception import Unauthorized

from b2sdk import v3
from b2sdk.v2 import B2Session
from b2sdk.v2 import B2Http, B2RawHTTPApi, B2Session
from test.helpers import patch_bind_params

from ..account_info.fixtures import * # noqa
Expand Down Expand Up @@ -74,6 +74,18 @@ def dummy_session():
return B2Session()


def test_session__default_classes_v2():
session = B2Session()

assert isinstance(session.raw_api, B2RawHTTPApi), 'Expected v2.B2RawHTTPApi, got %s' % type(
session.raw_api
)

assert isinstance(session.raw_api.b2_http, B2Http), 'Expected v2.B2Http, got %s' % type(
session.raw_api.b2_http
)


def test_session__upload_file__supports_file_infos(dummy_session, file_info):
"""Test v2.B2Session.upload_file support of deprecated file_infos param"""
with patch_bind_params(v3.B2Session, 'upload_file') as mock_method, pytest.warns(
Expand Down
3 changes: 3 additions & 0 deletions test/unit/v_all/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from apiver_deps import (
B2Api,
B2HttpApiConfig,
B2Session,
Bucket,
EncryptionMode,
EncryptionSetting,
Expand Down Expand Up @@ -73,6 +74,8 @@ def test_api_initialization(self, kwargs, _raw_api_class):

self.api = B2Api(self.account_info, self.cache, api_config=api_config, **kwargs)

assert isinstance(self.api.session, B2Session) # ensure correct apiver session is used

assert self.api.account_info is self.account_info
assert self.api.api_config is api_config
assert self.api.cache is self.cache
Expand Down