finale-file-parser
A parser for Finale music notation files (.mus/.musx).
Finale was discontinued in 2024 and its format is proprietary and undocumented. This project reads
those files and converts them to MusicXML, so scores that only exist as .mus or .musx can be
migrated, analysed or archived.
Installing
uv tool install finale-file-parser # just the `finale-parser` command
pip install finale-file-parser # or as a library, into your own environment
Python 3.12 or newer. Runtime dependencies are defusedxml, which makes parsing untrusted XML safe,
and Verovio, which engraves the inspection report's notation view.
To run a change that has landed on main but is not yet released:
uv tool install git+https://github.com/jsawruk/finale-file-parser
Using the library
from finale_file_parser import read_document, read_score
score = read_score("archive/score.musx")
document = read_document("archive/legacy-score.mus")
read_score is the ordinary high-level entry point and returns the format-neutral Score model.
read_document stops one layer earlier at EnigmaDocument for callers that need Finale records.
Both detect .mus versus .musx from the file contents rather than the filename extension, and
preserve the existing parser exceptions.
Converting scores
finale-parser convert score.mus # writes score.musicxml beside it
finale-parser convert score.musx -o out.musicxml
finale-parser convert ./scores -o ./converted # a whole tree, layout preserved
A batch does not stop at the first bad file: what fails is reported and skipped, the rest are
converted, and the exit status is non-zero if anything was skipped. Existing output is never
overwritten unless you pass --force.
finale-parser inspect score.mus # what the file is, and what was read from it
inspect prints the detected version and the shape of the score — parts, measures, events,
pitches.
finale-parser inspect score.mus --report score-report.html
Writes one self-contained HTML file showing what the parser saw: how far the pipeline got, the
engraved score and music tree it built, the records it read, and the raw bytes. A .musx report also
shows the file's complete EnigmaXML as a foldable tree; a binary .mus has no source XML, so that tab
is absent. The report is most informative when a document does not convert — it names the stage
that stopped and why, which is what to send when reporting a file that will not parse.
A .mus is read by reverse engineering, so a converted score can be missing things the original
had — part names come out positional, for instance. What is and is not carried is recorded in
UNTRANSLATED in src/finale_file_parser/enigma/mus_document.py.
How well does it read a file?
Of the 639 documents in the maintainer's test corpus, 632 build a score: 401 of 401 .musx, 99 of
99 Finale 2011 .mus, and 132 of 139 Finale 2001–2005 .mus. The seven are the files rather than
the reader — six are blank scores the parser refuses deliberately, one an incomplete export.
That corpus is licensed material and is not in this repository, so those sweeps do not run in
CI — they are skipped on any checkout without a corpus. CI verifies lint, formatting,
mypy --strict, and every test that does not need one.
Requirements for development
- uv (Python environment + package manager)
- Python 3.12+ (uv can install this for you)
Getting started
make install # create the virtual environment and install dependencies
make check # run lint, format-check, type-check, and tests
Development
This project uses a single command surface — run make help to see every target. All code quality
checks run together via make check, which is also what Continuous Integration (CI) runs on every
push and pull request.
Contributor and AI-assistant conventions for this repo live in CLAUDE.md; design notes and
decisions live in docs/.
make check is what CI runs, but a CI checkout has no corpus, so the corpus sweeps skip there. A
green CI run verifies less than a green local run on a machine that has one.
License
MIT — see LICENSE.
The format knowledge this project rests on came from elsewhere, and two modules were written from
third-party work: the PKWARE DCL decompressor is a port of Mark Adler's blast.c, and the
score.dat cipher parameters were taken from denigma. THIRD-PARTY-NOTICES.md
carries those notices; docs/REFERENCES.md records every source consulted.
The reference documents vendored in docs/ are third-party works reproduced for research and
scholarship, and are not covered by this project's MIT license. They are documentation only —
no published package contains them.
Metadata
Release files for finale-file-parser 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| finale_file_parser-0.3.0.tar.gz | 180.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| finale_file_parser-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 378.9 kB
Release files / finale_file_parser-0.3.0.tar.gz
| Download URL | finale_file_parser-0.3.0.tar.gz |
|---|---|
| Size | 180.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
2ee1e0e3ba6f494559b7505d53f455da0da0dc16854f303e66a1e156a21b5288
|
|
BLAKE2b-256 checksum How to use checksums |
072c0139b8f46a644a5a6e16db2d5f92567e0b9cc40f78ed33e9302d65781550
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.9.22 {"installer":{"name":"uv","version":"0.9.22","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / finale_file_parser-0.3.0-py3-none-any.whl
| Download URL | finale_file_parser-0.3.0-py3-none-any.whl |
|---|---|
| Size | 198.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9004e0886321767ecb89054c9b9923233db0c50dfe2add3dd52d304e19791a82
|
|
BLAKE2b-256 checksum How to use checksums |
255e8c62a785be8d3052334c013f08c4b44a32f61b84e5876c5e6893ef7931b1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.9.22 {"installer":{"name":"uv","version":"0.9.22","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|