Releases: Abjad/abjad
v3.19
Abjad 3.19 works with Python 3.10 (and 3.11) and LilyPond 2.23.6 (and later).
Abjad 3.19 is a maintenance release that makes only the following three changes.
#1554: FIXED: duplicated dynamics corner case.
#1556: CHANGED: lexical position of \tweaks
in LilyPond output.
#1559: CHANGED: names of abjad.StartTextSpan.style
strings.
v3.18
Abjad 3.18 works with Python 3.10 (and 3.11) and LilyPond 2.23.6 (and later).
Abjad 3.18 is a maintenance release that preserves the functionality of Abjad 3.17 without significant changes.
v3.17
Abjad 3.17 works with Python 3.10 (and 3.11) and LilyPond 2.23.6 (and later).
#1522. CHANGED. Cleaned up context initializers. This forces keyword parameters to be keyword-only:
OLD:
abjad.Score(
components=None,
lilypond_type: str = "Score",
simultaneous: bool = True,
name: str | None = None,
tag: _tag.Tag | None = None,
*,
language: str = "english",
)
abjad.Staff(
components=None,
lilypond_type: str = "Staff",
simultaneous: bool = False,
name: str | None = None,
tag: _tag.Tag | None = None,
*,
language: str = "english",
)
abjad.StaffGroup(
components=None,
lilypond_type: str = "StaffGroup",
simultaneous: bool = True,
name: str | None = None,
tag: _tag.Tag | None = None,
*,
language: str = "english",
)
abjad.Voice(
components=None,
lilypond_type: str = "Voice",
simultaneous: bool = False,
name: str | None = None,
tag: _tag.Tag | None = None,
*,
language: str = "english",
)
NEW:
abjad.Score(
components=None,
*,
language: str = "english",
lilypond_type: str = "Score",
name: str | None = None,
simultaneous: bool = True,
tag: _tag.Tag | None = None,
)
abjad.Staff(
components=None,
*,
language: str = "english",
lilypond_type: str = "Staff",
name: str | None = None,
simultaneous: bool = False,
tag: _tag.Tag | None = None,
)
abjad.StaffGroup(
components=None,
*,
language: str = "english",
lilypond_type: str = "StaffGroup",
name: str | None = None,
simultaneous: bool = True,
tag: _tag.Tag | None = None,
)
abjad.Voice(
components=None,
*,
language: str = "english",
lilypond_type: str = "Voice",
name: str | None = None,
simultaneous: bool = False,
tag: _tag.Tag | None = None,
)
#1523. CHANGED. Container input must now be flat:
OLD. Nested lists of components were allowed as container input through Abjad 3.16:
abjad.Staff(
[abjad.Note("c'4"), [abjad.Note("d'4")]]
)
NEW. Starting in Abjad 3.17, container input must be a flat list of components:
abjad.Staff(
[abjad.Note("c'4"), abjad.Note("d'4")]
)
#1525 CHANGED abjad.illustrators.selection()
to abjad.illustrators.components()
:
OLD: abjad.illustrators.selection()
NEW: abjad.illustrators.components()
OLD: abjad.illustrators.selection_to_score_markup_string()
NEW: abjad.illustrators.components_to_score_markup_string()
#1527. Cleaned up abjad.on_beat_grace_container()
:
CHANGED. Changed abjad.on_beat_grace_container()
parameter names:
OLD: abjad.on_beat_grace_container(..., anchor_voice_number=2)
NEW: abjad.on_beat_grace_container(..., nongrace_polyphony_command=r"\voiceTwo")
OLD: abjad.on_beat_grace_container(..., grace_voice_number=1)
NEW: abjad.on_beat_grace_container(..., grace_polyphony_command=r"\voiceOne")
OLD: abjad.on_beat_grace_container(..., font_size=-3)
NEW: abjad.on_beat_grace_container(..., grace_font_size=-3)
OLD: abjad.on_beat_grace_container(..., leaf_duration=None)
NEW: abjad.on_beat_grace_container(..., grace_leaf_duration=None)
CHANGED. Changed abjad.activate()
, abjad.deactivate()
return types:
OLD:
* both functions returned (text, count) pair when skipped=False
* both functions returned (text, count, skipped) triple when skipped=True
NEW:
* both functions return (text, count, skipped) triple
NEW. Added abjad.parse(..., tag=None)
keyword.
NEW. Added abjad.wf.check_overlapping_beams()
.
NEW. Added abjad.wf.check_beamed_lone_notes()
.
BUGFIX. Taught abjad.ForbidUpdate
to update indicators on entrance. Indicators need to be updated after swap; context manager updates indicators before forbidding further updates:
>>> staff = abjad.Staff(r"\times 1/1 { c'4 d' }")
>>> abjad.attach(abjad.Clef("alto"), staff[0][0])
>>> container = abjad.Container()
>>> abjad.mutate.swap(staff[0], container)
>>> with abjad.ForbidUpdate(staff):
... for note in staff[0]:
... print(note)
... print(abjad.get.effective(note, abjad.Clef))
...
Note("c'4")
Clef(name='alto', hide=False)
Note("d'4")
Clef(name='alto', hide=False)
Users encountered this bug (up to Abjad 3.16) only if using abjad.ForbidContext
immediately after some type of score mutatation, like in the example above.
#1528. NEW. Added abjad.VoiceNumber
indicator:
Set n to 1, 2, 3, 4 or none. Models LilyPond \voiceOne
, \voiceTwo
, \voiceThree
, \voiceFour
, \oneVoice
commands.
def make_staff():
staff = abjad.Staff()
voice_1 = abjad.Voice("g'8 a' b' c''")
command = abjad.VoiceNumber(n=1)
abjad.attach(command, voice_1[0])
voice_2 = abjad.Voice("e'8 f' g' a'")
command = abjad.VoiceNumber(n=2)
abjad.attach(command, voice_2[0])
container = abjad.Container([voice_1, voice_2], simultaneous=True)
staff.append(container)
voice = abjad.Voice("c''4 a'")
command = abjad.VoiceNumber()
abjad.attach(command, voice[0])
staff.append(voice)
>>> staff = make_staff()
>>> string = abjad.lilypond(staff)
>>> print(string)
\new Staff
{
<<
\new Voice
{
\voiceOne
g'8
a'8
b'8
c''8
}
\new Voice
{
\voiceTwo
e'8
f'8
g'8
a'8
}
>>
\new Voice
{
\oneVoice
c''4
a'4
}
}
The abjad.VoiceNumber indicator is contexted at the level of abjad.Voice. Use abjad.get.effective() to get the abjad.VoiceNumber indicator in effect for any leaf:
>>> for leaf in abjad.select.leaves(staff):
... command = abjad.get.effective(leaf, abjad.VoiceNumber)
... print(f"{leaf}, {command}")
Note("g'8"), VoiceNumber(n=1)
Note("a'8"), VoiceNumber(n=1)
Note("b'8"), VoiceNumber(n=1)
Note("c''8"), VoiceNumber(n=1)
Note("e'8"), VoiceNumber(n=2)
Note("f'8"), VoiceNumber(n=2)
Note("g'8"), VoiceNumber(n=2)
Note("a'8"), VoiceNumber(n=2)
Note("c''4"), VoiceNumber(n=None)
Note("a'4"), VoiceNumber(n=None)
#1529. CHANGED abjad.LilyPondLiteral
format site from "opening"
to "before"
:
Abjad leaves should only format "before" and "after" sites. (Though Abjad containers can format "before", "after", "opening" and "closing" sites.) Because abjad.LilyPondLiteral
objects almost always get attached to leaves (instead of containers), it makes sense to change the default format site of LilyPond literals from (container-like) "opening" to (leaf-like) "before".
#1534. CHANGED abjad.TimeSignature
context from "Staff"
to "Score"
:
Through Abjad 3.16, time signature application was most commonly abjad.attach(time_signature, note, context="Score")
.
Beginning in Abjad 3.17, abjad.attach(time_signature, note)
binds to the score context automatically.
#1537. Made abjad.TimeSignature
, abjad.MetronomeMark
initializers strict. That is, these initializers no longer coerce input:
Intialize metronome marks like this:
OLD:
* abjad.MetronomeMark(abjad.Duration(1, 4), 72)
* abjad.MetronomeMark((1, 4), 72)
NEW:
* abjad.MetronomeMark(abjad.Duration(1, 4), 72)
Initialize time signatures like this:
OLD:
* abjad.TimeSignature(pair)
* abjad.TimeSignature(duration)
* abjad.TimeSignature(time_signature)
NEW:
* abjad.TimeSignature(pair)
CHANGED. Moved LilyPond stop-hairpin \!
from articulations site to spanner-stops site in LilyPond output.
#1540. Cleaned up indicators:
CHANGED. The "site" argument to abjad.LilyPondLiteral
is now keyword-only:
OLD: abjad.LilyPondLiteral(..., site)
NEW: abjad.LilyPondLiteral(..., *, site="before")
CHANGED. Made abjad.MetricModulation
into frozen dataclass.
CHANGED. Renamed abjad.StaffChange
parameter:
OLD: abjad.StaffChange.staff
NEW: abjad.StaffChange.staff_name
REMOVED remove_ly keyword
from these:
* abjad.persist.as_midi()
* abjad.persist.as_pdf()
* abjad.persist.as_png()
#1542. Fixed abjad.beam(..., stemlet_length=None)
formatting:
EXAMPLE.
>>> voice = abjad.Voice("c'8 d' e' f'")
>>> abjad.beam(voice[:], stemlet_length=0.75)
>>> string = abjad.lilypond(voice)
OLD:
>>> print(string)
\new Voice
{
\override Staff.Stem.stemlet-length = 0.75
c'8
[
d'8
e'8
\revert Staff.Stem.stemlet-length
f'8
]
}
NEW:
>>> print(string)
\new Voice
{
\override Staff.Stem.stemlet-length = 0.75
c'8
[
d'8
e'8
f'8
]
\revert Staff.Stem.stemlet-length
}
CHANGED. abjad.illustrators.make_piano_score()
now includes explicit voices:
OLD:
>>> score = abjad.illustrators.make_piano_score()
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
<<
...
v3.16
Abjad 3.16 works with Python 3.10 (and 3.11) and LilyPond 2.23.6 (and later).
BREAKING CHANGES. Abjad 3.16 will break existing code. But the changes should be easy to follow. Removed abjad.Multiplier
, abjad.Ratio
, abjad.NonreducedFraction
, abjad.NonreducedRatio
in favor of built-in fractions.Fraction
and (int, int)
pairs. Also the types of abjad.Tuplet.multiplier
, abjad.Leaf.multiplier
and preprolated durations in the rhtyhmtrees
module are all now more tightly constrained.
This release contains primarily #1515
OLD: abjad.Multiplier
NEW: use built-in fractions.Fraction instead
OLD: abjad.NonreducedFraction
NEW: use (int, int) pair instead
OLD: abjad.NonreducedRatio
NEW: use (int, ...) tuple instead
OLD: abjad.Ratio
NEW: use (int, ...) tuple instead
BREAKING CHANGE. Leaf multiplier now returns a nonreduced fraction.
OLD: Leaf.multiplier could be either multiplier or nonreduced multiplier.
NEW: Leaf.multiplier is always an (int, int) pair.
BREAKING CHANGE. abjad.Tuplet.multiplier has changed:
OLD: abjad.Tuplet.multiplier accepted the following:
string, pair, duration, fraction, multiplier, nonreduced fraction
NEW: abjad.Tuplet.multiplier accepts only string and pair
OLD: abjad.Tuplet.multiplier returned nonreduced fraction (or none)
NEW: abjad.Tuplet.multiplier returns pair (or none)
OLD:
>>> abjad.Tuplet("3:2", "c'4 d' e'")
>>> abjad.Tuplet((2, 3), "c'4 d' e'")
>>> abjad.Tuplet(abjad.Multiplier(2, 3), "c'4 d' e'")
>>> abjad.Tuplet(abjad.Fraction(2, 3), "c'4 d' e'")
>>> abjad.Tuplet(abjad.NonreducedFraction(2, 3), "c'4 d' e'")
NEW:
>>> abjad.Tuplet("3:2", "c'4 d' e'")
>>> abjad.Tuplet((2, 3), "c'4 d' e'")
OLD: tuplet.multplier == 1
NEW: tuplet.multplier == (1, 1)
NEW: abjad.Fraction(*tuplet.multplier) == 1
CHANGED. Replaced abjad.Duration.with_denominator().
OLD:
>>> abjad.Duration(1, 4).with_denominator(16)
NonreducedFraction(4, 16)
NEW:
>>> duration = abjad.Duration(1, 4)
>>> pair = abjad.duration.with_denominator(duration, 16)
>>> pair
(4, 16)
>>> abjad.NonreducedFraction(pair)
NonreducedFraction(4, 16)
CHANGED. Constrained rhythmtree preprolated duration.
OLD: int, pair, duration, nonreduced fraction
NEW: pair, duration, nonreduced fraction
CHANGED. Set several sequence.py parameters keyword-only.
NEW. Added abjad.duration.pair():
>>> abjad.duration.pair((3, 6))
(3, 6)
>>> abjad.duration.pair(abjad.Fraction(3, 6))
(1, 2)
>>> abjad.duration.pair(abjad.Duration(3, 6))
(1, 2)
>>> abjad.duration.pair(abjad.Offset((3, 6)))
(1, 2)
>>> abjad.duration.pair(abjad.TimeSignature((3, 6)))
(3, 6)
NEW. Added abjad.duration.add_pairs().
v3.15
Abjad 3.15 works with Python 3.10 (and 3.11) and LilyPond 2.23.6 (and later).
Abjad 3.15 is a maintenance release that preserves the functionality of Abjad 3.14 without significant changes.
v3.14
Abjad 3.14 works with Python 3.10 (and 3.11) and LilyPond 2.23.6 (and later).
NEW: use python -m pip install abjad[dev]
to install Abjad's development dependencies. See #1483.
REMOVED: natural-language inequalities have been removed from abjad.Timespan
. See #1491.
REMOVED: replaced third-party quicktions
with built-in fractions
. See #1489.
REMOVED: abjad.NoteMaker
, abjad.LeafMaker
; use abjad.makers.make_notes()
, abjad.makers.make_leaves()
instead. See #1478.
FIXED: abjad.MetronomeMark.textual_indication
is now formatted exactly as entered by the user. See #1498.
v3.13
Abjad 3.13 works with Python 3.10 and LilyPond 2.23.6 (and later).
Abjad 3.13 completes the migration of Abjad rhythm-makers that began in Abjad 3.12. Users of Abjad's rhythm-makers should migrate to Abjad 3.12 first, and then migrate to Abjad 3.13. No other changes are included in this release.
REMOVED:
rmakers.accelerando()
rmakers.after_grace_container()
rmakers.beam()
rmakers.beam_groups()
rmakers.before_grace_container()
rmakers.denominator()
rmakers.duration_bracket()
rmakers.even_division()
rmakers.example()
rmakers.extract_trivial()
rmakers.feather_beam()
rmakers.force_augmentation()
rmakers.force_diminution()
rmakers.force_fraction()
rmakers.force_note()
rmakers.force_repeat_tie()
rmakers.force_rest()
rmakers.incised()
rmakers.interpolate()
rmakers.invisible_music()
rmakers.multiplied_duration()
rmakers.nongrace_leaves_in_each_tuplet()
rmakers.note()
rmakers.on_beat_grace_container()
rmakers.reduce_multiplier()
rmakers.repeat_tie()
rmakers.rewrite_dots()
rmakers.rewrite_meter()
rmakers.rewrite_rest_filled()
rmakers.rewrite_sustained()
rmakers.split_measures()
rmakers.talea()
rmakers.tie()
rmakers.tremolo_container()
rmakers.trivialize()
rmakers.tuplet()
rmakers.unbeam()
rmakers.untie()
rmakers.wrap_in_time_signature_staff()
rmakers.written_duration()
rmakers.AccelerandoRhythmMaker
rmakers.EvenDivisionRhythmMaker
rmakers.MultipliedDurationRhythmMaker
rmakers.NoteRhythmMaker
rmakers.TaleaRhythmMaker
rmakers.TupletRhythmMaker
rmakers.assign()
rmakers.bind()
rmakers.stack()
rmakers.Assign
rmakers.Bind
rmakers.Stack
RENAMED:
OLD:
rmakers.accelerando_function()
rmakers.after_grace_container_function()
rmakers.beam_function()
rmakers.beam_groups_function()
rmakers.before_grace_container_function()
rmakers.denominator_function()
rmakers.duration_bracket_function()
rmakers.even_division_function()
rmakers.example_function()
rmakers.extract_trivial_function()
rmakers.feather_beam_function()
rmakers.force_augmentation_function()
rmakers.force_diminution_function()
rmakers.force_fraction_function()
rmakers.force_note_function()
rmakers.force_repeat_tie_function()
rmakers.force_rest_function()
rmakers.incised_function()
rmakers.interpolate_function()
rmakers.invisible_music_function()
rmakers.multiplied_duration_function()
rmakers.nongrace_leaves_in_each_tuplet_function()
rmakers.note_function()
rmakers.on_beat_grace_container_function()
rmakers.reduce_multiplier_function()
rmakers.repeat_tie_function()
rmakers.rewrite_dots_function()
rmakers.rewrite_meter_function()
rmakers.rewrite_rest_filled_function()
rmakers.rewrite_sustained_function()
rmakers.split_measures_function()
rmakers.talea_function()
rmakers.tie_function()
rmakers.tremolo_container_function()
rmakers.trivialize_function()
rmakers.tuplet_function()
rmakers.unbeam_function()
rmakers.untie_function()
rmakers.wrap_in_time_signature_staff_function()
rmakers.written_duration_function()
NEW:
rmakers.accelerando()
rmakers.after_grace_container()
rmakers.beam()
rmakers.beam_groups()
rmakers.before_grace_container()
rmakers.denominator()
rmakers.duration_bracket()
rmakers.even_division()
rmakers.example()
rmakers.extract_trivial()
rmakers.feather_beam()
rmakers.force_augmentation()
rmakers.force_diminution()
rmakers.force_fraction()
rmakers.force_note()
rmakers.force_repeat_tie()
rmakers.force_rest()
rmakers.incised()
rmakers.interpolate()
rmakers.invisible_music()
rmakers.multiplied_duration()
rmakers.nongrace_leaves_in_each_tuplet()
rmakers.note()
rmakers.on_beat_grace_container()
rmakers.reduce_multiplier()
rmakers.repeat_tie()
rmakers.rewrite_dots()
rmakers.rewrite_meter()
rmakers.rewrite_rest_filled()
rmakers.rewrite_sustained()
rmakers.split_measures()
rmakers.talea()
rmakers.tie()
rmakers.tremolo_container()
rmakers.trivialize()
rmakers.tuplet()
rmakers.unbeam()
rmakers.untie()
rmakers.wrap_in_time_signature_staff()
rmakers.written_duration()
Abjad 3.12
Abjad 3.12 works with Python 3.10 and LilyPond 2.23.6 (and later).
Abjad 3.12 is a bridge release that helps users of Abjad's rhythm-makers migrate from Abjad 3.11 to Abjad 3.13. No other changes are included in the release.
In Abjad 3.11, the usual way of working with Abjad's rhythm-makers is through defining an (object-oriented and persistent) stack of (object-oriented and persistent) command objects. This is done with a collection of factory functions, and the resulting stack is then called (like a function) on a list of divisions to make notes, rests and tuplets:
stack = rmakers.stack(
rmakers.even_division([8], extra_counts=[1]),
rmakers.force_fraction(),
rmakers.beam(),
)
divisions = [(2, 8), (2, 8), (2, 8)]
stack(divisions)
[Tuplet('3:2', "c'8 c'8 c'8"), Tuplet('3:2', "c'8 c'8 c'8"), Tuplet('3:2', "c'8 c'8 c'8")]
In Abjad 3.12, this is no longer necessary. The package's command objects can be avoided in favor of pure functions. No object-oriented framework is required, and the output of each line of code can be examined after it runs. This makes rhythms easier to design and debug; it also makes it much easier to mix the functionality of Abjad's rhythm-makers with user-defined custom functions:
>>> divisions = [(2, 8), (2, 8), (2, 8)]
>>> music = rmakers.even_division_function(divisions, [8], extra_counts=[1])
>>> rmakers.force_fraction_function(music)
>>> rmakers.beam_function(music)
Rhythms designed to be used throughout a score can be encapsulated in function. And it makes sense to use a temporary Abjad container when building rhythms because Abjad recognizes tied notes only when they are housed in an Abjad container. The 200+ examples in the abjad-ext-rmakers
package have been rewritten according to a basic pattern that looks like this:
def make_rhythm(divisions):
music = rmakers.even_division_function(divisions, [8], extra_counts=[1])
container = abjad.Container(music)
rmakers.force_fraction_function(container)
rmakers.beam_function(container)
music = abjad.mutate.eject_contents(container)
return music
divisions = [(2, 8), (2, 8), (2, 8)]
make_rhythm(divisions)
[Tuplet('3:2', "c'8 c'8 c'8"), Tuplet('3:2', "c'8 c'8 c'8"), Tuplet('3:2', "c'8 c'8 c'8")]
How to migrate existing rhythm-maker code? Abjad 3.12 provides a shadow interface to facilitate migration. The old factory functions remain in the package but are deprecated in favor of a new set of pure functions, named in parallel:
DEPRECATED IN ABJAD 3.12:
rmakers.accelerando()
rmakers.after_grace_container()
rmakers.assign()
rmakers.beam()
rmakers.beam_groups()
rmakers.before_grace_container()
rmakers.bind()
rmakers.cache_state()
rmakers.denominator()
rmakers.duration_bracket()
rmakers.even_division()
rmakers.example()
rmakers.extract_trivial()
rmakers.feather_beam()
rmakers.force_augmentation()
rmakers.force_diminution()
rmakers.force_fraction()
rmakers.force_note()
rmakers.force_repeat_tie()
rmakers.force_rest()
rmakers.incised()
rmakers.invisible_music()
rmakers.multiplied_duration()
rmakers.note()
rmakers.on_beat_grace_container()
rmakers.reduce_multiplier()
rmakers.repeat_tie()
rmakers.rewrite_dots()
rmakers.rewrite_meter()
rmakers.rewrite_rest_filled()
rmakers.rewrite_sustained()
rmakers.split_measures()
rmakers.stack()
rmakers.talea()
rmakers.tie()
rmakers.tremolo_container()
rmakers.trivialize()
rmakers.tuplet()
rmakers.unbeam()
rmakers.untie()
rmakers.written_duration()
NEW IN ABJAD 3.12:
rmakers.accelerando_function()
rmakers.after_grace_container_function()
rmakers.beam_function()
rmakers.beam_groups_function()
rmakers.before_grace_container_function()
rmakers.denominator_function()
rmakers.duration_bracket_function()
rmakers.even_division_function()
rmakers.extract_trivial_function()
rmakers.feather_beam_function()
rmakers.force_augmentation_function()
rmakers.force_diminution_function()
rmakers.force_fraction_function()
rmakers.force_note_function()
rmakers.force_repeat_tie_function()
rmakers.force_rest_function()
rmakers.incised_function()
rmakers.invisible_music_function()
rmakers.multiplied_duration_function()
rmakers.note_function()
rmakers.on_beat_grace_container_function()
rmakers.reduce_multiplier_function()
rmakers.repeat_tie_function()
rmakers.rewrite_dots_function()
rmakers.rewrite_meter_function()
rmakers.rewrite_rest_filled_function()
rmakers.rewrite_sustained_function()
rmakers.split_measures_function()
rmakers.talea_function()
rmakers.tie_function()
rmakers.tremolo_container_function()
rmakers.trivialize_function()
rmakers.tuplet_function()
rmakers.unbeam_function()
rmakers.untie_function()
rmakers.written_duration_function()
Note that the pure functions introduced in Abjad 3.12 are suffixed in _function()
for only one release. In Abjad 3.13, the old factory functions will be removed, and the pure functions will lose their suffix. The Abjad 3.13 version of the pattern shown above will look like this:
def make_rhythm(divisions):
music = rmakers.even_division(divisions, [8], extra_counts=[1])
container = abjad.Container(music)
rmakers.force_fraction(container)
rmakers.beam(container)
music = abjad.mutate.eject_contents(container)
return music
TL;DR Abjad 3.12 implements two different interfaces to the functionality of Abjad's rhythm-makers. Use Abjad 3.12 to port existing rhythm-maker code from Abjad 3.11 to Abjad 3.13.
Abjad 3.11
Abjad 3.11 works with Python 3.10 and LilyPond 2.23.6 (and later).
Abjad 3.11 is a maintenance release that preserves the functionality of Abjad 3.10 without significant changes.
3.10
Abjad 3.10 works with Python 3.10 and LilyPond 2.23.6 (and later).
#1460: Cleaned up instrument classes
Abjad 3.10 reimplements Abjad's instrument classes as frozen data classes, removes four properties from all instrument classes, and changes the name of one property.
REMOVED:
* abjad.Instrument.markup
* abjad.Instrument.name
* abjad.Instrument.short_markup
* abjad.Instrument.short_name
CHANGED:
OLD: abjad.Instrument.allowable_clefs=("treble", "bass")
NEW: abjad.Instrument.clefs==("treble", "bass")
This means that instrument classes are left with four basic properties:
>>> abjad.Flute()
Flute(clefs=('treble',), context='Staff', middle_c_sounding_pitch=NamedPitch("c'"), pitch_range=PitchRange(range_string='[C4, D7]'))
Use abjad.InstrumentName
and abjad.ShortInstrumentName
to handle those properties independently.
#1459 : Cleaned up instrument name, short instrument name
LilyPond uses \instrumentName
to print markup to the left of the first system of a score. It makes no sense to change \instrumentName
after it is first set because the value of \instrumentName
is printed only once.
LilyPond uses \shortInstrumentName
to print markup to left the of nonfirst systems of a score. Changing \shortInstrumentName
is necessary whenever instrument changes (for example, from flute to piccolo) should be reflected to the left of each system. (Whether, and how, scores use left-positioned directives to reflective instrument changes seems to vary over time, and by publisher.)
Abjad 3.9 (and earlier) implemented abjad.StartMarkup
and abjad.MarginMarkup
classes to handle these two types of markup. Abjad 3.10 replaces these with abjad.InstrumentName
and abjad.ShortInstrumentName
classes that match LilyPond's \instrumentName
and \shortInstrumentName
commands.
OLD: abjad.StartMarkup(markup=abjad.Markup(r"\markup Cello"))
NEW: abjad.InstrumentName(r"\markup Cello")
OLD: abjad.MarginMarkup(markup=abjad.Markup(r"\markup Vc."))
NEW: abjad.ShortInstrumentName(r"\markup Vc.")
#1457 Cleaned up abjad.Octave initializer
OLD. Octave objects are usually initialized by octave number. But the abjad.Octave
initialzer allowed for undocumented initialization by tick string:
>>> abjad.Octave("'")
Octave(number=4)
NEW. Use the new abjad.Octave.from_ticks()
constructor instead:
abjad.Octave.from_ticks("'")
Octave(number=4)