Library / SDK
salu133445/muspy avatar
salu133445/muspy

muspy: symbolic music tooling whose last release was April 2022

A toolkit for symbolic music generation

524 stars59 forksPythonMIT

At a glance

What is it?
A Python library covering the shareable parts of a symbolic music generation pipeline: datasets, format conversion, four common representations and evaluation. The release history stopped four years before the last commit, and every dependency floor is a decade old with no ceiling anywhere.
Who is it for?
muspy is the kind of library that was finished and then left alone, which is a defensible outcome for a research toolkit and a poor foundation for a production pipeline without pinning. Two things to check first.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Activity is slowing. The repository last received commits 7 months ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 11, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The newest release is April 2022 and the last push is March 2026

Three releases are listed, and the newest is v0.5.0 from 2022-04-16. Before it, v0.4.0 from 2021-10-10 and v0.3.0 from 2021-01-03.

The last push to the default branch is dated 2026-03-11. That is more than three years after the newest tag.

The repository is not archived, and the commit history reaching into 2026 is not what a dead project looks like. What it looks like is a project where the tagged release line and the working branch have separated: somebody has been committing for four years without cutting a version.

That has a concrete consequence for anyone installing. From the package index you get v0.5.0, which is a 2022 state. From a clone you get whatever is on the branch, which is a 2026 state that no release corresponds to. The two are different code, and the page does not tell you which one its own documentation describes.

The version numbers themselves are also modest. The line is still at zero for its fourth listed release, which is consistent with a research library that stabilized long ago and is not aiming at a one release.

Nothing here says the project is abandoned. It says the releases and the source have not been kept in step, and that is the part worth knowing before you depend on it.

No framework is required, though PyTorch and TensorFlow interfaces are a feature

The first feature bullet promises a dataset management system with interfaces to PyTorch and TensorFlow. Neither framework appears among the install requirements.

The eleven runtime dependencies are a YAML parser, a bidirectional dictionary, joblib for parallelism, matplotlib for visualization, several MIDI libraries, a music theory library, an HTTP client and a progress bar. No numerical array library, no deep learning framework, nothing that would pull in a GPU stack.

That is the right design for this kind of library. A user who only wants to read MIDI files and render a piano roll should not install a deep learning framework to do it, and a user plugging the representations into their own model already has the framework.

It also means the framework interfaces are effectively optional features in the packaging sense, which the page does not say. The distinction between a feature the library provides and a feature the library requires is exactly the kind of thing that matters when you are writing a requirements file, and here the answer is that a PyTorch integration pulls in no extra dependency at all.

One test-related detail points the other way. The pytest configuration sets a TensorFlow log-level environment variable, which only makes sense if TensorFlow is present in at least some test paths. So the frameworks are exercised during development without being required at install time, which is consistent with the packaging but worth knowing if you are debugging a test run.

Every dependency floor is a decade old and not one has a ceiling

The install requirements are all lower bounds with no upper bounds, and the floors are remarkably old.

The YAML parser is floored at a version from the early 2010s. Matplotlib is floored at a 1.x release. Joblib is floored at 0.15. Requests at 2.0, tqdm at 4.0, and the MIDI libraries at floors around 1.0.

The one that matters most is the music theory library, floored at 6.0 with nothing above it. That library has changed shape across major versions, and a floor with no ceiling means a fresh resolve today will take whatever the current release is, not the release the library was written against.

The same pattern appears in the development extras, where the formatter is floored at a 19 release, which predates its own stable formatting behaviour.

So an install today is not reproducible in the sense the project means elsewhere on the page. The reproducibility claim in the project's own rationale is about implementing standard versions of published routines so that two labs get the same numbers, which is a different and legitimate thing.

For the install itself, there is no lockfile in the repository, no upper bound on any dependency, and no declared support window. A working environment from 2022 and a working environment from today are the same requirements file and quite different resolution.

The documented source install is an invocation setuptools no longer supports

Installation is one line from the package index:

bash
pip install muspy

The source route is described in one sentence: download the source and run the setup script with the install argument.

That specific invocation stopped being supported some time ago. Setuptools deprecated direct setup-script installation, and current versions remove it, so the documented path fails on a modern environment while the package-index line above works fine.

The project is not unusual in this. A readme written when the library was current tends to keep its install sentence, and this one dates from a period when that was still the normal way to do it.

The setup script itself is worth a look because it does two things that are no longer idiomatic. It reads the long description straight out of the readme file at build time, which is fine. And it derives the version by opening the package's own version module, scanning for a line that starts with the version dunder, deciding which quote character to split on, and taking the text between the first two occurrences. If no such line exists it raises a runtime error.

That is string parsing standing in for a version source, which breaks if the assignment is reformatted across two lines. It also means the packaging metadata lives in a Python file rather than in a declared field, so tooling that reads the metadata statically sees nothing.

doc/ and docs/ both exist, and the conda environment file is misspelled

The top-level listing contains both a documentation directory and a second one whose name differs by one letter, plus a conda environment file whose name is misspelled.

Two documentation directories is the classic residue of a rename. One of them is current and one is not, and nothing on the page says which builds the site. Both are in the repository, so a contributor looking for where to edit documentation has a fifty-fifty chance of picking the wrong one, and the wrong one will appear to be missing recent changes.

The environment file being misspelled matters less and is more annoying. It is not referenced anywhere in the readme, so nobody finds it by searching the documentation, but it is also not going to be found by a script or a contributor expecting a conventional name either. A project that ships a conda environment file and does not mention it in the installation instructions has already made the reader guess once.

Two other root entries are worth noting. A version-control workspace configuration directory is committed, so editor preferences are part of the repository. And a citation metadata file is present, which is the modern machine-readable way to handle attribution, sitting alongside a readme section that handles it in prose.

There is no changelog at the root. For a library whose releases stopped in 2022 and whose branch has continued, that is the one document that would most help someone reconstructing what changed.

The citation points at a 2020 paper while the code has moved since

The readme asks anyone publishing work that uses the library to cite a specific paper: the toolkit paper, presented at the twenty-first conference of the society for music information retrieval, in 2020.

Four authors are named on that paper, which is a different list from the single author recorded as the package author in the setup metadata.

Both facts are fine on their own. A library accumulates contributors, and a citation is a citation. But the interesting number is the gap: the citation describes a 2020 artefact, the first listed release is from January 2021, the newest release is from April 2022, and the branch is at March 2026.

So a reader following the citation instruction is citing a description of the library that is six years older than the code they actually used, and there is no second citation offered for the later state.

The readme also links a video, the paper as a PDF, slides, a poster, a preprint, the code and the documentation site, so all of the original artefacts remain reachable and none of them has been updated.

The citation metadata file at the repository root can carry more current information than the readme does. Whether it has been maintained is not something the page states, so for anyone who needs to cite accurately rather than conventionally, that file is the place to check first.

Five lint and type tools are configured, and one pylint category is off entirely

The packaging metadata contains no project table at all, only tool configuration. That is unusual and it tells you where the metadata actually lives, which is in the setup script.

What is in there is a lot of tooling. A formatter with a line length of 79, an import sorter configured to match that formatter's profile at the same width, a linter with its own good-names list and its own line length, a type checker configured to ignore missing imports, and a test runner.

Three separate linters are wired up, since the development extras add a fourth alongside the two already in the metadata. Running a linter, a separate linter, a type checker and a docstring checker over the same tree is a lot of configuration surface for a library whose package metadata is a single setup script.

The 79-column format width is the other notable choice, since it is well under the common default and explains why both the formatter and the linter agree on it.

The linter configuration is where the history shows. The disabled list is given as a broad prefix covering an entire category of refactoring checks, plus two specific style messages and one warning. Disabling a whole checker category at once is the shape a suppressions list takes when it has been accumulated one finding at a time and nobody has come back to delete the entries that no longer apply.

There is also a filename pattern for the tests that is missing a dot before its extension, which happens to match most test filenames and would not match all of them.

The dataset disclaimer refuses to vouch for quality or fairness

The disclaimer is the most direct paragraph in the readme, and it is about datasets rather than about the library.

The library is described as a utility that downloads and prepares public datasets. It states that it does not host or distribute them, does not vouch for their quality or fairness, and does not claim that a user has a licence to use any of them. Determining permission is placed on the user, under each dataset's own licence.

For a library whose first listed feature is dataset management, that is a stronger position than most tools take. Refusing to vouch for quality means a user cannot cite the toolkit as evidence that the data is sound. Refusing to vouch for fairness means the same about bias. Both are honest, and both are the kind of statement that costs a project something to make.

The last paragraph opens the door the other way. Dataset owners who want a description or citation corrected, or who want their dataset removed from the library entirely, are directed to a GitHub issue. Removal on request is a commitment, and having it in writing next to a refusal to vouch is what makes the disclaimer read as a position rather than boilerplate.

Everything else the library claims for itself is narrower: the shareable parts of a pipeline, implemented in standard versions so that two systems can be compared. That is a modest claim, and it is the one the package metadata, the dependency list and the release history all support.

Editorial conclusion

muspy is the kind of library that was finished and then left alone, which is a defensible outcome for a research toolkit and a poor foundation for a production pipeline without pinning. Two things to check first. The newest tagged release is from April 2022 while the last push to the default branch is dated 2026-03-11, so no release matches the source you would install from a checkout. And the dependency floors reach back a decade with no ceilings anywhere, including a music library whose major version has changed shape since. If reproducibility matters to you, pin everything yourself: the project's own claim to reproducibility is about its routines, not about your install.

Frequently asked questions

What does muspy provide?

The shareable parts of a symbolic music generation pipeline: dataset management for commonly used datasets, data input and output for formats such as MIDI, MusicXML and ABC, implementations of pitch-based, event-based, piano-roll and note-based representations, and evaluation tools covering audio rendering, visualizations and objective metrics.

Does muspy require PyTorch or TensorFlow?

No. Neither appears among the install requirements, even though interfaces to both are listed as a feature. The runtime dependencies are a YAML parser, a bidirectional dictionary, joblib, matplotlib, several MIDI libraries, music21, requests and tqdm.

How do I install muspy from source?

The documented route is to download the source and run the setup script with the install argument, which is an invocation that current setuptools versions no longer support. Installing from the package index with pip is the working path.

How current is muspy?

The newest tagged release is v0.5.0 from April 2022, and the last push to the default branch is dated 2026-03-11. The repository is not archived, but the release history stopped more than three years before that last commit.

What licence is muspy under, and what about the datasets?

The library is MIT. The datasets are separate: the project states it does not host or distribute them, does not vouch for their quality or fairness, and makes it the user's responsibility to check permission under each dataset's own licence.

Official sources

  1. License: MIT
  2. Project website
  3. README
  4. Releases
  5. salu133445/muspy on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/salu133445-muspy.svg)](https://hysenlabs.com/projects/salu133445-muspy)