A Python wrapper for the Kusto.Language parser (Microsoft.Azure.Kusto.Language NuGet package). Not affiliated with Microsoft.
Project description
Kustology
Not affiliated with Microsoft. This is an independent open-source project that wraps Microsoft's publicly distributed Apache 2.0–licensed library.
Kustology is a Python library that exposes Microsoft's KQL parser — the
same one Azure Data Explorer, Azure Monitor, and Microsoft Sentinel use
internally — through pythonnet. It has two tiers you can adopt
independently: a thin wrapper around Microsoft's syntax tree, and an
opt-in intermediate representation (IR) built from Pydantic.
Tier 1 — thin wrapper
The thin tier exposes Microsoft's parser, formatter, and validator, and adds AST analyzers for the questions a KQL author asks most often: which tables a query touches, which columns it reads, which operators chain through it, where time filters live, and how to rename a table everywhere it appears. You work with Microsoft's syntax tree directly.
Tier 2 — semantic IR
The IR tier gives you a typed Pydantic model of the parsed query —
FilterOp, BinOp, ColumnRef — for the questions an analyzer
asks: which source table a column came from after joins and renames,
what schema the pipeline produces at the end, whether two queries are
the same modulo formatting, and how to serialize the whole graph for a
UI, a service, or a language model.
Choosing a tier
Both tiers share the same parser; pick based on what shape of data your code wants to work with.
| Tier 1 — thin wrapper | Tier 2 — semantic IR | |
|---|---|---|
| Install | pip install kustology |
pip install 'kustology[ir]' |
| Dependencies | pythonnet + .NET 8 runtime |
adds pydantic |
| Returns | KustoQuery wrapping Microsoft's syntax tree |
QueryIR — Pydantic models |
| Traversal | Microsoft AST (node.Kind dispatch via pythonnet) |
Typed pipeline (isinstance dispatch) |
| Serialization | KustoQuery.to_dict() / to_json() |
model_dump_json (lossless) + to_llm_dict (LLM-tailored) |
| Schema binding | parse(query, schema=...) runs Microsoft's binder — semantic diagnostics plus symbol resolution accessible via AST methods |
SchemaAttacher materializes those binding results into Pydantic fields and computes Pipeline.result_schema |
| Best for | Formatting / linting, IDE integrations, extracting referenced tables/columns/functions/operators, surgical table renames | Lineage and anti-pattern analyzers, JSON-serializable query representations for APIs and UIs, schema-aware column flow, LLM-fed query graphs |
Prerequisites
- Python 3.10+
- .NET 8.0+ runtime
macOS / Homebrew
If you installed dotnet via Homebrew, the runtime layout differs from
Microsoft's installer (libhostfxr.dylib lives under libexec/, not bin/).
The bridge auto-detects this. If detection fails, set DOTNET_ROOT explicitly:
export DOTNET_ROOT=/opt/homebrew/opt/dotnet/libexec # Apple Silicon
export DOTNET_ROOT=/usr/local/opt/dotnet/libexec # Intel
Installation
pip install kustology # tier 1: thin .NET wrapper
pip install 'kustology[ir]' # tier 1 + tier 2: semantic IR (adds pydantic)
Quick start
from kustology import parse, format_query
query = (
"StormEvents | where StartTime > ago(7d) and DeathsDirect > 0 "
"| project StartTime, State, EventType"
)
print(format_query(query))
result = parse(query)
print(result.get_referenced_tables()) # {'StormEvents'}
print(result.get_referenced_columns()) # {'StartTime', 'DeathsDirect', 'State', 'EventType'}
print(result.get_referenced_functions()) # {'ago'}
print(result.get_structural_hash()[:16])
# Semantic binding via a schema enables column-aware analysis:
schema = {"StormEvents": {"StartTime": "datetime", "DeathsDirect": "int", "State": "string", "EventType": "string"}}
bound = parse(query, schema=schema)
assert bound.has_semantics
With the [ir] extra installed, the same KustoQuery builds a Pydantic IR:
from kustology import parse
from kustology.ir import FilterOp
schema = {"StormEvents": {"DeathsDirect": "int", "State": "string", "EventType": "string"}}
ir = parse("StormEvents | where DeathsDirect > 0", schema=schema).to_ir()
# A bound parse auto-runs SchemaAttacher: column types and table provenance
# are populated. Pass attach_schema=False to skip, or attach_schema={...} to
# override the schema used for the attach pass.
for op in ir.main_pipeline.operators:
if isinstance(op, FilterOp):
print(op.predicate.canonical_form) # StormEvents.DeathsDirect > 0
print(op.predicate.left.table) # StormEvents
print(op.predicate.left.result_type) # int (KustoType.INT)
CLI
The kustology console script ships with the base install:
kustology version # print package version
kustology format query.kql # reformat to canonical form
kustology validate query.kql # print parser diagnostics
kustology validate --json query.kql # diagnostics as JSON
kustology parse query.kql # print the .NET AST
kustology parse --ir query.kql # print the Pydantic IR (requires [ir])
kustology parse --ir --json query.kql # serializable IR
All subcommands also read from stdin when file is - or omitted. Exit codes:
0 success, 1 input had Error-severity diagnostics or a runtime failure,
2 usage error (bad flags, missing file, or missing [ir] extras for
parse --ir).
Development
git clone https://github.com/k4otix/kustology.git
cd kustology
pip install -e ".[dev]"
pytest
ruff check src tests scripts
mypy src
See CONTRIBUTING.md for the full workflow.
License
Apache License 2.0. See LICENSE, NOTICE.md, and
THIRD-PARTY-NOTICES.md. The bundled
Kusto.Language.dll is owned by Microsoft Corporation and redistributed
unmodified under Apache 2.0; it is pinned by SHA-256 and verified in CI —
see SECURITY.md.
Trademark notice
"Kusto", "KQL", "Microsoft", "Azure Data Explorer", "Azure Monitor", and "Microsoft Sentinel" are trademarks of Microsoft Corporation. References to those trademarks are nominative and used only to identify the upstream library this package wraps. Apache License 2.0 §6 does not grant trademark rights; nothing in this distribution should be construed as a trademark license.
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 kustology-0.1.0.tar.gz.
File metadata
- Download URL: kustology-0.1.0.tar.gz
- Upload date:
- Size: 615.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b4ff14d24cf7332b1e7c107ddf6590d12975a74f3af2613822366b31a7e4cfa8
|
|
| MD5 |
4a9a51642108e177f2bdde1dc28ca9c6
|
|
| BLAKE2b-256 |
e58b49d2d1dd8830a08fff36be6be44208520ac8482cf12fb7b728fecc108b19
|
Provenance
The following attestation bundles were made for kustology-0.1.0.tar.gz:
Publisher:
release.yml on k4otix/kustology
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
kustology-0.1.0.tar.gz -
Subject digest:
b4ff14d24cf7332b1e7c107ddf6590d12975a74f3af2613822366b31a7e4cfa8 - Sigstore transparency entry: 1692710779
- Sigstore integration time:
-
Permalink:
k4otix/kustology@8ad2b28872575cbd589f564dbf67d1004cca8a3b -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/k4otix
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@8ad2b28872575cbd589f564dbf67d1004cca8a3b -
Trigger Event:
push
-
Statement type:
File details
Details for the file kustology-0.1.0-py3-none-any.whl.
File metadata
- Download URL: kustology-0.1.0-py3-none-any.whl
- Upload date:
- Size: 612.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fd96a3cad1ea3e2e25dc9c7beebc5c038ad8253d17890b01a71bb2f5bde7b5c6
|
|
| MD5 |
8d398c209df6c6c78c3ede4c1a32040e
|
|
| BLAKE2b-256 |
69f335e792064140e9d390ef5af992020077d989185fdb258b83e2fca49d10e4
|
Provenance
The following attestation bundles were made for kustology-0.1.0-py3-none-any.whl:
Publisher:
release.yml on k4otix/kustology
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
kustology-0.1.0-py3-none-any.whl -
Subject digest:
fd96a3cad1ea3e2e25dc9c7beebc5c038ad8253d17890b01a71bb2f5bde7b5c6 - Sigstore transparency entry: 1692710929
- Sigstore integration time:
-
Permalink:
k4otix/kustology@8ad2b28872575cbd589f564dbf67d1004cca8a3b -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/k4otix
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@8ad2b28872575cbd589f564dbf67d1004cca8a3b -
Trigger Event:
push
-
Statement type: