Skip to content

v6.4.9 — Bytecode cache, timezone errors & inline_series isolation

Choose a tag to compare

@wallneradam wallneradam released this 04 Jun 13:37
· 476 commits to main since this release

What's new

Patch release with four runtime-correctness fixes. Three resolve reported issues (#58, #59, #61) that could silently break scripts after an upgrade, on Windows without tzdata, or when inline_series() ran at more than one call site; the fourth turns a confusing data-load error into a self-explanatory one.

Core

Stale Pyne bytecode invalidated after transform-pipeline upgrades (#58)

CPython validates a cached .pyc only against its source .py mtime and size, so a PyneCore upgrade that changes the AST transform output keeps executing obsolete bytecode while the unchanged user source masks the staleness — e.g. a builtin that moved from a module property (emitted as a call) to a plain variable then raised 'bool' object is not callable. PyneLoader.get_code now drops a Pyne module's cached bytecode whenever it is older than the transform pipeline itself (the newest mtime among import_hook.py and the transformers package, including module_properties.json, which shapes the output but has no bytecode of its own), forcing a recompile from source. Invalidation delegates to importlib.util.cache_from_source, so it targets the exact file CPython reads back and honours PYTHONPYCACHEPREFIX and the -O / -OO optimization level.

inline_series() buffer isolated per call site (#61)

inline_series() registered its series buffer under the registry key 'create_series', but the runtime isolator keys isolation on the function qualname ('inline_series'). The lookup missed, so isolation was skipped and every inline_series call site shared one module-global buffer. A second, unguarded inline_series in a script body overwrote the slot a request.security() expression's inline_series had written, silently corrupting the security delivery for unrelated contexts. The registry key is now aligned with the qualname so each call site gets its own buffer.

This also affects compiled strategies: PyneComp emits inline_series() for any subscripted expression whose base is not a bare identifier (e.g. ta.atr(14)[1], (high - low)[1]), not only hand-written code. New regression tests cover call-site isolation and the request.security() interaction.

Time & sessions

Missing timezone now raises an actionable error instead of returning silent na (#59)

time(timeframe.period, session, "America/Chicago") returned na on every bar when the IANA timezone database was unavailable (e.g. Windows without tzdata), so session-gated strategies produced 0 trades with no error. parse_timezone now raises TimezoneNotFoundError with a platform-aware, actionable message for any unresolved IANA name (not just a handful of short names) and reports a genuinely unknown name distinctly from a missing database. time() and time_close() re-raise this configuration error past the broad session-validation guard, while genuine out-of-session bars still return na.

Data

Clearer error on duplicate-timestamp rows during load

OHLCVWriter raised a generic Invalid interval: 0 when consecutive input rows shared a timestamp — typical for Databento exports carrying multiple publisher_id rows per bar — which hid the real cause. The check is now split: duplicate timestamps raise a duplicate-specific message that names the offending timestamp and points to pre-filtering the source, while strictly-decreasing timestamps keep the chronological-order message. This is the Invalid interval: 0 case flagged in the v6.4.8 notes.