Skip to content

Commit a3f65b8

Browse files
committed
Extend get_transformer to support non-Python built-in transform types
get_transformer now handles jq, xslt, jsonld-frame, and node in addition to python. Non-Python types are dispatched via a one-shot sub-subprocess running under the main venv interpreter (_MAIN_PYTHON), which has all ogc.bblocks dependencies (lxml, jq, pyld, rdflib, etc.) available regardless of any sandboxed venv the outer Python transform may be using. The callable signature gains an optional source_mime_type parameter so callers can tell transforms like jsonld-frame how to parse their input. For node transforms, npm dependencies declared in the transform's metadata are installed into <sandbox_base>/get_transformer/<bblock_id>/<transform_id>/node on the first call, mirroring the layout used by ordinary node sandboxes. Implementation changes: - TransformMetadata gains _transforms_registry and _sandbox_base_dir (underscore-prefixed: internal, not part of the transform author API) - _build_transforms_registry includes all _GET_TRANSFORMER_TYPES (python, node, jq, xslt, jsonld-frame), storing the transform type alongside code - apply_transforms passes _sandbox_base_dir=sandbox_dir to TransformMetadata - python.py restructured: harness generation split into _NON_PYTHON_HARNESS_CODE, _HARNESS_IMPORTS, and _HARNESS_BODY constants assembled by _build_persistent_harness, eliminating all brace-escaping from the harness template; _MAIN_PYTHON and _SANDBOX_BASE embedded as harness constants
1 parent c1bda3d commit a3f65b8

3 files changed

Lines changed: 249 additions & 92 deletions

File tree

ogc/bblocks/models.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -846,7 +846,8 @@ class TransformMetadata:
846846
sandbox_dir: Path | None = None
847847
id: str | None = None
848848
ctx: TransformContext | None = None
849-
transforms_registry: dict | None = None
849+
_transforms_registry: dict | None = None
850+
_sandbox_base_dir: Path | None = None
850851

851852

852853
@dataclasses.dataclass

ogc/bblocks/transform.py

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -296,42 +296,45 @@ def cleanup_sandbox(sandbox_dir: Path, bblocks: list[BuildingBlock]) -> None:
296296
# temporarily renamed) — leave sandboxes intact to avoid a full rebuild on rename-back
297297

298298

299+
_GET_TRANSFORMER_TYPES = frozenset({'python', 'node', 'jq', 'xslt', 'jsonld-frame'})
300+
301+
299302
def _build_transforms_registry(bblocks_register: BuildingBlockRegister) -> dict:
300303
registry = {}
301304

302305
for bblock_id, bblock in bblocks_register.bblocks.items():
303306
transforms = bblock.transforms
304307
if not transforms:
305308
continue
306-
python_transforms = {
307-
t['id']: {'code': t['code'], 'metadata': t.get('metadata') or {}}
308-
for t in transforms if t.get('type') == 'python' and t.get('code')
309+
supported_transforms = {
310+
t['id']: {'type': t['type'], 'code': t['code'], 'metadata': t.get('metadata') or {}}
311+
for t in transforms if t.get('type') in _GET_TRANSFORMER_TYPES and t.get('code')
309312
}
310-
if not python_transforms:
313+
if not supported_transforms:
311314
continue
312315
bblock_metadata = json.loads(json.dumps(bblock.metadata, default=str))
313316
registry[bblock_id] = {
314317
'name': bblock.metadata.get('name', bblock_id),
315318
'version': bblock.metadata.get('version'),
316319
'bblock_metadata': bblock_metadata,
317-
'transforms': python_transforms,
320+
'transforms': supported_transforms,
318321
}
319322

320323
for bblock_id, raw in bblocks_register.imported_bblocks.items():
321324
transforms = raw.get('transforms') or []
322-
python_transforms = {
323-
t['id']: {'code': t['code'], 'metadata': t.get('metadata') or {}}
324-
for t in transforms if t.get('type') == 'python' and t.get('code')
325+
supported_transforms = {
326+
t['id']: {'type': t['type'], 'code': t['code'], 'metadata': t.get('metadata') or {}}
327+
for t in transforms if t.get('type') in _GET_TRANSFORMER_TYPES and t.get('code')
325328
}
326-
if not python_transforms:
329+
if not supported_transforms:
327330
continue
328331
raw_copy = {k: v for k, v in raw.items() if k != 'register'}
329332
bblock_metadata = json.loads(json.dumps(raw_copy, default=str))
330333
registry[bblock_id] = {
331334
'name': raw.get('name', bblock_id),
332335
'version': raw.get('version'),
333336
'bblock_metadata': bblock_metadata,
334-
'transforms': python_transforms,
337+
'transforms': supported_transforms,
335338
}
336339

337340
return registry
@@ -490,8 +493,9 @@ def apply_transforms(bblock: BuildingBlock,
490493
input_data=snippet['code'],
491494
sandbox_dir=transform_sandboxes.get(
492495
transform['id'], sandbox_dir),
496+
_sandbox_base_dir=sandbox_dir,
493497
ctx=ctx,
494-
transforms_registry=transforms_registry)
498+
_transforms_registry=transforms_registry)
495499

496500
try:
497501
result = transformer.transform(transform_metadata)

0 commit comments

Comments
 (0)