Jsonnet is a data templating language that extends JSON with variables, conditionals, functions, and imports for configuration management
—
The Python bindings provide a high-level interface to Jsonnet with support for external variables, import callbacks, native extensions, and comprehensive error handling. The module exposes two main evaluation functions with extensive configuration options.
Primary functions for evaluating Jsonnet code from files or strings with flexible configuration.
def evaluate_file(filename, **kwargs):
"""
Evaluate Jsonnet file and return JSON string.
Args:
filename (str): Path to Jsonnet file to evaluate
jpathdir (str | list[str], optional): Import search paths
max_stack (int, optional): Maximum stack depth (default: 500)
gc_min_objects (int, optional): GC minimum objects (default: 1000)
gc_growth_trigger (float, optional): GC growth trigger (default: 2.0)
ext_vars (dict[str, str], optional): External string variables
ext_codes (dict[str, str], optional): External code variables
tla_vars (dict[str, str], optional): Top-level string arguments
tla_codes (dict[str, str], optional): Top-level code arguments
max_trace (int, optional): Maximum trace lines (default: 20)
import_callback (callable, optional): Custom import handler
native_callbacks (dict, optional): Native function callbacks
Returns:
str: JSON output string
Raises:
RuntimeError: On Jsonnet evaluation errors
TypeError: On invalid parameter types
"""
def evaluate_snippet(filename, src, **kwargs):
"""
Evaluate Jsonnet code string and return JSON string.
Args:
filename (str): Filename for error reporting
src (str): Jsonnet source code to evaluate
All other parameters same as evaluate_file()
Returns:
str: JSON output string
Raises:
RuntimeError: On Jsonnet evaluation errors
TypeError: On invalid parameter types
"""# Version string constant
version: str # "v0.21.0"# Single path
evaluate_file("config.jsonnet", jpathdir="/usr/local/lib/jsonnet")
# Multiple paths (searched in order)
evaluate_file("config.jsonnet", jpathdir=[
"./lib",
"/usr/local/lib/jsonnet",
"/opt/jsonnet/lib"
])# String variables accessible via std.extVar()
ext_vars = {
"environment": "production",
"version": "1.2.3",
"debug": "false"
}
# Code variables that are evaluated as Jsonnet
ext_codes = {
"config": "{ port: 8080, ssl: true }",
"features": "['auth', 'logging', 'metrics']"
}
result = evaluate_file("app.jsonnet", ext_vars=ext_vars, ext_codes=ext_codes)# For Jsonnet files that accept function parameters
# function(cluster, region="us-west-1") { ... }
tla_vars = {
"cluster": "production",
"region": "us-east-1"
}
tla_codes = {
"replicas": "if std.extVar('environment') == 'prod' then 3 else 1"
}
result = evaluate_file("deployment.jsonnet", tla_vars=tla_vars, tla_codes=tla_codes)# Performance tuning
result = evaluate_file("large-config.jsonnet",
max_stack=2000, # Increase stack for deep recursion
gc_min_objects=5000, # More objects before GC
gc_growth_trigger=3.0, # Less frequent GC
max_trace=50 # More error context
)def custom_import(base_path, relative_path):
"""
Custom import handler for loading files from alternative sources.
Args:
base_path (str): Directory containing the importing file
relative_path (str): Relative import path from Jsonnet code
Returns:
tuple[str, bytes]: (resolved_absolute_path, file_content_bytes)
Raises:
Exception: On import errors (converted to Jsonnet error)
"""
import os
# Resolve path
if relative_path.startswith("http://"):
# Handle HTTP imports
import urllib.request
response = urllib.request.urlopen(relative_path)
content = response.read()
return relative_path, content
else:
# Handle file system imports
abs_path = os.path.join(base_path, relative_path)
with open(abs_path, 'rb') as f:
content = f.read()
return abs_path, content
result = evaluate_file("config.jsonnet", import_callback=custom_import)def add_numbers(a, b):
"""Native function: add two numbers"""
return a + b
def get_timestamp():
"""Native function: get current timestamp"""
import time
return int(time.time())
def format_config(config, template):
"""Native function: format configuration with template"""
return template.format(**config)
# Register native functions
native_callbacks = {
"addNumbers": (["a", "b"], add_numbers),
"getTimestamp": ([], get_timestamp),
"formatConfig": (["config", "template"], format_config)
}
# Use in Jsonnet code:
# local timestamp = std.native("getTimestamp")();
# local sum = std.native("addNumbers")(10, 20);
result = evaluate_snippet('''
{
timestamp: std.native("getTimestamp")(),
sum: std.native("addNumbers")(10, 20),
formatted: std.native("formatConfig")(
{ name: "app", version: "1.0" },
"Application {name} version {version}"
)
}
''', native_callbacks=native_callbacks)Basic evaluation:
import _jsonnet
# Simple evaluation
result = _jsonnet.evaluate_snippet("example.jsonnet", '''
{
greeting: "Hello World!",
numbers: [1, 2, 3],
nested: {
key: "value"
}
}
''')
print(result) # JSON string outputFile evaluation with variables:
import _jsonnet
result = _jsonnet.evaluate_file("config.jsonnet",
ext_vars={
"environment": "production",
"region": "us-west-1"
},
tla_vars={
"service_name": "api-server"
}
)
# config.jsonnet might contain:
# function(service_name) {
# name: service_name,
# env: std.extVar("environment"),
# region: std.extVar("region")
# }Complex configuration with all options:
import _jsonnet
import os
def load_secret(base, rel):
# Custom import for loading secrets
secret_path = os.path.join("/etc/secrets", rel)
with open(secret_path, 'rb') as f:
return secret_path, f.read()
def encrypt_value(value):
# Native function for encryption
import base64
return base64.b64encode(value.encode()).decode()
result = _jsonnet.evaluate_file("app-config.jsonnet",
jpathdir=["/usr/local/lib/jsonnet", "./lib"],
max_stack=1500,
ext_vars={
"environment": "production",
"cluster": "us-west-1a"
},
ext_codes={
"database_config": '''
{
host: "db.example.com",
port: 5432,
ssl: true
}
'''
},
tla_vars={
"service_name": "user-service",
"replica_count": "3"
},
import_callback=load_secret,
native_callbacks={
"encrypt": (["value"], encrypt_value)
},
max_trace=30
)Error handling:
import _jsonnet
try:
result = _jsonnet.evaluate_snippet("invalid.jsonnet", '''
{
invalid: syntax error here
}
''')
except RuntimeError as e:
print(f"Jsonnet error: {e}")
# Error includes line numbers and contextWorking with complex imports:
import _jsonnet
import json
import urllib.request
def http_import(base, rel):
"""Handle HTTP/HTTPS imports"""
if rel.startswith(("http://", "https://")):
try:
response = urllib.request.urlopen(rel)
content = response.read()
return rel, content
except Exception as e:
raise Exception(f"Failed to fetch {rel}: {e}")
else:
# Fall back to file system
import os
full_path = os.path.join(base, rel)
with open(full_path, 'rb') as f:
return full_path, f.read()
# Jsonnet code can now import from URLs:
# local schema = import "https://api.example.com/schema.jsonnet";
result = _jsonnet.evaluate_snippet("remote.jsonnet", '''
local remote_config = import "https://config.example.com/base.jsonnet";
{
local_override: "value",
base: remote_config
}
''', import_callback=http_import)Integration with Python applications:
import _jsonnet
import json
import sys
class JsonnetConfig:
def __init__(self, config_file, **kwargs):
self.config_file = config_file
self.jsonnet_vars = kwargs
def load(self):
try:
result = _jsonnet.evaluate_file(
self.config_file,
ext_vars=self.jsonnet_vars
)
return json.loads(result)
except RuntimeError as e:
print(f"Config error: {e}", file=sys.stderr)
sys.exit(1)
# Usage in application
config = JsonnetConfig("app.jsonnet",
environment=os.getenv("ENV", "development"),
debug=str(os.getenv("DEBUG", "false")).lower()
).load()
print(f"Starting {config['service_name']} on port {config['port']}")Install with Tessl CLI
npx tessl i tessl/pypi-jsonnet