Operator registry and async-friendly execution layer for Jarvis
Project description
Jarvis-Operas
Jarvis-Operas is a standalone operator layer for registering, loading, and calling Python callables.
- Scope: operators only (likelihood, chi2, prior mapping, data transforms, etc.)
- No dependency on Jarvis-HEP internals
- Native async entrypoint for Jarvis-HEP style execution (
await registry.acall(...)) - Stable
"<namespace>.<name>"naming for references from Jarvis-HEP/Jarvis-PLOT YAML
Architecture and migration references:
docs/architecture.mddocs/migration.md
Install
pip install .
Or for development (includes pytest and installs terminal command):
pip install -e ".[dev]"
Terminal command (jopera)
After install, you can use:
jopera
jopera help examples
jopera list --namespace math
jopera list --namespace math --json
jopera info stat.chi2_cov --json
jopera call math.add --kwargs '{"a": 1, "b": 2}'
jopera acall stat.chi2_cov --arg residual=[1.0,-0.5] --arg cov=[[2.0,0.1],[0.1,1.0]]
jopera call helper.eggbox --kwargs '{"x":0.5,"y":0.0}'
jopera list --namespace math --log-mode info
jopera call math.add --kwargs '{"a": 1, "b": 2}' --log-mode debug
jopera init
jopera init --manifest ./manifest.json --cache-root ~/.jarvis-operas/curve-cache
jopera interp list
jopera interp validate
jopera --help-advanced
Load user operators directly in CLI:
jopera load /absolute/path/to/my_ops.py
jopera call my_ops.my_op --user-ops /absolute/path/to/my_ops.py --arg x=10
jopera info my_ops.my_op --json
CLI behavior:
jopera(no args) prints a quick start cardjopera listprints grouped human-readable output by default (id + name)jopera list --jsonprints machine-readable JSON objects withid/name/namespacejopera info <name_or_id>prints metadata (including a unique id) and a suggested next commandjopera load <path>persists a JO-managed source snapshot for future processesjopera load <path> --session-onlyloads without persistingjopera initprecompiles bundled interpolation manifest libraryjopera init --manifest <manifest.json>precompiles a custom curve JSON manifestjopera interp listlists root interpolation namespacesjopera interp validatevalidates root+namespace manifests- User write policy: the supported user write path is
jopera load - Developer-only write commands (
update,delete-func,delete-namespace,interp add/remove) requireJARVIS_OPERAS_DEV_WRITE=1
Core API
from jarvis_operas import get_global_operas_registry, get_global_operas
registry = get_global_operas_registry()
registry.call("math.add", a=1, b=2)
registry.call("math.identity", x={"k": 1})
operas = get_global_operas()
operas.call("math.add", a=1, b=2)
Supported namespace convention:
- Built-ins use feature namespaces, e.g.:
math.<name>stat.<name>helper.<name>
- User operator files default to
<script_name>.<func_name> - User operators cannot register into protected built-in namespaces (for example
math,stat,helper,interp, built-in interpolation namespaces).
Async call (Jarvis-HEP Factory/Module friendly)
result = await registry.acall(
"stat.chi2_cov",
residual=[1.0, -0.5],
cov=[[2.0, 0.1], [0.1, 1.0]],
)
Behavior:
- Async operator: awaited directly
- Sync operator: offloaded via
asyncio.to_threadby default (or custom executor) - Default numpy async concurrency is CPU-scaled (
os.cpu_count() * 3); override withget_global_operas(numpy_concurrency=...) - Batch helper concurrency:
await registry.acall_helper_many("eggbox", [...])
Example batch helper execution for Factory-side concurrent scans:
results = await registry.acall_helper_many(
"eggbox",
[
{"x": 0.1, "y": 0.2},
{"x": 0.3, "y": 0.4},
{"x": 0.5, "y": 0.6},
],
)
Logger injection
registry methods accept optional logger and operators can optionally define logger argument.
- If no logger is provided, Jarvis-Operas uses
loguru.loggerbound withmodule="Jarvis-Operas" - If logger is provided, Jarvis-Operas reuses it (no duplicate handler creation)
- Console format follows Jarvis-HEP style (
module -> time - [level] >>> message) - Default mode is
warning(only warning/error/critical are shown) - Optional modes:
info,debug
Utility:
from jarvis_operas import get_logger, set_log_mode
set_log_mode("info") # or "debug", default is "warning"
logger = get_logger()
Load user operators from file
from jarvis_operas import OperasRegistry, load_user_ops
registry = OperasRegistry()
loaded = load_user_ops("./my_ops.py", registry)
print(loaded)
Persistent registration for future Python processes:
from jarvis_operas import get_global_operas_registry, persist_user_ops
persist_user_ops("/absolute/path/to/my_ops.py")
registry = get_global_operas_registry() # auto-loads persisted sources
Persistence store location:
- Default sources registry:
~/.jarvis-operas/sources.json - Default override rules:
~/.jarvis-operas/overrides.json - Legacy base env (still supported):
JARVIS_OPERAS_PERSIST_FILE=/custom/path/persist_store.json- maps to sibling files
sources.jsonandoverrides.json
- maps to sibling files
- Optional explicit envs:
JARVIS_OPERAS_SOURCES_FILE=/custom/path/sources.jsonJARVIS_OPERAS_OVERRIDES_FILE=/custom/path/overrides.json
- Managed user source snapshots:
~/.jarvis-operas/user_sources/ - Override snapshot dir:
JARVIS_OPERAS_USER_SOURCE_DIR=/custom/path/user_sources - Legacy single-file
user_ops.jsonis still readable for backward compatibility
By default, load_user_ops("./my_ops.py", ...) uses my_ops as namespace, so
my_op becomes my_ops.my_op.
my_ops.py can export operators with either style:
- Decorator (recommended)
from jarvis_operas import oper
@oper("my_chi2")
def my_chi2(residual, cov, logger=None):
...
When loaded by load_user_ops("./my_ops.py", ...), this is registered as
my_ops.my_chi2.
- Explicit whitelist
def my_op(x):
return x
__JARVIS_OPERAS__ = {
"my_op": my_op,
}
Integration Contract (Jarvis-HEP / Jarvis-PLOT)
Downstream modules should depend on JO public API only:
- registry provider:
get_global_operas_registry() - runtime calls:
call/acall - lookup/introspection:
resolve_name/get/list/info
Avoid importing JO private modules or private symbols.
Function Docs Generation
Function docs are generated from OperaFunction.metadata:
python scripts/generate_function_docs.py --out docs/functions
Generated artifacts:
docs/functions/functions.jsondocs/functions/<namespace>/<function>.md
Curve publish/runtime cache (namespace manifests + JSON sources)
Use this flow when you have many 1D interpolation curves and want runtime speed:
- Source of truth:
- root index manifest (
interpolations.manifest.json) with namespace list - one manifest per namespace (function metadata list)
- per-function JSON source (
x/yarrays)
- root index manifest (
- Precompile once:
jopera init(bundled library) orjopera init --manifest ./manifest.json(custom)- optional:
jopera init --namespaces dmdd,interp1for partial namespace processing - optional maintenance:
jopera interp list|validate|add|remove
- optional:
- Runtime auto-registration:
get_global_operas_registry()registers hot curves asinterp.<curve_id> - Runtime load path uses
index.json+*.pklonly (no source JSON in hot path)
Namespace rule for registered interpolation operators:
- If
namespaceis set in curve item, register as<namespace>.<curve_id> - Else if
metadata.group(orgroup) is set, register as<group>.<curve_id> - Else fallback to
interp.<curve_id>
Bundled interpolation manifest library resource:
jarvis_operas/manifests/interpolations.manifest.json
Root index example:
{
"version": 2,
"kind": "jarvis_operas_interpolation_namespace_index",
"namespaces": [
{
"namespace": "dmdd",
"manifest": "dmdd/dmdd.manifest.json"
}
]
}
Namespace manifest example:
{
"namespace": "dmdd",
"functions": [
{
"name": "demo_curve",
"source": "dmdd/demo_curve.json",
"kind": "linear",
"hot": true,
"metadata": {
"group": "dmdd"
}
}
]
}
Curve source JSON example:
{
"x": [0.0, 1.0, 2.0],
"y": [0.0, 1.0, 4.0]
}
Python integration API:
from jarvis_operas import (
init_curve_cache,
interpolation_manifest_resource,
load_hot_curve_function_table,
load_interpolation_manifest_library,
register_hot_curves,
)
library_manifest = load_interpolation_manifest_library()
library_path = interpolation_manifest_resource()
init_curve_cache("./manifest.json")
table = load_hot_curve_function_table()
funcs = {}
updated = register_hot_curves(funcs)
Interpolation functions support:
numpybackend: native callablepolarsbackend:map_batchesfallback viaOperaFunction.return_dtype- sync:
registry.call(...) - async:
await registry.acall(...)
Built-in operators
math.add(a, b)stat.chi2_cov(residual, cov)helper.eggbox(x, y)math.identity(x)
All built-ins can be called via sync/async registry APIs and accept scalar, NumPy, and Pandas inputs where applicable. Example:
registry.call("math.add", a=1.0, b=2.0)
registry.call("stat.chi2_cov", residual=[1.0, 0.0], cov=[[2.0, 0.0], [0.0, 1.0]])
registry.call("helper.eggbox", x=0.5, y=0.0)
Query registry for external UIs (JHEP/JPlot)
registry.list()
registry.list(namespace="math")
registry.info("stat.chi2_cov")
registry.info(...) returns metadata, signature, docstring summary, backend support fields, and async flag.
Function docs generation (OperaFunction-driven)
Jarvis-Operas can auto-generate per-function docs from OperaFunction declarations.
python scripts/generate_function_docs.py
Output is generated under docs/functions/:
docs/functions/index.mddocs/functions/<namespace>/index.mddocs/functions/<namespace>/<function>.mddocs/functions/functions.json
Optional filters:
python scripts/generate_function_docs.py --namespaces math,stat
python scripts/generate_function_docs.py --out docs/custom_functions
Workspace clean
Clean local cache/build artifacts:
./scripts/clean_workspace.sh
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file jarvis_operas-1.3.0.tar.gz.
File metadata
- Download URL: jarvis_operas-1.3.0.tar.gz
- Upload date:
- Size: 72.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c10f04180369e97a3503dc53f17e31c83633382a33b9ab407547cf55b76bd2da
|
|
| MD5 |
3320c0be35f0ffa4b5d619df965e6e88
|
|
| BLAKE2b-256 |
0a55c691e7b01581ad690683d9e8b5d6dd4a41baaf4bfb44746bc51a1f21194d
|
File details
Details for the file jarvis_operas-1.3.0-py3-none-any.whl.
File metadata
- Download URL: jarvis_operas-1.3.0-py3-none-any.whl
- Upload date:
- Size: 68.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a278c147883ffec5b515e7967fc46f860f91d901efb21e02f34f2572f7d30014
|
|
| MD5 |
927c3a783e04469e1d8e351bae0a048b
|
|
| BLAKE2b-256 |
9abb4bc9a360f2e349625c16af73b9275b29cbddbee0accb19c62e303dc72b7c
|