Skip to content

python_remote: a callable named 'task' (the documented contract) raises a bare AssertionError; the verbatim docstring example raises IndentationError #1959

Closed

Description

@lmeyerov

Category: bare-crash on valid/documented input + doc-vs-code divergence. Repro-backed on master (84be35fb3); no server needed (both failures happen before any HTTP call).

1. Passing a callable literally named task — the documented contract — raises a bare AssertionError

Every python_remote_* docstring says the code must define "a top-level function task(g: Plottable)", and the signature is code: Union[str, Callable[..., object]]. The branch that converts a callable to source only runs when the name is not task (python_remote.py:100-106):

if callable(code):
    if code.__name__ != "task":          # <-- inverted: the correct name is the one skipped
        code_str = inspect.getsource(code)
        code = code_str.replace(f"def {old_name}", "def task", 1)
assert code is not None and isinstance(code, str), f"Expected code to be a string, received type: {type(code)}"

Repro:

def task(g):
    return {'n': len(g._edges)}

g.python_remote_json(task)      # AssertionError: Expected code to be a string, received type: <class 'function'>

def mytask(g):
    return {'n': len(g._edges)}

g.python_remote_json(mytask)    # works; sends "    def task(g):\n        return {'n': 1}\n"

So the only callable name that cannot be used is the one the documentation mandates, and the failure is an untyped AssertionError (which also disappears entirely under python -O, leaving a function object to be JSON-serialized).

Expected: accept a callable named task (skip the rename, keep the getsource conversion), or raise a typed error naming the limitation.

2. The verbatim docstring example raises IndentationError

The example that appears in all four python_remote_* docstrings (e.g. python_remote.py:85-97) passes an indented triple-quoted block:

code = '''
                    from typing import Any, Dict
                    from graphistry import Plottable

                    def task(g: Plottable) -> Dict[str, Any]:
                        return {'num_edges': len(g._edges)}
                '''
validate_python_str(code)
# IndentationError: unexpected indent (<unknown>, line 2)

validate_python_str calls ast.parse(code) with no textwrap.dedent (python_remote.py:25). Anyone who copies the documented snippet, or who simply writes the triple-quoted literal inside a function body (universal Python style), gets a raw IndentationError from a validator whose job is to produce a good message.

Expected: textwrap.dedent(code) before parsing (and before sending), or a typed error explaining the indentation requirement.

3. INDICATIVE: the blanket 4-space re-indent mutates multi-line string literals in user code

python_remote.py:136-138 prepends 4 spaces to every line, including continuation lines inside triple-quoted literals:

in : 'def task(g):\n    s = """line1\nline2"""\n    return {"s": s}\n'
out: '    def task(g):\n        s = """line1\n    line2"""\n        return {"s": s}\n    '

The literal's value silently gains 4 leading spaces on line 2. Whether this survives depends on how the server un-indents (the comment calls it a "workaround parsing bug ... TODO remove when server updated"); a uniform 4-space dedent restores it, anything else does not. Not verifiable from the client — flagged INDICATIVE. If the server-side workaround is still needed, wrapping (if True:\n + indent) or an explicit AST-preserving transform avoids touching literals.

Found by the 2026-08 remote/over-the-wire amplification probe (first pass over this surface).

Activity

  1. added a commit that references this issue on Aug 19, 2026
    5d49c55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions