Source code for mutwo.abjad_parameters.abc

import abc
import typing

import abjad

from mutwo import core_utilities
from mutwo import music_parameters


[docs]class AbjadAttachment(abc.ABC): """Abstract base class for all Abjad attachments."""
[docs] @classmethod def get_class_name(cls): return core_utilities.camel_case_to_snake_case(cls.__name__)
[docs] @classmethod def from_indicator_collection( cls, indicator_collection: music_parameters.abc.IndicatorCollection ) -> typing.Optional["AbjadAttachment"]: """Initialize :class:`AbjadAttachment` from :class:`~mutwo.parameters.abc.IndicatorCollection`. If no suitable :class:`~mutwo.parameters.abc.Indicator` could be found in the collection the method will simply return None. """ class_name = cls.get_class_name() try: indicator = getattr(indicator_collection, class_name) except AttributeError: return None # typing will run a correct error: # to make this method working, we also need to inherit # the inherited subclass from a mutwo.parameters.abc.Indicator # class return cls(**indicator.get_arguments_dict()) # type: ignore
[docs] @abc.abstractmethod def process_leaf_tuple( self, leaf_tuple: tuple[abjad.Leaf, ...], previous_attachment: typing.Optional["AbjadAttachment"], ) -> tuple[abjad.Leaf, ...]: raise NotImplementedError()
@property @abc.abstractmethod def is_active(self) -> bool: raise NotImplementedError()
[docs]class ToggleAttachment(AbjadAttachment): """Abstract base class for Abjad attachments which behave like a toggle. In Western notation one can differentiate between elements which only get notated if they change (for instance dynamics, tempo) and elements which have to be notated again and again (for instance arpeggi or tremolo). Attachments that inherit from :class:`ToggleAttachment` represent elements which only get notated if their value changes. """
[docs] @abc.abstractmethod def process_leaf( self, leaf: abjad.Leaf, previous_attachment: typing.Optional["AbjadAttachment"] ) -> typing.Union[abjad.Leaf, typing.Sequence[abjad.Leaf]]: raise NotImplementedError()
[docs] def process_leaf_tuple( self, leaf_tuple: tuple[abjad.Leaf, ...], previous_attachment: typing.Optional["AbjadAttachment"], ) -> tuple[abjad.Leaf, ...]: if previous_attachment != self: return ( self.process_leaf(leaf_tuple[0], previous_attachment), ) + leaf_tuple[1:] else: return leaf_tuple
[docs]class BangAttachment(AbjadAttachment): """Abstract base class for Abjad attachments which behave like a bang. In Western notation one can differentiate between elements which only get notated if they change (for instance dynamics, tempo) and elements which have to be notated again and again to be effective (for instance arpeggi or tremolo). Attachments that inherit from :class:`BangAttachment` represent elements which have to be notated again and again to be effective. """
[docs] @abc.abstractmethod def process_first_leaf(self, leaf: abjad.Leaf) -> abjad.Leaf: raise NotImplementedError()
[docs] @abc.abstractmethod def process_last_leaf(self, leaf: abjad.Leaf) -> abjad.Leaf: raise NotImplementedError()
[docs] @abc.abstractmethod def process_central_leaf(self, leaf: abjad.Leaf) -> abjad.Leaf: raise NotImplementedError()
[docs] def process_leaf_tuple( self, leaf_tuple: tuple[abjad.Leaf, ...], previous_attachment: typing.Optional["AbjadAttachment"], ) -> tuple[abjad.Leaf, ...]: n_leaf_tuple = len(leaf_tuple) new_leaf_list = [] if n_leaf_tuple > 0: new_leaf_list.append(self.process_first_leaf(leaf_tuple[0])) if n_leaf_tuple > 2: for leaf in leaf_tuple[1:-1]: new_leaf_list.append(self.process_central_leaf(leaf)) if n_leaf_tuple > 1: new_leaf_list.append(self.process_last_leaf(leaf_tuple[-1])) return tuple(new_leaf_list)
[docs]class BangEachAttachment(BangAttachment):
[docs] @abc.abstractmethod def process_leaf( self, leaf: abjad.Leaf ) -> typing.Union[abjad.Leaf, typing.Sequence[abjad.Leaf]]: raise NotImplementedError()
[docs] def process_first_leaf( self, leaf: abjad.Leaf ) -> typing.Union[abjad.Leaf, typing.Sequence[abjad.Leaf]]: return self.process_leaf(leaf)
[docs] def process_last_leaf( self, leaf: abjad.Leaf ) -> typing.Union[abjad.Leaf, typing.Sequence[abjad.Leaf]]: return self.process_leaf(leaf)
[docs] def process_central_leaf( self, leaf: abjad.Leaf ) -> typing.Union[abjad.Leaf, typing.Sequence[abjad.Leaf]]: return self.process_leaf(leaf)
[docs]class BangFirstAttachment(BangAttachment):
[docs] @abc.abstractmethod def process_leaf( self, leaf: abjad.Leaf ) -> typing.Union[abjad.Leaf, typing.Sequence[abjad.Leaf]]: raise NotImplementedError()
[docs] def process_first_leaf( self, leaf: abjad.Leaf ) -> typing.Union[abjad.Leaf, typing.Sequence[abjad.Leaf]]: return self.process_leaf(leaf)
[docs] def process_last_leaf( self, leaf: abjad.Leaf ) -> typing.Union[abjad.Leaf, typing.Sequence[abjad.Leaf]]: return leaf
[docs] def process_central_leaf( self, leaf: abjad.Leaf ) -> typing.Union[abjad.Leaf, typing.Sequence[abjad.Leaf]]: return leaf
[docs]class BangLastAttachment(BangAttachment):
[docs] @abc.abstractmethod def process_leaf( self, leaf: abjad.Leaf ) -> typing.Union[abjad.Leaf, typing.Sequence[abjad.Leaf]]: raise NotImplementedError()
[docs] def process_first_leaf(self, leaf: abjad.Leaf) -> abjad.Leaf: return leaf
[docs] def process_last_leaf(self, leaf: abjad.Leaf) -> abjad.Leaf: return self.process_leaf(leaf)
[docs] def process_central_leaf(self, leaf: abjad.Leaf) -> abjad.Leaf: return leaf
[docs] def process_leaf_tuple( self, leaf_tuple: tuple[abjad.Leaf, ...], previous_attachment: typing.Optional["AbjadAttachment"], ) -> tuple[abjad.Leaf, ...]: n_leaf_tuple = len(leaf_tuple) if n_leaf_tuple > 0: return leaf_tuple[:-1] + (self.process_last_leaf(leaf_tuple[-1]),) else: return leaf_tuple