litellm/tests/unit/proxy/mcp_server/faults/test_traversal.py
Mateo Wang 0a1dbc0fb4
refactor(mcp): drop the experimental label from the MCP server and client paths (#48513)
* refactor(mcp): drop the experimental label from the MCP server and client paths

Move litellm/proxy/_experimental/mcp_server to litellm/proxy/mcp_server and litellm/experimental_mcp_client to litellm/mcp_client, with the mirrored tests moved under tests/unit/proxy/mcp_server and tests/unit/mcp_client. Both old packages stay as shims that warn with DeprecationWarning, re-export the new package's public names and alias every submodule in sys.modules so deep imports keep resolving to the same objects. The OpenAPI docs gate now puts the merge base's enterprise package on PYTHONPATH so its base counts do not mix the checked-out enterprise code with the base litellm tree

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* ci(mcp): keep tests/unit/proxy/_experimental as a sharded root for the shim tests

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(mcp): alias namespace subpackages and bind attributes in the deprecated MCP shims

pkgutil.walk_packages skipped mcp_server/auth because it has no __init__.py, so old imports of litellm.proxy._experimental.mcp_server.auth.* failed, and sys.modules entries alone left litellm.experimental_mcp_client.tools unreachable as an attribute. Walk the package on disk and setattr each alias on its old parent.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-10-27 17:47:50 +00:00

53 lines
1.7 KiB
Python

"""Traversal contract for the shared exception-tree walk: the root is yielded first, explicit
links win (the ``raise ... from`` cause subtree, then ExceptionGroup members in raise order,
then the incidental ``__context__`` chain last), and adversarial shapes terminate."""
import sys
if sys.version_info < (3, 11): # BaseExceptionGroup is a builtin only from 3.11
from exceptiongroup import BaseExceptionGroup
from litellm.proxy.mcp_server.faults import iter_exception_tree
def test_yields_the_root_itself_first():
exc = ValueError("root")
assert list(iter_exception_tree(exc)) == [exc]
def test_cause_subtree_is_exhausted_before_context():
deep = KeyError("deep")
cause = RuntimeError("cause")
cause.__cause__ = deep
context = OSError("context")
root = ValueError("root")
root.__cause__ = cause
root.__context__ = context
assert list(iter_exception_tree(root)) == [root, cause, deep, context]
def test_group_members_yield_in_raise_order_between_cause_and_context():
first = KeyError("first")
second = IndexError("second")
group = BaseExceptionGroup("group", [first, second])
cause = RuntimeError("cause")
context = OSError("context")
group.__cause__ = cause
group.__context__ = context
assert list(iter_exception_tree(group)) == [group, cause, first, second, context]
def test_terminates_on_a_cause_cycle():
a = ValueError("a")
b = RuntimeError("b")
a.__cause__ = b
b.__cause__ = a
assert list(iter_exception_tree(a)) == [a, b]
def test_node_reachable_as_both_cause_and_context_yields_once():
inner = KeyError("inner")
root = ValueError("root")
root.__cause__ = inner
root.__context__ = inner
assert list(iter_exception_tree(root)) == [root, inner]