coco-framework 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- coco/__init__.py +3 -0
- coco/agents/__init__.py +9 -0
- coco/agents/_subagent_transformer.py +307 -0
- coco/agents/factory.py +2164 -0
- coco/agents/middleware/__init__.py +100 -0
- coco/agents/middleware/_execution.py +385 -0
- coco/agents/middleware/_redaction.py +454 -0
- coco/agents/middleware/_retry.py +134 -0
- coco/agents/middleware/_trace_policy.py +61 -0
- coco/agents/middleware/context_editing.py +306 -0
- coco/agents/middleware/file_search.py +433 -0
- coco/agents/middleware/human_in_the_loop.py +680 -0
- coco/agents/middleware/internal_call_transformer.py +108 -0
- coco/agents/middleware/model_call_limit.py +267 -0
- coco/agents/middleware/model_fallback.py +417 -0
- coco/agents/middleware/model_retry.py +327 -0
- coco/agents/middleware/pii.py +878 -0
- coco/agents/middleware/provider_tool_search.py +307 -0
- coco/agents/middleware/shell_tool.py +949 -0
- coco/agents/middleware/summarization.py +910 -0
- coco/agents/middleware/todo.py +357 -0
- coco/agents/middleware/tool_call_limit.py +495 -0
- coco/agents/middleware/tool_emulator.py +251 -0
- coco/agents/middleware/tool_error.py +209 -0
- coco/agents/middleware/tool_retry.py +421 -0
- coco/agents/middleware/tool_selection.py +515 -0
- coco/agents/middleware/types.py +2201 -0
- coco/agents/structured_output.py +472 -0
- coco/chat_models/__init__.py +7 -0
- coco/chat_models/base.py +1082 -0
- coco/embeddings/__init__.py +18 -0
- coco/embeddings/base.py +279 -0
- coco/mcp/__init__.py +36 -0
- coco/mcp/adapter.py +245 -0
- coco/mcp/elicitation.py +394 -0
- coco/mcp/tools.py +307 -0
- coco/messages/__init__.py +73 -0
- coco/py.typed +0 -0
- coco/rate_limiters/__init__.py +13 -0
- coco/tools/__init__.py +22 -0
- coco/tools/tool_node.py +20 -0
- coco_anthropic/__init__.py +15 -0
- coco_anthropic/_client_utils.py +81 -0
- coco_anthropic/_compat.py +228 -0
- coco_anthropic/_sdk_compat.py +124 -0
- coco_anthropic/_version.py +3 -0
- coco_anthropic/chat_models.py +3349 -0
- coco_anthropic/data/__init__.py +1 -0
- coco_anthropic/data/_profiles.py +491 -0
- coco_anthropic/data/profile_augmentations.toml +69 -0
- coco_anthropic/experimental.py +140 -0
- coco_anthropic/llms.py +428 -0
- coco_anthropic/middleware/__init__.py +25 -0
- coco_anthropic/middleware/anthropic_tools.py +1197 -0
- coco_anthropic/middleware/bash.py +84 -0
- coco_anthropic/middleware/file_search.py +360 -0
- coco_anthropic/middleware/prompt_caching.py +276 -0
- coco_anthropic/output_parsers.py +93 -0
- coco_anthropic/py.typed +0 -0
- coco_core/__init__.py +20 -0
- coco_core/_api/__init__.py +87 -0
- coco_core/_api/beta_decorator.py +266 -0
- coco_core/_api/deprecation.py +637 -0
- coco_core/_api/internal.py +23 -0
- coco_core/_api/path.py +50 -0
- coco_core/_import_utils.py +41 -0
- coco_core/_protocol.py +625 -0
- coco_core/_security/__init__.py +36 -0
- coco_core/_security/_exceptions.py +9 -0
- coco_core/_security/_policy.py +313 -0
- coco_core/_security/_ssrf_protection.py +155 -0
- coco_core/_security/_transport.py +254 -0
- coco_core/agents.py +258 -0
- coco_core/caches.py +272 -0
- coco_core/callbacks/__init__.py +132 -0
- coco_core/callbacks/base.py +1229 -0
- coco_core/callbacks/file.py +266 -0
- coco_core/callbacks/manager.py +2826 -0
- coco_core/callbacks/stdout.py +123 -0
- coco_core/callbacks/streaming_stdout.py +154 -0
- coco_core/callbacks/usage.py +124 -0
- coco_core/chat_history.py +267 -0
- coco_core/chat_loaders.py +26 -0
- coco_core/chat_sessions.py +19 -0
- coco_core/cross_encoders.py +18 -0
- coco_core/document_loaders/__init__.py +36 -0
- coco_core/document_loaders/base.py +155 -0
- coco_core/document_loaders/blob_loaders.py +38 -0
- coco_core/documents/__init__.py +55 -0
- coco_core/documents/base.py +347 -0
- coco_core/documents/compressor.py +74 -0
- coco_core/documents/transformers.py +79 -0
- coco_core/embeddings/__init__.py +31 -0
- coco_core/embeddings/embeddings.py +78 -0
- coco_core/embeddings/fake.py +129 -0
- coco_core/env.py +22 -0
- coco_core/example_selectors/__init__.py +47 -0
- coco_core/example_selectors/base.py +60 -0
- coco_core/example_selectors/length_based.py +131 -0
- coco_core/example_selectors/semantic_similarity.py +366 -0
- coco_core/exceptions.py +166 -0
- coco_core/globals.py +72 -0
- coco_core/indexing/__init__.py +53 -0
- coco_core/indexing/api.py +954 -0
- coco_core/indexing/base.py +661 -0
- coco_core/indexing/in_memory.py +104 -0
- coco_core/language_models/__init__.py +116 -0
- coco_core/language_models/_compat_bridge.py +844 -0
- coco_core/language_models/_utils.py +343 -0
- coco_core/language_models/base.py +500 -0
- coco_core/language_models/chat_model_stream.py +1525 -0
- coco_core/language_models/chat_models.py +2748 -0
- coco_core/language_models/fake.py +137 -0
- coco_core/language_models/fake_chat_models.py +396 -0
- coco_core/language_models/llms.py +1569 -0
- coco_core/language_models/model_profile.py +183 -0
- coco_core/load/__init__.py +44 -0
- coco_core/load/_validation.py +191 -0
- coco_core/load/dump.py +120 -0
- coco_core/load/load.py +828 -0
- coco_core/load/mapping.py +1097 -0
- coco_core/load/serializable.py +406 -0
- coco_core/messages/__init__.py +198 -0
- coco_core/messages/ai.py +854 -0
- coco_core/messages/base.py +518 -0
- coco_core/messages/block_translators/__init__.py +112 -0
- coco_core/messages/block_translators/anthropic.py +534 -0
- coco_core/messages/block_translators/bedrock.py +108 -0
- coco_core/messages/block_translators/bedrock_converse.py +329 -0
- coco_core/messages/block_translators/coco_v0.py +303 -0
- coco_core/messages/block_translators/google_genai.py +610 -0
- coco_core/messages/block_translators/google_vertexai.py +21 -0
- coco_core/messages/block_translators/groq.py +157 -0
- coco_core/messages/block_translators/openai.py +1089 -0
- coco_core/messages/chat.py +64 -0
- coco_core/messages/content.py +1488 -0
- coco_core/messages/function.py +62 -0
- coco_core/messages/human.py +70 -0
- coco_core/messages/modifier.py +33 -0
- coco_core/messages/system.py +70 -0
- coco_core/messages/tool.py +418 -0
- coco_core/messages/utils.py +2442 -0
- coco_core/output_parsers/__init__.py +101 -0
- coco_core/output_parsers/base.py +361 -0
- coco_core/output_parsers/format_instructions.py +16 -0
- coco_core/output_parsers/json.py +139 -0
- coco_core/output_parsers/list.py +249 -0
- coco_core/output_parsers/openai_functions.py +324 -0
- coco_core/output_parsers/openai_tools.py +383 -0
- coco_core/output_parsers/pydantic.py +141 -0
- coco_core/output_parsers/string.py +63 -0
- coco_core/output_parsers/transform.py +175 -0
- coco_core/output_parsers/xml.py +301 -0
- coco_core/outputs/__init__.py +66 -0
- coco_core/outputs/chat_generation.py +147 -0
- coco_core/outputs/chat_result.py +39 -0
- coco_core/outputs/generation.py +80 -0
- coco_core/outputs/llm_result.py +112 -0
- coco_core/outputs/run_info.py +22 -0
- coco_core/prompt_values.py +161 -0
- coco_core/prompts/__init__.py +101 -0
- coco_core/prompts/base.py +508 -0
- coco_core/prompts/chat.py +1495 -0
- coco_core/prompts/dict.py +177 -0
- coco_core/prompts/few_shot.py +483 -0
- coco_core/prompts/few_shot_with_templates.py +239 -0
- coco_core/prompts/image.py +177 -0
- coco_core/prompts/loading.py +296 -0
- coco_core/prompts/message.py +97 -0
- coco_core/prompts/prompt.py +312 -0
- coco_core/prompts/string.py +399 -0
- coco_core/prompts/structured.py +214 -0
- coco_core/py.typed +0 -0
- coco_core/rate_limiters.py +254 -0
- coco_core/retrievers.py +328 -0
- coco_core/runnables/__init__.py +136 -0
- coco_core/runnables/base.py +6725 -0
- coco_core/runnables/branch.py +457 -0
- coco_core/runnables/config.py +712 -0
- coco_core/runnables/configurable.py +710 -0
- coco_core/runnables/fallbacks.py +663 -0
- coco_core/runnables/graph.py +741 -0
- coco_core/runnables/graph_ascii.py +366 -0
- coco_core/runnables/graph_mermaid.py +503 -0
- coco_core/runnables/graph_png.py +215 -0
- coco_core/runnables/history.py +631 -0
- coco_core/runnables/passthrough.py +849 -0
- coco_core/runnables/retry.py +379 -0
- coco_core/runnables/router.py +239 -0
- coco_core/runnables/schema.py +188 -0
- coco_core/runnables/utils.py +798 -0
- coco_core/stores.py +291 -0
- coco_core/structured_query.py +203 -0
- coco_core/sys_info.py +154 -0
- coco_core/tools/__init__.py +95 -0
- coco_core/tools/base.py +1948 -0
- coco_core/tools/convert.py +497 -0
- coco_core/tools/render.py +67 -0
- coco_core/tools/retriever.py +94 -0
- coco_core/tools/simple.py +208 -0
- coco_core/tools/structured.py +322 -0
- coco_core/tracers/__init__.py +47 -0
- coco_core/tracers/_compat.py +95 -0
- coco_core/tracers/_context.py +337 -0
- coco_core/tracers/_streaming.py +53 -0
- coco_core/tracers/base.py +955 -0
- coco_core/tracers/coco.py +279 -0
- coco_core/tracers/context.py +205 -0
- coco_core/tracers/core.py +766 -0
- coco_core/tracers/event_stream.py +1101 -0
- coco_core/tracers/log_stream.py +765 -0
- coco_core/tracers/memory_stream.py +200 -0
- coco_core/tracers/root_listeners.py +130 -0
- coco_core/tracers/run_collector.py +40 -0
- coco_core/tracers/schemas.py +14 -0
- coco_core/tracers/stdout.py +205 -0
- coco_core/utils/__init__.py +111 -0
- coco_core/utils/_gateway.py +274 -0
- coco_core/utils/_merge.py +218 -0
- coco_core/utils/aiter.py +357 -0
- coco_core/utils/env.py +86 -0
- coco_core/utils/formatting.py +80 -0
- coco_core/utils/function_calling.py +869 -0
- coco_core/utils/html.py +132 -0
- coco_core/utils/image.py +15 -0
- coco_core/utils/input.py +82 -0
- coco_core/utils/interactive_env.py +12 -0
- coco_core/utils/iter.py +229 -0
- coco_core/utils/json.py +230 -0
- coco_core/utils/json_schema.py +273 -0
- coco_core/utils/mustache.py +706 -0
- coco_core/utils/pydantic.py +631 -0
- coco_core/utils/strings.py +69 -0
- coco_core/utils/usage.py +61 -0
- coco_core/utils/utils.py +528 -0
- coco_core/utils/uuid.py +57 -0
- coco_core/vectorstores/__init__.py +53 -0
- coco_core/vectorstores/base.py +1111 -0
- coco_core/vectorstores/in_memory.py +546 -0
- coco_core/vectorstores/utils.py +163 -0
- coco_core/version.py +3 -0
- coco_framework-0.1.0.dist-info/METADATA +184 -0
- coco_framework-0.1.0.dist-info/RECORD +400 -0
- coco_framework-0.1.0.dist-info/WHEEL +4 -0
- coco_framework-0.1.0.dist-info/licenses/LICENSE +24 -0
- coco_framework-0.1.0.dist-info/licenses/NOTICE +15 -0
- coco_graph/_internal/__init__.py +4 -0
- coco_graph/_internal/_cache.py +31 -0
- coco_graph/_internal/_config.py +474 -0
- coco_graph/_internal/_constants.py +140 -0
- coco_graph/_internal/_fields.py +213 -0
- coco_graph/_internal/_future.py +220 -0
- coco_graph/_internal/_pydantic.py +275 -0
- coco_graph/_internal/_queue.py +124 -0
- coco_graph/_internal/_replay.py +90 -0
- coco_graph/_internal/_retry.py +29 -0
- coco_graph/_internal/_runnable.py +969 -0
- coco_graph/_internal/_scratchpad.py +19 -0
- coco_graph/_internal/_serde.py +253 -0
- coco_graph/_internal/_timeout.py +25 -0
- coco_graph/_internal/_typing.py +54 -0
- coco_graph/cache/base/__init__.py +48 -0
- coco_graph/cache/base/py.typed +0 -0
- coco_graph/cache/memory/__init__.py +73 -0
- coco_graph/cache/redis/__init__.py +144 -0
- coco_graph/cache/sqlite/__init__.py +120 -0
- coco_graph/callbacks.py +394 -0
- coco_graph/channels/__init__.py +29 -0
- coco_graph/channels/any_value.py +72 -0
- coco_graph/channels/base.py +121 -0
- coco_graph/channels/binop.py +155 -0
- coco_graph/channels/delta.py +202 -0
- coco_graph/channels/ephemeral_value.py +79 -0
- coco_graph/channels/last_value.py +151 -0
- coco_graph/channels/named_barrier_value.py +167 -0
- coco_graph/channels/topic.py +94 -0
- coco_graph/channels/untracked_value.py +73 -0
- coco_graph/checkpoint/base/__init__.py +861 -0
- coco_graph/checkpoint/base/id.py +109 -0
- coco_graph/checkpoint/base/py.typed +0 -0
- coco_graph/checkpoint/memory/__init__.py +698 -0
- coco_graph/checkpoint/memory/py.typed +0 -0
- coco_graph/checkpoint/postgres/__init__.py +602 -0
- coco_graph/checkpoint/postgres/_ainternal.py +23 -0
- coco_graph/checkpoint/postgres/_internal.py +21 -0
- coco_graph/checkpoint/postgres/aio.py +691 -0
- coco_graph/checkpoint/postgres/base.py +666 -0
- coco_graph/checkpoint/postgres/py.typed +0 -0
- coco_graph/checkpoint/postgres/shallow.py +967 -0
- coco_graph/checkpoint/serde/__init__.py +0 -0
- coco_graph/checkpoint/serde/_msgpack.py +97 -0
- coco_graph/checkpoint/serde/base.py +64 -0
- coco_graph/checkpoint/serde/encrypted.py +80 -0
- coco_graph/checkpoint/serde/event_hooks.py +52 -0
- coco_graph/checkpoint/serde/jsonplus.py +883 -0
- coco_graph/checkpoint/serde/py.typed +0 -0
- coco_graph/checkpoint/serde/types.py +68 -0
- coco_graph/checkpoint/sqlite/__init__.py +645 -0
- coco_graph/checkpoint/sqlite/_delta.py +172 -0
- coco_graph/checkpoint/sqlite/aio.py +738 -0
- coco_graph/checkpoint/sqlite/py.typed +0 -0
- coco_graph/checkpoint/sqlite/utils.py +116 -0
- coco_graph/config.py +196 -0
- coco_graph/constants.py +64 -0
- coco_graph/errors.py +241 -0
- coco_graph/func/__init__.py +620 -0
- coco_graph/graph/__init__.py +12 -0
- coco_graph/graph/_branch.py +225 -0
- coco_graph/graph/_node.py +103 -0
- coco_graph/graph/message.py +437 -0
- coco_graph/graph/state.py +1978 -0
- coco_graph/graph/ui.py +227 -0
- coco_graph/managed/__init__.py +3 -0
- coco_graph/managed/base.py +31 -0
- coco_graph/managed/is_last_step.py +24 -0
- coco_graph/prebuilt/__init__.py +23 -0
- coco_graph/prebuilt/_tool_call_stream.py +117 -0
- coco_graph/prebuilt/_tool_call_transformer.py +165 -0
- coco_graph/prebuilt/chat_agent_executor.py +1015 -0
- coco_graph/prebuilt/interrupt.py +105 -0
- coco_graph/prebuilt/py.typed +0 -0
- coco_graph/prebuilt/tool_node.py +2030 -0
- coco_graph/prebuilt/tool_validator.py +221 -0
- coco_graph/pregel/__init__.py +3 -0
- coco_graph/pregel/_algo.py +1460 -0
- coco_graph/pregel/_call.py +298 -0
- coco_graph/pregel/_checkpoint.py +331 -0
- coco_graph/pregel/_config.py +0 -0
- coco_graph/pregel/_draw.py +294 -0
- coco_graph/pregel/_executor.py +223 -0
- coco_graph/pregel/_io.py +174 -0
- coco_graph/pregel/_log.py +3 -0
- coco_graph/pregel/_loop.py +1988 -0
- coco_graph/pregel/_messages.py +461 -0
- coco_graph/pregel/_read.py +312 -0
- coco_graph/pregel/_retry.py +854 -0
- coco_graph/pregel/_runner.py +941 -0
- coco_graph/pregel/_tools.py +268 -0
- coco_graph/pregel/_utils.py +221 -0
- coco_graph/pregel/_validate.py +120 -0
- coco_graph/pregel/_write.py +192 -0
- coco_graph/pregel/debug.py +302 -0
- coco_graph/pregel/main.py +4364 -0
- coco_graph/pregel/protocol.py +288 -0
- coco_graph/pregel/types.py +38 -0
- coco_graph/py.typed +0 -0
- coco_graph/runtime.py +350 -0
- coco_graph/store/base/__init__.py +1322 -0
- coco_graph/store/base/batch.py +371 -0
- coco_graph/store/base/embed.py +436 -0
- coco_graph/store/base/py.typed +0 -0
- coco_graph/store/memory/__init__.py +592 -0
- coco_graph/store/memory/py.typed +0 -0
- coco_graph/store/postgres/__init__.py +4 -0
- coco_graph/store/postgres/aio.py +592 -0
- coco_graph/store/postgres/base.py +1480 -0
- coco_graph/store/postgres/py.typed +0 -0
- coco_graph/store/sqlite/__init__.py +4 -0
- coco_graph/store/sqlite/aio.py +632 -0
- coco_graph/store/sqlite/base.py +1514 -0
- coco_graph/stream/__init__.py +45 -0
- coco_graph/stream/_convert.py +32 -0
- coco_graph/stream/_mux.py +523 -0
- coco_graph/stream/_types.py +330 -0
- coco_graph/stream/run_stream.py +735 -0
- coco_graph/stream/stream_channel.py +341 -0
- coco_graph/stream/transformers.py +1039 -0
- coco_graph/types.py +1079 -0
- coco_graph/typing.py +48 -0
- coco_graph/utils/__init__.py +1 -0
- coco_graph/utils/config.py +4 -0
- coco_graph/utils/runnable.py +3 -0
- coco_graph/version.py +13 -0
- coco_graph/warnings.py +69 -0
- coco_openai/__init__.py +20 -0
- coco_openai/_compat.py +45 -0
- coco_openai/_version.py +3 -0
- coco_openai/chat_models/__init__.py +6 -0
- coco_openai/chat_models/_client_utils.py +684 -0
- coco_openai/chat_models/_compat.py +525 -0
- coco_openai/chat_models/azure.py +1227 -0
- coco_openai/chat_models/base.py +5654 -0
- coco_openai/chat_models/codex.py +557 -0
- coco_openai/chatgpt_oauth.py +1063 -0
- coco_openai/data/__init__.py +1 -0
- coco_openai/data/_profiles.py +1655 -0
- coco_openai/data/profile_augmentations.toml +127 -0
- coco_openai/embeddings/__init__.py +6 -0
- coco_openai/embeddings/azure.py +240 -0
- coco_openai/embeddings/base.py +820 -0
- coco_openai/llms/__init__.py +6 -0
- coco_openai/llms/azure.py +249 -0
- coco_openai/llms/base.py +919 -0
- coco_openai/middleware/__init__.py +11 -0
- coco_openai/middleware/openai_moderation.py +484 -0
- coco_openai/output_parsers/__init__.py +9 -0
- coco_openai/output_parsers/tools.py +9 -0
- coco_openai/py.typed +0 -0
- coco_openai/tools/__init__.py +5 -0
- coco_openai/tools/custom_tool.py +111 -0
|
@@ -0,0 +1,637 @@
|
|
|
1
|
+
"""Helper functions for deprecating parts of the Coco API.
|
|
2
|
+
|
|
3
|
+
This module was adapted from matplotlib's [`_api/deprecation.py`](https://github.com/matplotlib/matplotlib/blob/main/lib/matplotlib/_api/deprecation.py)
|
|
4
|
+
module.
|
|
5
|
+
|
|
6
|
+
!!! warning
|
|
7
|
+
|
|
8
|
+
This module is for internal use only. Do not use it in your own code. We may change
|
|
9
|
+
the API at any time with no warning.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
import contextlib
|
|
13
|
+
import functools
|
|
14
|
+
import inspect
|
|
15
|
+
import sys
|
|
16
|
+
import warnings
|
|
17
|
+
from collections.abc import Callable, Generator
|
|
18
|
+
from contextvars import ContextVar
|
|
19
|
+
from typing import (
|
|
20
|
+
TYPE_CHECKING,
|
|
21
|
+
Any,
|
|
22
|
+
ParamSpec,
|
|
23
|
+
TypeGuard,
|
|
24
|
+
TypeVar,
|
|
25
|
+
cast,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
from pydantic.fields import FieldInfo
|
|
29
|
+
|
|
30
|
+
from coco_core._api.internal import is_caller_internal
|
|
31
|
+
|
|
32
|
+
if TYPE_CHECKING:
|
|
33
|
+
from pydantic.v1.fields import FieldInfo as FieldInfoV1
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _is_pydantic_v1_field_info(obj: Any) -> TypeGuard["FieldInfoV1"]:
|
|
37
|
+
"""Check if `obj` is a `pydantic.v1.fields.FieldInfo` without forcing import.
|
|
38
|
+
|
|
39
|
+
Importing `pydantic.v1` emits a `UserWarning` on Python 3.14+. Skipping the
|
|
40
|
+
import entirely when no caller has constructed a v1 `FieldInfo` keeps that
|
|
41
|
+
warning out of `coco_core`'s import path. If a caller did construct one,
|
|
42
|
+
`pydantic.v1.fields` is already in `sys.modules` and isinstance is safe.
|
|
43
|
+
"""
|
|
44
|
+
mod = sys.modules.get("pydantic.v1.fields")
|
|
45
|
+
if mod is None:
|
|
46
|
+
return False
|
|
47
|
+
return isinstance(obj, mod.FieldInfo)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def _build_deprecation_message(
|
|
51
|
+
*,
|
|
52
|
+
alternative: str = "",
|
|
53
|
+
alternative_import: str = "",
|
|
54
|
+
) -> str:
|
|
55
|
+
"""Build a simple deprecation message for `__deprecated__` attribute.
|
|
56
|
+
|
|
57
|
+
Args:
|
|
58
|
+
alternative: An alternative API name.
|
|
59
|
+
alternative_import: A fully qualified import path for the alternative.
|
|
60
|
+
|
|
61
|
+
Returns:
|
|
62
|
+
A deprecation message string for IDE/type checker display.
|
|
63
|
+
"""
|
|
64
|
+
if alternative_import:
|
|
65
|
+
return f"Use {alternative_import} instead."
|
|
66
|
+
if alternative:
|
|
67
|
+
return f"Use {alternative} instead."
|
|
68
|
+
return "Deprecated."
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
class CocoDeprecationWarning(DeprecationWarning):
|
|
72
|
+
"""A class for issuing deprecation warnings for Coco users."""
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
class CocoPendingDeprecationWarning(PendingDeprecationWarning):
|
|
76
|
+
"""A class for issuing deprecation warnings for Coco users."""
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
# Tracks when callers intentionally silence Coco deprecation warnings.
|
|
80
|
+
# Suppressed warnings should not consume a deprecated callable's one-time
|
|
81
|
+
# warning state; otherwise an internal compatibility path can prevent the first
|
|
82
|
+
# user-visible call from warning.
|
|
83
|
+
_SUPPRESSING_COCO_DEPRECATION_WARNING = ContextVar(
|
|
84
|
+
"_SUPPRESSING_COCO_DEPRECATION_WARNING", default=False
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
# PUBLIC API
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
# Bound is `Any` (not `FieldInfoV1`) because importing `pydantic.v1` at module
|
|
92
|
+
# scope emits a `UserWarning` on Python 3.14+; v1 `FieldInfo` support is handled
|
|
93
|
+
# at runtime via `_is_pydantic_v1_field_info`.
|
|
94
|
+
T = TypeVar("T", bound=type | Callable[..., Any] | Any)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def _validate_deprecation_params(
|
|
98
|
+
removal: str,
|
|
99
|
+
alternative: str,
|
|
100
|
+
alternative_import: str,
|
|
101
|
+
*,
|
|
102
|
+
pending: bool,
|
|
103
|
+
) -> None:
|
|
104
|
+
"""Validate the deprecation parameters."""
|
|
105
|
+
if pending and removal:
|
|
106
|
+
msg = "A pending deprecation cannot have a scheduled removal"
|
|
107
|
+
raise ValueError(msg)
|
|
108
|
+
if alternative and alternative_import:
|
|
109
|
+
msg = "Cannot specify both alternative and alternative_import"
|
|
110
|
+
raise ValueError(msg)
|
|
111
|
+
|
|
112
|
+
if alternative_import and "." not in alternative_import:
|
|
113
|
+
msg = (
|
|
114
|
+
"alternative_import must be a fully qualified module path. Got "
|
|
115
|
+
f" {alternative_import}"
|
|
116
|
+
)
|
|
117
|
+
raise ValueError(msg)
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def deprecated(
|
|
121
|
+
since: str,
|
|
122
|
+
*,
|
|
123
|
+
message: str = "",
|
|
124
|
+
name: str = "",
|
|
125
|
+
alternative: str = "",
|
|
126
|
+
alternative_import: str = "",
|
|
127
|
+
pending: bool = False,
|
|
128
|
+
obj_type: str = "",
|
|
129
|
+
addendum: str = "",
|
|
130
|
+
removal: str = "",
|
|
131
|
+
package: str = "",
|
|
132
|
+
) -> Callable[[T], T]:
|
|
133
|
+
"""Decorator to mark a function, a class, or a property as deprecated.
|
|
134
|
+
|
|
135
|
+
When deprecating a classmethod, a staticmethod, or a property, the `@deprecated`
|
|
136
|
+
decorator should go *under* `@classmethod` and `@staticmethod` (i.e., `deprecated`
|
|
137
|
+
should directly decorate the underlying callable), but *over* `@property`.
|
|
138
|
+
|
|
139
|
+
When deprecating a class `C` intended to be used as a base class in a multiple
|
|
140
|
+
inheritance hierarchy, `C` *must* define an `__init__` method (if `C` instead
|
|
141
|
+
inherited its `__init__` from its own base class, then `@deprecated` would mess up
|
|
142
|
+
`__init__` inheritance when installing its own (deprecation-emitting) `C.__init__`).
|
|
143
|
+
|
|
144
|
+
Parameters are the same as for `warn_deprecated`, except that *obj_type* defaults to
|
|
145
|
+
'class' if decorating a class, 'attribute' if decorating a property, and 'function'
|
|
146
|
+
otherwise.
|
|
147
|
+
|
|
148
|
+
Args:
|
|
149
|
+
since: The release at which this API became deprecated.
|
|
150
|
+
message: Override the default deprecation message.
|
|
151
|
+
|
|
152
|
+
The `%(since)s`, `%(name)s`, `%(alternative)s`, `%(obj_type)s`,
|
|
153
|
+
`%(addendum)s`, and `%(removal)s` format specifiers will be replaced by the
|
|
154
|
+
values of the respective arguments passed to this function.
|
|
155
|
+
name: The name of the deprecated object.
|
|
156
|
+
alternative: An alternative API that the user may use in place of the deprecated
|
|
157
|
+
API.
|
|
158
|
+
|
|
159
|
+
The deprecation warning will tell the user about this alternative if
|
|
160
|
+
provided.
|
|
161
|
+
alternative_import: An alternative import that the user may use instead.
|
|
162
|
+
pending: If `True`, uses a `PendingDeprecationWarning` instead of a
|
|
163
|
+
`DeprecationWarning`.
|
|
164
|
+
|
|
165
|
+
Cannot be used together with removal.
|
|
166
|
+
obj_type: The object type being deprecated.
|
|
167
|
+
addendum: Additional text appended directly to the final message.
|
|
168
|
+
removal: The expected removal version.
|
|
169
|
+
|
|
170
|
+
With the default (an empty string), no removal version is shown in the
|
|
171
|
+
warning message.
|
|
172
|
+
|
|
173
|
+
Cannot be used together with pending.
|
|
174
|
+
package: The package of the deprecated object.
|
|
175
|
+
|
|
176
|
+
Returns:
|
|
177
|
+
A decorator to mark a function or class as deprecated.
|
|
178
|
+
|
|
179
|
+
Example:
|
|
180
|
+
```python
|
|
181
|
+
@deprecated("1.4.0")
|
|
182
|
+
def the_function_to_deprecate():
|
|
183
|
+
pass
|
|
184
|
+
```
|
|
185
|
+
"""
|
|
186
|
+
_validate_deprecation_params(
|
|
187
|
+
removal, alternative, alternative_import, pending=pending
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
def deprecate(
|
|
191
|
+
obj: T,
|
|
192
|
+
*,
|
|
193
|
+
_obj_type: str = obj_type,
|
|
194
|
+
_name: str = name,
|
|
195
|
+
_message: str = message,
|
|
196
|
+
_alternative: str = alternative,
|
|
197
|
+
_alternative_import: str = alternative_import,
|
|
198
|
+
_pending: bool = pending,
|
|
199
|
+
_addendum: str = addendum,
|
|
200
|
+
_package: str = package,
|
|
201
|
+
) -> T:
|
|
202
|
+
"""Implementation of the decorator returned by `deprecated`."""
|
|
203
|
+
|
|
204
|
+
def emit_warning() -> None:
|
|
205
|
+
"""Emit the warning."""
|
|
206
|
+
warn_deprecated(
|
|
207
|
+
since,
|
|
208
|
+
message=_message,
|
|
209
|
+
name=_name,
|
|
210
|
+
alternative=_alternative,
|
|
211
|
+
alternative_import=_alternative_import,
|
|
212
|
+
pending=_pending,
|
|
213
|
+
obj_type=_obj_type,
|
|
214
|
+
addendum=_addendum,
|
|
215
|
+
removal=removal,
|
|
216
|
+
package=_package,
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
warned = False
|
|
220
|
+
|
|
221
|
+
def warning_emitting_wrapper(*args: Any, **kwargs: Any) -> Any:
|
|
222
|
+
"""Wrapper for the original wrapped callable that emits a warning.
|
|
223
|
+
|
|
224
|
+
Args:
|
|
225
|
+
*args: The positional arguments to the function.
|
|
226
|
+
**kwargs: The keyword arguments to the function.
|
|
227
|
+
|
|
228
|
+
Returns:
|
|
229
|
+
The return value of the function being wrapped.
|
|
230
|
+
"""
|
|
231
|
+
nonlocal warned
|
|
232
|
+
if not warned and not is_caller_internal():
|
|
233
|
+
emit_warning()
|
|
234
|
+
# Only mark the warning as emitted if it was not intentionally
|
|
235
|
+
# suppressed by `suppress_coco_deprecation_warning()`.
|
|
236
|
+
warned = not _SUPPRESSING_COCO_DEPRECATION_WARNING.get()
|
|
237
|
+
return wrapped(*args, **kwargs)
|
|
238
|
+
|
|
239
|
+
async def awarning_emitting_wrapper(*args: Any, **kwargs: Any) -> Any:
|
|
240
|
+
"""Same as warning_emitting_wrapper, but for async functions."""
|
|
241
|
+
nonlocal warned
|
|
242
|
+
if not warned and not is_caller_internal():
|
|
243
|
+
emit_warning()
|
|
244
|
+
# Only mark the warning as emitted if it was not intentionally
|
|
245
|
+
# suppressed by `suppress_coco_deprecation_warning()`.
|
|
246
|
+
warned = not _SUPPRESSING_COCO_DEPRECATION_WARNING.get()
|
|
247
|
+
return await wrapped(*args, **kwargs)
|
|
248
|
+
|
|
249
|
+
_package = _package or obj.__module__.split(".")[0].replace("_", "-")
|
|
250
|
+
|
|
251
|
+
if isinstance(obj, type):
|
|
252
|
+
if not _obj_type:
|
|
253
|
+
_obj_type = "class"
|
|
254
|
+
wrapped = obj.__init__ # type: ignore[misc]
|
|
255
|
+
_name = _name or obj.__qualname__
|
|
256
|
+
old_doc = obj.__doc__
|
|
257
|
+
|
|
258
|
+
def finalize(_: Callable[..., Any], new_doc: str, /) -> T:
|
|
259
|
+
"""Finalize the deprecation of a class."""
|
|
260
|
+
# Can't set new_doc on some extension objects.
|
|
261
|
+
with contextlib.suppress(AttributeError):
|
|
262
|
+
obj.__doc__ = new_doc
|
|
263
|
+
|
|
264
|
+
def warn_if_direct_instance(
|
|
265
|
+
self: Any, *args: Any, **kwargs: Any
|
|
266
|
+
) -> Any:
|
|
267
|
+
"""Warn that the class is in beta."""
|
|
268
|
+
nonlocal warned
|
|
269
|
+
if not warned and type(self) is obj and not is_caller_internal():
|
|
270
|
+
emit_warning()
|
|
271
|
+
# Only mark the warning as emitted if it was not intentionally
|
|
272
|
+
# suppressed by `suppress_coco_deprecation_warning()`.
|
|
273
|
+
warned = not _SUPPRESSING_COCO_DEPRECATION_WARNING.get()
|
|
274
|
+
return wrapped(self, *args, **kwargs)
|
|
275
|
+
|
|
276
|
+
obj.__init__ = functools.wraps(obj.__init__)( # type: ignore[misc]
|
|
277
|
+
warn_if_direct_instance
|
|
278
|
+
)
|
|
279
|
+
# Set __deprecated__ for PEP 702 (IDE/type checker support)
|
|
280
|
+
obj.__deprecated__ = _build_deprecation_message( # type: ignore[attr-defined]
|
|
281
|
+
alternative=alternative,
|
|
282
|
+
alternative_import=alternative_import,
|
|
283
|
+
)
|
|
284
|
+
return obj
|
|
285
|
+
|
|
286
|
+
elif _is_pydantic_v1_field_info(obj):
|
|
287
|
+
wrapped = None
|
|
288
|
+
if not _obj_type:
|
|
289
|
+
_obj_type = "attribute"
|
|
290
|
+
if not _name:
|
|
291
|
+
msg = f"Field {obj} must have a name to be deprecated."
|
|
292
|
+
raise ValueError(msg)
|
|
293
|
+
old_doc = obj.description
|
|
294
|
+
|
|
295
|
+
def finalize(_: Callable[..., Any], new_doc: str, /) -> T:
|
|
296
|
+
from pydantic.v1.fields import FieldInfo as FieldInfoV1 # noqa: PLC0415
|
|
297
|
+
|
|
298
|
+
return cast(
|
|
299
|
+
"T",
|
|
300
|
+
FieldInfoV1(
|
|
301
|
+
default=obj.default,
|
|
302
|
+
default_factory=obj.default_factory,
|
|
303
|
+
description=new_doc,
|
|
304
|
+
alias=obj.alias,
|
|
305
|
+
exclude=obj.exclude,
|
|
306
|
+
),
|
|
307
|
+
)
|
|
308
|
+
|
|
309
|
+
elif isinstance(obj, FieldInfo):
|
|
310
|
+
wrapped = None
|
|
311
|
+
if not _obj_type:
|
|
312
|
+
_obj_type = "attribute"
|
|
313
|
+
if not _name:
|
|
314
|
+
msg = f"Field {obj} must have a name to be deprecated."
|
|
315
|
+
raise ValueError(msg)
|
|
316
|
+
old_doc = obj.description
|
|
317
|
+
|
|
318
|
+
def finalize(_: Callable[..., Any], new_doc: str, /) -> T:
|
|
319
|
+
return cast(
|
|
320
|
+
"T",
|
|
321
|
+
FieldInfo(
|
|
322
|
+
default=obj.default,
|
|
323
|
+
default_factory=obj.default_factory,
|
|
324
|
+
description=new_doc,
|
|
325
|
+
alias=obj.alias,
|
|
326
|
+
exclude=obj.exclude,
|
|
327
|
+
),
|
|
328
|
+
)
|
|
329
|
+
|
|
330
|
+
elif isinstance(obj, property):
|
|
331
|
+
if not _obj_type:
|
|
332
|
+
_obj_type = "attribute"
|
|
333
|
+
wrapped = None
|
|
334
|
+
_name = _name or cast("type", obj.fget).__qualname__
|
|
335
|
+
old_doc = obj.__doc__
|
|
336
|
+
|
|
337
|
+
class _DeprecatedProperty(property):
|
|
338
|
+
"""A deprecated property."""
|
|
339
|
+
|
|
340
|
+
def __init__(
|
|
341
|
+
self,
|
|
342
|
+
fget: Callable[[Any], Any] | None = None,
|
|
343
|
+
fset: Callable[[Any, Any], None] | None = None,
|
|
344
|
+
fdel: Callable[[Any], None] | None = None,
|
|
345
|
+
doc: str | None = None,
|
|
346
|
+
) -> None:
|
|
347
|
+
super().__init__(fget, fset, fdel, doc)
|
|
348
|
+
self.__orig_fget = fget
|
|
349
|
+
self.__orig_fset = fset
|
|
350
|
+
self.__orig_fdel = fdel
|
|
351
|
+
|
|
352
|
+
def __get__(self, instance: Any, owner: type | None = None) -> Any:
|
|
353
|
+
if instance is not None or owner is not None:
|
|
354
|
+
emit_warning()
|
|
355
|
+
if self.fget is None:
|
|
356
|
+
return None
|
|
357
|
+
return self.fget(instance)
|
|
358
|
+
|
|
359
|
+
def __set__(self, instance: Any, value: Any) -> None:
|
|
360
|
+
if instance is not None:
|
|
361
|
+
emit_warning()
|
|
362
|
+
if self.fset is not None:
|
|
363
|
+
self.fset(instance, value)
|
|
364
|
+
|
|
365
|
+
def __delete__(self, instance: Any) -> None:
|
|
366
|
+
if instance is not None:
|
|
367
|
+
emit_warning()
|
|
368
|
+
if self.fdel is not None:
|
|
369
|
+
self.fdel(instance)
|
|
370
|
+
|
|
371
|
+
def __set_name__(self, owner: type | None, set_name: str) -> None:
|
|
372
|
+
nonlocal _name
|
|
373
|
+
if _name == "<lambda>":
|
|
374
|
+
_name = set_name
|
|
375
|
+
|
|
376
|
+
def finalize(_: Callable[..., Any], new_doc: str, /) -> T:
|
|
377
|
+
"""Finalize the property."""
|
|
378
|
+
prop = _DeprecatedProperty(
|
|
379
|
+
fget=obj.fget, fset=obj.fset, fdel=obj.fdel, doc=new_doc
|
|
380
|
+
)
|
|
381
|
+
# Set __deprecated__ for PEP 702 (IDE/type checker support)
|
|
382
|
+
prop.__deprecated__ = _build_deprecation_message( # type: ignore[attr-defined]
|
|
383
|
+
alternative=alternative,
|
|
384
|
+
alternative_import=alternative_import,
|
|
385
|
+
)
|
|
386
|
+
return cast("T", prop)
|
|
387
|
+
|
|
388
|
+
else:
|
|
389
|
+
_name = _name or cast("type", obj).__qualname__
|
|
390
|
+
if not _obj_type:
|
|
391
|
+
# edge case: when a function is within another function
|
|
392
|
+
# within a test, this will call it a "method" not a "function"
|
|
393
|
+
_obj_type = "function" if "." not in _name else "method"
|
|
394
|
+
wrapped = obj
|
|
395
|
+
old_doc = wrapped.__doc__
|
|
396
|
+
|
|
397
|
+
def finalize(wrapper: Callable[..., Any], new_doc: str, /) -> T:
|
|
398
|
+
"""Wrap the wrapped function using the wrapper and update the docstring.
|
|
399
|
+
|
|
400
|
+
Args:
|
|
401
|
+
wrapper: The wrapper function.
|
|
402
|
+
new_doc: The new docstring.
|
|
403
|
+
|
|
404
|
+
Returns:
|
|
405
|
+
The wrapped function.
|
|
406
|
+
"""
|
|
407
|
+
wrapper = functools.wraps(wrapped)(wrapper)
|
|
408
|
+
wrapper.__doc__ = new_doc
|
|
409
|
+
# Set __deprecated__ for PEP 702 (IDE/type checker support)
|
|
410
|
+
wrapper.__deprecated__ = _build_deprecation_message( # type: ignore[attr-defined]
|
|
411
|
+
alternative=alternative,
|
|
412
|
+
alternative_import=alternative_import,
|
|
413
|
+
)
|
|
414
|
+
return cast("T", wrapper)
|
|
415
|
+
|
|
416
|
+
old_doc = inspect.cleandoc(old_doc or "").strip("\n")
|
|
417
|
+
|
|
418
|
+
# old_doc can be None
|
|
419
|
+
if not old_doc:
|
|
420
|
+
old_doc = ""
|
|
421
|
+
|
|
422
|
+
# Modify the docstring to include a deprecation notice.
|
|
423
|
+
if (
|
|
424
|
+
_alternative
|
|
425
|
+
and _alternative.rsplit(".", maxsplit=1)[-1].lower()
|
|
426
|
+
== _alternative.rsplit(".", maxsplit=1)[-1]
|
|
427
|
+
) or _alternative:
|
|
428
|
+
_alternative = f"`{_alternative}`"
|
|
429
|
+
|
|
430
|
+
if (
|
|
431
|
+
_alternative_import
|
|
432
|
+
and _alternative_import.rsplit(".", maxsplit=1)[-1].lower()
|
|
433
|
+
== _alternative_import.rsplit(".", maxsplit=1)[-1]
|
|
434
|
+
) or _alternative_import:
|
|
435
|
+
_alternative_import = f"`{_alternative_import}`"
|
|
436
|
+
|
|
437
|
+
components = [
|
|
438
|
+
_message,
|
|
439
|
+
f"Use {_alternative} instead." if _alternative else "",
|
|
440
|
+
f"Use {_alternative_import} instead." if _alternative_import else "",
|
|
441
|
+
_addendum,
|
|
442
|
+
]
|
|
443
|
+
details = " ".join([component.strip() for component in components if component])
|
|
444
|
+
package = _package or (
|
|
445
|
+
_name.split(".")[0].replace("_", "-") if "." in _name else None
|
|
446
|
+
)
|
|
447
|
+
if removal:
|
|
448
|
+
if removal.startswith("1.") and package and package.startswith("coco"):
|
|
449
|
+
removal_str = f"It will not be removed until {package}=={removal}."
|
|
450
|
+
else:
|
|
451
|
+
removal_str = f"It will be removed in {package}=={removal}."
|
|
452
|
+
else:
|
|
453
|
+
removal_str = ""
|
|
454
|
+
new_doc = f"""\
|
|
455
|
+
!!! deprecated "{since} {details} {removal_str}"
|
|
456
|
+
|
|
457
|
+
{old_doc}\
|
|
458
|
+
"""
|
|
459
|
+
|
|
460
|
+
if inspect.iscoroutinefunction(obj):
|
|
461
|
+
return finalize(awarning_emitting_wrapper, new_doc)
|
|
462
|
+
return finalize(warning_emitting_wrapper, new_doc)
|
|
463
|
+
|
|
464
|
+
return deprecate
|
|
465
|
+
|
|
466
|
+
|
|
467
|
+
@contextlib.contextmanager
|
|
468
|
+
def suppress_coco_deprecation_warning() -> Generator[None, None, None]:
|
|
469
|
+
"""Context manager to suppress `CocoDeprecationWarning`."""
|
|
470
|
+
token = _SUPPRESSING_COCO_DEPRECATION_WARNING.set(True)
|
|
471
|
+
try:
|
|
472
|
+
with warnings.catch_warnings():
|
|
473
|
+
warnings.simplefilter("ignore", CocoDeprecationWarning)
|
|
474
|
+
warnings.simplefilter("ignore", CocoPendingDeprecationWarning)
|
|
475
|
+
yield
|
|
476
|
+
finally:
|
|
477
|
+
_SUPPRESSING_COCO_DEPRECATION_WARNING.reset(token)
|
|
478
|
+
|
|
479
|
+
|
|
480
|
+
def warn_deprecated(
|
|
481
|
+
since: str,
|
|
482
|
+
*,
|
|
483
|
+
message: str = "",
|
|
484
|
+
name: str = "",
|
|
485
|
+
alternative: str = "",
|
|
486
|
+
alternative_import: str = "",
|
|
487
|
+
pending: bool = False,
|
|
488
|
+
obj_type: str = "",
|
|
489
|
+
addendum: str = "",
|
|
490
|
+
removal: str = "",
|
|
491
|
+
package: str = "",
|
|
492
|
+
) -> None:
|
|
493
|
+
"""Display a standardized deprecation.
|
|
494
|
+
|
|
495
|
+
Args:
|
|
496
|
+
since: The release at which this API became deprecated.
|
|
497
|
+
message: Override the default deprecation message.
|
|
498
|
+
|
|
499
|
+
The `%(since)s`, `%(name)s`, `%(alternative)s`, `%(obj_type)s`,
|
|
500
|
+
`%(addendum)s`, and `%(removal)s` format specifiers will be replaced by the
|
|
501
|
+
values of the respective arguments passed to this function.
|
|
502
|
+
name: The name of the deprecated object.
|
|
503
|
+
alternative: An alternative API that the user may use in place of the
|
|
504
|
+
deprecated API.
|
|
505
|
+
|
|
506
|
+
The deprecation warning will tell the user about this alternative if
|
|
507
|
+
provided.
|
|
508
|
+
alternative_import: An alternative import that the user may use instead.
|
|
509
|
+
pending: If `True`, uses a `PendingDeprecationWarning` instead of a
|
|
510
|
+
`DeprecationWarning`.
|
|
511
|
+
|
|
512
|
+
Cannot be used together with removal.
|
|
513
|
+
obj_type: The object type being deprecated.
|
|
514
|
+
addendum: Additional text appended directly to the final message.
|
|
515
|
+
removal: The expected removal version.
|
|
516
|
+
|
|
517
|
+
With the default (an empty string), no removal version is shown in the
|
|
518
|
+
warning message.
|
|
519
|
+
|
|
520
|
+
Cannot be used together with pending.
|
|
521
|
+
package: The package of the deprecated object.
|
|
522
|
+
"""
|
|
523
|
+
if not pending and removal:
|
|
524
|
+
removal = f"in {removal}"
|
|
525
|
+
|
|
526
|
+
if not message:
|
|
527
|
+
message = ""
|
|
528
|
+
package_ = (
|
|
529
|
+
package or name.split(".", maxsplit=1)[0].replace("_", "-")
|
|
530
|
+
if "." in name
|
|
531
|
+
else "Coco"
|
|
532
|
+
)
|
|
533
|
+
|
|
534
|
+
if obj_type:
|
|
535
|
+
message += f"The {obj_type} `{name}`"
|
|
536
|
+
else:
|
|
537
|
+
message += f"`{name}`"
|
|
538
|
+
|
|
539
|
+
if pending:
|
|
540
|
+
message += " will be deprecated in a future version"
|
|
541
|
+
else:
|
|
542
|
+
message += f" was deprecated in {package_} {since}"
|
|
543
|
+
|
|
544
|
+
if removal:
|
|
545
|
+
message += f" and will be removed {removal}"
|
|
546
|
+
|
|
547
|
+
if alternative_import:
|
|
548
|
+
alt_package = alternative_import.split(".", maxsplit=1)[0].replace("_", "-")
|
|
549
|
+
if alt_package == package_:
|
|
550
|
+
message += f". Use {alternative_import} instead."
|
|
551
|
+
else:
|
|
552
|
+
alt_module, alt_name = alternative_import.rsplit(".", 1)
|
|
553
|
+
message += (
|
|
554
|
+
f". An updated version of the {obj_type} exists in the "
|
|
555
|
+
f"{alt_package} package and should be used instead. To use it run "
|
|
556
|
+
f"`pip install -U {alt_package}` and import as "
|
|
557
|
+
f"`from {alt_module} import {alt_name}`."
|
|
558
|
+
)
|
|
559
|
+
elif alternative:
|
|
560
|
+
message += f". Use {alternative} instead."
|
|
561
|
+
|
|
562
|
+
if addendum:
|
|
563
|
+
message += f" {addendum}"
|
|
564
|
+
|
|
565
|
+
warning_cls = (
|
|
566
|
+
CocoPendingDeprecationWarning if pending else CocoDeprecationWarning
|
|
567
|
+
)
|
|
568
|
+
warning = warning_cls(message)
|
|
569
|
+
warnings.warn(warning, category=CocoDeprecationWarning, stacklevel=4)
|
|
570
|
+
|
|
571
|
+
|
|
572
|
+
def surface_coco_deprecation_warnings() -> None:
|
|
573
|
+
"""Unmute Coco deprecation warnings."""
|
|
574
|
+
warnings.filterwarnings(
|
|
575
|
+
"default",
|
|
576
|
+
category=CocoPendingDeprecationWarning,
|
|
577
|
+
)
|
|
578
|
+
|
|
579
|
+
warnings.filterwarnings(
|
|
580
|
+
"default",
|
|
581
|
+
category=CocoDeprecationWarning,
|
|
582
|
+
)
|
|
583
|
+
|
|
584
|
+
|
|
585
|
+
_P = ParamSpec("_P")
|
|
586
|
+
_R = TypeVar("_R")
|
|
587
|
+
|
|
588
|
+
|
|
589
|
+
def rename_parameter(
|
|
590
|
+
*,
|
|
591
|
+
since: str,
|
|
592
|
+
removal: str,
|
|
593
|
+
old: str,
|
|
594
|
+
new: str,
|
|
595
|
+
) -> Callable[[Callable[_P, _R]], Callable[_P, _R]]:
|
|
596
|
+
"""Decorator indicating that parameter *old* of *func* is renamed to *new*.
|
|
597
|
+
|
|
598
|
+
The actual implementation of *func* should use *new*, not *old*. If *old* is passed
|
|
599
|
+
to *func*, a `DeprecationWarning` is emitted, and its value is used, even if *new*
|
|
600
|
+
is also passed by keyword.
|
|
601
|
+
|
|
602
|
+
Args:
|
|
603
|
+
since: The version in which the parameter was renamed.
|
|
604
|
+
removal: The version in which the old parameter will be removed.
|
|
605
|
+
old: The old parameter name.
|
|
606
|
+
new: The new parameter name.
|
|
607
|
+
|
|
608
|
+
Returns:
|
|
609
|
+
A decorator indicating that a parameter was renamed.
|
|
610
|
+
|
|
611
|
+
Example:
|
|
612
|
+
```python
|
|
613
|
+
@_api.rename_parameter("3.1", "bad_name", "good_name")
|
|
614
|
+
def func(good_name): ...
|
|
615
|
+
```
|
|
616
|
+
"""
|
|
617
|
+
|
|
618
|
+
def decorator(f: Callable[_P, _R]) -> Callable[_P, _R]:
|
|
619
|
+
@functools.wraps(f)
|
|
620
|
+
def wrapper(*args: _P.args, **kwargs: _P.kwargs) -> _R:
|
|
621
|
+
if new in kwargs and old in kwargs:
|
|
622
|
+
msg = f"{f.__name__}() got multiple values for argument {new!r}"
|
|
623
|
+
raise TypeError(msg)
|
|
624
|
+
if old in kwargs:
|
|
625
|
+
warn_deprecated(
|
|
626
|
+
since,
|
|
627
|
+
removal=removal,
|
|
628
|
+
message=f"The parameter `{old}` of `{f.__name__}` was "
|
|
629
|
+
f"deprecated in {since} and will be removed "
|
|
630
|
+
f"in {removal} Use `{new}` instead.",
|
|
631
|
+
)
|
|
632
|
+
kwargs[new] = kwargs.pop(old)
|
|
633
|
+
return f(*args, **kwargs)
|
|
634
|
+
|
|
635
|
+
return wrapper
|
|
636
|
+
|
|
637
|
+
return decorator
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import inspect
|
|
2
|
+
from typing import cast
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def is_caller_internal(depth: int = 2) -> bool:
|
|
6
|
+
"""Return whether the caller at `depth` of this function is internal."""
|
|
7
|
+
try:
|
|
8
|
+
frame = inspect.currentframe()
|
|
9
|
+
except AttributeError:
|
|
10
|
+
return False
|
|
11
|
+
if frame is None:
|
|
12
|
+
return False
|
|
13
|
+
try:
|
|
14
|
+
for _ in range(depth):
|
|
15
|
+
frame = frame.f_back
|
|
16
|
+
if frame is None:
|
|
17
|
+
return False
|
|
18
|
+
# Directly access the module name from the frame's global variables
|
|
19
|
+
module_globals = frame.f_globals
|
|
20
|
+
caller_module_name = cast("str", module_globals.get("__name__", ""))
|
|
21
|
+
return caller_module_name.startswith("coco")
|
|
22
|
+
finally:
|
|
23
|
+
del frame
|