astral-sh/ruff · critical

Implement Ipy escape command support

Error message

Implement Ipy escape command support

What it means

While checking, ty evaluates expressions in type-expression positions (annotations, base classes, subscripts of generics). If an IPython escape command (%magic, !shell, etc.) lands in such a position — possible when notebook cells are parsed with IPython syntax — inference reaches todo!("Implement Ipy escape command support") and the checker panics rather than degrading. Per the 2025-08 comment in the source, this is the only remaining todo! in ruff/ty, kept loud on purpose.

Source

Thrown at crates/ty_python_semantic/src/types/infer/builder/type_expression.rs:958

                    format_args!(
                        "Set comprehensions are not allowed in {}s",
                        self.type_expression_context()
                    ),
                );
                Type::unknown()
            }

            ast::Expr::Generator(generator) => {
                if !self.in_string_annotation() {
                    self.infer_generator_expression(generator, TypeContext::default());
                }
                self.report_invalid_type_expression(
                    expression,
                    format_args!(
                        "Generator expressions are not allowed in {}s",
                        self.type_expression_context()
                    ),
                );
                Type::unknown()
            }

            ast::Expr::Await(await_expression) => {
                if !self.in_string_annotation() {
                    self.infer_await_expression(await_expression, TypeContext::default());
                }
                self.report_invalid_type_expression(
                    expression,
                    format_args!(
                        "`await` expressions are not allowed in {}s",
                        self.type_expression_context()
                    ),
                );
                Type::unknown()
            }

            ast::Expr::Yield(yield_expression) => {

View on GitHub (pinned to 15f3fe6b15)

Solutions

  1. Move or remove the magic so no escape command sits in an annotation/type-expression position (put %time on its own line, outside the annotation).
  2. Update ty and re-test — the todo may since have been implemented or converted into a diagnostic; check the changelog and issue tracker.
  3. Exclude the affected notebook from checking until support lands (e.g. via respect-excludes / ignore patterns).
  4. If it reproduces on current ty, file a [ty] issue with the minimal cell contents.

Example fix

# before (notebook cell; magic inside an annotation slot)
count: %time int = 0

# after
count: int = 0
Defensive patterns

Strategy: validation

Validate before calling

import json, re
from pathlib import Path

MAGIC = re.compile(r'^\s*[%!]\w+')


def notebook_has_magics(path: Path) -> bool:
    nb = json.loads(path.read_text())
    lines = (
        ''.join(cell.get('source', []))
        for cell in nb.get('cells', [])
        if cell.get('cell_type') == 'code'
    )
    return any(MAGIC.match(line) for chunk in lines for line in chunk.splitlines())


files = [
    p for p in map(Path, sys.argv[1:])
    if p.suffix != '.ipynb' or not notebook_has_magics(p)
]

Try / catch

proc = subprocess.run(['ty', 'check', *files], capture_output=True, text=True)
if proc.returncode != 0 and 'not yet implemented' in proc.stderr:
    proc = subprocess.run(
        ['ty', 'check', *[f for f in files if f.suffix != '.ipynb']],
        capture_output=True,
        text=True,
    )

Prevention

When it happens

Trigger: Running ty check on a .ipynb (or a .py parsed with jupyter magics enabled) where a cell places an escape command in a type slot, e.g. 'count: %time int = 0' or a magic on an annotation/decorator line.

Common situations: Notebooks converted to/from scripts where magics drift into annotation positions; cells mixing magics with typed signatures; CI pipelines type-checking raw notebooks.

Related errors


AI-assisted analysis of astral-sh/ruff@15f3fe6b15 (2026-08-20). Data as JSON: /api/errors/d2b4589107748b00. Report an issue: GitHub.