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

Diagram

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):

  1. Exact (namespace, name, version) if provided and registered.
  2. 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

PathRole
src/pynescript/ast/evaluator/libraries.pyLibraryModule, LibraryRegistry
src/pynescript/ast/evaluator/statements.pyexport registration, import visit, library finalize
src/pynescript/ast/evaluator/base.pyregistry fields on BaseEvaluator
src/pynescript/ast/evaluator/__init__.pyregister_library_source, lookup_library
src/pynescript/runtime/host.pyRuntime.run(..., libraries=) + auto-mode forward
tests/test_library_export_import.pyRound-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

  1. Evaluate library before consumer (or register source for lazy import). Empty registry → import failure.
  2. Same evaluator instance (or shared registry) must see both scripts—registries are not process-global unless the host shares them.
  3. Version is part of the path key. Mismatched version does not fall back to another version automatically when namespace is specified.
  4. Title registration always updates _by_title so simple local titles work without publisher metadata.
  5. 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

SymptomCause
Import resolves to nothingLibrary never registered / wrong title
Library 'X' has no exported member 'y'Missing export or typo
Stale exportsRe-evaluated library without re-import; host cache
Version conflictMultiple libs same title—last register wins for title key

See also