Skip to main content

Kustology

License Python 3.10+ .NET 8.0+

Not affiliated with Microsoft. This is an independent open-source project that wraps Microsoft's publicly distributed Apache 2.0–licensed library.

Kustology gives Python programs Microsoft's own KQL parser, the one behind Azure Data Explorer, Azure Monitor, and Microsoft Sentinel. It loads the official Kusto.Language library through pythonnet, so queries parse exactly as the service parses them.

The library comes in two tiers. Either one works on its own.

The two tiers

Tier 1: thin wrapper

Tier 1 exposes Microsoft's parser, formatter, and validator, and adds analyzers for the questions a KQL author asks most: which tables a query reads, which columns it touches, which operators it chains, where its time filters sit, and how to rename a table everywhere it appears. You work with Microsoft's syntax tree directly.

Tier 2: semantic IR

Tier 2 builds a typed Pydantic model of the parsed query, with classes like FilterOp, BinOp, and ColumnRef. It suits the questions an analyzer asks: which source table a column came from after joins, renames, and let aliases; what schema the pipeline produces; whether two queries mean the same thing despite formatting; how much two queries overlap or where two versions of a rule diverge; and how to serialize the whole graph for a UI, a service, or a language model.

Choosing a tier

Both tiers use the same parser. Pick based on the shape of data your code wants.

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, dispatching on node.Kind Typed pipeline, dispatching on isinstance
Serialization to_dict() / to_json() model_dump_json(), which round-trips, plus to_llm_dict() for language models
Schema binding parse(query, schema=...) runs Microsoft's binder for semantic diagnostics and symbol resolution; the dict declares tables, and a FunctionSchema value declares a function to_ir() on a bound parse carries per-operator schemas and column types; without a schema it still types literals and built-in calls
Best for Formatting, linting, IDE integrations, extracting tables and columns, surgical table renames Lineage and anti-pattern analyzers, JSON for APIs and UIs, schema-aware column flow, query graphs for language models

Prerequisites

If you installed dotnet through Homebrew, its runtime layout differs from Microsoft's installer and libhostfxr.dylib sits under libexec/ instead of bin/. Kustology detects this. If detection fails, set DOTNET_ROOT yourself:

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)
pip install 'kustology[examples]' # Colour output in examples/ (adds rich)

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)
result.get_referenced_tables()      # {'StormEvents'}
result.get_referenced_columns()     # {'StartTime', 'DeathsDirect', 'State', 'EventType'}
result.get_referenced_functions()   # {'ago'}

# Pass a schema to bind the query and get semantic diagnostics.
schema = {"StormEvents": {"StartTime": "datetime", "DeathsDirect": "int",
                          "State": "string", "EventType": "string"}}
bound = parse(query, schema=schema)
bound.has_semantics                 # True
bound.diagnostics                   # []

With the [ir] extra installed, the same parse builds a Pydantic IR:

from kustology import parse
from kustology.ir import FilterOp

schema = {"StormEvents": {"DeathsDirect": "int", "State": "string"}}
ir = parse("StormEvents | where DeathsDirect > 0", schema=schema).to_ir()

for op in ir.main_pipeline.operators:
    if isinstance(op, FilterOp):
        op.predicate.canonical_form   # StormEvents.DeathsDirect > 0
        op.predicate.left.table       # StormEvents
        op.predicate.left.result_type # int  (KustoType.INT)

CLI

The kustology console script ships with the base install:

kustology format query.kql        # reformat to canonical form
kustology validate query.kql      # print parser diagnostics
kustology parse --ir query.kql    # print the Pydantic IR (needs [ir])
kustology sources query.kql       # report every source the query reads

Every subcommand, the --schema and --json flags, and the exit codes CI branches on are in the CLI reference.

Examples

Each script runs standalone and explains its own output as it goes, and tests/test_examples.py runs all of them, so none can drift away from the library without CI noticing.

examples/walk_tree.py Direct AST traversal
examples/query_analysis.py End-to-end analysis of a non-trivial query
examples/binding_comparison.py What passing a schema adds
examples/safe_interpolation.py Interpolating a caller-supplied name into KQL safely
examples/walk_ir.py The same walk over the typed IR
examples/find_all_demo.py Generic IR traversal with find_all
examples/analyzer_demo.py Composing analyzers and reading Findings
examples/linter.py A working KQL linter built on the IR
examples/llm_view.py IR serialization for language models
examples/semantic_hash_demo.py What semantic_hash merges and what it splits
examples/query_similarity.py Graded similarity, containment, and diffing between related queries
examples/lookback_window.py Outer lookback via result_type, prune and span_of

The IR examples need the [ir] extra. The rest run on the base install. Add the [examples] extra for colour and syntax highlighting; without it the same output prints as plain text.

Documentation

Working with the syntax tree Tier 1 in depth, and the pythonnet behavior that catches people off guard
The Tier 2 IR How let names, operators, and function bodies lower into IR nodes
CLI reference Subcommands, flags, JSON output, exit codes
Versioning and semantic_hash Compatibility tags, and what the digest ignores
Graded similarity Comparing queries by degree: subtree overlap, containment, and diffing
Architecture Code layout, for contributors
Contributing Setup and the development loop

Versioning

This is a 0.y release, so the public API can still change at a minor version (SemVer §4). Tier 1 is on a stabilization track and reaches 1.0 once it survives external use without correctness breaks. Tier 2 keeps evolving at minor cadence.

Three numbers describe compatibility: kustology.__version__ tags the library, kustology.ir.IR_SCHEMA_VERSION tags the IR's field shape, and kustology.ir.SEMANTIC_HASH_SCHEME tags the hash canonicalization rules. A QueryIR dump carries its ir_schema_version, and QueryIR.model_validate rejects a dump tagged with any other version or with none. A semantic_hash carries its scheme as a prefix. See Versioning and semantic_hash for the full contract.

Development

git clone https://github.com/k4otix/kustology.git
cd kustology
uv sync --locked --extra dev

uv run pytest
uv run ruff check src tests scripts examples
uv run 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.

Metadata

Release files for kustology 0.4.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for kustology 0.4.0
File Size Uploaded Provenance Actions
kustology-0.4.0.tar.gz 1.1 MB With provenance Details for kustology-0.4.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for kustology 0.4.0
File Interpreter ABI Platform Actions
kustology-0.4.0-py3-none-any.whl Python 3 none any Details for kustology-0.4.0-py3-none-any.whl

Total release size: 1.9 MB

Release files / kustology-0.4.0.tar.gz

Download URL kustology-0.4.0.tar.gz
Size 1.1 MB
Tags Source
SHA-256 checksum
How to use checksums
6fefb4aa4520f66f07cf5933e00c1d9375f885f500d46a65ae9a971390dddd25
BLAKE2b-256 checksum
How to use checksums
1a573130c81e04032e15101fb0586f5832dbfc74c860f38cc01c867d5fa274ab
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 16, 2026.

Transparency log

Release files / kustology-0.4.0-py3-none-any.whl

Download URL kustology-0.4.0-py3-none-any.whl
Size 774.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
90499b0e4d4007389275fcb2408d220c3dc90de7fd4276017b8edfd4ba2dc278
BLAKE2b-256 checksum
How to use checksums
33b686ceb7f8d708a5dc21f88ae2e9df59bca7bc8acb40dffbf129174f067f47
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 16, 2026.

Transparency log

Security for kustology 0.4.0

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.

Full provenance

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for kustology-0.4.0.tar.gz

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 16, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page