diff --git a/src/anthropic/__init__.py b/src/anthropic/__init__.py index 2b6b1a54..7a44880e 100644 --- a/src/anthropic/__init__.py +++ b/src/anthropic/__init__.py @@ -1,51 +1,113 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +from __future__ import annotations + +import os as _os import typing as _t +import logging as _logging -from . import types -from ._types import NOT_GIVEN, Omit, NoneType, NotGiven, Transport, ProxiesTypes, omit, not_given -from ._utils import file_from_path -from ._client import ( - Client, - Stream, - Timeout, - Anthropic, - Transport, - AsyncClient, - AsyncStream, - AsyncAnthropic, - RequestOptions, -) -from ._models import BaseModel from ._version import __title__, __version__ -from ._response import APIResponse as APIResponse, AsyncAPIResponse as AsyncAPIResponse -from ._constants import ( - AI_PROMPT as AI_PROMPT, - HUMAN_PROMPT as HUMAN_PROMPT, - DEFAULT_TIMEOUT, - DEFAULT_MAX_RETRIES, - DEFAULT_CONNECTION_LIMITS, -) -from ._exceptions import ( - APIError, - ConflictError, - NotFoundError, - AnthropicError, - APIStatusError, - RateLimitError, - APITimeoutError, - BadRequestError, - APIConnectionError, - AuthenticationError, - InternalServerError, - PermissionDeniedError, - UnprocessableEntityError, - APIWebhookValidationError, - APIResponseValidationError, -) -from ._base_client import DefaultHttpxClient, DefaultAioHttpClient, DefaultAsyncHttpxClient -from ._utils._logs import setup_logging as _setup_logging -from .lib._parse._transform import transform_schema + +if _t.TYPE_CHECKING: + from . import types as types + from ._types import NOT_GIVEN, Omit, NoneType, NotGiven, Transport, ProxiesTypes, omit, not_given + from ._utils import file_from_path as file_from_path + from ._client import ( + Client as Client, + Stream as Stream, + Timeout as Timeout, + Anthropic as Anthropic, + AsyncClient as AsyncClient, + AsyncStream as AsyncStream, + AsyncAnthropic as AsyncAnthropic, + RequestOptions as RequestOptions, + ) + from ._models import BaseModel as BaseModel + from .lib.aws import AnthropicAWS as AnthropicAWS, AsyncAnthropicAWS as AsyncAnthropicAWS + from ._response import APIResponse as APIResponse, AsyncAPIResponse as AsyncAPIResponse + from .lib.tools import beta_tool as beta_tool, beta_async_tool as beta_async_tool + from ._constants import ( + AI_PROMPT as AI_PROMPT, + HUMAN_PROMPT as HUMAN_PROMPT, + DEFAULT_TIMEOUT as DEFAULT_TIMEOUT, + DEFAULT_MAX_RETRIES as DEFAULT_MAX_RETRIES, + DEFAULT_CONNECTION_LIMITS as DEFAULT_CONNECTION_LIMITS, + ) + from .lib.vertex import AnthropicVertex as AnthropicVertex, AsyncAnthropicVertex as AsyncAnthropicVertex + from ._exceptions import ( + APIError as APIError, + ConflictError as ConflictError, + NotFoundError as NotFoundError, + AnthropicError as AnthropicError, + APIStatusError as APIStatusError, + RateLimitError as RateLimitError, + APITimeoutError as APITimeoutError, + BadRequestError as BadRequestError, + APIConnectionError as APIConnectionError, + AuthenticationError as AuthenticationError, + InternalServerError as InternalServerError, + PermissionDeniedError as PermissionDeniedError, + UnprocessableEntityError as UnprocessableEntityError, + APIWebhookValidationError as APIWebhookValidationError, + APIResponseValidationError as APIResponseValidationError, + ) + from .lib.bedrock import ( + AnthropicBedrock as AnthropicBedrock, + AsyncAnthropicBedrock as AsyncAnthropicBedrock, + AnthropicBedrockMantle as AnthropicBedrockMantle, + AsyncAnthropicBedrockMantle as AsyncAnthropicBedrockMantle, + ) + from .lib.foundry import AnthropicFoundry as AnthropicFoundry, AsyncAnthropicFoundry as AsyncAnthropicFoundry + from ._base_client import ( + DefaultHttpxClient as DefaultHttpxClient, + DefaultAioHttpClient as DefaultAioHttpClient, + DefaultAsyncHttpxClient as DefaultAsyncHttpxClient, + ) + from .lib.streaming import ( + TextEvent as TextEvent, + BetaTextEvent as BetaTextEvent, + MessageStream as MessageStream, + InputJsonEvent as InputJsonEvent, + MessageStopEvent as MessageStopEvent, + BetaMessageStream as BetaMessageStream, + AsyncMessageStream as AsyncMessageStream, + BetaInputJsonEvent as BetaInputJsonEvent, + MessageStreamEvent as MessageStreamEvent, + ParsedBetaTextEvent as ParsedBetaTextEvent, + MessageStreamManager as MessageStreamManager, + ContentBlockStopEvent as ContentBlockStopEvent, + BetaAsyncMessageStream as BetaAsyncMessageStream, + BetaMessageStreamEvent as BetaMessageStreamEvent, + ParsedMessageStopEvent as ParsedMessageStopEvent, + BetaMessageStreamManager as BetaMessageStreamManager, + ParsedMessageStreamEvent as ParsedMessageStreamEvent, + AsyncMessageStreamManager as AsyncMessageStreamManager, + BetaContentBlockStopEvent as BetaContentBlockStopEvent, + ParsedBetaMessageStopEvent as ParsedBetaMessageStopEvent, + ParsedContentBlockStopEvent as ParsedContentBlockStopEvent, + ParsedBetaMessageStreamEvent as ParsedBetaMessageStreamEvent, + BetaAsyncMessageStreamManager as BetaAsyncMessageStreamManager, + ParsedBetaContentBlockStopEvent as ParsedBetaContentBlockStopEvent, + ) + from .lib.credentials import ( + EnvToken as EnvToken, + TokenCache as TokenCache, + AccessToken as AccessToken, + StaticToken as StaticToken, + InMemoryConfig as InMemoryConfig, + AccessTokenAuth as AccessTokenAuth, + CredentialsFile as CredentialsFile, + CredentialResult as CredentialResult, + IdentityTokenFile as IdentityTokenFile, + AccessTokenProvider as AccessTokenProvider, + IdentityTokenProvider as IdentityTokenProvider, + WorkloadIdentityError as WorkloadIdentityError, + WorkloadIdentityCredentials as WorkloadIdentityCredentials, + default_credentials as default_credentials, + exchange_federation_assertion as exchange_federation_assertion, + ) + from .lib._parse._transform import transform_schema as transform_schema + from ._utils._resources_proxy import resources as resources __all__ = [ "types", @@ -97,16 +159,146 @@ "transform_schema", ] -if not _t.TYPE_CHECKING: - from ._utils._resources_proxy import resources as resources +_LAZY_ATTRS: dict[str, tuple[str, str | None]] = { + "types": (".types", None), + "NoneType": ("._types", "NoneType"), + "Transport": ("._types", "Transport"), + "ProxiesTypes": ("._types", "ProxiesTypes"), + "NotGiven": ("._types", "NotGiven"), + "NOT_GIVEN": ("._types", "NOT_GIVEN"), + "not_given": ("._types", "not_given"), + "Omit": ("._types", "Omit"), + "omit": ("._types", "omit"), + "Timeout": ("._client", "Timeout"), + "RequestOptions": ("._client", "RequestOptions"), + "Client": ("._client", "Client"), + "AsyncClient": ("._client", "AsyncClient"), + "Stream": ("._client", "Stream"), + "AsyncStream": ("._client", "AsyncStream"), + "Anthropic": ("._client", "Anthropic"), + "AsyncAnthropic": ("._client", "AsyncAnthropic"), + "file_from_path": ("._utils", "file_from_path"), + "BaseModel": ("._models", "BaseModel"), + "DEFAULT_TIMEOUT": ("._constants", "DEFAULT_TIMEOUT"), + "DEFAULT_MAX_RETRIES": ("._constants", "DEFAULT_MAX_RETRIES"), + "DEFAULT_CONNECTION_LIMITS": ("._constants", "DEFAULT_CONNECTION_LIMITS"), + "HUMAN_PROMPT": ("._constants", "HUMAN_PROMPT"), + "AI_PROMPT": ("._constants", "AI_PROMPT"), + "AnthropicError": ("._exceptions", "AnthropicError"), + "APIError": ("._exceptions", "APIError"), + "APIStatusError": ("._exceptions", "APIStatusError"), + "APITimeoutError": ("._exceptions", "APITimeoutError"), + "APIConnectionError": ("._exceptions", "APIConnectionError"), + "APIResponseValidationError": ("._exceptions", "APIResponseValidationError"), + "APIWebhookValidationError": ("._exceptions", "APIWebhookValidationError"), + "BadRequestError": ("._exceptions", "BadRequestError"), + "AuthenticationError": ("._exceptions", "AuthenticationError"), + "PermissionDeniedError": ("._exceptions", "PermissionDeniedError"), + "NotFoundError": ("._exceptions", "NotFoundError"), + "ConflictError": ("._exceptions", "ConflictError"), + "UnprocessableEntityError": ("._exceptions", "UnprocessableEntityError"), + "RateLimitError": ("._exceptions", "RateLimitError"), + "InternalServerError": ("._exceptions", "InternalServerError"), + "APIResponse": ("._response", "APIResponse"), + "AsyncAPIResponse": ("._response", "AsyncAPIResponse"), + "DefaultHttpxClient": ("._base_client", "DefaultHttpxClient"), + "DefaultAsyncHttpxClient": ("._base_client", "DefaultAsyncHttpxClient"), + "DefaultAioHttpClient": ("._base_client", "DefaultAioHttpClient"), + "resources": ("._utils._resources_proxy", "resources"), + "AnthropicAWS": (".lib.aws", "AnthropicAWS"), + "AsyncAnthropicAWS": (".lib.aws", "AsyncAnthropicAWS"), + "beta_tool": (".lib.tools", "beta_tool"), + "beta_async_tool": (".lib.tools", "beta_async_tool"), + "AnthropicVertex": (".lib.vertex", "AnthropicVertex"), + "AsyncAnthropicVertex": (".lib.vertex", "AsyncAnthropicVertex"), + "AnthropicBedrock": (".lib.bedrock", "AnthropicBedrock"), + "AsyncAnthropicBedrock": (".lib.bedrock", "AsyncAnthropicBedrock"), + "AnthropicBedrockMantle": (".lib.bedrock", "AnthropicBedrockMantle"), + "AsyncAnthropicBedrockMantle": (".lib.bedrock", "AsyncAnthropicBedrockMantle"), + "AnthropicFoundry": (".lib.foundry", "AnthropicFoundry"), + "AsyncAnthropicFoundry": (".lib.foundry", "AsyncAnthropicFoundry"), + "TextEvent": (".lib.streaming", "TextEvent"), + "InputJsonEvent": (".lib.streaming", "InputJsonEvent"), + "MessageStream": (".lib.streaming", "MessageStream"), + "BetaTextEvent": (".lib.streaming", "BetaTextEvent"), + "AsyncMessageStream": (".lib.streaming", "AsyncMessageStream"), + "MessageStopEvent": (".lib.streaming", "MessageStopEvent"), + "MessageStreamEvent": (".lib.streaming", "MessageStreamEvent"), + "BetaInputJsonEvent": (".lib.streaming", "BetaInputJsonEvent"), + "MessageStreamManager": (".lib.streaming", "MessageStreamManager"), + "ContentBlockStopEvent": (".lib.streaming", "ContentBlockStopEvent"), + "ParsedBetaTextEvent": (".lib.streaming", "ParsedBetaTextEvent"), + "BetaMessageStream": (".lib.streaming", "BetaMessageStream"), + "BetaAsyncMessageStream": (".lib.streaming", "BetaAsyncMessageStream"), + "AsyncMessageStreamManager": (".lib.streaming", "AsyncMessageStreamManager"), + "BetaMessageStreamEvent": (".lib.streaming", "BetaMessageStreamEvent"), + "ParsedMessageStopEvent": (".lib.streaming", "ParsedMessageStopEvent"), + "BetaMessageStreamManager": (".lib.streaming", "BetaMessageStreamManager"), + "ParsedMessageStreamEvent": (".lib.streaming", "ParsedMessageStreamEvent"), + "BetaContentBlockStopEvent": (".lib.streaming", "BetaContentBlockStopEvent"), + "ParsedBetaMessageStopEvent": (".lib.streaming", "ParsedBetaMessageStopEvent"), + "ParsedContentBlockStopEvent": (".lib.streaming", "ParsedContentBlockStopEvent"), + "BetaAsyncMessageStreamManager": (".lib.streaming", "BetaAsyncMessageStreamManager"), + "ParsedBetaMessageStreamEvent": (".lib.streaming", "ParsedBetaMessageStreamEvent"), + "ParsedBetaContentBlockStopEvent": (".lib.streaming", "ParsedBetaContentBlockStopEvent"), + "EnvToken": (".lib.credentials", "EnvToken"), + "TokenCache": (".lib.credentials", "TokenCache"), + "AccessToken": (".lib.credentials", "AccessToken"), + "StaticToken": (".lib.credentials", "StaticToken"), + "AccessTokenAuth": (".lib.credentials", "AccessTokenAuth"), + "InMemoryConfig": (".lib.credentials", "InMemoryConfig"), + "CredentialsFile": (".lib.credentials", "CredentialsFile"), + "CredentialResult": (".lib.credentials", "CredentialResult"), + "IdentityTokenFile": (".lib.credentials", "IdentityTokenFile"), + "AccessTokenProvider": (".lib.credentials", "AccessTokenProvider"), + "default_credentials": (".lib.credentials", "default_credentials"), + "IdentityTokenProvider": (".lib.credentials", "IdentityTokenProvider"), + "WorkloadIdentityError": (".lib.credentials", "WorkloadIdentityError"), + "WorkloadIdentityCredentials": (".lib.credentials", "WorkloadIdentityCredentials"), + "exchange_federation_assertion": (".lib.credentials", "exchange_federation_assertion"), + "transform_schema": (".lib._parse._transform", "transform_schema"), +} + + +def __getattr__(name: str) -> _t.Any: + if name not in _LAZY_ATTRS: + raise AttributeError(f"module {__name__!r} has no attribute {name!r}") + + import importlib + + module_name, attr_name = _LAZY_ATTRS[name] + module = importlib.import_module(module_name, __name__) + attr = module if attr_name is None else getattr(module, attr_name) + globals()[name] = attr + + try: + attr.__module__ = "anthropic" + except (TypeError, AttributeError): + pass + + return attr + + +def _setup_logging() -> None: + logger = _logging.getLogger("anthropic") + httpx_logger = _logging.getLogger("httpx") + + env = _os.environ.get("ANTHROPIC_LOG") + if env == "debug": + _logging.basicConfig( + format="[%(asctime)s - %(name)s:%(lineno)d - %(levelname)s] %(message)s", + datefmt="%Y-%m-%d %H:%M:%S", + ) + logger.setLevel(_logging.DEBUG) + httpx_logger.setLevel(_logging.DEBUG) + elif env == "info": + _logging.basicConfig( + format="[%(asctime)s - %(name)s:%(lineno)d - %(levelname)s] %(message)s", + datefmt="%Y-%m-%d %H:%M:%S", + ) + logger.setLevel(_logging.INFO) + httpx_logger.setLevel(_logging.INFO) -from .lib.aws import AnthropicAWS as AnthropicAWS, AsyncAnthropicAWS as AsyncAnthropicAWS -from .lib.tools import beta_tool, beta_async_tool -from .lib.vertex import * -from .lib.bedrock import * -from .lib.foundry import AnthropicFoundry as AnthropicFoundry, AsyncAnthropicFoundry as AsyncAnthropicFoundry -from .lib.streaming import * -from .lib.credentials import * _setup_logging() @@ -119,6 +311,8 @@ if not __name.startswith("__"): try: __locals[__name].__module__ = "anthropic" + except KeyError: + pass except (TypeError, AttributeError): # Some of our exported symbols are builtins which we can't set attributes for. pass diff --git a/src/anthropic/_exceptions.py b/src/anthropic/_exceptions.py index c0556fa8..2ea4f9f4 100644 --- a/src/anthropic/_exceptions.py +++ b/src/anthropic/_exceptions.py @@ -2,13 +2,17 @@ from __future__ import annotations -from typing import Union, cast +from typing import TYPE_CHECKING, Union, cast from typing_extensions import Literal import httpx from ._utils import is_dict -from .types.shared.error_type import ErrorType + +if TYPE_CHECKING: + from .types.shared.error_type import ErrorType +else: + ErrorType = str __all__ = [ "BadRequestError", diff --git a/tests/test_imports.py b/tests/test_imports.py new file mode 100644 index 00000000..c0978c69 --- /dev/null +++ b/tests/test_imports.py @@ -0,0 +1,94 @@ +from __future__ import annotations + +import os +import sys +import json +import subprocess +from typing import Any +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[1] + + +def run_import_check(code: str) -> dict[str, Any]: + env = os.environ.copy() + env["PYTHONPATH"] = str(ROOT / "src") + result = subprocess.run([sys.executable, "-c", code], check=True, capture_output=True, text=True, env=env) + return json.loads(result.stdout) + + +def test_import_anthropic_does_not_load_heavy_reexports() -> None: + result = run_import_check( + """ +import json +import sys + +import anthropic + +modules = [ + "httpx", + "pydantic", + "anthropic._types", + "anthropic._client", + "anthropic._models", + "anthropic._base_client", + "anthropic._response", + "anthropic.types", + "anthropic.resources", + "anthropic.lib.tools", + "anthropic.lib.vertex", + "anthropic.lib.bedrock", + "anthropic.lib.streaming", + "anthropic.lib._parse._transform", +] + +print(json.dumps({module: module in sys.modules for module in modules})) +""" + ) + + assert result == { + "httpx": False, + "pydantic": False, + "anthropic._types": False, + "anthropic._client": False, + "anthropic._models": False, + "anthropic._base_client": False, + "anthropic._response": False, + "anthropic.types": False, + "anthropic.resources": False, + "anthropic.lib.tools": False, + "anthropic.lib.vertex": False, + "anthropic.lib.bedrock": False, + "anthropic.lib.streaming": False, + "anthropic.lib._parse._transform": False, + } + + +def test_lazy_root_reexports_still_resolve() -> None: + result = run_import_check( + """ +import json + +from anthropic import Anthropic, AnthropicBedrock, AnthropicVertex, NotGiven, beta_tool, transform_schema, types + +print(json.dumps({ + "types": types.__name__, + "Anthropic": Anthropic.__name__, + "AnthropicVertex": AnthropicVertex.__name__, + "AnthropicBedrock": AnthropicBedrock.__name__, + "NotGiven": NotGiven.__name__, + "beta_tool": beta_tool.__name__, + "transform_schema": transform_schema.__name__, +})) +""" + ) + + assert result == { + "types": "anthropic.types", + "Anthropic": "Anthropic", + "AnthropicVertex": "AnthropicVertex", + "AnthropicBedrock": "AnthropicBedrock", + "NotGiven": "NotGiven", + "beta_tool": "beta_tool", + "transform_schema": "transform_schema", + }