This release has been yanked by its maintainers, and will be ignored by installers, except when explicitly specified.
Reason given by maintainers: Renamed to pqtools - run: pip install pqtools
mquery-toolkit
Offline command-line and Python tooling for Power Query M source: parse, format,
lint (check), and safely rename a let binding.
Unofficial. Not affiliated with or endorsed by Microsoft. Not an M runtime - it parses and formats M source text; it does not evaluate queries.
Install
pip install mquery-toolkit
Requires Node.js 22 or newer on PATH, or point MQUERY_NODE at a Node
binary. The Microsoft parser and formatter packages are bundled inside the
wheel (_bridge.cjs) - no npm install needed.
Quick start
# Parse to deterministic JSON (tokens, root kind, bindings/references)
mquery parse query.pq
# Format - dry run prints a unified diff, nothing is written
mquery format query.pq
# Format and write in place (atomic replace, preserves mode/newline/encoding)
mquery format query.pq --write
# Lint, machine-readable output; exit code 2 if any diagnostic is severity=error
mquery check query.pq --json
# Rename one top-level let binding - dry run first
mquery rename query.pq --old OldName --new NewName
Python API
from mquery_toolkit import check, format_source, parse, rename, update_file
parsed = parse(source_text) # dict: tokens, rootKind, analysis
formatted = format_source(source_text) # formatted M source, same encoding
diagnostics = check(source_text, "query.pq") # list[Diagnostic]
renamed = rename(source_text, "OldName", "NewName")
# File-level edit with the same dry-run/--write safety model as the CLI
diff = update_file(path, format_source) # dry run: unified diff
diff = update_file(path, format_source, write=True) # atomic write
Diagnostics
| Code | Severity | Meaning |
|---|---|---|
M_PARSE_ERROR |
error | source does not parse |
M001 |
error | duplicate let binding name |
M002 |
warning | Web.Contents called with a non-literal (dynamic) URL |
M003 |
warning | credential-like literal (password/token/secret = "...") |
M004 |
warning | let binding unreachable from the result |
M005 |
warning | unresolved unqualified reference |
M006 |
info | source-function inventory (*.Contents dependency) |
M002 and M003 are conservative text-pattern checks on the raw source, not
AST checks; expect occasional false positives inside comments or strings.
Every matching occurrence is reported, one diagnostic per call site or
literal.
check --json emits stable objects; check without --json prints
file:line:column: severity code: message per diagnostic. The CLI exits 2
when any diagnostic has severity error, 0 otherwise.
Safety model
- Dry-run by default. Every edit command (
format,rename,replace-source) prints a unified diff and touches nothing unless--writeis passed. --writeis an atomic replace: the file is written to a sibling temp file,fsync'd,chmod'd to match the original, then moved into place withos.replace.- Layout is preserved: UTF-8 encoding, a leading BOM (present in every
Power Query SDK connector file), newline convention (
\nvs\r\n), final-newline state, and file mode all round-trip unchanged. - Refuses symlinks and hardlinks - writes require a regular, single-link file.
- Detects concurrent change: the source is snapshotted before the
transform and re-checked immediately before the atomic replace - this final
snapshot check, not the lock, is the guarantee against lost updates; a
change in that microsecond window raises
SafeWriteError. - Advisory lock while writing only - a
--writecall takes a cross-process advisory lock (fcntl/msvcrt) for the duration of the write and removes the lock file afterward, best-effort. It only serialises cooperatingmqueryprocesses and is not a correctness guarantee: because the lock file is removed after use, a waiting process and a freshly started one can end up locking different inodes. Dry-run calls take no lock and create no lock file. - This is not mandatory locking - no OS provides a portable mandatory lock, and the advisory lock is not itself the correctness guard. Use source control or external exclusive ownership for concurrent editors.
Limits
- Input and output are capped at 10 MiB.
- The Node subprocess is bounded to a 30 second timeout.
- Supported extensions:
.pq,.m,.pqm, and any*.query.pqfile. renamescope: exactly one unquoted top-levelletbinding. It refuses quoted identifiers (#"..."), record literals, lambda expressions, and non-ASCII source.Retry-Afteron the Fabric adapter must be whole seconds; HTTP-date values are rejected.
Optional adapters
fabricextra (pip install "mquery-toolkit[fabric]") - a Fabric Execute Query client that takes a caller-provided bearer token and an injected HTTP transport. It never manages credentials itself and is fully mocked in tests (no network access in the test suite).pqtest- a bounded wrapper around a user-installed Microsoft PQTest executable, Windows-only, pinned to version2.155.2. It never downloads a binary; it only validates and runs one already on disk.
What it is not
- Not an M language runtime or evaluator.
- Not a Power BI or Fabric client, and it does not manage credentials.
- Not a general-purpose file editor - it only touches files with a supported extension and only through the safety model above.
- Not a replacement for Microsoft's own parser/formatter - it vendors and calls them directly rather than reimplementing M syntax.
Development
git clone https://github.com/GopalGB/mquery-toolkit
cd mquery-toolkit
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev,fabric]"
npm ci --ignore-scripts
pytest -q --cov=mquery_toolkit --cov-fail-under=80
mypy src
ruff check .
ruff format --check .
npm test
python -m build
License
MIT - see LICENSE. Bundled Microsoft packages
(@microsoft/powerquery-parser, @microsoft/powerquery-formatter) and their
dependencies are also MIT; see THIRD_PARTY_NOTICES.txt and NOTICE.
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 mquery_toolkit-0.1.0.tar.gz.
File metadata
- Download URL: mquery_toolkit-0.1.0.tar.gz
- Upload date:
- Size: 347.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3345e1569c5a364ce74edff3416c4eeae89bae08fd3075e9bb46afe244ba72b2
|
|
| MD5 |
810ef49b947bb532b4023bec471618f6
|
|
| BLAKE2b-256 |
a62a9a18015e9958fbb09042a523095f3ac1338a68e7ba41465b4c03606f958f
|
Provenance
The following attestation bundles were made for mquery_toolkit-0.1.0.tar.gz:
Publisher:
release.yml on GopalGB/mquery-toolkit
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mquery_toolkit-0.1.0.tar.gz -
Subject digest:
3345e1569c5a364ce74edff3416c4eeae89bae08fd3075e9bb46afe244ba72b2 - Sigstore transparency entry: 2695262584
- Sigstore integration time:
-
Permalink:
GopalGB/mquery-toolkit@ec1a58a9949c8f752f0f803a11d824eea7b28b10 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/GopalGB
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@ec1a58a9949c8f752f0f803a11d824eea7b28b10 -
Trigger Event:
push
-
Statement type:
File details
Details for the file mquery_toolkit-0.1.0-py3-none-any.whl.
File metadata
- Download URL: mquery_toolkit-0.1.0-py3-none-any.whl
- Upload date:
- Size: 346.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f6c0aa7c73c75e1aacec1c0e640b9264e1b259bd43c4b18d7a9251cd3c5442f7
|
|
| MD5 |
7bdc5f8bbaace9ddaf184c65ff52be38
|
|
| BLAKE2b-256 |
48f6023d49cd894dfc8e9e635f433252d96325e09ec1f8cacffc71004000e55f
|
Provenance
The following attestation bundles were made for mquery_toolkit-0.1.0-py3-none-any.whl:
Publisher:
release.yml on GopalGB/mquery-toolkit
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mquery_toolkit-0.1.0-py3-none-any.whl -
Subject digest:
f6c0aa7c73c75e1aacec1c0e640b9264e1b259bd43c4b18d7a9251cd3c5442f7 - Sigstore transparency entry: 2695262596
- Sigstore integration time:
-
Permalink:
GopalGB/mquery-toolkit@ec1a58a9949c8f752f0f803a11d824eea7b28b10 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/GopalGB
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@ec1a58a9949c8f752f0f803a11d824eea7b28b10 -
Trigger Event:
push
-
Statement type: