warnings-and-environment
Skill2.6k starsChanged 10 days agoBSD-3-ClauseView on GitHub
How music21 tells users about problems: `warnings.warn` with a module Warning class, `environLocal.warn`, and `environLocal.printDebug`. Read before adding a warning or debug message, and before writing a test or doctest that triggers one — tests must never print warnings to the console.
We split this skill into the rules it gives an agent
3 rules. About 0 are common, 0 are distinctive, and 3 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈0
Distinctive · estimate
This author's own choices. Worth a look.
3
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 24
Not unified. In 2026 the code has about 73 environLocal.warn, 41 warnings.warn (some with a module class, some bare), 800 printDebug, and …
- Very specific: line 62
When the warning is the point of the example, record it and show it.
- Very specific: line 76
When it is incidental, hide the silencing from the docs (see writing-docs for #_DOCS_HIDE/#_DOCS_SHOW):
≈ “Common” is an estimate: at least 1 in 5 of the 308,232 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Warnings and the Environment
Three channels
| Call | Goes to | Can a caller catch or silence it? |
warnings.warn(MusicXMLWarning('...'), stacklevel=2) | Python's warnings system | Yes: filters, catch_warnings, assertWarns |
environLocal.warn('...') | sys.stderr.write, every time | No (only by redirecting stderr) |
environLocal.printDebug('...') | stderr, only when debug is on | Toggle with music21/test/toggleDebug.py |
environLocal = environment.Environment('moduleName') at the top of the module.
Where things stand
Not unified. In 2026 the code has about 73 environLocal.warn, 41
warnings.warn (some with a module class, some bare), 800 printDebug, and no
logging. We are moving slowly toward Python's warnings and logging systems.
It is low priority: convert a call when you are already changing it, never as
a sweep.
For new code, prefer warnings.warn for anything a caller might reasonably want to catch,
silence, or test. By default Python shows each distinct message once per call
site, so a message that names the object (f'{p.nameWithOctave} is ...') shows
for each different object. Use environLocal.warn only when the user must hear
it every time.
Never print().
Warning classes
A module with its own warnings defines one class subclassing UserWarning
(MusicXMLWarning in musicxml/xmlObjects.py, TranslateWarning in
midi/translate.py). Warnings are not exceptions, so they do not subclass
Music21Exception.
Set stacklevel so the reported line is in the caller's code, not ours: 2 from
the method the user called, more if the warning comes from a helper.
Tests
In a unittest, catch it and check it:
with self.assertWarnsRegex(MusicXMLWarning, 'C-1'):
mxPitch = MEX.pitchToXml(pitch.Pitch('C', octave=-1))Doctests
doctest captures only stdout, so any warning goes straight to the console of whoever runs the tests. Every doctest that triggers a warning must catch it.
When the warning is the point of the example, record it and show it.
simplefilter('always') keeps Python from swallowing a repeat of a warning an
earlier test already raised:
>>> import warnings
>>> with warnings.catch_warnings(record=True) as w:
... warnings.simplefilter('always') #_DOCS_HIDE
... musicxml.m21ToXml.moveOctaveIntoMusicxmlRange(12, 'C12')
9
>>> w[0].message
MusicXMLWarning('C12 is out of MusicXML range; writing octave 9')When it is incidental, hide the silencing from the docs (see writing-docs for
#_DOCS_HIDE/#_DOCS_SHOW):
>>> import warnings #_DOCS_HIDE
>>> with warnings.catch_warnings(): #_DOCS_HIDE
... warnings.simplefilter('ignore') #_DOCS_HIDE
... out = midi.translate.timeSignatureToMidiEvents(ts) #_DOCS_HIDE
>>> #_DOCS_SHOW out = midi.translate.timeSignatureToMidiEvents(ts)catch_warnings cannot stop environLocal.warn. If a doctest has to trigger
one, wrap it in contextlib.redirect_stderr(io.StringIO()).
Trending
More talk lately.about the whole repository
Who's talking about cuthbertLab/music21
- Stack Overflow“Playing cross-platform, mobile, MIDI in Python for Kivy - is this possible?”Stack Overflow · Sep 17, 2014 · 4 votes
- Stack Overflow“Silence music21 warnings”Stack Overflow · Sep 29, 2021 · 3 votes
- Stack Overflow“UnicodeDecodeError: 'utf-8' codec can't decode byte 0xa9 in position 10: invalid start byte”Stack Overflow · Oct 28, 2020 · 3 votes
- cuthbertLab/music21j“Allow making beams according to meters from context”GitHub · Sep 4, 2022 · 2 reactions
- Stack Overflow“Why is music21 using pitch attributes in an unexpected way?”Stack Overflow · May 18, 2015 · 2 votes
The biggest 5 of 36 mentions linking to the repository that our crawl found. Each line is their own headline.
See all 36
Talked about on GitHub and Stack Overflow (36 times).
On GitHub · 29
- Sep 4, 2022Allow making beams according to meters from context — cuthbertLab/music21j2 reactions
- Sep 2, 2026Add support for implicit octaves — cuthbertLab/music21j1 reaction
- Jul 3, 2026Fix xmlForward offset calculation — cuthbertLab/music21j1 reaction · 1 comment
- Nov 20, 2022Inference result shows pollution across modules — pylint-dev/astroid1 reaction · 2 comments
- Oct 27, 2026Bump music21 from 9.3.0 to 10.5.1 in /apps-backend in the python group across 1 directory — fourscoreandmore/fourscoreandmore.org0 reactions
24 more on GitHub
- Oct 27, 2026build(deps): bump music21 from 10.5.0 to 10.5.1 in the version-updates group — oli-ver/midi-to-part-mp3s0 reactions
- Oct 25, 2026Bump the all-pip group with 21 updates — ollisulopuisto/transposer0 reactions
- Oct 25, 2026Write the music dictionary for notes — Akurganow/sound-to-patch0 reactions
- Oct 17, 2026Bump music21 from 9.9.2 to 10.5.0 — nschlaepfer/skitz0 reactions
- Oct 16, 2026chore(deps): update music21 requirement from >=9.1.0 to >=10.5.0 in /backend — Blevene/Explorator0 reactions
- Oct 9, 2026chore(deps-dev): Update music21 requirement from >=9 to >=9.9.2 — Julian-B-Smith/Tonality0 reactions
- Sep 8, 2026build(deps): bump music21 from 9.9.1 to 9.9.2 — xavierxav/cantateo0 reactions
- Aug 16, 2026build(deps): bump music21 from 9.9.1 to 10.5.0 — cheguevara-great-man/notefall88-px-s70000 reactions · 1 comment
- Jul 25, 2026Update music21 requirement from >=9.3 to >=10.5.0 in /backend — AndreaOsma/Riffbase0 reactions
- Jun 16, 2026TYPE_CHECKING block fooled by typing alias — astral-sh/ty0 reactions · 5 comments
- Sep 23, 2025Doesn't work in latest version of music21? — jisungk/deepjazz0 reactions · 1 comment
- Mar 23, 2025music21: figure out how the heck to use getContextByClass() — melodysium/harmonimation0 reactions
- Mar 12, 2025Develop an AI-based melody transcription app — ministryofjustice/modernisation-platform0 reactions · 1 comment
- Jun 19, 2023Bump music21 from 6.7.1 to 9.1.0 — darkpanther99/DeepLearningMusicGeneration0 reactions
- Dec 24, 2022`used-before-assignment` when import guarded by `TYPE_CHECKING` guarded again when used — pylint-dev/pylint0 reactions
- Apr 18, 2022[package request] - music21 — on-nix/python0 reactions · 3 comments
- Dec 15, 2021Inconsistent use of slow and fast 3/8 — MarkGotham/When-in-Rome0 reactions · 5 comments
- Nov 12, 2018Check that music21j.voiceLeading is in sync with music21.voiceLeading — cuthbertLab/music21j0 reactions
- Aug 28, 2017One-line parallel call... — joblib/joblib0 reactions · 4 comments
- Oct 27, 2016Symbolic link in new_http_archive causes error — bazelbuild/bazel0 reactions · 11 comments
- May 16, 2016Replace music21 dependency — DDMAL/cantus0 reactions
- Mar 23, 2016Add music21 — noteflakes/awesome-music0 reactions
- Nov 4, 2013Music21 on GitHub now. — bewest/music21-bewest.clone0 reactions
- Nov 4, 2013Vendor on GitHub now — jsundram/music210 reactions
On Stack Overflow · 7
- Sep 17, 2014Playing cross-platform, mobile, MIDI in Python for Kivy - is this possible?4 votes · 1 answer
- Sep 29, 2021Silence music21 warnings3 votes
- Oct 28, 2020UnicodeDecodeError: 'utf-8' codec can't decode byte 0xa9 in position 10: invalid start byte3 votes
- May 18, 2015Why is music21 using pitch attributes in an unexpected way?2 votes
- May 21, 2022Music21 merge midi/merge instruments1 vote
2 more on Stack Overflow
- May 16, 2021XDG_RUNTIME_DIR , propagateSizeHints() errors0 votes
- Jan 27, 2021Music21 AttributeError: module 'importlib' has no attribute 'util'0 votes
In this repository4 other files it gives its agents.
- AGENTS.mdAGENTS.md
- bump-versionSkill
- running-testsSkill
- writing-docsSkill
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

