← board

nilpy: fallback import (try/except ImportError)

Motivation

try: import X … except ImportError: import Y is the single most common real-world Python portability idiom — every serious package uses it for optional/alternative deps. Supporting it makes far more real-world Python compile under nilpy (push generality down — [[frank2-mission-compile-real-world-asis]]), and it is the honest mechanism for platform-split backends:

try:
    from reportlab.pdfgen import canvas     # cpython: real reportlab
except ImportError:
    from pxxpdf import canvas                # nilpy: pxx pdfgen-backed compat lib

Under cpython the first import wins. Under nilpy reportlab is unresolvable, so nilpy must soft-fail that import and compile the except branch — instead of today's hard error. Consumer code downstream is identical (both bind canvas), which is why [[feature-lib-pxxpdf-reportlab-compat]] mimics reportlab's API.

Rene also floated a short import X if not import Y form — decide whether to add sugar or just support the try/except ImportError shape (the latter is standard Python and preferred).

Current walls

Intended surface

  1. Recognize try: <import(s)> except ImportError: <import(s)> at module scope.
  2. Attempt the try-branch imports; on unresolvable module (not a runtime error — a compile-time resolution miss), discard that branch and compile the except-branch imports instead. No hard error for the skipped module.
  3. Must PARSE (consume) a dotted from a.b import c in the try-branch even though it will be skipped under nilpy — do NOT need to RESOLVE a.b (we never load reportlab). Parsing-to-skip only.
  4. Bind the names from whichever branch was taken.

Acceptance

Consider (Track U, not here)

A sys.implementation.name == 'nilpy' marker would enable an explicit if nilpy: split as an alternative to try/except. Out of scope; file a decide-* if wanted (try/except is the standard idiom and covers the need).

Log