graphify-objectscript
InterSystems ObjectScript (.cls/.mac/.inc/.rtn) support for
graphify (PyPI: graphifyy),
for customers running the current release rather than a fork -- until this
ships natively upstream.
A bridge, not a fork. The extractor in this package is the same code proposed upstream in Graphify-Labs/graphify#3921. Once graphify releases native support (
uv tool install "graphifyy[objectscript]"), this package detects it and becomes a no-op; a final release will then mark it deprecated. Supported range today:graphifyy>=0.9.71,<0.10.
Without this package, stock graphifyy:
- mis-parses
.clsclass files as Salesforce Apex, - mis-parses
.incmacro includes as Pascal, - skips
.mac/.rtnroutines entirely (no extractor is registered for them), and - never appears in
graphify-out/graph.jsonwithmetadata.language == "objectscript", so/graphifyand the knowledge graph it builds have no idea your IRIS code exists.
graphify-objectscript patches a running graphify in place, the moment it
is imported, so .cls/.mac/.inc/.rtn files get real ObjectScript
extraction instead: class/method/routine/label/macro nodes, and cross-file
call resolution (##class(...) calls, Do Label^Routine, $$$MACRO
usage, XData-referenced classes, inheritance).
Install
Either of these puts graphifyy and this package's plugin into the same
environment:
uv tool install graphifyy --with graphify-objectscript
pip install graphifyy graphify-objectscript
Both work with any recent graphifyy release in the >=0.9.71,<0.10 range
(see Limitations below for what that floor buys you).
Verify it worked
uvx --from graphifyy python -c "import graphify.extract as e; print('.mac' in e._DISPATCH)"
should print True. This intentionally never imports graphify_objectscript
itself -- that is the whole point: installing this package alongside
graphifyy is enough, because of the import hook described below.
How it works
Installing this package drops one .pth file at the site-packages root
(graphify_objectscript.pth, containing a single
import graphify_objectscript._autoload line). Python's site module runs
every .pth file at interpreter start-up, before your own code runs -- so
graphify_objectscript._autoload installs a lightweight import hook and
returns in well under a millisecond, long before anything imports
graphify itself.
The moment something later does import graphify.extract or
import graphify.detect (directly, or indirectly via from graphify.extract import ...), the hook lets that import finish normally and then calls
graphify_objectscript.register(), which:
- adds
.mac/.rtntographify.extract._DISPATCH, pointing at this package's ObjectScript extractor, - wraps
graphify.extract._get_extractorso a.cls/.incfile is content-sniffed: it only reroutes to the ObjectScript extractor when the file positively looks like ObjectScript (a line-anchoredClass Name ...header,ROUTINE ... [Type=INC],#define/#includedirectives, ...), so every existing Apex.clsand Pascal.inccorpus is unaffected, files whose sniff is inconclusive keep their historical default, - adds
.mac/.rtntographify.detect.CODE_EXTENSIONS(and tographify.watch._WATCHED_EXTENSIONS, ifgraphify.watchhappens to be imported already), and - registers a cross-file resolver (
objectscript_calls) that turns raw in-body calls into real graph edges once every file has been parsed.
This works identically inside a ProcessPoolExecutor worker: macOS's
default spawn start method re-runs a full interpreter start-up (and thus
this .pth hook) in every worker process, which is exactly why this has to
be an import-time hook rather than, say, a console-script wrapper -- nothing
else would run early enough. It also works for the exact invocation the
/graphify skill itself uses,
python -c "from graphify.extract import ...", since the hook is already
installed by the time that one-line script starts running.
Set GRAPHIFY_OBJECTSCRIPT_DEBUG=1 to get one line on stderr if the hook or
register() ever declines to do something (unsupported graphifyy version,
an unexpected module shape, ...) -- by design this package never raises or
prints noisily on its own; it fails open and stock behavior continues.
The sidegraph fallback
Some environments cannot run a .pth hook at all -- a locked-down sandbox,
an interpreter started with -S/-I, a zipapp, or simply a machine where
you only have stock graphifyy installed and want an ObjectScript graph
built somewhere else and merged in later. For those, graphify-objectscript
installs a sidegraph subcommand that does not depend on the import hook at
all -- it calls register() directly in its own process:
graphify-objectscript sidegraph /path/to/iris/code --out sidegraph.json
This walks /path/to/iris/code, keeps only .cls/.mac/.inc/.rtn
files, extracts them, and writes a standalone {"nodes": [...], "edges": [...]} JSON file. Fold it into a normal graph built by plain graphify
(run anywhere, even a machine without this package at all) with:
graphify merge-graphs graphify-out/graph.json sidegraph.json --out graphify-out/graph.json
(see graphify merge-graphs --help for the exact flags your installed
graphifyy version supports).
The graphify-objectscript console script itself is also a drop-in
graphify replacement for everything else -- graphify-objectscript update . registers ObjectScript support and then delegates straight to graphify update . with the same arguments, which is handy in an environment where
the .pth hook did not run but a console script still can.
Limitations
- Supported
graphifyyrange:>=0.9.71,<0.10. Below the floor, the private names this package patches (graphify.extract._DISPATCH/_get_extractor/register_language_resolver,graphify.detect.CODE_EXTENSIONS) may not exist yet or have a different shape;register()checks this and fails open (one stderr line, no patching) rather than guessing. Comes the day agraphifyyrelease ships ObjectScript support natively,register()notices (.macis already in_DISPATCH) and does nothing further -- this package quietly becomes a no-op rather than fighting the native implementation. - The Pascal-resolver guard is fork-only. The fork this extractor comes
from also patches
graphify.pascal_resolution._pascal_raw_callsto ignore raw calls taggedlanguage="objectscript", so a.incfile that happens to also get swept up by the shared Pascal unit-name resolver never gets a spurious Pascal edge. On stockgraphifyyan ObjectScript raw call is never a Pascal call owner, so this does not come up in practice -- it is called out here only so it is not mistaken for a bug. - The qualified-call gate is emulated. The fork's
extract.pyskips raw calls taggedis_qualified_callin its shared bare-name resolution pass (every ObjectScript call names its own target scope:##class(X).M(),$$Label^Routine,$$$MACRO). Stockgraphifyyhas no such gate, soextract_objectscript_stockre-applies the flag it does honour,is_member_call: True, to every qualified call before the pass sees it. Either way only this package's ownobjectscript_callsresolver turns these calls into graph edges, with that qualified evidence. - No language-family table entries. Unlike the fork, this package does
not (and safely cannot) add
.cls/.inc/.mac/.rtnto graphify's suffix-keyed language-family tables (used bybuild/analyze, not byextract); the qualified-call gate above is what keeps cross-language bare-name matches out. .int(compiled output) is intentionally never dispatched, on stock or on the fork -- it duplicates every.mac/.clssymbol and would only produce double-counted nodes.
Development
uv build
uv venv .venv-test --python 3.13
uv pip install --python .venv-test/bin/python "graphifyy==0.9.71" dist/*.whl pytest
.venv-test/bin/python -m pytest tests -q
scripts/sync_from_fork.py re-copies extractor.py and
tests/fixtures/objectscript/ from a sibling
graphify-objectscript/graphify fork checkout and writes SYNC_SHA; run it
after the fork's extractor changes. tests/test_sync.py checks this
package still matches SYNC_SHA unconditionally, and additionally against
a live fork checkout when one is present next to this package.
Metadata
Release files for graphify-objectscript 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| graphify_objectscript-0.1.0.tar.gz | 35.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| graphify_objectscript-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 66.2 kB
Release files / graphify_objectscript-0.1.0.tar.gz
| Download URL | graphify_objectscript-0.1.0.tar.gz |
|---|---|
| Size | 35.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
80191b6fc9ba6574bff4617971d592062b9545dcfec256cb6da84e9435356eb3
|
|
BLAKE2b-256 checksum How to use checksums |
0394197aec3386e43a850b666afae5c14a9ec4a8e9687f021ea11a7794f6d0b3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 29, 2026.
Transparency logRelease files / graphify_objectscript-0.1.0-py3-none-any.whl
| Download URL | graphify_objectscript-0.1.0-py3-none-any.whl |
|---|---|
| Size | 30.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e1c0935c3a785deebe7846cd5989e754a176160be03511808ea12bcbea82dd0d
|
|
BLAKE2b-256 checksum How to use checksums |
3f2abd1fd9d0fb20ad3d01e943b8e4e5d8fc3bf8a61f62a91d05c19b48900835
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 29, 2026.
Transparency log