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.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mquery_toolkit-0.1.0.tar.gz (347.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mquery_toolkit-0.1.0-py3-none-any.whl (346.1 kB view details)

Uploaded Python 3

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

Hashes for mquery_toolkit-0.1.0.tar.gz
Algorithm Hash digest
SHA256 3345e1569c5a364ce74edff3416c4eeae89bae08fd3075e9bb46afe244ba72b2
MD5 810ef49b947bb532b4023bec471618f6
BLAKE2b-256 a62a9a18015e9958fbb09042a523095f3ac1338a68e7ba41465b4c03606f958f

See more details on using hashes here.

Provenance

The following attestation bundles were made for mquery_toolkit-0.1.0.tar.gz:

Publisher: release.yml on GopalGB/mquery-toolkit

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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

Hashes for mquery_toolkit-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f6c0aa7c73c75e1aacec1c0e640b9264e1b259bd43c4b18d7a9251cd3c5442f7
MD5 7bdc5f8bbaace9ddaf184c65ff52be38
BLAKE2b-256 48f6023d49cd894dfc8e9e635f433252d96325e09ec1f8cacffc71004000e55f

See more details on using hashes here.

Provenance

The following attestation bundles were made for mquery_toolkit-0.1.0-py3-none-any.whl:

Publisher: release.yml on GopalGB/mquery-toolkit

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 files

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