Changelogs » Abjad

PyUp Safety actively tracks 232,000 Python packages for vulnerabilities and notifies you when to upgrade.

Abjad

3.0.0

NEW CONFIGURATION FUNCTIONALITY:
  
  * Added AbjadConfiguration.composer_scores_directory
  
  * Added composer template data to AbjadConfiguration
  
  * Integrated pathlib into abjad.Configuration
  
  The four main abjad.Configuration properties now return path objects
  instead of strings:
  
  * abjad.Configuration.configuration_directory
  * abjad.Configuration.configuration_file_path
  * abjad.Configuration.home_directory
  * abjad.Configuration.temp_directory
  
  * Changed 'directory_path' to just 'directory' in abjad.Configuration
  
  OLD: Configuration.configuration_file_name
  NEW: Configuration.file_path
  
  OLD: Configuration.configuration_directory_name
  NEW: Configuration.configuration_directory
  
  NEW CONTAINER FUNCTIONALITY:
  
  * Added bracket comments to measure-open, measure-close.
  
  OLD:
  
  >>> measure = abjad.Measure((3, 4), "c'4 d' e'")
  >>> abjad.f(measure)
  {
  \time 3/4
  c'4
  d'4
  e'4
  }
  
  NEW:
  
  >>> measure = abjad.Measure((3, 4), "c'4 d' e'")
  >>> abjad.f(measure)
  { % measure
  \time 3/4
  c'4
  d'4
  e'4
  } % measure
  
  * Removed Container.reverse(); no longer supported
  
  * Removed Component.name; preserved Container.name
  
  * Taught containers to initialize from collections of strings:
  
  staff = abjad.Staff([
  r"\times 9/10 { r8 c'16 c'16 bf'4 ~ bf'16 r16 }",
  r"\times 9/10 { bf'16 e''16 e''4 ~ e''16 r16 fs''16 af''16 }",
  r"\times 4/5 { a'16 r4 }",
  ])
  
  abjad.f(staff)
  \new Staff {
  {
  \tweak text tuplet-number::calc-fraction-text
  \times 9/10 {
  r8
  c'16
  c'16
  bf'4 ~
  bf'16
  r16
  }
  }
  {
  \tweak text tuplet-number::calc-fraction-text
  \times 9/10 {
  bf'16
  e''16
  e''4 ~
  e''16
  r16
  fs''16
  af''16
  }
  }
  {
  \times 4/5 {
  a'16
  r4
  }
  }
  }
  
  * Taught simultaneous containers to accept vanilla containers
  (in addition to contexts)
  
  OLD: abjad.Container.music
  NEW: abjad.Container.components
  
  NEW CONTEXT FUNCTIONALITY:
  
  OLD: abjad.Context.context_name
  NEW: abjad.Context.lilypond_type
  
  * Closes 895
  
  NEW DATA STRUCTURE FUNCTIONALITY:
  
  * Removed abjad.ClefList; use list instead
  * Removed abjad.PerformerList; use list instead
  * Removed abjad.PitchRangeList; use list instead
  
  * Removed abjad.InstrumentDictionary; use abjad.OrderedDict instead
  * Removed abjad.MetronomeMarkDictionary; use abjad.OrderedDict instead
  
  OLD: abjad.TypedOrderedDict
  NEW: abjad.OrderedDict
  
  * Closes 909
  
  NEW FORMAT FUNCTIONALITY:
  
  * Added abjad.Container.identifier property. Use to set parse handles on any
  Abjad container:
  
  >>> container = abjad.Container("c'4 d' e' f'")
  >>> container.identifier = '%*% AB'
  
  >>> abjad.f(container)
  {   %*% AB
  c'4
  d'4
  e'4
  f'4
  }   %*% AB
  
  * Changed context open-statement formatting to strictly one-per-line:
  
  OLD:
  
  \new Score \with {
  \override BarLine.stencil = f
  \override BarNumber.transparent = t
  \override SpanBar.stencil = f
  \override TimeSignature.stencil = f
  } <<
  \new PianoStaff <<
  \context Staff = "Treble Staff" {
  \clef "treble"
  r16
  r16
  r16
  r16
  r16
  c'16
  d'16
  e'16
  f'16
  g'16
  }
  \context Staff = "Bass Staff" {
  \clef "bass"
  c16
  d16
  e16
  f16
  g16
  r16
  r16
  r16
  r16
  r16
  }
  >>
  >>
  
  NEW:
  
  \new Score
  \with
  {
  \override BarLine.stencil = f
  \override BarNumber.transparent = t
  \override SpanBar.stencil = f
  \override TimeSignature.stencil = f
  }
  <<
  \new PianoStaff
  <<
  \context Staff = "Treble Staff"
  {
  \clef "treble"
  r16
  r16
  r16
  r16
  r16
  c'16
  d'16
  e'16
  f'16
  g'16
  }
  \context Staff = "Bass Staff"
  {
  \clef "bass"
  c16
  d16
  e16
  f16
  g16
  r16
  r16
  r16
  r16
  r16
  }
  >>
  >>
  
  MODEL. Note that this makes lexical postprocessing incredibly easy. Any chunk
  of anything can be parsed out of Abjad's LilyPond output as a sequence of
  consecutive lines. Target application might be anything from assignment to
  variables (for externalization in complex scores) or tagging parts of LilyPond
  files on and off.
  
  * Removed 'right' format slot
  
  NEW INDICATOR FUNCTIONALITY:
  
  * Added abjad.hairpin() factory function:
  
  With three-part string descriptor:
  
  >>> staff = abjad.Staff("c'4 d' e' f'")
  >>> abjad.hairpin('p < f', staff[:])
  >>> abjad.override(staff[0]).dynamic_line_spanner.staff_padding = 4
  
  >>> abjad.f(staff)
  \new Staff
  {
  \once \override DynamicLineSpanner.staff-padding = 4
  c'4
  \p
  \<
  d'4
  e'4
  f'4
  \f
  }
  
  With dynamic objects:
  
  >>> staff = abjad.Staff("c'4 d' e' f'")
  >>> start = abjad.Dynamic('niente', command=r'\!')
  >>> trend = abjad.DynamicTrend('o<')
  >>> abjad.tweak(trend).color = 'blue'
  >>> stop = abjad.Dynamic('"f"')
  >>> abjad.hairpin([start, trend, stop], staff[:])
  >>> abjad.override(staff[0]).dynamic_line_spanner.staff_padding = 4
  
  >>> abjad.f(staff)
  \new Staff
  {
  \once \override DynamicLineSpanner.staff-padding = 4
  c'4
  \!
  - \tweak color blue
  - \tweak circled-tip t
  - \tweak stencil abjad-flared-hairpin
  \<
  d'4
  e'4
  f'4
  _ (make-dynamic-script
  (markup
  :whiteout
  :line (
  :general-align Y -2 :normal-text :larger "“"
  :hspace -0.4
  :dynamic "f"
  :hspace -0.2
  :general-align Y -2 :normal-text :larger "”"
  )
  )
  )
  }
  
  * Closes 991
  
  * Added abjad.HairpinStart:
  
  >>> staff = abjad.Staff("c'4 d' e' f' c' d' e' r4")
  >>> abjad.attach(abjad.Dynamic('p'), staff[0])
  >>> abjad.attach(abjad.HairpinStart('<|'), staff[0])
  >>> abjad.attach(abjad.Dynamic('f'), staff[3])
  >>> abjad.attach(abjad.Dynamic('f'), staff[4])
  >>> abjad.attach(abjad.HairpinStart('|>o'), staff[4])
  >>> abjad.attach(abjad.Dynamic('niente', command=r'\!'), staff[-1])
  >>> abjad.override(staff).dynamic_line_spanner.staff_padding = 4.5
  
  >>> abjad.f(staff)
  \new Staff
  \with
  {
  \override DynamicLineSpanner.staff-padding = 4.5
  }
  {
  c'4
  \p
  - \tweak stencil abjad-flared-hairpin
  \<
  d'4
  e'4
  f'4
  \f
  c'4
  \f
  - \tweak circled-tip t
  - \tweak stencil abjad-flared-hairpin
  \>
  d'4
  e'4
  r4
  \!
  }
  
  * Added abjad-flared-hairpin to docs/source/_stylesheets/default.ily
  
  * Added abjad.text_spanner() factory function:
  
  Single spanner:
  
  >>> staff = abjad.Staff("c'4 d' e' f'")
  >>> start_text_span = abjad.StartTextSpan(
  ...     left_text=abjad.Markup('pont.').upright(),
  ...     right_text=abjad.Markup('tasto').upright(),
  ...     style='solid_line_with_arrow',
  ...     )
  >>> abjad.text_spanner(staff[:], start_text_span=start_text_span)
  >>> abjad.override(staff[0]).text_spanner.staff_padding = 4
  
  >>> abjad.f(staff)
  \new Staff
  {
  \once \override TextSpanner.staff-padding = 4
  c'4
  - \abjad_solid_line_with_arrow
  - \tweak bound-details.left.text \markup {
  \concat
  {
  \upright
  pont.
  \hspace
  0.5
  }
  }
  - \tweak bound-details.right.text \markup {
  \upright
  tasto
  }
  \startTextSpan
  d'4
  e'4
  f'4
  \stopTextSpan
  }
  
  * Added abjad.StartTextSpan, abjad.StopTextSpan indicators
  
  * Closes 989
  
  * Added abjad.Dynamic.command property:
  
  >>> dynamic = abjad.Dynamic('mf', command=r'\sub_mf')
  >>> abjad.f(dynamic)
  \sub_mf
  
  Allows composers to define arbitrary dynamics (in external stylesheet) and
  format with Abjad dynamic objects.
  
  * Added abjad.Dynamic.name_is_textual property:
  
  The property allows for ad hoc dynamic indications of the type like "barely
  audible", "extremely quiet", "extremely loud", etc.
  
  Textual dynamics format like this when initialized without an explicit
  command:
  
  >>> voice = abjad.Voice("c'4 d' e' f'")
  >>> dynamic = abjad.Dynamic('appena udibile', name_is_textual=True)
  >>> abjad.attach(dynamic, voice[0])
  
  >>> abjad.f(voice)
  \new Voice
  {
  c'4 _ (make-dynamic-script (markup :whiteout :normal-text :italic "appena udibile"))
  d'4
  e'4
  f'4
  }
  
  Textual dynamics format like this when initialized with an explicit
  command:
  
  >>> voice = abjad.Voice("c'4 d' e' f'")
  >>> dynamic = abjad.Dynamic(
  ...     'appena udibile',
  ...     command=r'\appena_udibile',
  ...     name_is_textual=True,
  ...     )
  >>> abjad.attach(dynamic, voice[0])
  
  >>> abjad.f(voice)
  \new Voice
  {
  c'4 \appena_udibile
  d'4
  e'4
  f'4
  }
  
  * Added abjad.MarginMarkup
  
  * Added abjad.Momento for persistent indicator storage to disk
  
  * Added abjad.RehearsalMark.from_string()
  
  * Added abjad.TimeSignature.from_string() constructor
  
  * Added abjad.MetricModulation.hide property
  
  * Added new 'hide' property to three persistent indicators:
  
  * abjad.Clef.hide
  * abjad.Dynamic.hide
  * abjad.MetronomeMark.hide
  
  * Constrained MetronomeMark.units_per_minute to rationals
  
  * Exteneded abjad.LilyPondLiteral to work with multiline input
  
  * Fixed annotation / abjad.inspect().get_effective() bug
  
  * Fixed abjad.mutate().wrap() / contexted indicator bug
  
  * Set 'persistent' property on persistent indicators
  
  * Closes 894
  
  * Set 'redraw' class constant to true:
  
  * abjad.Clef
  * abjad.Instrument
  * abjad.KeySignature
  
  * Taught abjad.attach(..., context='CustomContext') to work with custom
  context names
  
  OLD: default_scope
  NEW: context
  
  OLD: abjad.attach(..., scope='Staff')
  NEW: abjad.attach(..., context='Staff')
  
  * Closes 873.
  
  OLD: abjad.Dynamic.context == 'Staff'
  NEW: abjad.Dynamic.context == 'Voice'
  
  OLD: abjad.Instrument.short_name_markup
  NEW: abjad.Instrument.short_markup
  
  OLD: abjad.Instrument.name_markup
  NEW: abjad.Instrument.markup
  
  OLD: abjad.KeyCluster.suppress
  NEW: abjad.KeyCluster.hide
  
  OLD: abjad.LilyPondCommand is removed
  NEW: use abjad.LilyPondLiteral instead
  
  OLD: abjad.TimeSignature.suppress
  NEW: abjad.TimeSignature.hide
  
  * Removed abjad.SystemBreak; use abjad.LilyPondLiteral instead
  
  * Removed abjad.Accelerando
  * Removed abjad.Ritardando
  
  * Removed ArrowLineSegment
  * Removed LineSegment
  
  NEW INSPECTION FUNCTIONALITY:
  
  OLD: abjad.select().get_spanners()
  NEW: abjad.inspect().get_spanners()
  
  OLD: abjad.inspect().get_spanners() returned a SET
  NEW: abjad.inspect().get_spanners() returns a LIST
  
  OLD: abjad.select().get_duration()
  NEW: abjad.inspect().get_duration()
  
  OLD: abjad.select().get_pitches()
  NEW: abjad.inspect().get_pitches()
  
  OLD: abjad.select().get_timespan()
  NEW: abjad.inspect().get_timespan()
  
  OLD: abjad.inspect().tabulate_well_formedness_violations()
  NEW: abjad.inspect().tabulate_wellformedness()
  
  OLD:
  
  * abjad.inspect().get_after_grace_container()
  * abjad.inspect().get_annotation()
  * abjad.inspect().get_badly_formed_components()
  * abjad.inspect().get_contents()
  * abjad.inspect().get_descendants()
  * abjad.inspect().get_duration()
  * abjad.inspect().get_effective()
  * abjad.inspect().get_effective_staff()
  * abjad.inspect().get_effective_wrapper()
  * abjad.inspect().get_grace_container()
  * abjad.inspect().get_indicator()
  * abjad.inspect().get_indicators()
  * abjad.inspect().get_leaf()
  * abjad.inspect().get_lineage()
  * abjad.inspect().get_logical_tie()
  * abjad.inspect().get_markup()
  * abjad.inspect().get_parentage()
  * abjad.inspect().get_pitches()
  * abjad.inspect().get_sounding_pitch()
  * abjad.inspect().get_sounding_pitches()
  * abjad.inspect().get_spanner()
  * abjad.inspect().get_spanners()
  * abjad.inspect().get_tuplet()
  * abjad.inspect().get_vertical_moment()
  * abjad.inspect().get_vertical_moment_at()
  
  NEW:
  
  * abjad.inspect().after_grace_container()
  * abjad.inspect().annotation()
  * abjad.inspect().badly_formed_components()
  * abjad.inspect().contents()
  * abjad.inspect().descendants()
  * abjad.inspect().duration()
  * abjad.inspect().effective()
  * abjad.inspect().effective_staff()
  * abjad.inspect().effective_wrapper()
  * abjad.inspect().grace_container()
  * abjad.inspect().indicator()
  * abjad.inspect().indicators()
  * abjad.inspect().leaf()
  * abjad.inspect().lineage()
  * abjad.inspect().logical_tie()
  * abjad.inspect().markup()
  * abjad.inspect().parentage()
  * abjad.inspect().pitches()
  * abjad.inspect().sounding_pitch()
  * abjad.inspect().sounding_pitches()
  * abjad.inspect().spanner()
  * abjad.inspect().spanners()
  * abjad.inspect().tuplet()
  * abjad.inspect().vertical_moment()
  * abjad.inspect().vertical_moment_at()
  
  NEW INSTRUMENT FUNCTIONALITY:
  
  * Abjad instruments no longer format LilyPond \instrumentName, \shortInstrumentName:
  
  * Use abjad.StartMarkup to format LilyPond \instrumentName
  * Use abjad.MarginMarkup to format LilyPond \shortInstrumentName
  
  * Closes 464
  
  OLD: abjad.Instrument.short_instrument_name
  NEW: abjad.Instrument.short_name
  
  OLD: abjad.Instrument.sounding_pitch_of_written_middle_c
  NEW: abjad.Instrument.middle_c_sounding_pitch
  
  NEW ITERATION FUNCTIONALITY:
  
  OLD:
  
  * abjad.iterate().by_prototype()
  * abjad.iterate().by_leaf_pair()
  * abjad.iterate().by_leaf()
  * abjad.iterate().by_logical_tie()
  * abjad.iterate().by_pitch()
  * abjad.iterate().by_timeline()
  * abjad.iterate().by_vertical_moment()
  
  NEW:
  
  * abjad.iterate().components()
  * abjad.iterate().leaf_pairs()
  * abjad.iterate().leaves()
  * abjad.iterate().logical_ties()
  * abjad.iterate().pitches()
  * abjad.iterate().timeline()
  * abjad.iterate().vertical_moments()
  
  OLD: abjad.iterate().by_timeline_and_logical_tie()
  NEW: use abjad.iterate().by_timeline() instead
  
  OLD: abjad.iterate().by_timeline_from_component()
  NEW: use abjad.iterate().timeline() instead
  
  OLD: abjad.iterate().components(pitched=None) keyword
  NEW: abjad.iterate().leaves(pitched=None) keyword
  
  OLD: with_grace_notes=True
  NEW: grace_notes=True
  
  OLD: abjad.iterate().components(start=None, stop=None) keywords.
  NEW: abjad.iterate().components()[:]
  
  OLD: abjad.iterate().leaves(start=None, stop=None) keywords.
  NEW: abjad.iterate().leaves()[:]
  
  * Removed abjad.iterate().by_topmost_logical_ties_and_components().
  
  Disambiguated meaning of 'nontrivial' keyword in logical tie iteration:
  
  OLD:
  
  * abjad.iterate().logical_ties(nontrivial=None):
  yield all logical ties
  * abjad.iterate().logical_ties(nontrivial=False):
  yield all logical ties
  * abjad.iterate().logical_ties(nontrivial=True):
  yield only nontrivial logical ties
  
  NEW:
  
  * abjad.iterate().logical_ties(nontrivial=None):
  yield all logical ties
  * abjad.iterate().logical_ties(nontrivial=False):
  yield only trivial logical ties
  * abjad.iterate().logical_ties(nontrivial=True):
  yield only nontrivial logical ties
  
  Disambiguated meaning of abjad.iterate().leaves(grace_notes=None) keyword:
  
  OLD:
  
  * abjad.iterate().leaves(grace_notes=None):
  yield big leaves only (ie, without grace notes)
  * abjad.iterate().leaves(grace_notes=False):
  same as above
  * abjad.iterate().leaves(grace_notes=True):
  yield both big leaves and grace leaves
  
  NEW:
  
  * abjad.iterate().leaves(grace_notes=None):
  yield both big leaves and grace leaves
  * abjad.iterate().leaves(grace_notes=False):
  yield only big leaves (ie, without grace notes)
  * abjad.iterate().leaves(grace_notes=True):
  yield only grace leaves (ie, without big notes)
  
  * Made abjad.iterate()._depth_first() private for developers
  
  NEW LABEL FUNCTIONALITY:
  
  * Added abjad.label().with_pitches(locale='us') keyword.
  
  * Added abjad.label().with_start_offsets(global_offset=None) keyword.
  
  * Taught abjad.label().with_start_offsets() to return total duration.
  
  * Added abjad.Label.with_start_offsets(..., markup_command=None) keyword:
  
  Provides a generalized hook for user-defined custom markup commands:
  
  >>> staff = abjad.Staff(r"c'2 d' e' f'")
  >>> score = abjad.Score([staff])
  >>> mark = abjad.MetronomeMark((1, 4), 60)
  >>> abjad.attach(mark, staff[0])
  >>> abjad.label(staff).with_start_offsets(
  ...     clock_time=True,
  ...     markup_command='make-dark-cyan',
  ...     )
  
  >>> abjad.f(score)
  \new Score
  <<
  \new Staff
  {
  \tempo 4=60
  c'2
  ^ \markup {
  \make-dark-cyan
  0'00''
  }
  d'2
  ^ \markup {
  \make-dark-cyan
  0'02''
  }
  e'2
  ^ \markup {
  \make-dark-cyan
  0'04''
  }
  f'2
  ^ \markup {
  \make-dark-cyan
  0'06''
  }
  }
  >>
  
  Note that the markup command make-dark-cyan must be user-defined and included
  for LilyPond for interpret the output shown above. Example definition:
  
  (define-markup-command (make-dark-cyan layout props text) (markup?)
  "Dark cyan with font size 3."
  (interpret-markup layout props
  {\markup \fontsize 3 \with-color (x11-color 'DarkCyan) { text } }
  )
  )
  
  NEW LILYPONDFILE FUNCTIONALITY:
  
  OLD: abjad.LilyPondFile.new() included a date-time token by default.
  NEW: abjad.LilyPondFile.new() no longer includes a date-time token by default. (Use abjad.LilyPondFile.new(..., date_time_token=True) for the old behavior.
  
  The motivation is that the date-time comment included at the top of
  most realworld files just leads to versioning contention under Git.
  Easier to just exclude by default and then allow users to include in
  the cases where they actually need it.
  
  NEW MARKUP FUNCTIONALITY:
  
  * Added abjad.Markup.abjad_metronome_mark()
  
  * Added abjad.Markup.from_literal(). Enables markup initialization that
  bypasses the parser.
  
  * Added Markup.literal property:
  
  >>> string = r'\custom-function 1 4'
  >>> markup = abjad.Markup.from_literal(string, literal=True)
  
  >>> abjad.f(markup)
  \markup \custom-function 1 4
  
  * Added abjad.Markup.with_literal() method:
  
  >>> markup = abjad.Markup('Allegro assai')
  >>> markup = markup.bold()
  >>> markup = markup.with_literal(r'\user-markup-command')
  
  >>> abjad.f(markup)
  \markup {
  \user-markup-command
  \bold
  "Allegro assai"
  }
  
  * Fixed longstanding abjad.MarkupCommand.__eq__() bug.
  
  * Removed unused abjad.Markup.stack_priority property
  
  * Removed markup courtesy autocolumn:
  
  OLD:
  
  >>> staff = abjad.Staff("c'4 d' e' f'")
  >>> abjad.attach(abjad.Markup('Allegro'), staff[0])
  >>> abjad.attach(abjad.Markup('non troppo'), staff[0])
  
  >>> abjad.f(staff)
  \new Staff
  {
  c'4
  - \markup {
  \column
  {
  \line
  {
  Allegro
  }
  \line
  {
  "non troppo"
  }
  }
  }
  d'4
  e'4
  f'4
  }
  
  NEW:
  
  >>> staff = abjad.Staff("c'4 d' e' f'")
  >>> abjad.attach(abjad.Markup('Allegro'), staff[0])
  >>> abjad.attach(abjad.Markup('non troppo'), staff[0])
  
  >>> abjad.f(staff)
  \new Staff
  {
  c'4
  - \markup { Allegro }
  - \markup { "non troppo" }
  d'4
  e'4
  f'4
  }
  
  * Closes 977
  
  * Taught abjad.Markup.with_color() about abjad.SchemeColor.
  
  NEW MATH FUNCTIONALITY:
  
  * Added abjad.Ratio.reciprocal
  
  NEW MUTATION FUNCTIONALITY:
  
  * Fixed abjad.mutate().copy() bug from mutating dictionary while iterating
  
  * Removed include_enclosing_containers=None keyword from
  abjad.mutate().copy(); no longer supported
  
  * Removed n=1 keyword from abjad.mutate().copy(); no longer supported
  
  NEW NOTE-HEAD FUNCTIONALITY:
  
  * Added abjad.NoteHead.alternative for edition-tagging. Set the
  read / write NoteHead.alternative_property to a triple:
  
  * alternative note-head
  * (deactivated) other-edition tag
  * active this-edition tag
  
  >>> chord = abjad.Chord("<c' d' bf''>4")
  >>> alternative = abjad.new(chord.note_heads[0])
  >>> alternative.is_forced = True
  >>> chord.note_heads[0].alternative = (alternative, '-PARTS', '+PARTS')
  
  >>> abjad.f(chord, strict=50)
  <
  c'                                            %! +PARTS
  %% c'!                                           %! -PARTS
  d'
  bf''
  >4
  
  The example above allows the C-natural to print with a forced natural sign
  in the score (-PARTS) while printing normally (no forced accidental) in the
  parts (+PARTS).
  
  NEW PATTERN FUNCTIONALITY:
  
  OLD:
  
  * abjad.index_except()
  * abjad.index_every()
  * abjad.index_first()
  * abjad.index_last()
  
  NEW:
  
  * abjad.index()
  
  NEW PITCH FUNCTIONALITY:
  
  * All Abjad pitch classes have been extensively refactored, cleaned up and
  tested. Check the API entries for individual classes to see changes to
  class initializers
  
  * Added quartertone transposition.
  
  * Closes 983
  
  * Fixed 925:
  
  OLD:
  
  >>> abjad.NamedPitch(23.9)
  NamedPitch("c''")  C5
  
  FIXED:
  
  >>> abjad.NamedPitch(23.9)
  NamedPitch("c'''")  C6
  
  * Closes 925
  
  * Removed abjad.Registration; no longer supported
  
  * Taught abjad.NamedPitch to initialize named quartertones:
  
  >>> abjad.medPitch('Aqs6')
  
  NEW RHYTHM-MAKER FUNCTIONALITY:
  
  * The old rhythmmakertools package has been externalized and renamed
  rmakers:
  
  OLD: abjad.rhythmmakertools
  NEW: abjad-ext-rmakers
  
  * Visit https://github.com/Abjad/abjad-ext-rmakers to clone
  
  * Added rmakers.SilenceMask.__invert__()
  * Added rmakers.SustainMask.__invert__()
  
  * Added rmakers.Talea.advance():
  
  >>> talea = rmakers.Talea(
  ...     counts=[2, 1, 3, 2, 4, 1, 1],
  ...     denominator=16,
  ...     preamble=[1, 1, 1, 1],
  ...     )
  
  >>> abjad.f(talea.advance(0))
  rmakers.Talea(
  counts=[2, 1, 3, 2, 4, 1, 1],
  denominator=16,
  preamble=[1, 1, 1, 1],
  )
  
  >>> abjad.f(talea.advance(1))
  rmakers.Talea(
  counts=[2, 1, 3, 2, 4, 1, 1],
  denominator=16,
  preamble=[1, 1, 1],
  )
  
  >>> abjad.f(talea.advance(2))
  rmakers.Talea(
  counts=[2, 1, 3, 2, 4, 1, 1],
  denominator=16,
  preamble=[1, 1],
  )
  
  >>> abjad.f(talea.advance(3))
  rmakers.Talea(
  counts=[2, 1, 3, 2, 4, 1, 1],
  denominator=16,
  preamble=[1],
  )
  
  >>> abjad.f(talea.advance(4))
  rmakers.Talea(
  counts=[2, 1, 3, 2, 4, 1, 1],
  denominator=16,
  )
  
  >>> abjad.f(talea.advance(5))
  rmakers.Talea(
  counts=[2, 1, 3, 2, 4, 1, 1],
  denominator=16,
  preamble=[1, 1, 3, 2, 4, 1, 1],
  )
  
  >>> abjad.f(talea.advance(6))
  rmakers.Talea(
  counts=[2, 1, 3, 2, 4, 1, 1],
  denominator=16,
  preamble=[1, 3, 2, 4, 1, 1],
  )
  
  >>> abjad.f(talea.advance(7))
  rmakers.Talea(
  counts=[2, 1, 3, 2, 4, 1, 1],
  denominator=16,
  preamble=[3, 2, 4, 1, 1],
  )
  
  >>> abjad.f(talea.advance(8))
  rmakers.Talea(
  counts=[2, 1, 3, 2, 4, 1, 1],
  denominator=16,
  preamble=[2, 2, 4, 1, 1],
  )
  
  * Added abjad.Talea.period
  
  * Added abjad.Talea.preamble; use for introductory counts prior to
  repetition of talea counts
  
  * Added TaleaRhythmMaker.__call__(..., state=None) keyword;
  changed rhythm-maker rotation=None keyword to state=None dictionary;
  pass {'rotation': value} to recoup previous interface
  
  * Added abjad.Talea.__contains__()
  
  * Taught TaleaRhythmMaker about previous weight consumed;
  TaleaRhythmMaker publishes postcall state['talea_weight_consumed']
  
  * Taught TaleaRhythmMaker to respect TupletSpecifier.diminution property:
  
  Makes diminshed tuplets by default:
  
  >>> rhythm_maker = rmakers.TaleaRhythmMaker(
  ...     extra_counts_per_division=[-1],
  ...     talea=rmakers.Talea(
  ...         counts=[1],
  ...         denominator=16,
  ...         ),
  ...     )
  
  >>> divisions = [(1, 4), (1, 4)]
  >>> selections = rhythm_maker(divisions)
  >>> lilypond_file = abjad.LilyPondFile.rhythm(
  ...     selections,
  ...     divisions,
  ...     )
  
  >>> abjad.f(lilypond_file[abjad.Staff])
  \new RhythmicStaff
  {
  {   % measure
  \times 2/3 {
  c'8 [
  c'8
  c'8 ]
  }
  }   % measure
  {   % measure
  \times 2/3 {
  c'8 [
  c'8
  c'8 ]
  }
  }   % measure
  }
  
  Makes augmented tuplets when ``diminution`` is set to false:
  
  >>> rhythm_maker = rmakers.TaleaRhythmMaker(
  ...     extra_counts_per_division=[-1],
  ...     talea=rmakers.Talea(
  ...         counts=[1],
  ...         denominator=16,
  ...         ),
  ...     tuplet_specifier=rmakers.TupletSpecifier(
  ...         diminution=False,
  ...         ),
  ...     )
  
  >>> divisions = [(1, 4), (1, 4)]
  >>> selections = rhythm_maker(divisions)
  >>> lilypond_file = abjad.LilyPondFile.rhythm(
  ...     selections,
  ...     divisions,
  ...     )
  
  >>> abjad.f(lilypond_file[abjad.Staff])
  \new RhythmicStaff
  {
  {   % measure
  \tweak text tuplet-number::calc-fraction-text
  \times 4/3 {
  c'16 [
  c'16
  c'16 ]
  }
  }   % measure
  {   % measure
  \tweak text tuplet-number::calc-fraction-text
  \times 4/3 {
  c'16 [
  c'16
  c'16 ]
  }
  }   % measure
  }
  
  OLD:
  
  * abjad.silence_except()
  * abjad.silence_every()
  * abjad.silence_first()
  * abjad.silence_last()
  * abjad.sustain_except()
  * abjad.sustain_every()
  * abjad.sustain_first()
  * abjad.sustain_last()
  
  NEW:
  
  * rmakers.silence()
  * rmakers.sustain()
  
  OLD: rmakers.TupletSpecifier.flatten_trivial_tuplets
  NEW: rmakers.TupletSpecifier.extract_trivial
  
  OLD: rmakers.TupletSpecifier.preferred_denominator
  NEW: rmakers.TupletSpecifier.denominator
  
  OLD: rmakers.TupletSpecifier.rewrite_rest_filled_tuplets
  NEW: rmakers.TupletSpecifier.rewrite_rest_filled
  
  NEW SEGMENT-MAKER FUNCTIONALITY:
  
  OLD: SegmentMaker.__call__()
  NEW: SegmentMaker.run()
  
  Motivation: makes SegmentMaker.__call__() available for command
  accumulation inside definition.py files; command accumulation happens
  many times; run() is called only once:
  
  maker(
  ...
  ...
  ...
  )
  
  maker(
  ...
  ...
  ...
  )
  
  maker(
  ...
  ...
  ...
  )
  
  lilypond_file = maker.run()
  
  NEW SELECTOR FUNCTIONALITY:
  
  * Collapsed all of old selectiontools into single abjad.Selection class
  
  * Collapsed all of old selectortools into same abjad.Selection class
  
  * Integrated abjad.Expression into abjad.Selection
  
  * Allows enchained, object-oriented partial evaluation of all methods.
  
  * Defined concept of selection (and selection item) explicitly:
  
  * SELECTION: an Abjad selection is an iterable of items such that each
  item is an Abjad component or else another Abjad selection. The
  definition allows for nested selections (but forbids the inclusion of
  built-in tuples or lists as items in a selection)
  
  * OLD: Selection.components
  
  * NEW: Selection.items
  
  * Replaced flatten=False keyword with Selection.flatten() method:
  
  OLD: flatten keyword was required in most (but not all) methods to
  return a flat selection of objects:
  
  >>> abjad.select().by_leaf(flatten=True)  defaulted to flatten=False
  >>> abjad.select().by_logical_tie(flatten=True)  def to flatten=True
  >>> abjad.select().by_prototype(flatten=True)  def to flatten=False
  
  NEW: all methods that say that they return a flat selection now do so:
  
  >>> abjad.select().leaves()
  >>> abjad.select().logical_ties()
  >>> abjad.select().components()
  
  * Replaced apply_to_each=False keyword with Selection.map() method:
  
  OLD: apply_to_each keyword was required to get logical tie heads,
  logical tie bodies, logical tie tails:
  
  >>> abjad.select().by_logical_tie().get_item(
  ...     0,
  ...     apply_to_each=True,
  ...     )
  >>> abjad.select().by_logical_tie().get_slice(
  ...     start=1,
  ...     apply_to_each=True,
  ...     )
  >>> abjad.select().by_logical_tie().get_item(
  ...     -1,
  ...     apply_to_each=True,
  ...     )
  
  NEW: Selector.map() is fully generalized; this cleans irregularities in
  apply_to_each; composers can make arbitrarily mapped selections that
  were not possible with apply_to_each:
  
  >>> abjad.select().logical_ties().map(abjad.select()[0])
  >>> abjad.select().logical_ties().map(abjad.select()[1:])
  >>> abjad.select().logical_ties().map(abjad.select()[-1])
  
  Note that object-oriented map() is now implemented as a bound method as
  both abjad.Sequence.map() and abjad.Selection.map(). This allows for
  functional composition of select expressions. Most common is a two-part
  getter-map pattern; here are three examples:
  
  Gets the leaves in each tuplet (as separate selections):
  
  >>> getter = abjad.select().leaves()
  >>> abjad.select().tuplets().map(getter)
  
  Gets the first leaf in each tuplet:
  
  >>> getter = abjad.select().leaf(0)
  >>> abjad.select().tuplets().map(getter)
  
  Gets the nonfirst leaves in each tuplet (as separate selections):
  
  >>> getter = abjad.select().leaves()[1:]
  >>> abjad.select().tuplets().map(getter)
  
  All other combinations also work: mapping against contiguity, runs,
  inequalites, etc.
  
  * Generalized the select / filter interface:
  
  NEW:
  
  * abjad.select().filter()
  * abjad.select().filter_duration()
  * abjad.select().filter_length()
  * abjad.select().filter_pitches()
  * abjad.select().filter_preprolated()
  
  The abjad.select().filter() method generalizes the filter interface;
  composers may filter arbitrarily on other frozen select expressions or
  on lambdas or arbitrary Python callables.
  
  * Generalized the select / group-by interface:
  
  NEW:
  
  * abjad.select().group_by()
  * abjad.select().group_by_contiguity()
  * abjad.select().group_by_duration()
  * abjad.select().group_by_length()
  * abjad.select().group_by_measure()
  * abjad.select().group_by_pitch()
  
  The abjad.select().group_by() method generalizes the group-by
  interface; composers may group arbitrarily on other frozen select
  expressions or on lambdas or arbitrary Python callables.
  
  * Added three new inequality factory functions for filter / group-by:
  
  NEW:
  
  * abjad.length()
  * abjad.duration()
  * abjad.pitches()
  
  * Shortened by-phrase method names to direct object method names:
  
  OLD:
  
  * abjad.select().by_leaf()
  * abjad.select().by_logical_tie()
  * abjad.select().by_run()
  
  NEW:
  
  * abjad.select().leaves()
  * abjad.select().logical_ties()
  * abjad.select().runs()
  
  * Paired singular / plural select methods:
  
  NEW:
  
  * abjad.select().leaves()
  * abjad.select().leaf()
  
  * abjad.select().logical_ties()
  * abjad.select().logical_tie()
  
  * abjad.select().runs()
  * abjad.select().run()
  
  * Generalized select __getitem__() to support Python get-item idioms
  transparently:
  
  OLD:
  
  * abjad.select().first()
  * abjad.select().last()
  * abjad.select().most()
  * abjad.select().middle()
  * abjad.select().rest()
  
  NEW:
  
  * abjad.select()[0]
  * abjad.select()[-1]
  * abjad.select()[:-1]
  * abjad.select()[1:-1]
  * abjad.select()[1:]
  
  * Extended abjad.Selection.__getitem__() to accept abjad.Pattern objects
  for patterned item-getting
  
  * Harmonized Iteration / Selection.
  * Complete grace note iteration / selection integration
  * Taught reverse iteration work with grace notes.
  * Set iteration to include grace notes by default.
  * Integrated grace_notes=False keyword into all select methods.
  
  * Added Selector.template property.
  * Added abjad.FormatSpecification.storage_format_forced_override property.
  * Format templates are turned on in abjad.Selection; these allow for
  maximally compact storage representations of frozen select expressions,
  to arbitrary levels of functional composition through dot-chaining:
  
  >>> abjad.f(abjad.select())
  abjad.select()
  
  >>> abjad.f(abjad.select().leaves())
  abjad.select().leaves()
  
  >>> abjad.f(abjhad.select().leaves()[1:-1])
  abjad.select().leaves()[1:-1]
  
  * Built out selector interface:
  
  * abjad.select().chord()
  * abjad.select().chords()
  * abjad.select().components()
  * abjad.select().contiguous()
  * abjad.select().filter()
  * abjad.select().filter_duration()
  * abjad.select().filter_length()
  * abjad.select().filter_pitches()
  * abjad.select().flatten()
  * abjad.select().group()
  * abjad.select().group_duration()
  * abjad.select().group_length()
  * abjad.select().group_pitches()
  * abjad.select().leaf()
  * abjad.select().leaves()
  * abjad.select().logical_measures()
  * abjad.select().logical_ties()
  * abjad.select().map()
  * abjad.select().note()
  * abjad.select().notes()
  * abjad.select().partition_by_counts()
  * abjad.select().partition_by_durations()
  * abjad.select().partition_by_ratio()
  * abjad.select().rest()
  * abjad.select().rests()
  * abjad.select().run()
  * abjad.select().runs()
  * abjad.select().top()
  * abjad.select().tuplet()
  * abjad.select().tuplets()
  
  * Added abjad.Selector.color() for API illustration
  
  * Added abjad.Selector.print() for API illustration
  
  * Fixed longstanding abjad.iterate().by_logical_tie() bug
  
  * Closes 850
  
  * Closes 411
  
  NEW SEQUENCE FUNCTIONALITY:
  
  IMPORTANT SEARCH-AND-REPLACE FOR COMPOSERS PORTING TO ABJAD 3:
  
  OLD:
  
  >>> abjad.sequence().flatten()
  
  NEW:
  
  >>> abjad.sequence().flatten(depth=-1)
  
  OLD: abjad.Sequence.flatten(depth=-1)
  NEW: abjad.Sequence.flatten(depth=1) [changed negative index to positive]
  
  * Added "enchained" partition:
  
  sequence = abjad.sequence(range(16))
  parts = sequence.partition_by_counts(
  [5],
  cyclic=True,
  enchain=True,
  overhang=True,
  )
  >>> for part in parts:
  ...     part
  ...
  Sequence([0, 1, 2, 3, 4])
  Sequence([4, 5, 6, 7, 8])
  Sequence([8, 9, 10, 11, 12])
  Sequence([12, 13, 14, 15])
  
  * Added abjad.Selection.partition_by_counts(enchain=False) keyword
  
  NEW SCHEME FUNCTIONALITY:
  
  * Taught Scheme.format_scheme_value() more about pound-initiated strings:
  
  staff = abjad.Staff("c'4 d' e' f'")
  score = abjad.Score([staff])
  abjad.tweak(staff[0].note_head).stencil = 'my-custom-stencil'
  abjad.override(staff[1]).note_head.color = 'my-custom-stencil'
  abjad.setting(score).mark_formatter = 'my-custom-mark-formatter'
  
  abjad.f(score)
  \new Score
  \with
  {
  markFormatter = my-custom-mark-formatter
  }
  <<
  \new Staff
  {
  \tweak stencil my-custom-stencil
  c'4
  \once \override NoteHead.color = my-custom-stencil
  d'4
  e'4
  f'4
  }
  >>
  
  * Closes 973
  
  OLD: abjad.SchemeMoment.duration returned duration
  NEW: abjad.SchemeMoment.duration returns nonreduced fraction
  
  NEW SCORE PACKAGE FUNCTIONALITY
  
  The new abjad.Path class provides an object-oriented interface to the
  directory structure of Abjad score packages:
  
  * Score package convenience properties:
  
  * abjad.Path.builds
  * abjad.Path.contents
  * abjad.Path.distribution
  * abjad.Path.etc
  * abjad.Path.materials
  * abjad.Path.segments
  * abjad.Path.stylesheets
  * abjad.Path.test
  * abjad.Path.tools
  * abjad.Path.wrapper
  * abjad.Path._segments
  
  * Score package path predicates:
  
  * abjad.Path.is_build()
  * abjad.Path.is_builds()
  * abjad.Path.is_contents
  * abjad.Path.is_distribution()
  * abjad.Path.is_etc()
  * abjad.Path.is_material()
  * abjad.Path.is_materials()
  * abjad.Path.is_segment()
  * abjad.Path.is_segments()
  * abjad.Path.is_stylesheets()
  * abjad.Path.is_test()
  * abjad.Path.is_tools()
  * abjad.Path.is_wrapper()
  * abjad.Path.is__segments()
  
  * Score package path tree-handling methods:
  
  * abjad.Path.get_next_package()
  * abjad.Path.get_next_score()
  * abjad.Path.get_previous_package()
  * abjad.Path.get_previous_score()
  * abjad.Path.list_paths()
  * abjad.Path.segment_number_to_path()
  * abjad.Path.with_name()
  * abjad.Path.with_parent()
  * abjad.Path.with_score()
  
  * Score package name-handling:
  
  * abjad.Path.coerce()
  * abjad.Path.get_asset_type()
  * abjad.Path.get_identifier()
  * abjad.Path.get_name_predicate()
  * abjad.Path.get_title()
  
  * Metadata interface:
  
  * abjad.Path.add_metadatum()
  * abjad.Path.remove_metadatum()
  * abjad.Path.update_order_dependent_segment_metadata()
  
  * See the abjad.Path API entry for examples
  
  NEW SPANNER FUNCTIONALITY:
  
  OLD: abjad.Spanner.components
  NEW: abjad.Spanner.leaves
  
  NEW BEAM FUNCTIONALITY:
  
  NEW:
  
  * abjad.Beam.beam_lone_notes
  * abjad.Beam.beam_rests
  * abjad.Beam.durations
  * abjad.Beam.span_beam_count
  * abjad.Beam.stemlet_length
  
  REMOVED:
  
  * abjad.ComplexBeam
  * abjad.DuratedComplexBeam
  * abjad.MeasuredComplexBeam
  * abjad.MultipartBeam
  
  * Closes 319
  
  NEW GLISSANDO PROPERITES:
  
  Added abjad.Glissando.stems property:
  
  >>> staff = abjad.Staff("c'8 d'8 e'8 f'8")
  >>> glissando = abjad.Glissando(stems=True)
  >>> abjad.attach(glissando, staff[:])
  
  >>> abjad.f(staff)
  \new Staff
  {
  c'8 \glissando
  \hide NoteHead
  \override NoteColumn.glissando-skip = t
  \override NoteHead.no-ledgers = t
  d'8 \glissando
  e'8 \glissando
  \revert NoteColumn.glissando-skip
  \revert NoteHead.no-ledgers
  \undo \hide NoteHead
  f'8
  }
  
  Added abjad.Glissando.style property:
  
  >>> staff = abjad.Staff("c'8 d'8 e'8 f'8")
  >>> glissando = abjad.Glissando(style='trill')
  >>> abjad.attach(glissando, staff[:])
  
  >>> abjad.f(staff)
  \new Staff
  {
  \override Glissando.style = 'trill
  c'8 \glissando
  d'8 \glissando
  e'8 \glissando
  \revert Glissando.style
  f'8
  }
  
  OLD:
  
  * Glissando.allow_repeat_pitches
  * Glissando.parenthesize_repeated_pitches
  
  NEW:
  
  * Glissando.allow_repeats
  * Glissando.parenthesize_repeats
  
  NEW TEXT SPANNER FUNCTIONALITY: Simultaneous text spanners are now
  available in a single voice:
  
  >>> staff = abjad.Staff("c'4 d'4 e'4 fs'4")
  
  >>> spanner_1 = abjad.TextSpanner(lilypond_id=1)
  >>> abjad.attach(spanner_1, staff[:])
  >>> spanner_1.attach(abjad.Markup('ord.').upright(), spanner_1[0])
  >>> spanner_1.attach(abjad.ArrowLineSegment(), spanner_1[0])
  >>> spanner_1.attach(abjad.Markup('pont.').upright(), spanner_1[-1])
  >>> abjad.tweak(spanner_1).staff_padding = 2.5
  
  >>> spanner = abjad.TextSpanner()
  >>> abjad.attach(spanner, staff[:])
  >>> spanner.attach(abjad.Markup('A').upright(), spanner[0])
  >>> spanner.attach(abjad.ArrowLineSegment(), spanner[0])
  >>> spanner.attach(abjad.Markup('B').upright(), spanner[-1])
  >>> abjad.tweak(spanner).staff_padding = 5
  
  >>> abjad.f(staff)
  \new Staff
  {
  c'4
  - \tweak staff-padding 2.5
  - \tweak Y-extent f
  - \tweak bound-details.left.text \markup {
  \concat
  {
  \upright
  ord.
  \hspace
  0.25
  }
  }
  - \tweak arrow-width 0.25
  - \tweak dash-fraction 1
  - \tweak bound-details.left.stencil-align-dir-y center
  - \tweak bound-details.right.arrow t
  - \tweak bound-details.right-broken.padding 0
  - \tweak bound-details.right-broken.text f
  - \tweak bound-details.right.padding 0.5
  - \tweak bound-details.right.stencil-align-dir-y center
  - \tweak bound-details.right.text \markup {
  \concat
  {
  \hspace
  0.0
  \upright
  pont.
  }
  }
  \startTextSpanOne
  - \tweak staff-padding 5
  - \tweak Y-extent f
  - \tweak bound-details.left.text \markup {
  \concat
  {
  \upright
  A
  \hspace
  0.25
  }
  }
  - \tweak arrow-width 0.25
  - \tweak dash-fraction 1
  - \tweak bound-details.left.stencil-align-dir-y center
  - \tweak bound-details.right.arrow t
  - \tweak bound-details.right-broken.padding 0
  - \tweak bound-details.right-broken.text f
  - \tweak bound-details.right.padding 0.5
  - \tweak bound-details.right.stencil-align-dir-y center
  - \tweak bound-details.right.text \markup {
  \concat
  {
  \hspace
  0.0
  \upright
  B
  }
  }
  \startTextSpan
  d'4
  e'4
  fs'4
  \stopTextSpanOne
  \stopTextSpan
  }
  
  Closes 932.
  
  * Added text-spanner-id.ily from David Nalesnik to default.ly
  stylesheet
  
  NEW TIE FUNCTIONALITY:
  
  * Taught abjad.Tie to allow enharmonic renotation:
  
  >>> staff = abjad.Staff("c'4 bs c' dff'")
  >>> abjad.attach(abjad.Tie(), staff[:])
  
  >>> abjad.f(staff)
  \new Staff
  {
  c'4 ~
  bs4 ~
  c'4 ~
  dff'4
  }
  
  * Extended abjad.Tie.repeat property to allow repeat-tie threshold:
  
  abjad.Tie objects may now format both conventional ties (~) and repeat-ties
  (\repeatTie) on different leaves in the same tie.
  
  Set the repeat-tie threshold as a duration inequality:
  
  >>> tie = abjad.Tie(repeat=(1, 4))
  >>> abjad.f(tie.repeat)
  abjad.DurationInequality(
  operator_string='>=',
  duration=abjad.Duration(1, 4),
  )
  
  >>> staff = abjad.Staff("c'2 c'8 c'4.")
  >>> abjad.attach(tie, staff[:])
  
  >>> abjad.f(staff)
  \new Staff
  {
  c'2
  c'8
  \repeatTie
  ~
  c'4.
  }
  
  Durations that satisfy inequality can be said to "meet repeat-tie
  threshold." Durations that do not meet repeat-tie threshold format
  conventional tie on current note; durations that do meet repeat-tie
  threshold format repeat-tie on following note.
  
  LILYPOND FIX: abjad.Tie now corrects for down-positioned midstaff repeat ties.
  
  abjad.Tie automatically tweaks repeat tie direction up when repeat tie connects
  to long-duration note at staff position zero:
  
  >>> tie = abjad.Tie(repeat=True)
  >>> staff = abjad.Staff(r"b'4 b'4 b'2 b'1 b'\breve")
  >>> abjad.attach(abjad.TimeSignature((8, 4)), staff[-1])
  >>> abjad.attach(tie, staff[:])
  
  >>> abjad.f(staff)
  \new Staff
  {
  b'4
  b'4
  \repeatTie
  b'2
  \repeatTie
  b'1
  - \tweak direction up
  \repeatTie
  \time 8/4
  b'\breve
  - \tweak direction up
  \repeatTie
  }
  
  * Removed abjad.ComplexTrillSpanner; use abjad.TrillSpanner instead
  
  * Removed abjad.MetronomeMarkSpanner
  
  * Removed abjad.Spanner.name property
  
  * Unsubscribed all spanners from pieceiwse definition protocol
  
  OLD: you could attach arbitrary information to spanners:
  
  >>> beam = abjad.Beam()
  >>> abjad.attach(99, beam)
  
  NEW: you can no longer do this
  
  OLD: abjad.HorizontalBracketSpanner
  NEW: abjad.HorizontalBracket
  
  OLD: abjad.Tie.repeat_ties
  NEW: abjad.Tie.repeat
  
  NEW STRICT FORMATTING / ATTACH-TAGGING FUNCTIONALITY:
  
  Conventional (nonstrict) formatting positions some format contributions to
  the right of leaves:
  
  >>> staff = abjad.Staff("c'4 d' e' f'")
  >>> abjad.attach(abjad.Articulation('^'), staff[0])
  >>> abjad.attach(abjad.Markup('Allegro', direction=abjad.Up), staff[0])
  >>> abjad.attach(abjad.StemTremolo(), staff[0])
  
  >>> abjad.f(staff)
  \new Staff {
  c'4 :16 -\marcato ^ \markup { Allegro }
  d'4
  e'4
  f'4
  }
  
  Strict formatting avoids right-slot formatting;
  Strict formatting positions contributions strictly one-per-line;
  Tags are introduced with %!;
  IndicatorWrapper numbers tags (on a per-leaf basis) at attach-time;
  Use to tag individual output lines for lexical postprocessing:
  
  >>> staff = abjad.Staff("c'4 d' e' f'")
  >>> abjad.attach(abjad.Articulation('^'), staff[0], tag='RED')
  >>> markup = abjad.Markup('Allegro', direction=abjad.Up)
  >>> abjad.attach(markup, staff[0], tag='GREEN')
  >>> abjad.attach(abjad.StemTremolo(), staff[0], tag='BLUE')
  
  >>> abjad.f(staff, strict=True)
  \new Staff {
  c'4
  :16 %! BLUE:2
  -\marcato %! RED:1
  ^ \markup { Allegro } %! GREEN:3
  d'4
  e'4
  f'4
  }
  
  IMPORTANCE: attach tagging (which should always be combined with strict
  formatting) enables to composes to tag the exact 'moment' at which any one
  thing is attached to any other one thing. It doesn't matter what *type*
  of thing is being attached to some other thing: it is rather an exact call
  to abjad.attach() that is tagged when the tag keyword is set. This enables
  generalized *(lexical) postprocessing* on the LilyPond files Abjad
  produces: composer-authored Python (or other) scripts that selectively
  activate and deactivate tagged lines down to any level of specificity.
  
  Some examples:
  
  * Courtesy metronome marks (at the start of a segment) can be tagged
  for removal when segments are concatenated into a complete score
  
  * Courtesy time signatures (at the start of a segment) can be tagged
  the same way (for removal at segment concatenation time)
  
  * Arbitrary amounts of (tagged) markup can be added to LilyPond files
  now: markup showing spacing, clocktime duration, compositional
  annotations and so on without limit can now be tag-attached to Abjad
  leaves during composition and then removed by postprocessing scripts
  at later stages of a composer's score-building toolchain
  
  * Added abjad.f(..., strict=False) keyword.
  
  * Added abjad.attach(..., tag=None) keyword.
  
  * Added abjad.label(tag=None) keyword.
  
  NEW STRING FUNCTIONALITY:
  
  * Added abjad.String.is_shout_case()
  
  * Added abjad.String.is_roman()
  
  * Added abjad.String.sort_roman()
  
  >>> strings = ['ViolinXI', 'ViolinX', 'ViolinIX']
  >>> abjad.String.sort_roman(strings)
  ['ViolinIX', 'ViolinX', 'ViolinXI']
  
  * Added abjad.String.strip_roman()
  
  * Added abjad.String.to_indicator_stem()
  
  * Added abjad.String.to_shout_case()
  
  NEW TONAL ANALYSIS FUNCTIONALITY:
  
  * Externalized abjad.tonalanalysistools to abjad-ext-tonality
  
  * Visit https://github.com/Abjad/abjad-ext-tonality to clone
  
  NEW TUPLET FUNCTIONALITY:
  
  * All settable tuplet properties are now available at initialization:
  
  OLD:
  
  abjad.Tuplet.__init__(
  multiplier=None,
  components=Nonbe,
  )
  
  NEW:
  
  abjad.Tuplet.__init__(
  multiplier=None,
  components=Nonbe,
  denominator=None,
  force_fraction=None,
  hide=None,
  )
  
  * Added abjad.Tuplet.normalize_multiplier():
  
  >>> tuplet = abjad.Tuplet((1, 3), "c'4 d' e'")
  >>> abjad.f(tuplet)
  \times 1/3 {
  c'4
  d'4
  e'4
  }
  
  >>> tuplet.multiplier.normalized()
  False
  
  >>> tuplet.normalize_multiplier()
  >>> abjad.f(tuplet)
  \times 2/3 {
  c'8
  d'8
  e'8
  }
  
  >>> tuplet.multiplier.normalized()
  True
  
  NEW: Added abjad.Tuplet.trivialize():
  
  >>> tuplet = abjad.Tuplet((3, 4), "c'2")
  
  >>> abjad.f(tuplet)
  \tweak text tuplet-number::calc-fraction-text
  \times 3/4 {
  c'2
  }
  
  >>> tuplet.trivializable()
  True
  
  >>> tuplet.trivialize()
  
  >>> abjad.f(tuplet)
  {
  c'4.
  }
  
  Changed LilyPond format of trivial (1:1) tuplets:
  
  OLD:
  
  >>> tuplet = abjad.Tuplet((1, 1), "c'8 d' e' ")
  >>> abjad.f(tuplet)
  {
  c'8
  d'8
  e'8
  }
  
  NEW:
  
  >>> tuplet = abjad.Tuplet((1, 1), "c'8 d' e'")
  >>> abjad.f(tuplet)
  \tweak text tuplet-number::calc-fraction-text
  \times 1/1 {
  c'8
  d'8
  e'8
  }
  
  This means that 1:1 tuplets now appear as explicit tuplets in output.
  
  To recoup the old behavior, set abjad.Tuplet.hide to true:
  
  >>> tuplet = abjad.Tuplet((1, 1), "c'8 d' e'", hide=True)
  >>> abjad.f(tuplet)
  \scaleDurations '(1 . 1) {
  c'8
  d'8
  e'8
  }
  
  * Added abjad.Tuplet.rewrite_dots()
  * Added abjad.Multiplier.from_dot_count()
  
  Rewrites double dots as 7:4 prolation:
  
  >>> tuplet = abjad.Tuplet(1, "c'8.. c'8..")
  >>> abjad.f(tuplet)
  \tweak text tuplet-number::calc-fraction-text
  \times 1/1 {
  c'8..
  c'8..
  }
  
  >>> tuplet.rewrite_dots()
  >>> abjad.f(tuplet)
  \tweak text tuplet-number::calc-fraction-text
  \times 7/4 {
  c'8
  c'8
  }
  
  Cleaned up tuplet constructors:
  
  OLD:
  
  Tuplet.from_duration_and_ratio(
  duration,
  ratio,
  avoid_dots=True,
  decrease_monotonic=True,
  diminution=True,
  )
  
  NEW:
  
  Tuplet.from_duration_and_ratio(
  duration,
  ratio,
  decrease_monotonic=True,
  )
  
  OLD:
  
  Tuplet.from_leaf_and_ratio(leaf, ratio, diminution=True)
  
  NEW:
  
  Tuplet.from_leaf_and_ratio(leaf, ratio)
  
  OLD:
  
  Tuplet.from_ratio_and_pair(
  ratio,
  fraction,
  allow_trivial=False,
  )
  
  NEW:
  
  Tuplet.from_ratio_and_pair(ratio, fraction)
  
  OLD:
  
  Tuplet.toggle_prolation() incorrectly changed trivial (1:1) prolation
  to 1:2 prolation.
  
  NEW:
  
  Tuplet.toggle_prolation() leaves trivial (1:1) prolation unchanged.
  
  * Closes 970
  
  OLD: abjad.Tuplet.from_nonreduced_ratio_and_nonreduced_fraction()
  NEW: abjad.Tuplet.from_ratio_and_pair()
  
  OLD: abjad.Tuplet.invisible
  NEW: abjad.Tuplet.hide
  
  OLD: abjad.Tuplet.is_augmentation (property)
  NEW: abjad.Tuplet.augmentation() (method)
  
  OLD: abjad.Tuplet.is_diminution (property)
  NEW: abjad.Tuplet.diminution() (method)
  
  OLD: abjad.Tuplet.is_redundant (property)
  NEW: abjad.Tuplet.trivializable() (method)
  
  OLD: abjad.Tuplet.is_trivial (property)
  NEW: abjad.Tuplet.trivial() (method
  
  OLD: abjad.Tuplet.preferred_denominator
  NEW: abjad.Tuplet.denominator
  
  NEW TWEAK FUNCTIONALITY:
  
  * Added tuplet tweaks:
  
  >>> tuplet_1 = abjad.Tuplet((2, 3), "c'4 ( d'4 e'4 )")
  >>> abjad.tweak(tuplet_1).color = 'red'
  >>> abjad.tweak(tuplet_1).staff_padding = 2
  
  >>> tuplet_2 = abjad.Tuplet((2, 3), "c'4 ( d'4 e'4 )")
  >>> abjad.tweak(tuplet_2).color = 'green'
  >>> abjad.tweak(tuplet_2).staff_padding = 2
  
  >>> tuplet_3 = abjad.Tuplet((5, 4), [tuplet_1, tuplet_2])
  >>> abjad.tweak(tuplet_3).color = 'blue'
  >>> abjad.tweak(tuplet_3).staff_padding = 4
  
  >>> staff = abjad.Staff([tuplet_3])
  >>> leaves = abjad.select(staff).leaves()
  >>> abjad.attach(abjad.TimeSignature((5, 4)), leaves[0])
  >>> literal = abjad.LilyPondLiteral(r'\set tupletFullLength = t')
  >>> abjad.attach(literal, staff)
  
  >>> abjad.f(staff)
  \new Staff
  {
  \set tupletFullLength = t
  \tweak text tuplet-number::calc-fraction-text
  \tweak color blue
  \tweak staff-padding 4
  \times 5/4 {
  \tweak color red
  \tweak staff-padding 2
  \times 2/3 {
  \time 5/4
  c'4
  (
  d'4
  e'4
  )
  }
  \tweak color green
  \tweak staff-padding 2
  \times 2/3 {
  c'4
  (
  d'4
  e'4
  )
  }
  }
  }
  
  * Added indicator tweaks:
  
  * Arpeggio
  * Articulation
  * BendAfter
  * ColorFingering
  * Dynamic
  * Fermata
  * LaissezVibrer
  * LilyPondLiteral
  * Staccatissimo
  * Staccato
  * BreathMark
  * KeySignature
  * RehearsalMark
  
  ARPEGGIO TWEAKS:
  
  >>> chord = abjad.Chord("<c' e' g' c''>4")
  >>> arpeggio = abjad.Arpeggio()
  >>> abjad.tweak(arpeggio).color = 'blue'
  >>> abjad.attach(arpeggio, chord)
  
  >>> abjad.f(chord)
  <c' e' g' c''>4
  - \tweak color blue
  \arpeggio
  
  ARTICULATION TWEAKS:
  
  >>> note = Note("c'4")
  >>> articulation = abjad.Articulation('marcato')
  >>> abjad.tweak(articulation).color = 'blue'
  >>> abjad.attach(articulation, note)
  
  >>> abjad.f(note)
  c'4
  - \tweak color blue
  -\marcato
  
  DYNAMIC TWEAKS:
  
  >>> note = Note("c'4")
  >>> dynamic = abjad.Dynamic('f')
  >>> abjad.tweak(dynamic).color = 'blue'
  >>> abjad.attach(dynamic, note)
  
  >>> abjad.f(note)
  c'4
  - \tweak color blue
  \f
  
  * Closes 957
  
  * Added support for tweak expressions; use the abjad.tweak() factory
  function:
  
  >>> abjad.tweak('red').color
  LilyPondTweakManager(('color', 'red'))
  
  >>> abjad.tweak(6).Y_offset
  LilyPondTweakManager(('Y_offset', 6))
  
  >>> abjad.tweak(False).bound_details__left_broken__text
  LilyPondTweakManager(('bound_details__left_broken__text', False))
  
  GLOBAL NAME CHANGES:
  
  OLD: decrease_durations_monotonically
  NEW: decrease_monotonic
  
  OLD: forbidden_written_duration
  NEW: forbidden_duration
  
  OLD: is_once
  NEW: once
  
  OLD: use_messiaen_style_ties
  NEW: repeat_ties
  
  CHANGES FOR DEVELOPERS:
  
  * Integrated pathlib
  
  OLD:
  
  * abjad.agenttools.InspectionAgent
  * abjad.agenttools.IterationAgent
  * abjad.agenttools.LabelAgent
  * abjad.agenttools.MutatinAgent
  * abjad.agenttools.PersistenceAgent
  
  NEW:
  
  * abjad.Inspection
  * abjad.Iteration
  * abjad.Label
  * abjad.Mutation
  * abjad.PersistenceManager
  
  OLD: abjad.Component._indicator_wrappers
  NEW: abjad.Component._wrappers
  
  OLD: abjad.StorageFormatAgent
  NEW: abjad.StorageFormatManager
  
  OLD: abjad.IndicatorWrapper
  NEW: abjad.Wrapper
  
  OLD: abjad.Wrapper.is_annotation
  NEW: abjad.Wrapper.annotation

3.0.0rc1


        

2.21

- `Pitch.named_pitch`
  - `Pitch.named_pitch_class`
  - `Pitch.numbered_pitch`
  - `Pitch.numbered_pitch_class`
  - `Pitch.pitch_class_name`
  - `Pitch.pitch_class_number`
  - `Pitch.pitch_class_octave_label`
  - `Pitch.pitch_name`
  - `Pitch.pitch_number`
  - `Retrogression.period`
  - `Rotation.period`
  
  Bugfixes
  
  - Fixed definition of `pitchtools.NumberedPitch.multiply()`.
  - Fixed edge-cases in `abjad.new(expression)`.
  - Taught `rhythmmakertools.BeamSpecifier` to respect `beam_rests` setting.

2.20

Improvements (global)
  
  - Greatly expanded Abjad global namespace:
  
  ['Accelerando', 'Annotation', 'Arpeggio', 'Arrow', 'Articulation',
  'BarLine', 'Beam', 'BendAfter', 'BowContactPoint', 'BowContactSpanner',
  'BowMotionTechnique', 'BowPressure', 'BreathMark', 'Chord', 'Clef',
  'ClefSpanner', 'Cluster', 'ColorFingering', 'ComplexBeam',
  'ComplexTrillSpanner', 'Component', 'Container', 'Context', 'Crescendo',
  'CyclicTuple', 'Decrescendo', 'DuratedComplexBeam', 'Duration', 'Dynamic',
  'Expression', 'Fermata', 'FixedDurationTuplet', 'Fraction',
  'GeneralizedBeam', 'Glissando', 'GraceContainer', 'Hairpin',
  'HiddenStaffSpanner', 'HorizontalBracketSpanner', 'Infinity', 'Inversion',
  'KeyCluster', 'KeySignature', 'LaissezVibrer', 'Leaf', 'LilyPondCommand',
  'LilyPondComment', 'LilyPondFile', 'LilyPondLiteral', 'LineSegment',
  'Markup', 'MarkupList', 'Measure', 'MeasuredComplexBeam', 'Meter',
  'MetricModulation', 'MultimeasureRest', 'MultipartBeam', 'Multiplication',
  'Multiplier', 'NamedInterval', 'NamedIntervalClass', 'NamedPitch',
  'NamedPitchClass', 'NonreducedFraction', 'NonreducedRatio', 'Note',
  'NumberedInterval', 'NumberedIntervalClass', 'NumberedPitch',
  'NumberedPitchClass', 'OctavationSpanner', 'Offset', 'PageBreak',
  'Pattern', 'PhrasingSlur', 'PianoPedalSpanner', 'PitchClassSegment',
  'PitchClassSet', 'PitchRange', 'PitchSegment', 'PitchSet', 'Ratio',
  'Registration', 'RehearsalMark', 'Repeat', 'Rest', 'Retrograde',
  'Ritardando', 'Rotation', 'Scheme', 'SchemeMoment', 'SchemePair',
  'SchemeSymbol', 'SchemeVector', 'Score', 'Selection', 'Selector',
  'Sequence', 'SetClass', 'Skip', 'Slur', 'Spanner', 'Staff', 'StaffChange',
  'StaffGroup', 'StaffLinesSpanner', 'StemTremolo', 'StemTremoloSpanner',
  'StringContactPoint', 'StringNumber', 'SystemBreak', 'Tempo',
  'TempoSpanner', 'TextSpanner', 'Tie', 'TimeSignature', 'Timespan',
  'Transposition', 'Tremolo', 'TrillSpanner', 'Tuning', 'Tuplet',
  'TwelveToneRow', 'TypedOrderedDict', 'Voice', 'abctools',
  'abjad_configuration', 'agenttools', 'attach', 'commandlinetools',
  'datastructuretools', 'demos', 'detach', 'documentationtools',
  'durationtools', 'exceptiontools', 'expressiontools', 'ext', 'f', 'graph',
  'indicatortools', 'inspect_', 'instrumenttools', 'ipythontools', 'iterate',
  'label', 'lilypondfiletools', 'lilypondnametools', 'lilypondparsertools',
  'ly', 'markuptools', 'mathtools', 'metertools', 'mutate', 'new',
  'override', 'parse', 'patterntools', 'persist', 'pitchtools', 'play',
  'print_function', 'quantizationtools', 'rhythmmakertools',
  'rhythmtreetools', 'schemetools', 'scoretools', 'select', 'select_all',
  'select_every', 'select_first', 'select_last', 'selectiontools',
  'selectortools', 'sequence', 'sequencetools', 'set_', 'show', 'silence',
  'silence_all', 'silence_every', 'silence_except', 'silence_first',
  'silence_last', 'spannertools', 'stringtools', 'sustain', 'sustain_all',
  'sustain_every', 'sustain_first', 'sustain_last', 'systemtools',
  'templatetools', 'timespantools', 'tonalanalysistools', 'topleveltools',
  'tweak']
  
  - Integrated `quicktions` library for optional C-accelerated calculations with
  rational numbers. Install via `pip install abjad[accelerated]`.
  - Taught `systemtools.ImportManager` about Cython `.pyx` files.
  - Extended scripts:
  - Added `ajv doctest` `--abjad-only` option to suppress implicit `from
  abjad import *` imports at the beginning of each doctest.
  - Taught `ajk script` to ignore EPS files and private `_doc` directories.
  - Taught `ajk script` to ignore private `_doc` directories.
  
  Improvements (by package):
  
  - **`expressiontools`**:
  - Collapsed `expressiontools.Callback`, `expressiontools.LabelExpression`,
  and `expressiontools.SequenceExpression` into
  `expressiontools.Expression`.
  - Added `expressiontools.Expression.__eq__()`.
  - Added `expressiontools.Signature` decorator.
  
  - **`indicatortools`**:
  - Added `indicatortools.LilyPondLiteral`.
  - Added `sfffz` to known dynamic names.
  
  - **`lilypondfiletools`**:
  - Added `lilypondfiletools.LilyPondFile` anonymous context retrieval.
  - Added `lilypondfiletools.LilyPondFile` custom context retrieval.
  
  - **`markuptools`**:
  - Added `markuptools.MarkupInventory.center_column()`.
  - Added `markuptools.MarkupInventory.combine()`.
  - Added `markuptools.MarkupInventory.concat()`.
  - Added `markuptools.MarkupInventory.__illustrate__()`.
  - Added `markuptools.MarkupInventory.__lt__()`.
  
  - **`mathtools`**:
  - Added `Infinity.__float__()`.
  
  - **`patterntools`**:
  - Added `patterntools.CompoundPattern.get_matching_items()`.
  - Added `patterntools.Pattern.get_matching_items()`.
  
  - **`pitchtools`**:
  - Added `NumberedPitch.from_pitch_class_octave()`.
  - Added `Pitch.pitch_class`.
  - Added `Pitch.name`.
  - Added `Pitch.number`.
  - Added `PitchClassSet.__illustrate__()`.
  - Added `PitchClassSegment.permute(row=None)`.
  - Added `PitchClassSegment.to_pitch_classes()`.
  - Added `PitchClassSegment.to_pitches()`.
  - Added `PitchSegment.to_pitch_classes()`.
  - Added `PitchSegment.to_pitches()`.
  - Added `PitchSet.__illustrate__()`.
  - Added `SetClass`.
  
  - **`scoretools`**:
  - Added `scoretools.make_leaves(skips_instead_of_rests=False)` keyword.
  - Taught `scoretools.Container` to initialize mixed selection / component
  input.
  
  - **`selectortools`**:
  - Added `Selector.group_by_pitch()`.
  - Added `Selector.by_leaf(head=None)` keyword.
  - Added `Selector.by_leaf(pitched=True)` keyword.
  - Added `Selector.by_leaf(prototype=None)` keyword.
  - Added `Selector.by_leaf(tail=None)` keyword.
  - Added `Selector.by_leaf(trim=None)` keyword.
  - Added `Selector.select()`.
  
  - **`sequencetools`**:
  - Added `sequencetools.Enumeration` class:
  - `Enumeration.yield_combinations()`
  - `Enumeration.yield_outer_product()`
  - `Enumeration.yield_pairs()`
  - `Enumeration.yield_partitions()`
  - `Enumeration.yield_permutations()`
  - `Enumeration.yield_subsequences()`
  - Added `Sequence.reverse(recurse=False)` keyword.
  - Added `Sequence.sort()` method.
  
  - **`systemtools`**:
  - Taught `systemtools.StorageFormatAgent` about keyword-only parameters.
  
  - **`timespantools`**:
  - Added `timespantools.Timespan.__illustrate__(scale=None)` keyword.
  - Added `timespantools.TimespanInventory.__invert__()`.
  
  - **`topleveltools`**:
  - Added `topleveltools.tweak()` function.
  
  Changes (global)
  
  - Changed `_lilypond_format property` to `_get_lilypond_format()` method.
  - Changed `args` to `arguments` in most places in the codebase.
  - Changed `expr` to `argument` in most places in the codebase.
  - Changed `kwargs` to `keywords` in most places in the codebase.
  - Changed `note head` to `note-head` globally.
  - Taught `LilyPondOutputProxy` to omit empty layout and paper blocks.
  
  Changes (by package)
  
  - **`datastructuretools`**:
  - Removed `datastructuretools.Matrix`.
  - Removed `datastructuretools.CyclicMatrix`.
  - Replaced `TypedTuple.__getslice__()` with `__getitem__()`.
  - Rewired `CyclicTuple` to remove multiple inheritance.
  
  - **`documentationtools`**:
  - All `Graphviz*` classes have been moved into a new `graphtools`
  subpackage.
  
  - **`durationtools`**:
  - Removed `durationtools.Division`.
  
  - **`indicatortools`**:
  - Changed `ClefInventory` to `ClefList`.
  - Moved `ClefInventory` from `indicatortools` to `instrumenttools`.
  - Removed `IsAtSoundingPitch`.
  - Removed `IsUnpitched`.
  - Removed `SpacingIndication`.
  
  - **`lilypondfiletools`**:
  - Removed `lilypondfiletools.make_basic_lilypond_file()`.
  Use `lilypondfiletools.LilyPondFile.new()` instead.
  
  - **`markuptools`**:
  - Removed `Markup.make_*()` methods.
  - Changed `Markup.super_()` to `Markup.super()`.
  - Changed `Markup.line()` to static method.
  - Changed `MarkupInventory` to `MarkupList`.
  - Changed the following methods to accept markup list:
  - `Markup.center_column(markup_list)`
  - `Markup.column(markup_list)`
  - `Markup.concat(markup_list)`
  - `Markup.left_column(markup_list)`
  - `Markup.line(markup_list)`
  - `Markup.overlay(markup_list)`
  - `Markup.right_column(markup_list)`
  - Changed `Markup` interpreter representation
  - OLD: `Markup(contents=('Allegro assai',))`
  - NEW: `Markup(contents=['Allegro assai'])`
  - Changed Markup.combine() signature:
  - OLD: `Markup.combine(markup_1, markup_2)`
  - NEW: `Markup.combine([markup_1, markup_2])`
  - Reimplemented all `markuptools` pytests as doctests.
  
  - **`pitchtools`**:
  - Removed `PitchArray*` classes.
  - Changed `Rotation.transpose` default from `True` to `None`.
  - Changed `has_duplicates` property to method:
  - `IntervalClassSegment.has_duplicates()`
  - `IntervalSegment.has_duplicates()`
  - `PitchClassSegment.has_duplicates()`
  - `PitchSegment.has_duplicates()`
  - `Segment.has_duplicates()`
  - `TwelveToneRow.has_duplicates()`
  - Renamed `Octave.octave_number` to `Octave.number`.
  - Renamed `Octave.octave_tick_string` to `Octave.tick_string`.
  - Renamed `Pitch.octave_number` to `Pitch.octave.number`.
  - Renamed `.index` to `.n`:
  - `Multiplication.index` to `Multiplication.n`
  - `Rotation.index` to `Rotation.n`
  - `Transposition.index` to `Transposition.n`
  - Renamed `PitchOperation` to `CompoundOperator`.
  - Renamed `Retrogression` to `Retrograde`.
  - Named Stravinsky-style rotation explicitly:
  - `PitchClassSegment.rotate(n=-1, transpose=True)` to
  `PitchClassSegment.rotate(n=-1, stravinsky=True)`
  - `TwelveToneRow.rotate(n=-1, transpose=True)` to
  `TwelveToneRow.rotate(n=-1, stravinsky=True)`
  
  - **`selectortools`**:
  - Renamed `select_all_but_first_logical_tie_in_pitched_runs()` to
  `select_nonfirst_logical_tie_in_pitched_runs()`.
  - Renamed `select_all_but_last_logical_tie_in_pitched_runs()` to
  `select_nonlast_logical_tie_in_pitched_runs()`.
  
  - **`sequencetools`**:
  
  - Changed all `sequencetools` functions to `Sequence` methods.
  - Renamed `Sequence.rotate(index=0)` to `Sequence.rotate(n=0)`.
  - Renamed `sequencetools.join_subsequences()` to `Sequence.join()`.
  - Renamed `sequencetools.permute_sequence()` to `Sequence.permute()`.
  - Renamed `sequencetools.split_sequence()` to `Sequence.split()`.
  - Renamed `sequencetools.flatten_sequence()` to `Sequence.flatten()`.
  - Renamed `sequencetools.reverse_sequence()` to `Sequence.reverse()`.
  - Renamed `sequencetools.rotate_sequence()` to `Sequence.rotate()`.
  - Renamed `sequencetools.repeat_sequence()` to `Sequence.repeat()`.
  - Renamed `sequencetools.repeat_sequence()` to `Sequence.repeat()`.
  - Renamed `sequencetools.partition_sequence_by_counts()` to
  `Sequence.partition_by_counts()`.
  - Renamed `sequencetools.zip_sequences()` to `Sequence.zip()`.
  - Renamed `sequencetools.truncate_sequence()` to `Sequence.truncate()`.
  - Renamed `sequence.partition_sequence_by_value_of_elements()` to
  `Sequence.group_by()`.
  - Renamed `sequencetools.partition_sequence_by_ratio_of_lengths()` to
  `Sequence.partition_by_ratio_of_lengths()`.
  - Renamed `sequencetools.partition_sequence_by_ratio_of_weights()` to
  `Sequence.partition_by_ratio_of_weights()`.
  - Renamed `sequencetools.partition_sequence_by_weights()` to
  `Sequence.partition_by_weights()`.
  - Renamed `sequencetools.iterate_sequence_nwise()` to
  `Sequence.nwise()`.
  - Renamed `sequencetools.sum_consecutive_elements_by_sign()` to
  `Sequence.sum_by_sign()`.
  - Renamed `sequencetools.repeat_sequence_to_length()` to
  `Sequence.repeat_to_length()`.
  - Renamed `sequencetools.repeat_sequence_to_weight()` to
  `Sequence.repeat_to_weight()`.
  - Renamed `sequencetools.remove_repeated_elements()` to
  `Sequence.remove_repeats()`.
  - Renamed `sequencetools.remove_elements()` to `Sequence.remove()`.
  - Renamed `sequencetools.replace_elements()` to `Sequence.replace()`.
  - Renamed `sequencetools.retain_elements()` to `Sequence.retain()`.
  - Renamed `sequencetools.Enumeration.yield_pairs()` to
  `Enumeration.yield_outer_product()`.
  - Renamed `Enumeration.yield_unordered_pairs()` to
  `Enumeration.yield_pairs()`.
  - Removed the following sequencetools functions (because composer-specific
  or too complex to belong in the public API):
  - `sequencetools.join_subsequences_by_sign_of_elements()`
  - `sequencetools.increase_elements()`
  - `sequencetools.interlace_sequences()`
  - `sequencetools.iterate_sequence_boustrophedon()`
  - `sequencetools.negate_elements()`
  - `sequencetools.overwrite_elements()`
  - `sequencetools.partition_sequence_by_sign_of_elements()`
  - `sequencetools.remove_subsequence_of_weight_at_index()`
  - `sequencetools.repeat_elements()`
  - `sequencetools.splice_between_elements()`
  
  - **`spannertools`**:
  
  - Renamed `Glissando.allow_repeated_pitches` to `Glissando.allow_repeat_pitches`.
  
  - **`systemtools`**:
  
  - Removed `Memoize` decorator.
  - Changed `_storage_format_specification` property to
  `_get_storage_format_specification()` method.
  - Changed `IOManager.profile_expr()` to `IOManager.profile()`.
  
  Deprecated

2.19

Improvements
  - [740] Proofread ‘For beginners’ section of docs. Thanks delucis!
  - [741] LilyPond's log is displayed on LilyPond compilation error.
  - [749] Added `LilyPondCommand` to Abjad's global namespace.
  - [752] Taught `detach()` about different types of grace container.
  - [753] Taught `Dynamics` about _sforzando_ dynamic names.
  - [744] Refactoring and cleanup in `schemetools`. Thanks ajyoon!
  - [745] Reimplemented Abjad's repr, storage format and object templating system.
  - [755, 760, 761, 763] Cleaned-up class member ordering via a new command-line script. Thanks ajyoon!
  - [766] Abjad's `ajv` looks for `.ajv` config files in $HOME, the current directory and any parent directory thereof. A [doctest] section can specify imports to be run at the beginning of each doctest in `ajv doctest` via an `imports` key.
  
  Changes
  - [745] `AbjadObject`'s `_storage_format_specification` and `_repr_specification` properties are deprecated in favor of a new unified `_get_format_specification()` method. The old properties will no longer be supported in the next Abjad release: 2.20.
  
  Bugfixes
  - [762] Improved interaction between chords and ties. Thanks quesebifurcan!
  - [764] `IOManager.open_file()` respects Abjad's config when opening MIDI files. Thanks quesebifurcan!
  - [767] Fixed edge-cases in Graphviz attribute-handling and append/extend behavior.
  - [774] NamedPitch.invert() guards against errors from multiply-augmented or diminished intervals.

2.18

Improvements
  - [715] Grace notes are now aware of their parentage above and beyond their enclosing `GraceContainer`.
  - [703] Added a `synthetic_offset` keyword to `attach()` and `IndicatorExpression`.
  - This allows composers to attach effective indicators which start _before_ the score starts, allowing composers to model how various indicators hold over from a previous section.
  - For example: `attach(Dynamic('f'), voice, synthetic_offset=-1)`
  - [640] Many optimizations:
  - Optimized hot code paths in Duration and Offset instantiation.
  - Optimized timespan comparison.
  - Optimized parser instantiation.
  - [626, 726] `Dynamic` now recognizes `sffp`, `sffz` and `niente` as valid dynamic names.
  - [726] `Hairpin` is now niente-aware.
  - [628] Implemented a collection of command-line tools for working with score packages.
  - `ajv score`, `ajv material`, `ajv segment`, `ajv target`.
  - These tools are provisional pending more extensive use.
  - [719] Implemented `TupletSpellingSpecifier.preferred_denominator`.
  - This mirrors `Tuplet.preferred_denominator`.
  - [666] Abjad now formats LilyPond properties using the newer dot-chained syntax, not the old `'...` syntax.
  - As always, Abjad targets the development version of LilyPond, currently the 2.19 series.
  - [720] Non-reduced fractions can be attached to leaves just like `Multiplier` objects.
  - [724] Equipped `Sequence.partition_by_counts()` with a `reverse` keyword.
  - [725] Equipped `Markup` with `.sub()` and `.super()` markup command methods.
  
  Changes
  - [709] Spanners now attach **only to leaves**, **never to containers**.
  - This represents a significant simplification in Abjad's score model.
  - This change should generally be transparent to users, as `attach()` does the work of iterating leaves in its component expression.
  - [709] Many spanners now attach only to 2 or more leaves at once, including `Slur` and `Tie`.
  - [709] Removed `Container.select_leaves()`.
  - To select a container's leaves, use `list(iterate(container).by_leaf())`.
  - To select the _first leaf_ of a container, use `next(iterate(container).by_leaf())`.
  - To select the _last leaf_ of a container, use `next(iterate(container).by_leaf(reverse=True))`.
  - [628, 644, 643, 702] Tool-chain clean-up and refactoring
  - `developerscripttools` was renamed `commandlinetools`.
  - `DeveloperScript` was renamed `CommandlineScript`.
  - Unused and obsolete scripts have been removed.
  - [717] Out-ported various classes to https://github.com/trevorbaca/baca:
  - `Cursor`, `PitchClassTree`, `PayloadTree`, `CyclicPayloadTree`.
  - [714] `Selector.by_leaves()` is now `Selector.by_leaf()`. This harmonizes with `IterationAgent.by_leaf()`.
  - [721] Added a new LilyPondCommand.prefix property.
  - This makes it easy to position arbitrary strings relative to components.
  
  Bugfixes
  - [655] `Tuplet._simplify_redundant_tuplet()` takes logical ties into account.
  - [680] Abjad's docs post-process SVG images under Python 2.7 properly.
  - [736] Registration now takes quarter tones into account.

2.17

Improvements:
  - Abjad's documentation has seen extensive work, including:
  - a new theme based off of https://github.com/snide/sphinx_rtd_theme
  - crisp SVG Graphviz output for all class lineage graphs
  - expandable image thumbnails
  - a score gallery page showing notation examples from many scores created with Abjad
  - revised installation instructions
  - virtually all code examples in the docs are now interpreted via the `abjad-book` Sphinx extension, guaranteeing correctness
  - many enhancements to Abjad's Sphinx extension
  - A new `PackageGitCommitToken` class for embedding Python package version information in LilyPond files.
  - A new `IterationAgent.by_timeline_and_logical_tie()` method.
  - A provisional collection of new classes in `lilypondnametools` for object-modeling various LilyPond entities: `LilyPondGrob`, `LilyPondGrobInterface`, `LilyPondContext` and `LilyPondEngraver`.
  - Abjad now supports PyPy.
  
  Changes:
  - Abjad's dependencies have been separated into `standard`, `development` and `ipython`. See our installation docs for details.
  - Abjad's IPython extension now uses `timidity` instead of `ffmpeg` and `fluidsynth` to embed audio output from calls to `play()`. OSX users can install `timidity` via HomeBrew.
  - `GraphvizEdge.__call__()` has been removed in favor of explicit `.attach(node_one, node_two)` and `.detach()` methods.
  - `sievetools` functionality has been merged into the classes housed in `patterntools`.
  - All `labeltools` functionality has been migrated into the `agentools.LabelAgent` class.
  - `LilyPondFile` properties such as `paper_size`, `includes`, etc. are now immutable. Set them during instantiation. See the API example for details.
  - `TimeSignature` can now only be instantiated from a pair, such as `(3, 4)`: `TimeSignature((3, 4))`.
  
  Bugfixes:
  - `GraphvizGraph` instances can now be copied with edges intact.
  - `Markup` now properly quotes strings containing `` symbols.

2.16


        

2.15


        

2.14