Skip to content

SDK drift: Python's _exchanges.py defines a dead, shadowed duplicate Router class with an incomplete constructor #1682

Description

@realfishsam

Drift

Python's generated _exchanges.py includes a Router class stamped out by the same generic exchange-wrapper generator used for ordinary exchanges. This class is missing all of Router's real functionality and is immediately shadowed by the real Router class from router.py on package import — but it remains reachable via pmxt._exchanges.Router, is dead code from the public API's perspective, and disagrees with the real Router on its own auto_start_server default. TypeScript has no equivalent duplication: it defines exactly one Router class, in router.ts.

TypeScript SDK

No Router class exists in client.ts (the file structurally analogous to _exchanges.py). TypeScript's only Router class is in sdks/typescript/pmxt/router.ts:218-221, taking a RouterOptions object with autoStartServer defaulting to false.

Python SDK

Dead/shadowed duplicate: sdks/python/pmxt/_exchanges.py:601-623

class Router(Exchange):
    """Router exchange client."""
    def __init__(
        self,
        base_url: Optional[str] = None,
        auto_start_server: Optional[bool] = None,
        pmxt_api_key: Optional[str] = None,
    ) -> None:
        super().__init__(
            exchange_name="router",
            base_url=base_url,
            auto_start_server=auto_start_server,
            pmxt_api_key=pmxt_api_key,
        )

This has none of Router's real methods (fetch_market_matches, compare_market_prices, fetch_hedges, fetch_arbitrage, etc.) and defaults auto_start_server to None.

Real, actually-used class: sdks/python/pmxt/router.py:106-141

class Router(Exchange):
    def __init__(
        self,
        pmxt_api_key: Optional[str] = None,
        base_url: Optional[str] = None,
        auto_start_server: bool = False,
    ) -> None:
        ...

auto_start_server defaults to False, and it has full Router functionality.

Shadowing point: sdks/python/pmxt/__init__.py:23-24

from ._exchanges import Polymarket, ..., Rain, Hunch, Mock, Router
from .router import Router

Line 24 immediately overwrites the name imported on line 23, so pmxt.Router always resolves to router.py's version in normal usage.

Expected

core/scripts/generate-python-exchanges.js should exclude router from the set of venues it generates a generic wrapper for in _exchanges.py, the same way both SDKs already hand-maintain a single, feature-complete Router class elsewhere (router.ts / router.py).

Impact

Low runtime impact for normal import pmxt; pmxt.Router(...) usage since the real class wins, but: (1) it's a landmine for anyone importing from pmxt._exchanges import Router directly, or introspecting pmxt._exchanges.__all__/module contents, who will silently get a non-functional stub instead of a real Router; (2) the two Python definitions of "the same class" don't even agree with each other on the auto_start_server default (None vs False), which is confusing for maintainers and a source of future bugs if the generator or router.py changes independently; (3) it's dead code that should either be excluded from generation or removed.


Found by automated SDK cross-language drift audit

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions