Libraries
In-process library export/import, LibraryRegistry, and evaluate-order requirements.
This page
Libraries
Abstract
TradingView libraries publish as namespace/Name/version with exported members. PYNE implements an in-process analogue: evaluate a library("Title") script (or register source by path), collect exports (export const, exported functions, types), then import binds an alias to a LibraryModule for alias.member access. There is no network publish step—the registry is the host’s responsibility.
Conceptual model
Rendering…
Interface surface
Library script
//@version=6
library("MyMath")
export add(float a, float b) =>
a + b
export const float PHI = 1.6180339887
On script completion, StatementEvaluator finalizes _pending_library_exports onto the active LibraryModule and calls LibraryRegistry.register.
Consumer import
//@version=6
indicator("use")
import user/MyMath/1 as M
plot(M.add(close, M.PHI))
Resolution (LibraryRegistry.lookup):
- Exact
(namespace, name, version)if provided and registered. - Else title-only match (
MyMath) for local evaluation workflows without publisher path.
API on the evaluator
ev.register_library_source(namespace, name, version, source_str)
mod = ev.lookup_library(namespace=..., name=..., version=...)
register_library_source stores Pine text for lazy load on the first matching import. _load_library_source evaluates definitions only (skips showcase body) and finalizes _pending_library_exports onto the LibraryModule so export const / exported functions bind (0.3.8). Evaluating a library script on the same evaluator still populates exports eagerly.
Host evaluate (0.3.7+)
Hosts pass published sources without a pre-eval step:
Runtime(symbol="TEST").run(
consumer_source,
ohlcv,
mode="interpret", # or "auto" — import is compile-ineligible
libraries=[
{"namespace": "ns", "name": "Lib", "version": 1, "source": library_source},
],
)
The same list is accepted on Pro API and pyne-worker POST /run as libraries. pyne-worker also stores the array on deployed scripts so cron / script_id reuse it. Pro API slices to 32 entries (backend/app.py); Runtime.run itself does not cap. mode=compile has no import path — mode=auto treats import as compile-ineligible and forwards libraries= into interpret fallback (0.3.9).
LibraryModule
Dataclass with title, optional namespace/version, and exports: dict[str, Any]. Attribute access reads exports; missing members raise AttributeError with a clear message. NameEvaluator routes alias.member when the base value is a LibraryModule.
Internals
| Path | Role |
|---|---|
src/pynescript/ast/evaluator/libraries.py | LibraryModule, LibraryRegistry |
src/pynescript/ast/evaluator/statements.py | export registration, import visit, library finalize |
src/pynescript/ast/evaluator/base.py | registry fields on BaseEvaluator |
src/pynescript/ast/evaluator/__init__.py | register_library_source, lookup_library |
src/pynescript/runtime/host.py | Runtime.run(..., libraries=) + auto-mode forward |
tests/test_library_export_import.py | Round-trip coverage |
Exportable values include callables (user functions), constants, and type-related bindings depending on declaration paths. Exported methods participate in the same call machinery as local functions once retrieved from the module.
Invariants & edge cases
- Evaluate library before consumer (or register source for lazy import). Empty registry → import failure.
- Same evaluator instance (or shared registry) must see both scripts—registries are not process-global unless the host shares them.
- Version is part of the path key. Mismatched version does not fall back to another version automatically when namespace is specified.
- Title registration always updates
_by_titleso simple local titles work without publisher metadata. - No TV account auth. Publishing/versioning outside the process is out of scope.
Worked examples
Explicit registration
from pynescript.ast.evaluator import NodeLiteralEvaluator
ev = NodeLiteralEvaluator()
ev.evaluate_script(library_source) # registers by title
ev.evaluate_script(consumer_source) # import by title or path
Path registration without pre-eval
ev.register_library_source("user", "MyMath", 1, library_source)
# import user/MyMath/1 loads definitions and finalizes exports on first visit
Failure modes
| Symptom | Cause |
|---|---|
| Import resolves to nothing | Library never registered / wrong title |
Library 'X' has no exported member 'y' | Missing export or typo |
| Stale exports | Re-evaluated library without re-import; host cache |
| Version conflict | Multiple libs same title—last register wins for title key |