Skip to content

Commit

Permalink
[Big] Adding github action for tests, fixes, black formatting, type h…
Browse files Browse the repository at this point in the history
…ints, new pianoroll methods

* adding test github action, fixes, black formatting, type hints, update setup.py

* new notes2pianoroll method, scipy dependency removed, pianoroll tests, constants file, black formatting

* pianoroll2notes now have a pitch_range argument
  • Loading branch information
Natooz authored Nov 13, 2023
1 parent ca4808e commit 005f46e
Show file tree
Hide file tree
Showing 50 changed files with 681 additions and 534 deletions.
18 changes: 18 additions & 0 deletions .github/codecov.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Codecov params

coverage:
status:
project:
default: false # disable the default status that measures entire project
tests:
paths:
- "tests/"
target: 70%
source:
paths:
- "miditoolkit/"
target: 75%
threshold: 0.5%
patch:
default:
enabled: no # target: 75% # new contributions should have a coverage at least equal to target
40 changes: 40 additions & 0 deletions .github/workflows/pytest.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# PyTest workflow

name: Test

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"]
os: [ ubuntu-latest, macOS-latest, windows-latest ]

steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
# Install local package with tests dependencies extras
python -m pip install --upgrade pip
pip install -e ".[tests]"
- name: Lint with flake8
run: |
# stop the build if there are Python syntax errors or undefined names
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
- name: Test with pytest
run: |
pytest --cov=./ --cov-report=xml -n auto
- name: Codecov
uses: codecov/[email protected]
6 changes: 3 additions & 3 deletions miditoolkit/__init__.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
'''
"""
Author: Wen-Yi Hsiao, Taiwan
Update date: 2020.06.23
'''
"""

from .midi import *
from .pianoroll import *

__version__ = '0.1.16'
__version__ = "1.0.1"
5 changes: 5 additions & 0 deletions miditoolkit/constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
""" Constants files
"""

PITCH_RANGE = (0, 127)
2 changes: 1 addition & 1 deletion miditoolkit/midi/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
from .parser import *
from .utils import *

__all__ = [_ for _ in dir() if not _.startswith('_')]
__all__ = [_ for _ in dir() if not _.startswith("_")]
75 changes: 37 additions & 38 deletions miditoolkit/midi/containers.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@ class Note:
Note velocity.
pitch : int
Note pitch, as a MIDI note number.
start : float
start : int
Note on time, absolute, in ticks.
end : float
end : int
Note off time, absolute, in ticks.
"""

velocity: str
velocity: int
pitch: int
start: int
end: int
Expand All @@ -37,15 +37,15 @@ class Pedal:
Parameters
----------
start : float
start : int
Time where the pedal starts.
end : float
end : int
Time where the pedal ends.
"""

start: float
end: float
start: int
end: int

@property
def duration(self):
Expand All @@ -60,13 +60,13 @@ class PitchBend:
----------
pitch : int
MIDI pitch bend amount, in the range ``[-8192, 8191]``.
time : float
time : int
Time where the pitch bend occurs.
"""

pitch: int
time: float
time: int


@dataclass
Expand All @@ -79,14 +79,14 @@ class ControlChange:
The control change number, in ``[0, 127]``.
value : int
The value of the control change, in ``[0, 127]``.
time : float
time : int
Time where the control change occurs.
"""

number: int
value: int
time: float
time: int


@dataclass
Expand All @@ -100,32 +100,28 @@ class TimeSignature:
Numerator of time signature.
denominator : int
Denominator of time signature.
time : float
time : int
Time of event in ticks.
Examples
--------
Instantiate a TimeSignature object with 6/8 time signature at 3.14 ticks:
Instantiate a TimeSignature object with 6/8 time signature at the tick 384:
>>> ts = TimeSignature(6, 8, 3.14)
>>> ts = TimeSignature(6, 8, 384)
>>> print ts
6/8 at 3.14 ticks
6/8 at the tick 384
"""

numerator: int
denominator: int
time: float
time: int

def __post_init__(self):
if self.numerator <= 0:
raise ValueError(
f"{self.numerator} is not a valid `numerator` value"
)
raise ValueError(f"{self.numerator} is not a valid `numerator` value")
if self.denominator <= 0:
raise ValueError(
f"{self.denominator} is not a valid `denominator` value"
)
raise ValueError(f"{self.denominator} is not a valid `denominator` value")
if self.time < 0:
raise ValueError(f"{self.time} is not a valid `time` value")

Expand All @@ -143,20 +139,20 @@ class KeySignature:
key_name : str
Key number according to ``[0, 11]`` Major, ``[12, 23]`` minor.
For example, 0 is C Major, 12 is C minor.
time : float
time : int
Time of event in ticks.
Examples
--------
Instantiate a C# minor KeySignature object at 3.14 ticks:
Instantiate a C# minor KeySignature object at the tick 384:
>>> ks = KeySignature("C#", 3.14)
>>> ks = KeySignature("C#", 384)
>>> print ks
C# minor at 3.14 ticks
C# minor at the tick 384
"""

key_name: str
time: float
time: int

def __post_init__(self):
if self.time < 0:
Expand All @@ -175,7 +171,7 @@ def __str__(self):
@dataclass
class Marker:
text: str
time: float
time: int

def __repr__(self):
return 'Marker(text="{}", time={})'.format(
Expand All @@ -196,12 +192,12 @@ class Lyric:
----------
text : str
The text of the lyric.
time : float
time : int
The time in ticks of the lyric.
"""

text: str
time: float
time: int

def __repr__(self):
return 'Lyric(text="{}", time={})'.format(
Expand All @@ -220,21 +216,21 @@ class TempoChange:
----------
tempo : int
Tempo value.
time : float
time : int
Time of event in ticks.
Examples
--------
Instantiate a Tempo object with BPM=120 at 3.14 ticks:
Instantiate a Tempo object with BPM=120 at the tick 384:
>>> ts = TempoChange(120, 3.14)
>>> ts = TempoChange(120, 384)
>>> print ts
6/8 at 3.14 ticks
Tempo of 120 bpm at the tick 384.
"""

tempo: Union[float, int]
time: float
time: int

def __str__(self):
return f"{self.tempo} BPM at {self.time:d} ticks"
Expand Down Expand Up @@ -288,7 +284,7 @@ def __init__(
self.control_changes = [] if control_changes is None else control_changes
self.pedals = [] if pedals is None else pedals

def remove_invalid_notes(self, verbose=True):
def remove_invalid_notes(self, verbose: bool = True):
"""Removes any notes whose end time is before or at their start time."""
# Crete a list of all invalid notes
notes_to_delete = []
Expand Down Expand Up @@ -330,14 +326,17 @@ def __eq__(self, other):
for list_attr in lists_attr:
if len(getattr(self, list_attr)) != len(getattr(other, list_attr)):
return False
if any(a1 != a2 for a1, a2 in zip(getattr(self, list_attr), getattr(other, list_attr))):
if any(
a1 != a2
for a1, a2 in zip(getattr(self, list_attr), getattr(other, list_attr))
):
return False

# All good, both tracks holds the exact same content
return True


def _key_name_to_key_number(key_string):
def _key_name_to_key_number(key_string: str):
# Create lists of possible mode names (major or minor)
major_strs = ["M", "Maj", "Major", "maj", "major"]
minor_strs = ["m", "Min", "Minor", "min", "minor"]
Expand Down
Loading

0 comments on commit 005f46e

Please sign in to comment.