-
Couldn't load subscription status.
- Fork 0
feat: add legacy type compatibility aliases for v1.x migration #69
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -102,6 +102,7 @@ def __init__( | |
| self, | ||
| *, | ||
| bearer_token: str | None = None, | ||
| api_token: str | None = None, # Legacy compatibility parameter | ||
| base_url: str | httpx.URL | None = None, | ||
| timeout: Union[float, Timeout, None, NotGiven] = NOT_GIVEN, | ||
| max_retries: int = DEFAULT_MAX_RETRIES, | ||
|
|
@@ -124,7 +125,17 @@ def __init__( | |
| """Construct a new synchronous Replicate client instance. | ||
|
|
||
| This automatically infers the `bearer_token` argument from the `REPLICATE_API_TOKEN` environment variable if it is not provided. | ||
|
|
||
| For legacy compatibility, you can also pass `api_token` instead of `bearer_token`. | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm, not a fan of the term "legacy" here, that won't age too well (legacy is relative). I think it would be better to mention a major version number instead? |
||
| """ | ||
| # Handle legacy api_token parameter | ||
| if api_token is not None and bearer_token is not None: | ||
| raise ReplicateError( | ||
| "Cannot specify both 'bearer_token' and 'api_token'. Please use 'bearer_token' (recommended) or 'api_token' for legacy compatibility." | ||
| ) | ||
| if api_token is not None: | ||
| bearer_token = api_token | ||
|
|
||
| if bearer_token is None: | ||
| bearer_token = _get_api_token_from_environment() | ||
| if bearer_token is None: | ||
|
|
@@ -324,6 +335,7 @@ def copy( | |
| self, | ||
| *, | ||
| bearer_token: str | None = None, | ||
| api_token: str | None = None, # Legacy compatibility parameter | ||
| base_url: str | httpx.URL | None = None, | ||
| timeout: float | Timeout | None | NotGiven = NOT_GIVEN, | ||
| http_client: httpx.Client | None = None, | ||
|
|
@@ -336,7 +348,17 @@ def copy( | |
| ) -> Self: | ||
| """ | ||
| Create a new client instance re-using the same options given to the current client with optional overriding. | ||
|
|
||
| For legacy compatibility, you can also pass `api_token` instead of `bearer_token`. | ||
| """ | ||
| # Handle legacy api_token parameter | ||
| if api_token is not None and bearer_token is not None: | ||
| raise ValueError( | ||
| "Cannot specify both 'bearer_token' and 'api_token'. Please use 'bearer_token' (recommended) or 'api_token' for legacy compatibility." | ||
| ) | ||
| if api_token is not None: | ||
| bearer_token = api_token | ||
|
|
||
| if default_headers is not None and set_default_headers is not None: | ||
| raise ValueError("The `default_headers` and `set_default_headers` arguments are mutually exclusive") | ||
|
|
||
|
|
@@ -477,6 +499,7 @@ def __init__( | |
| self, | ||
| *, | ||
| bearer_token: str | None = None, | ||
| api_token: str | None = None, # Legacy compatibility parameter | ||
| base_url: str | httpx.URL | None = None, | ||
| timeout: Union[float, Timeout, None, NotGiven] = NOT_GIVEN, | ||
| max_retries: int = DEFAULT_MAX_RETRIES, | ||
|
|
@@ -499,7 +522,17 @@ def __init__( | |
| """Construct a new async AsyncReplicate client instance. | ||
|
|
||
| This automatically infers the `bearer_token` argument from the `REPLICATE_API_TOKEN` environment variable if it is not provided. | ||
|
|
||
| For legacy compatibility, you can also pass `api_token` instead of `bearer_token`. | ||
| """ | ||
| # Handle legacy api_token parameter | ||
| if api_token is not None and bearer_token is not None: | ||
| raise ReplicateError( | ||
| "Cannot specify both 'bearer_token' and 'api_token'. Please use 'bearer_token' (recommended) or 'api_token' for legacy compatibility." | ||
| ) | ||
| if api_token is not None: | ||
| bearer_token = api_token | ||
|
|
||
| if bearer_token is None: | ||
| bearer_token = _get_api_token_from_environment() | ||
| if bearer_token is None: | ||
|
|
@@ -699,6 +732,7 @@ def copy( | |
| self, | ||
| *, | ||
| bearer_token: str | None = None, | ||
| api_token: str | None = None, # Legacy compatibility parameter | ||
| base_url: str | httpx.URL | None = None, | ||
| timeout: float | Timeout | None | NotGiven = NOT_GIVEN, | ||
| http_client: httpx.AsyncClient | None = None, | ||
|
|
@@ -711,7 +745,17 @@ def copy( | |
| ) -> Self: | ||
| """ | ||
| Create a new client instance re-using the same options given to the current client with optional overriding. | ||
|
|
||
| For legacy compatibility, you can also pass `api_token` instead of `bearer_token`. | ||
| """ | ||
| # Handle legacy api_token parameter | ||
| if api_token is not None and bearer_token is not None: | ||
| raise ValueError( | ||
| "Cannot specify both 'bearer_token' and 'api_token'. Please use 'bearer_token' (recommended) or 'api_token' for legacy compatibility." | ||
| ) | ||
| if api_token is not None: | ||
| bearer_token = api_token | ||
|
|
||
| if default_headers is not None and set_default_headers is not None: | ||
| raise ValueError("The `default_headers` and `set_default_headers` arguments are mutually exclusive") | ||
|
|
||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| """ | ||
| Legacy compatibility module for replicate-python v1.x type names. | ||
|
|
||
| This module provides backward compatibility for code that imports types | ||
| using the old v1.x import paths like: | ||
| from replicate.model import Model | ||
| from replicate.model import Version | ||
| """ | ||
|
|
||
| from __future__ import annotations | ||
|
|
||
| from typing import TYPE_CHECKING | ||
|
|
||
| from .types import Prediction as Prediction | ||
|
|
||
| # Import the actual types from their new locations | ||
| from .lib._models import Model as Model, Version as Version | ||
|
|
||
| # Also provide aliases for the response types for type checking | ||
| if TYPE_CHECKING: | ||
| from .types import ModelGetResponse as ModelResponse | ||
| from .types.models.version_get_response import VersionGetResponse as VersionResponse | ||
| else: | ||
| # At runtime, make the response types available under legacy names | ||
| from .types import ModelGetResponse as ModelResponse | ||
| from .types.models.version_get_response import VersionGetResponse as VersionResponse | ||
|
|
||
| __all__ = [ | ||
| "Model", | ||
| "Version", | ||
| "Prediction", | ||
| "ModelResponse", | ||
| "VersionResponse", | ||
| ] | ||
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,88 @@ | ||
| """Tests for api_token legacy compatibility during client instantiation.""" | ||
|
|
||
| from __future__ import annotations | ||
|
|
||
| import pytest | ||
|
|
||
| from replicate import Replicate, AsyncReplicate, ReplicateError | ||
| from replicate._client import Client | ||
|
|
||
|
|
||
| class TestApiTokenCompatibility: | ||
| """Test that api_token parameter works as a legacy compatibility option.""" | ||
|
|
||
| def test_sync_client_with_api_token(self) -> None: | ||
| """Test that Replicate accepts api_token parameter.""" | ||
| client = Replicate(api_token="test_token_123") | ||
| assert client.bearer_token == "test_token_123" | ||
|
|
||
| def test_async_client_with_api_token(self) -> None: | ||
| """Test that AsyncReplicate accepts api_token parameter.""" | ||
| client = AsyncReplicate(api_token="test_token_123") | ||
| assert client.bearer_token == "test_token_123" | ||
|
|
||
| def test_sync_client_with_bearer_token(self) -> None: | ||
| """Test that Replicate still accepts bearer_token parameter.""" | ||
| client = Replicate(bearer_token="test_token_123") | ||
| assert client.bearer_token == "test_token_123" | ||
|
|
||
| def test_async_client_with_bearer_token(self) -> None: | ||
| """Test that AsyncReplicate still accepts bearer_token parameter.""" | ||
| client = AsyncReplicate(bearer_token="test_token_123") | ||
| assert client.bearer_token == "test_token_123" | ||
|
|
||
| def test_sync_client_both_tokens_error(self) -> None: | ||
| """Test that providing both api_token and bearer_token raises an error.""" | ||
| with pytest.raises(ReplicateError, match="Cannot specify both 'bearer_token' and 'api_token'"): | ||
| Replicate(api_token="test_api", bearer_token="test_bearer") | ||
|
|
||
| def test_async_client_both_tokens_error(self) -> None: | ||
| """Test that providing both api_token and bearer_token raises an error.""" | ||
| with pytest.raises(ReplicateError, match="Cannot specify both 'bearer_token' and 'api_token'"): | ||
| AsyncReplicate(api_token="test_api", bearer_token="test_bearer") | ||
|
|
||
| def test_sync_client_no_token_with_env(self, monkeypatch: pytest.MonkeyPatch) -> None: | ||
| """Test that client reads from environment when no token is provided.""" | ||
| monkeypatch.setenv("REPLICATE_API_TOKEN", "env_token_123") | ||
| client = Replicate() | ||
| assert client.bearer_token == "env_token_123" | ||
|
|
||
| def test_async_client_no_token_with_env(self, monkeypatch: pytest.MonkeyPatch) -> None: | ||
| """Test that async client reads from environment when no token is provided.""" | ||
| monkeypatch.setenv("REPLICATE_API_TOKEN", "env_token_123") | ||
| client = AsyncReplicate() | ||
| assert client.bearer_token == "env_token_123" | ||
|
|
||
| def test_sync_client_no_token_no_env(self, monkeypatch: pytest.MonkeyPatch) -> None: | ||
| """Test that client raises error when no token is provided and env is not set.""" | ||
| monkeypatch.delenv("REPLICATE_API_TOKEN", raising=False) | ||
| with pytest.raises(ReplicateError, match="The bearer_token client option must be set"): | ||
| Replicate() | ||
|
|
||
| def test_async_client_no_token_no_env(self, monkeypatch: pytest.MonkeyPatch) -> None: | ||
| """Test that async client raises error when no token is provided and env is not set.""" | ||
| monkeypatch.delenv("REPLICATE_API_TOKEN", raising=False) | ||
| with pytest.raises(ReplicateError, match="The bearer_token client option must be set"): | ||
| AsyncReplicate() | ||
|
|
||
| def test_legacy_client_alias(self) -> None: | ||
| """Test that legacy Client import still works as an alias.""" | ||
| assert Client is Replicate | ||
|
|
||
| def test_legacy_client_with_api_token(self) -> None: | ||
| """Test that legacy Client alias works with api_token parameter.""" | ||
| client = Client(api_token="test_token_123") | ||
| assert client.bearer_token == "test_token_123" | ||
| assert isinstance(client, Replicate) | ||
|
|
||
| def test_api_token_overrides_env(self, monkeypatch: pytest.MonkeyPatch) -> None: | ||
| """Test that explicit api_token overrides environment variable.""" | ||
| monkeypatch.setenv("REPLICATE_API_TOKEN", "env_token") | ||
| client = Replicate(api_token="explicit_token") | ||
| assert client.bearer_token == "explicit_token" | ||
|
|
||
| def test_bearer_token_overrides_env(self, monkeypatch: pytest.MonkeyPatch) -> None: | ||
| """Test that explicit bearer_token overrides environment variable.""" | ||
| monkeypatch.setenv("REPLICATE_API_TOKEN", "env_token") | ||
| client = Replicate(bearer_token="explicit_token") | ||
| assert client.bearer_token == "explicit_token" |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.