Metadata-Version: 2.4
Name: finale-file-parser
Version: 0.2.0
Summary: A parser for Finale music notation files (.mus/.musx).
Author: jsawruk
License-Expression: MIT
Project-URL: Homepage, https://github.com/jsawruk/finale-file-parser
Project-URL: Repository, https://github.com/jsawruk/finale-file-parser
Project-URL: Issues, https://github.com/jsawruk/finale-file-parser/issues
Keywords: finale,music,notation,musicxml,enigma,musx
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: End Users/Desktop
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Multimedia :: Sound/Audio :: Conversion
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.12
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: defusedxml>=0.7.1
Dynamic: license-file

# 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

```bash
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. The only runtime dependency is `defusedxml`.

To run a change that has landed on `main` but is not yet released:

```bash
uv tool install git+https://github.com/jsawruk/finale-file-parser
```

## Converting scores

```bash
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`.

```bash
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.

```bash
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
score it built, the records it read, and the raw bytes. It is most informative when the document
does *not* convert — the report 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, 631 build a score: 401 of 401 `.musx`, 99 of
99 Finale 2011 `.mus`, and 131 of 139 Finale 2001–2005 `.mus`. The eight are the files rather than
the reader — six are blank scores the parser refuses deliberately, one is a mirror, 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](https://docs.astral.sh/uv/) (Python environment + package manager)
- Python 3.12+ (uv can install this for you)

## Getting started

```bash
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`](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`](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.
