Skip to main content
Yanked

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 --write is passed.
  • --write is an atomic replace: the file is written to a sibling temp file, fsync'd, chmod'd to match the original, then moved into place with os.replace.
  • Layout is preserved: UTF-8 encoding, a leading BOM (present in every Power Query SDK connector file), newline convention (\n vs \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 --write call 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 cooperating mquery processes 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.pq file.
  • rename scope: exactly one unquoted top-level let binding. It refuses quoted identifiers (#"..."), record literals, lambda expressions, and non-ASCII source.
  • Retry-After on the Fabric adapter must be whole seconds; HTTP-date values are rejected.

Optional adapters

  • fabric extra (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 version 2.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.

Metadata

Release files for mquery-toolkit 0.1.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 mquery-toolkit 0.1.0
File Size Uploaded Provenance Actions
mquery_toolkit-0.1.0.tar.gz 347.8 kB With provenance Details for mquery_toolkit-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for mquery-toolkit 0.1.0
File Interpreter ABI Platform Actions
mquery_toolkit-0.1.0-py3-none-any.whl Python 3 none any Details for mquery_toolkit-0.1.0-py3-none-any.whl

Total release size: 693.9 kB

Release files / mquery_toolkit-0.1.0.tar.gz

Download URL mquery_toolkit-0.1.0.tar.gz
Size 347.8 kB
Tags Source
SHA-256 checksum
How to use checksums
3345e1569c5a364ce74edff3416c4eeae89bae08fd3075e9bb46afe244ba72b2
BLAKE2b-256 checksum
How to use checksums
a62a9a18015e9958fbb09042a523095f3ac1338a68e7ba41465b4c03606f958f
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 3, 2026.

Transparency log

Release files / mquery_toolkit-0.1.0-py3-none-any.whl

Download URL mquery_toolkit-0.1.0-py3-none-any.whl
Size 346.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f6c0aa7c73c75e1aacec1c0e640b9264e1b259bd43c4b18d7a9251cd3c5442f7
BLAKE2b-256 checksum
How to use checksums
48f6023d49cd894dfc8e9e635f433252d96325e09ec1f8cacffc71004000e55f
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 3, 2026.

Transparency log

Security for mquery-toolkit 0.1.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 mquery_toolkit-0.1.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 3, 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.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files Full provenance

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