Skip to content

Pitch.octave is always an int - #2023

Merged
mscuthbert merged 26 commits into
masterfrom
octave-int
Sep 1, 2026
Merged

Pitch.octave is always an int#2023
mscuthbert merged 26 commits into
masterfrom
octave-int

Conversation

@mscuthbert

Copy link
Copy Markdown
Member

Fixes #2009 and implements the old "octave is None" implicit octave check via "Pitch.octaveIsImplicit" bool.

Adds a changelist for migrating from v10 to v11.

Adds rules for how Agents should use @deprecated and how to avoid (in the future) the huge list of commits here.

AI-Assisted (Claude) -- myke reviewed.

First step toward issue #2009 (octave becomes an int). `octaveIsImplicit`
is True when a Pitch was never given an octave; setting it False gives
the default octave explicitly, setting it True forgets the octave. Every
internal check of `octave is None` / `octave = None` now goes through it,
so the switch to an int-valued `octave` in the next commit changes no
behavior in scales, intervals, keys, chords, serial rows or MusicXML
key-octave output.

The old `if p.octave is None: p.octave = p.implicitOctave` narrowing is
gone, so mypy reports eight `int | None` operand errors until the next
commit makes `octave` an int.

AI-assisted (Claude)
Closes #2009. A Pitch created without an octave now reports the default
octave (defaults.pitchOctave, 4) from `.octave` instead of None, so
notation and layout code can do arithmetic on it directly. Nothing else
changes: such a Pitch still prints without an octave number, still
transposes without an octave, still differs from an explicit C4 under
`==` and `hash`, and `.octaveIsImplicit` reports which case it is.
Setting `.octave = None` keeps working and is the same as setting
`.octaveIsImplicit = True`.

`.implicitOctave` is now a plain synonym for `.octave`, to be deprecated
no earlier than v12; all internal uses switch to `.octave`. Note.octave
follows Pitch.octave. The `if p.octave is None: p.octave = p.implicitOctave`
idiom in chord, roman, scale, lily, capella, musedata and musicxml
collapses to plain arithmetic.

AI-assisted (Claude)
Adds "Migrating to music21 v11" under About, with the octave change as its
first section: what changed, a before/after table, and what stops crashing.
User's Guide chapter 3 gains a short passage introducing octaveIsImplicit
where it first shows .octave.

AI-assisted (Claude)
Adding to p.octave already stores an explicit octave.

AI-assisted (Claude)
Adds the "in-progress guide" note requested at the top, then walks through
the v11 changes relative to the m21_10 branch: Python 3.12 minimum and PEP
695 generics, integer octaves, integer KeySignature.sharps, Chord indexing
to Notes, VoiceLeadingQuartet's required notes, roman-numeral fixes,
duration/sorting changes, Stream additions and removals, accidental and
microtone fixes, per-format improvements (ABC lyrics, Humdrum durations,
LilyPond modernization, MEI bTrem, MusicXML, MIDI, Vexflow removal),
figuredBass/features/tree API changes, developer-facing changes, and two
tables of everything removed or deprecated. Sources: the merged PRs since
June 2026 and every `New in v11` / `Changed in v11` marker in the code.

AI-assisted (Claude)
…ToXml

_setTagTextFromAttribute already derives the attribute name from the tag.

AI-assisted (Claude)
c[i] and c['G4'] returned Notes before v11 too; the change is the removal
of attribute paths and Note keys.

AI-assisted (Claude)
Drop the bug fixes (infinite durations, microtone transposition, accidental
display, Humdrum chord durations and global comments, LilyPond
MetronomeMarks, MEI bTrem, MusicXML grace notes), the speed notes, and the
mypy line, which was true before v11 too.

AI-assisted (Claude)
… loops

The first shift makes the octave explicit, so the loop conditions never
needed the check.

AI-assisted (Claude)
…rule

`@common.deprecated` never goes on a property, since IDEs read every property
while inspecting an object and the warning would fire on people who never
used it. `implicitOctave` therefore gets a `* Deprecated in v11` marker and
a `# Add real deprecation message here in v12` comment in the body. The rule
is now in AGENTS.md (Code style) and the writing-docs skill (Version
markers); the migration page says the warning arrives in v12.

AI-assisted (Claude)
"Octaveless" replaces "forget the octave" in the Pitch docstrings,
diatonicNoteNum says the default octave is a basis for a pitch with no
octave, and fixDefaultOctaveForPitchList's docstring names
octaveIsImplicit as the reason the octave stays put. AGENTS.md now says
how to commit during a review: leave changes unstaged until the round is
done, then one commit; prefer new commits to amend and force-push.

AI-assisted (Claude)
@coveralls

Copy link
Copy Markdown

Coverage Status

coverage: 93.343% (+0.007%) from 93.336% — octave-int into master

@mscuthbert
mscuthbert merged commit e9c3c2b into master Sep 1, 2026
7 checks passed
@mscuthbert
mscuthbert deleted the octave-int branch September 1, 2026 22:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Discussion/Proposal: octave as int

2 participants