concertina_helper.type_defs
1from __future__ import annotations 2from collections.abc import Callable, Iterator 3from dataclasses import dataclass 4from enum import Enum, auto 5from typing import Any, Iterable 6 7from pyabc2 import Pitch as AbcPitch 8 9 10@dataclass(frozen=True) 11class Pitch: 12 ''' 13 Immutable class representing a musical pitch. 14 ''' 15 name: str 16 17 # TODO: post_init validation: fail if name != normalized name 18 19 @property 20 def _pitch(self) -> AbcPitch: 21 return AbcPitch.from_name(self.name) 22 23 @property 24 def class_name(self) -> str: 25 return self._pitch.class_name 26 27 def transpose(self, semitones: int) -> Pitch: 28 return Pitch(AbcPitch(self._pitch.value + semitones).name) 29 30 def __str__(self) -> str: 31 return self.name 32 33 def __eq__(self, other: Any) -> bool: 34 if type(self) != type(other): 35 raise TypeError('mixed operand types') 36 return self._pitch.value == other._pitch.value 37 38 39@dataclass(frozen=True) 40class PitchMatrix: 41 ''' 42 Represents the pitches that can be produced by one half of a concertina, 43 on either the push or pull, if bisonoric. 44 ''' 45 matrix: tuple[tuple[Pitch, ...], ...] 46 47 def transpose(self, semitones: int) -> PitchMatrix: 48 return PitchMatrix( 49 tuple( 50 tuple( 51 proxy.transpose(semitones) 52 for proxy in row 53 ) 54 for row in self.matrix 55 ) 56 ) 57 58 def __getitem__(self, i: int) -> tuple[Pitch, ...]: 59 return self.matrix[i] 60 61 def __iter__(self) -> Iterator[tuple[Pitch, ...]]: 62 return iter(self.matrix) 63 64 65@dataclass(frozen=True) 66class Mask: 67 ''' 68 A boolean matix. `True` represents a key held down. 69 70 >>> Mask(((True, False),)) | Mask(((False, True),)) 71 Mask(bool_matrix=((True, True),)) 72 ''' 73 bool_matrix: tuple[tuple[bool, ...], ...] 74 75 @property 76 def shape(self) -> Iterable[int]: 77 return [len(row) for row in self.bool_matrix] 78 79 def __getitem__(self, i: int) -> tuple[bool, ...]: 80 return self.bool_matrix[i] 81 82 def __iter__(self) -> Iterator[tuple[bool, ...]]: 83 return iter(self.bool_matrix) 84 85 def __or__(self, other: Any) -> Mask: 86 if type(self) != type(other): 87 raise TypeError('mixed operand types') 88 if self.shape != other.shape: 89 raise ValueError('different shapes') 90 return Mask( 91 tuple( 92 tuple( 93 self_bool or other_bool 94 for self_bool, other_bool 95 in zip(self_row, other_row) 96 ) 97 for self_row, other_row 98 in zip(self, other) 99 ) 100 ) 101 102 103Shape = tuple[Iterable[int], Iterable[int]] 104''' 105Describes the button arrangement of an instrument: 106respectively the left and right faces, and for each face, 107the number of buttons in each row. 108''' 109 110PitchToStr = Callable[[Pitch], str] 111''' 112A function which takes a pitch and returns a string. 113(Should the octave number be printed? 114Should unicode characters be used for accidentals? 115Those sort of details are handled by the function.) 116''' 117 118 119class Direction(Enum): 120 ''' 121 `PUSH` and `PULL`are paired with a unisonoric fingering 122 to create a bisonoric fingering 123 ''' 124 PUSH = auto() 125 PULL = auto() 126 127 def __repr__(self) -> str: 128 return f'Direction.{self.name}' 129 130 131@dataclass(frozen=True, kw_only=True) 132class Annotation: 133 pitch: Pitch 134 measure: int
@dataclass(frozen=True)
class
Pitch:
11@dataclass(frozen=True) 12class Pitch: 13 ''' 14 Immutable class representing a musical pitch. 15 ''' 16 name: str 17 18 # TODO: post_init validation: fail if name != normalized name 19 20 @property 21 def _pitch(self) -> AbcPitch: 22 return AbcPitch.from_name(self.name) 23 24 @property 25 def class_name(self) -> str: 26 return self._pitch.class_name 27 28 def transpose(self, semitones: int) -> Pitch: 29 return Pitch(AbcPitch(self._pitch.value + semitones).name) 30 31 def __str__(self) -> str: 32 return self.name 33 34 def __eq__(self, other: Any) -> bool: 35 if type(self) != type(other): 36 raise TypeError('mixed operand types') 37 return self._pitch.value == other._pitch.value
Immutable class representing a musical pitch.
@dataclass(frozen=True)
class
PitchMatrix:
40@dataclass(frozen=True) 41class PitchMatrix: 42 ''' 43 Represents the pitches that can be produced by one half of a concertina, 44 on either the push or pull, if bisonoric. 45 ''' 46 matrix: tuple[tuple[Pitch, ...], ...] 47 48 def transpose(self, semitones: int) -> PitchMatrix: 49 return PitchMatrix( 50 tuple( 51 tuple( 52 proxy.transpose(semitones) 53 for proxy in row 54 ) 55 for row in self.matrix 56 ) 57 ) 58 59 def __getitem__(self, i: int) -> tuple[Pitch, ...]: 60 return self.matrix[i] 61 62 def __iter__(self) -> Iterator[tuple[Pitch, ...]]: 63 return iter(self.matrix)
Represents the pitches that can be produced by one half of a concertina, on either the push or pull, if bisonoric.
PitchMatrix(matrix: tuple[tuple[concertina_helper.type_defs.Pitch, ...], ...])
@dataclass(frozen=True)
class
Mask:
66@dataclass(frozen=True) 67class Mask: 68 ''' 69 A boolean matix. `True` represents a key held down. 70 71 >>> Mask(((True, False),)) | Mask(((False, True),)) 72 Mask(bool_matrix=((True, True),)) 73 ''' 74 bool_matrix: tuple[tuple[bool, ...], ...] 75 76 @property 77 def shape(self) -> Iterable[int]: 78 return [len(row) for row in self.bool_matrix] 79 80 def __getitem__(self, i: int) -> tuple[bool, ...]: 81 return self.bool_matrix[i] 82 83 def __iter__(self) -> Iterator[tuple[bool, ...]]: 84 return iter(self.bool_matrix) 85 86 def __or__(self, other: Any) -> Mask: 87 if type(self) != type(other): 88 raise TypeError('mixed operand types') 89 if self.shape != other.shape: 90 raise ValueError('different shapes') 91 return Mask( 92 tuple( 93 tuple( 94 self_bool or other_bool 95 for self_bool, other_bool 96 in zip(self_row, other_row) 97 ) 98 for self_row, other_row 99 in zip(self, other) 100 ) 101 )
A boolean matix. True
represents a key held down.
>>> Mask(((True, False),)) | Mask(((False, True),))
Mask(bool_matrix=((True, True),))
Shape =
tuple[typing.Iterable[int], typing.Iterable[int]]
Describes the button arrangement of an instrument: respectively the left and right faces, and for each face, the number of buttons in each row.
PitchToStr =
collections.abc.Callable[[concertina_helper.type_defs.Pitch], str]
A function which takes a pitch and returns a string. (Should the octave number be printed? Should unicode characters be used for accidentals? Those sort of details are handled by the function.)
class
Direction(enum.Enum):
120class Direction(Enum): 121 ''' 122 `PUSH` and `PULL`are paired with a unisonoric fingering 123 to create a bisonoric fingering 124 ''' 125 PUSH = auto() 126 PULL = auto() 127 128 def __repr__(self) -> str: 129 return f'Direction.{self.name}'
PUSH =
Direction.PUSH
PULL =
Direction.PULL
Inherited Members
- enum.Enum
- name
- value
@dataclass(frozen=True, kw_only=True)
class
Annotation:
Annotation(*, pitch: concertina_helper.type_defs.Pitch, measure: int)