adcp 2.12.1__py3-none-any.whl → 2.13.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.
- adcp/__init__.py +2 -1
- adcp/protocols/a2a.py +315 -204
- adcp/protocols/mcp.py +95 -16
- adcp/types/_generated.py +476 -97
- adcp/types/aliases.py +1 -3
- adcp/types/base.py +193 -0
- adcp/types/generated_poc/adagents.py +1 -1
- adcp/types/generated_poc/core/activation_key.py +1 -1
- adcp/types/generated_poc/core/assets/audio_asset.py +1 -1
- adcp/types/generated_poc/core/assets/css_asset.py +1 -1
- adcp/types/generated_poc/core/assets/daast_asset.py +1 -1
- adcp/types/generated_poc/core/assets/html_asset.py +1 -1
- adcp/types/generated_poc/core/assets/image_asset.py +1 -1
- adcp/types/generated_poc/core/assets/javascript_asset.py +1 -1
- adcp/types/generated_poc/core/assets/text_asset.py +1 -1
- adcp/types/generated_poc/core/assets/url_asset.py +1 -1
- adcp/types/generated_poc/core/assets/vast_asset.py +1 -1
- adcp/types/generated_poc/core/assets/video_asset.py +1 -1
- adcp/types/generated_poc/core/assets/webhook_asset.py +1 -1
- adcp/types/generated_poc/core/brand_manifest.py +1 -1
- adcp/types/generated_poc/core/context.py +1 -1
- adcp/types/generated_poc/core/creative_asset.py +1 -1
- adcp/types/generated_poc/core/creative_assignment.py +1 -1
- adcp/types/generated_poc/core/creative_filters.py +1 -1
- adcp/types/generated_poc/core/creative_manifest.py +1 -1
- adcp/types/generated_poc/core/creative_policy.py +1 -1
- adcp/types/generated_poc/core/delivery_metrics.py +1 -1
- adcp/types/generated_poc/core/deployment.py +1 -1
- adcp/types/generated_poc/core/destination.py +1 -1
- adcp/types/generated_poc/core/dimensions.py +1 -1
- adcp/types/generated_poc/core/error.py +1 -1
- adcp/types/generated_poc/core/ext.py +1 -1
- adcp/types/generated_poc/core/format.py +1 -1
- adcp/types/generated_poc/core/format_id.py +1 -1
- adcp/types/generated_poc/core/frequency_cap.py +1 -1
- adcp/types/generated_poc/core/measurement.py +1 -1
- adcp/types/generated_poc/core/media_buy.py +1 -1
- adcp/types/generated_poc/core/package.py +1 -1
- adcp/types/generated_poc/core/performance_feedback.py +1 -1
- adcp/types/generated_poc/core/placement.py +1 -1
- adcp/types/generated_poc/core/product.py +1 -1
- adcp/types/generated_poc/core/product_filters.py +1 -1
- adcp/types/generated_poc/core/promoted_offerings.py +1 -1
- adcp/types/generated_poc/core/promoted_products.py +1 -1
- adcp/types/generated_poc/core/property.py +1 -1
- adcp/types/generated_poc/core/property_id.py +1 -1
- adcp/types/generated_poc/core/property_tag.py +1 -1
- adcp/types/generated_poc/core/protocol_envelope.py +1 -1
- adcp/types/generated_poc/core/publisher_property_selector.py +1 -1
- adcp/types/generated_poc/core/push_notification_config.py +1 -1
- adcp/types/generated_poc/core/reporting_capabilities.py +1 -1
- adcp/types/generated_poc/core/response.py +1 -1
- adcp/types/generated_poc/core/signal_filters.py +1 -1
- adcp/types/generated_poc/core/sub_asset.py +1 -1
- adcp/types/generated_poc/core/targeting.py +1 -1
- adcp/types/generated_poc/core/webhook_payload.py +1 -1
- adcp/types/generated_poc/creative/list_creative_formats_request.py +1 -1
- adcp/types/generated_poc/creative/list_creative_formats_response.py +1 -1
- adcp/types/generated_poc/creative/preview_creative_request.py +1 -1
- adcp/types/generated_poc/creative/preview_creative_response.py +1 -1
- adcp/types/generated_poc/creative/preview_render.py +1 -1
- adcp/types/generated_poc/enums/adcp_domain.py +1 -1
- adcp/types/generated_poc/enums/asset_content_type.py +1 -1
- adcp/types/generated_poc/enums/auth_scheme.py +1 -1
- adcp/types/generated_poc/enums/available_metric.py +1 -1
- adcp/types/generated_poc/enums/channels.py +1 -1
- adcp/types/generated_poc/enums/co_branding_requirement.py +1 -1
- adcp/types/generated_poc/enums/creative_action.py +1 -1
- adcp/types/generated_poc/enums/creative_agent_capability.py +1 -1
- adcp/types/generated_poc/enums/creative_sort_field.py +1 -1
- adcp/types/generated_poc/enums/creative_status.py +1 -1
- adcp/types/generated_poc/enums/daast_tracking_event.py +1 -1
- adcp/types/generated_poc/enums/daast_version.py +1 -1
- adcp/types/generated_poc/enums/delivery_type.py +1 -1
- adcp/types/generated_poc/enums/dimension_unit.py +1 -1
- adcp/types/generated_poc/enums/feed_format.py +1 -1
- adcp/types/generated_poc/enums/feedback_source.py +1 -1
- adcp/types/generated_poc/enums/format_category.py +1 -1
- adcp/types/generated_poc/enums/format_id_parameter.py +1 -1
- adcp/types/generated_poc/enums/frequency_cap_scope.py +1 -1
- adcp/types/generated_poc/enums/history_entry_type.py +1 -1
- adcp/types/generated_poc/enums/http_method.py +1 -1
- adcp/types/generated_poc/enums/identifier_types.py +1 -1
- adcp/types/generated_poc/enums/javascript_module_type.py +1 -1
- adcp/types/generated_poc/enums/landing_page_requirement.py +1 -1
- adcp/types/generated_poc/enums/markdown_flavor.py +1 -1
- adcp/types/generated_poc/enums/media_buy_status.py +1 -1
- adcp/types/generated_poc/enums/metric_type.py +1 -1
- adcp/types/generated_poc/enums/notification_type.py +1 -1
- adcp/types/generated_poc/enums/pacing.py +1 -1
- adcp/types/generated_poc/enums/preview_output_format.py +1 -1
- adcp/types/generated_poc/enums/pricing_model.py +1 -1
- adcp/types/generated_poc/enums/property_type.py +1 -1
- adcp/types/generated_poc/enums/publisher_identifier_types.py +1 -1
- adcp/types/generated_poc/enums/reporting_frequency.py +1 -1
- adcp/types/generated_poc/enums/signal_catalog_type.py +1 -1
- adcp/types/generated_poc/enums/sort_direction.py +1 -1
- adcp/types/generated_poc/enums/standard_format_ids.py +1 -1
- adcp/types/generated_poc/enums/task_status.py +1 -1
- adcp/types/generated_poc/enums/task_type.py +1 -1
- adcp/types/generated_poc/enums/update_frequency.py +1 -1
- adcp/types/generated_poc/enums/url_asset_type.py +1 -1
- adcp/types/generated_poc/enums/validation_mode.py +1 -1
- adcp/types/generated_poc/enums/vast_tracking_event.py +1 -1
- adcp/types/generated_poc/enums/vast_version.py +1 -1
- adcp/types/generated_poc/enums/webhook_response_type.py +1 -1
- adcp/types/generated_poc/enums/webhook_security_method.py +1 -1
- adcp/types/generated_poc/media_buy/build_creative_request.py +1 -1
- adcp/types/generated_poc/media_buy/build_creative_response.py +1 -1
- adcp/types/generated_poc/media_buy/create_media_buy_request.py +1 -1
- adcp/types/generated_poc/media_buy/create_media_buy_response.py +1 -1
- adcp/types/generated_poc/media_buy/get_media_buy_delivery_request.py +1 -1
- adcp/types/generated_poc/media_buy/get_media_buy_delivery_response.py +1 -1
- adcp/types/generated_poc/media_buy/get_products_request.py +1 -1
- adcp/types/generated_poc/media_buy/get_products_response.py +1 -1
- adcp/types/generated_poc/media_buy/list_authorized_properties_request.py +1 -1
- adcp/types/generated_poc/media_buy/list_authorized_properties_response.py +1 -1
- adcp/types/generated_poc/media_buy/list_creative_formats_request.py +1 -1
- adcp/types/generated_poc/media_buy/list_creative_formats_response.py +1 -1
- adcp/types/generated_poc/media_buy/list_creatives_request.py +1 -1
- adcp/types/generated_poc/media_buy/list_creatives_response.py +1 -1
- adcp/types/generated_poc/media_buy/package_request.py +1 -1
- adcp/types/generated_poc/media_buy/provide_performance_feedback_request.py +1 -1
- adcp/types/generated_poc/media_buy/provide_performance_feedback_response.py +1 -1
- adcp/types/generated_poc/media_buy/sync_creatives_request.py +1 -1
- adcp/types/generated_poc/media_buy/sync_creatives_response.py +1 -1
- adcp/types/generated_poc/media_buy/update_media_buy_request.py +1 -1
- adcp/types/generated_poc/media_buy/update_media_buy_response.py +1 -1
- adcp/types/generated_poc/pricing_options/cpc_option.py +1 -1
- adcp/types/generated_poc/pricing_options/cpcv_option.py +1 -1
- adcp/types/generated_poc/pricing_options/cpm_auction_option.py +1 -1
- adcp/types/generated_poc/pricing_options/cpm_fixed_option.py +1 -1
- adcp/types/generated_poc/pricing_options/cpp_option.py +1 -1
- adcp/types/generated_poc/pricing_options/cpv_option.py +1 -1
- adcp/types/generated_poc/pricing_options/flat_rate_option.py +1 -1
- adcp/types/generated_poc/pricing_options/vcpm_auction_option.py +1 -1
- adcp/types/generated_poc/pricing_options/vcpm_fixed_option.py +1 -1
- adcp/types/generated_poc/protocols/adcp_extension.py +1 -1
- adcp/types/generated_poc/signals/activate_signal_request.py +1 -1
- adcp/types/generated_poc/signals/activate_signal_response.py +1 -1
- adcp/types/generated_poc/signals/get_signals_request.py +1 -1
- adcp/types/generated_poc/signals/get_signals_response.py +1 -1
- {adcp-2.12.1.dist-info → adcp-2.13.0.dist-info}/METADATA +1 -1
- adcp-2.13.0.dist-info/RECORD +176 -0
- adcp-2.12.1.dist-info/RECORD +0 -176
- {adcp-2.12.1.dist-info → adcp-2.13.0.dist-info}/WHEEL +0 -0
- {adcp-2.12.1.dist-info → adcp-2.13.0.dist-info}/entry_points.txt +0 -0
- {adcp-2.12.1.dist-info → adcp-2.13.0.dist-info}/licenses/LICENSE +0 -0
- {adcp-2.12.1.dist-info → adcp-2.13.0.dist-info}/top_level.txt +0 -0
adcp/protocols/mcp.py
CHANGED
|
@@ -9,6 +9,16 @@ from contextlib import AsyncExitStack
|
|
|
9
9
|
from typing import TYPE_CHECKING, Any
|
|
10
10
|
from urllib.parse import urlparse
|
|
11
11
|
|
|
12
|
+
# ExceptionGroup and BaseExceptionGroup are available in Python 3.11+
|
|
13
|
+
# In 3.11+, they're built-in types. For 3.10, we need to handle their absence.
|
|
14
|
+
try:
|
|
15
|
+
_ExceptionGroup: type[BaseException] | None = ExceptionGroup # type: ignore[name-defined]
|
|
16
|
+
_BaseExceptionGroup: type[BaseException] | None = BaseExceptionGroup # type: ignore[name-defined]
|
|
17
|
+
except NameError:
|
|
18
|
+
# Python 3.10 - ExceptionGroup doesn't exist
|
|
19
|
+
_ExceptionGroup = None
|
|
20
|
+
_BaseExceptionGroup = None
|
|
21
|
+
|
|
12
22
|
logger = logging.getLogger(__name__)
|
|
13
23
|
|
|
14
24
|
if TYPE_CHECKING:
|
|
@@ -23,6 +33,14 @@ try:
|
|
|
23
33
|
except ImportError:
|
|
24
34
|
MCP_AVAILABLE = False
|
|
25
35
|
|
|
36
|
+
try:
|
|
37
|
+
from httpx import HTTPStatusError
|
|
38
|
+
|
|
39
|
+
HTTPX_AVAILABLE = True
|
|
40
|
+
except ImportError:
|
|
41
|
+
HTTPX_AVAILABLE = False
|
|
42
|
+
HTTPStatusError = None # type: ignore[assignment, misc]
|
|
43
|
+
|
|
26
44
|
from adcp.exceptions import ADCPConnectionError, ADCPTimeoutError
|
|
27
45
|
from adcp.protocols.base import ProtocolAdapter
|
|
28
46
|
from adcp.types.core import DebugInfo, TaskResult, TaskStatus
|
|
@@ -56,23 +74,80 @@ class MCPAdapter(ProtocolAdapter):
|
|
|
56
74
|
self._session = None
|
|
57
75
|
try:
|
|
58
76
|
await old_stack.aclose()
|
|
59
|
-
except
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
#
|
|
72
|
-
|
|
73
|
-
|
|
77
|
+
except BaseException as cleanup_error:
|
|
78
|
+
# Handle all cleanup errors including ExceptionGroup
|
|
79
|
+
# Re-raise KeyboardInterrupt and SystemExit immediately
|
|
80
|
+
if isinstance(cleanup_error, (KeyboardInterrupt, SystemExit)):
|
|
81
|
+
raise
|
|
82
|
+
|
|
83
|
+
if isinstance(cleanup_error, asyncio.CancelledError):
|
|
84
|
+
logger.debug(f"MCP session cleanup cancelled {context}")
|
|
85
|
+
return
|
|
86
|
+
|
|
87
|
+
# Handle ExceptionGroup/BaseExceptionGroup from task group failures (Python 3.11+)
|
|
88
|
+
# ExceptionGroup: for Exception subclasses (e.g., HTTPStatusError)
|
|
89
|
+
# BaseExceptionGroup: for BaseException subclasses (e.g., CancelledError)
|
|
90
|
+
# We need both because CancelledError is a BaseException, not an Exception
|
|
91
|
+
is_exception_group = (
|
|
92
|
+
_ExceptionGroup is not None and isinstance(cleanup_error, _ExceptionGroup)
|
|
93
|
+
) or (
|
|
94
|
+
_BaseExceptionGroup is not None
|
|
95
|
+
and isinstance(cleanup_error, _BaseExceptionGroup)
|
|
74
96
|
)
|
|
75
97
|
|
|
98
|
+
if is_exception_group:
|
|
99
|
+
# Check if all exceptions in the group are CancelledError
|
|
100
|
+
# If so, treat the entire group as a cancellation
|
|
101
|
+
all_cancelled = all(
|
|
102
|
+
isinstance(exc, asyncio.CancelledError)
|
|
103
|
+
for exc in cleanup_error.exceptions # type: ignore[attr-defined]
|
|
104
|
+
)
|
|
105
|
+
if all_cancelled:
|
|
106
|
+
logger.debug(f"MCP session cleanup cancelled {context}")
|
|
107
|
+
return
|
|
108
|
+
|
|
109
|
+
# Mixed group: skip CancelledErrors and log real errors
|
|
110
|
+
exceptions = cleanup_error.exceptions # type: ignore[attr-defined]
|
|
111
|
+
cancelled_errors = [
|
|
112
|
+
exc for exc in exceptions if isinstance(exc, asyncio.CancelledError)
|
|
113
|
+
]
|
|
114
|
+
cancelled_count = len(cancelled_errors)
|
|
115
|
+
if cancelled_count > 0:
|
|
116
|
+
logger.debug(
|
|
117
|
+
f"Skipping {cancelled_count} CancelledError(s) "
|
|
118
|
+
f"in mixed exception group {context}"
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
# Log each non-cancelled exception individually
|
|
122
|
+
for exc in exceptions:
|
|
123
|
+
if not isinstance(exc, asyncio.CancelledError):
|
|
124
|
+
self._log_cleanup_error(exc, context)
|
|
125
|
+
else:
|
|
126
|
+
self._log_cleanup_error(cleanup_error, context)
|
|
127
|
+
|
|
128
|
+
def _log_cleanup_error(self, exc: BaseException, context: str) -> None:
|
|
129
|
+
"""Log a cleanup error without raising."""
|
|
130
|
+
# Check for known cleanup error patterns from httpx/anyio
|
|
131
|
+
exc_str = str(exc).lower()
|
|
132
|
+
|
|
133
|
+
# Common cleanup errors that are expected when connection fails
|
|
134
|
+
is_known_cleanup_error = (
|
|
135
|
+
isinstance(exc, RuntimeError)
|
|
136
|
+
and ("cancel scope" in exc_str or "async context" in exc_str)
|
|
137
|
+
) or (
|
|
138
|
+
# HTTP errors during cleanup (if httpx is available)
|
|
139
|
+
HTTPX_AVAILABLE
|
|
140
|
+
and HTTPStatusError is not None
|
|
141
|
+
and isinstance(exc, HTTPStatusError)
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
if is_known_cleanup_error:
|
|
145
|
+
# Expected cleanup errors - log at debug level without stack trace
|
|
146
|
+
logger.debug(f"Ignoring expected cleanup error {context}: {exc}")
|
|
147
|
+
else:
|
|
148
|
+
# Truly unexpected cleanup errors - log at warning with full context
|
|
149
|
+
logger.warning(f"Unexpected error during cleanup {context}: {exc}", exc_info=True)
|
|
150
|
+
|
|
76
151
|
async def _get_session(self) -> ClientSession:
|
|
77
152
|
"""
|
|
78
153
|
Get or create MCP client session with URL fallback handling.
|
|
@@ -146,7 +221,11 @@ class MCPAdapter(ProtocolAdapter):
|
|
|
146
221
|
)
|
|
147
222
|
|
|
148
223
|
return self._session # type: ignore[no-any-return]
|
|
149
|
-
except
|
|
224
|
+
except BaseException as e:
|
|
225
|
+
# Catch BaseException to handle CancelledError from failed initialization
|
|
226
|
+
# Re-raise KeyboardInterrupt and SystemExit immediately
|
|
227
|
+
if isinstance(e, (KeyboardInterrupt, SystemExit)):
|
|
228
|
+
raise
|
|
150
229
|
last_error = e
|
|
151
230
|
# Clean up the exit stack on failure to avoid resource leaks
|
|
152
231
|
await self._cleanup_failed_connection("during connection attempt")
|