Skip to content

Fix abuse of return in a with test block #85

@Technologicat

Description

@Technologicat

As of 0.15.1, the contents of a with test block are implicitly lifted into a function. This in itself is fine; it is documented behavior, and arguably the simplest way to achieve what the macro needs to do.

The problem is that to declare the expression whose value should be checked to decide the result of the test, the syntax is currently return expr. This is effectively a keyword hijack — in the spirit of pytest's assert rewriting — where a standard Python construct is repurposed to mean something else inside a specific block. Not very pythonic. It conflicts with the established meaning of return and will confuse code analyzers and human readers alike.

Plan

Step 1 — 2.2.0 (non-breaking)

Add an expr macro to declare the tested expression, so the code reads more like standard Python. Name needs some thought:

  • returns[] — closest to intent, but will confuse humans as to why there is a separate returns vs. the standard return.
  • result[], results_in[], evaluates_into[] — semantically slightly off; we want to declare a check, not a result.
  • check[] — checkmate in t(h)ree? Probably the best so far.
  • Whatever the final name, it should be compact (preferably one short-ish word) while making the intent blindingly obvious.

During 2.2.0, using return expr inside a with test block continues to work, but emits a DeprecationWarning suggesting the new macro.

Step 2 — 3.0.0 (breaking)

Let return inside a with test block have its usual Python meaning (return from the enclosing function). unpythonic aims to be as pythonic as possible; undoing the keyword hijack — not banning return — is the point.

This likely means the with test: body can no longer be implicitly lifted to a function (or the lift has to transparently propagate return out to the enclosing function). Implementation details TBD — tracked here because the user-visible end state is clear even if the mechanism needs design work.

Scope note

Local variables assigned inside with test: would still be test-local under the current implementation (scope boundary from the implicit lift), which is acceptable precedent — comprehensions and generator expressions do the same, as do unpythonic's continuations. If a variable needs to be visible in the parent scope, use a box (or nonlocal / global as appropriate).

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions