Migrating to music21 v11¶
(This is an in-progress guide that was automatically generated by Myke’s AI Agent.)
What changed between the v10 line and v11, and what to use instead. The big, code-breaking items come first, then smaller improvements by area, then one table of everything removed or deprecated.
Python 3.12 or newer¶
Python 3.11 support is gone; 3.12, 3.13, and 3.14 are tested. The payoff is
real generics: Stream and its iterators use the PEP 695 bracket form, so a
type checker can follow stream.Stream[note.Note]() all the way to
for n in s: n.pitch.
Octaves are always integers¶
In one line: octave is always an int, and octaveIsImplicit says whether you gave one.
Before v11, pitch.Pitch('F#').octave was None: a lovely idea (an
F-sharp in any octave) that crashed the moment someone wrote
p.octave + 1. The pitch knew all along which octave it would use for
MIDI or a staff. It kept that in implicitOctave, a property that nobody
remembered. Now octave does that job itself:
>>> from music21 import *
>>> anyFSharp = pitch.Pitch('F#')
>>> anyFSharp.octave
4
>>> anyFSharp.octaveIsImplicit
True
Nothing else about an octave-less pitch changes. It still prints without a number, transposes without one, and is not equal to an explicit F#4:
>>> anyFSharp
<music21.pitch.Pitch F#>
>>> anyFSharp.transpose('P8')
<music21.pitch.Pitch F#>
>>> anyFSharp == pitch.Pitch('F#4')
False
Give it an octave and the flag flips:
>>> anyFSharp.octave = 5
>>> anyFSharp.octaveIsImplicit
False
>>> anyFSharp
<music21.pitch.Pitch F#5>
Notes follow along: note.Note('B-').octave is 4, and the flag lives
on the note’s pitch, n.pitch.octaveIsImplicit.
Before v11 |
v11 |
|---|---|
|
|
|
|
|
|
|
|
|
|
p.octave + 1 and f'{p.name}{p.octave}' no longer crash. The few
methods that need a pitch’s own octave, such as
transposeAboveTarget(), still raise for an
implicit one; set .octave first. implicitOctave stays as a synonym
so nothing breaks today, but it is deprecated and starts warning in v12.
KeySignature.sharps is always an int¶
Similar idea to Octave. KeySignature.sharps (and Key.sharps) is an
int you can add to and subtract from. A non-traditional signature is a
flag plus a list of pitches. sharps=None still works but warns:
>>> unusual = key.KeySignature()
>>> unusual.isNonTraditional = True
>>> unusual.alteredPitches = ['E-', 'G#4']
>>> unusual
<music21.key.KeySignature of pitches: [E-, G#4]>
Chord indexing gets simpler¶
c[1], c['G4'] and c[somePitch] still return the chord’s
Note; everything fancier is gone. Attribute paths
such as c['2.tie'] and c['D-4.style.color'] no longer work, a Note is
no longer accepted as a key (use its pitch), and the per-note getters and
setters (getTie, setColor, getNotehead, and their siblings) are
deprecated. Index, then use the Note:
>>> c = chord.Chord('C4 E4 G4')
>>> c['E4'].tie = tie.Tie('start')
>>> c[1].tie
<music21.tie.Tie start>
VoiceLeadingQuartet needs its four notes¶
voiceLeading.VoiceLeadingQuartet(v1n1, v1n2, v2n1, v2n2) requires all
four notes up front, the first Music21Object ever to insist on arguments. In
return they are always Notes, never None. analyticKey is now
key, vIntervals and hIntervals are tuples, and two dogmatic names
got truer ones: opensIncorrectly() is not modalOpening() and
closesIncorrectly() is not clausulaVera().
Roman numerals¶
romanNumeralFromChordkeeps the sharp on major-quality chords built on the raised sixth and seventh degrees in minor:#VI, notVI#63.correctRNAlterationForMinorgained achordHasMajorThirdkeyword for the same reason.Figures containing
x,yorzraise.RomanNumeral('IIIx')used to be a III13 chord by accident.FigureTupleandPitchFigureTupleare typed NamedTuples, andFigureTuple.fromPitchAndReference()replacesfigureTupleSolo.
Durations and sorting¶
Two Durations with
expressionIsInferredTrue are equal when their quarterLengths match; type, dots and tuplets are free to be re-expressed.sorting.SortTupleis a modern NamedTuple.priorityandclassSortOrdermay be floats, andmodify()with a bad field name raisesValueError.tinyNotation’s undocumented
0duration (a whole bar plus a fermata) is deprecated.
Streams¶
New
Stream.isAtEnd(el)says whetherstoreAtEndputelthere.Stream.hasElement(el)is removed: writeel in s.hasElementOfClassis deprecated: writeif s.getElementsByClass(X):.
Pitches¶
pitch.simplifyMultipleEnharmonics takes criterion and keyContext
as keyword-only arguments.
File formats¶
ABC:
w:lyric lines are imported, with hyphenation and*skips.abcToStreamOpusalways returns an Opus.Humdrum: grace notes keep their written duration instead of becoming eighths; duration parsing lives in a new
hdStringToDuration; a token with no duration warns when a quarter is assumed;GlobalReferenceis no longer a Music21Object.LilyPond: output targets current LilyPond (
\tuplet, modern barline names,\markuplist), and everystringOutput()returns astr.MIDI:
midiEventsToInstrumentis removed; usemidiEventToInstrument.Vexflow: the
music21.vexflowmodule is gone. It had not worked in a decade; music21j is the way to draw in a browser.configure: choosing MuseScore as the MusicXML reader also sets
musescoreDirectPNGPath.
figuredBass, features, tree¶
figuredBass:
hiddenFifthandhiddenOctaveare nowhiddenFifthsandhiddenOctaves, matchingparallelFifths.FiguredBassScale’s first argument isscaleTonic, notscaleValue. Rests inside a possibility are typed sentinels rather than the string'RT'.features:
Feature.vectorstarts as[]rather thanNone, andFeatureExtractor.dimensionsdefaults to 1.tree:
ElementTimespanandPitchedTimespantake their arguments in the same order asTimespan;offset,endTimeandelementare required.
For developers¶
Type annotations across nearly the whole library, with
t.cast()for narrowing and@propertydecorators throughout.common.enums.ContainsEnumis not needed: Python 3.12’sStrEnumsuffices, orHexEnumfor hex values such as MIDI. The alias leaves in v12.common.defaultlistis deprecated.The test runners import modules the normal way, so a module’s tests no longer need
from music21.key import KeySignatureto compare types.AI agents get their own instructions, skills and shared memory in
AGENTS.mdand.agents/.
Removed and deprecated¶
Gone |
Use instead |
|---|---|
Python 3.11 |
Python 3.12 or newer |
|
music21j |
|
|
|
|
|
|
a string for |
an |
|
|
|
|
a Note as a Chord index, |
|
Deprecated |
Use instead |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
a |
|
not needed: |
tinyNotation |
the duration plus an |
|
|