From 6dfe6e77ab00cceb34d4ed33dfc4413675f4a711 Mon Sep 17 00:00:00 2001 From: Andrew McLeod Date: Sun, 30 Aug 2020 12:11:25 +0200 Subject: [PATCH] Updated degradations to use logging. #132 --- mdtk/degradations.py | 71 ++-- mdtk/tests/test_degradations.py | 552 ++++++++++++++------------------ 2 files changed, 270 insertions(+), 353 deletions(-) diff --git a/mdtk/degradations.py b/mdtk/degradations.py index cf306dc..d7c4432 100644 --- a/mdtk/degradations.py +++ b/mdtk/degradations.py @@ -1,6 +1,6 @@ """Code to perform the degradations i.e. edits to the midi data""" +import logging import sys -import warnings import numpy as np import pandas as pd @@ -22,7 +22,7 @@ TRIES_DEFAULT = 10 TRIES_WARN_MSG = ( - "WARNING: Generated invalid (overlapping) degraded excerpt " + "Generated invalid (overlapping) degraded excerpt " "too many times. Try raising tries parameter (default 10). " "Returning None." ) @@ -231,9 +231,7 @@ def pitch_shift( or None if the degradation cannot be performed. """ if len(excerpt) == 0: - warnings.warn( - "WARNING: No notes to pitch shift. Returning None.", category=UserWarning - ) + logging.warning("No notes to pitch shift. Returning None.") return None excerpt = pre_process(excerpt) @@ -255,8 +253,8 @@ def pitch_shift( distribution[zero_idx] = 0 if np.sum(distribution) == 0: - warnings.warn( - "WARNING: distribution contains only 0s after " + logging.warning( + "distribution contains only 0s after " "setting distribution[zero_idx] value to 0. " "Returning None." ) @@ -278,8 +276,8 @@ def pitch_shift( ].tolist() if not valid_notes: - warnings.warn( - "WARNING: No valid pitches to shift given " + logging.warning( + "No valid pitches to shift given " f"min_pitch {min_pitch}, max_pitch {max_pitch}, " f"and distribution {distribution} (after setting " "distribution[zero_idx] to 0). Returning None." @@ -312,7 +310,7 @@ def pitch_shift( # Check if overlaps if overlaps(degraded, note_index) or degraded.loc[note_index, "pitch"] == pitch: if tries == 1: - warnings.warn(TRIES_WARN_MSG) + logging.warning(TRIES_WARN_MSG) return None return pitch_shift( excerpt, @@ -415,10 +413,7 @@ def time_shift( valid_notes = list(valid.index[valid]) if not valid_notes: - warnings.warn( - "WARNING: No valid notes to time shift. Returning " "None.", - category=UserWarning, - ) + logging.warning("No valid notes to time shift. Returning None.") return None # Sample a random note @@ -443,7 +438,7 @@ def time_shift( # Check if overlaps if overlaps(degraded, index): if tries == 1: - warnings.warn(TRIES_WARN_MSG) + logging.warning(TRIES_WARN_MSG) return None return time_shift( excerpt, @@ -600,10 +595,7 @@ def onset_shift( valid_notes = list(valid.index[valid]) if not valid_notes: - warnings.warn( - "WARNING: No valid notes to onset shift. Returning " "None.", - category=UserWarning, - ) + logging.warning("No valid notes to onset shift. Returning None.") return None # Sample a random note @@ -645,7 +637,7 @@ def onset_shift( # Check if overlaps if overlaps(degraded, index): if tries == 1: - warnings.warn(TRIES_WARN_MSG) + logging.warning(TRIES_WARN_MSG) return None return onset_shift( excerpt, @@ -765,10 +757,7 @@ def offset_shift( valid_notes = list(valid.index[valid]) if not valid_notes: - warnings.warn( - "WARNING: No valid notes to offset shift. Returning " "None.", - category=UserWarning, - ) + logging.warning("No valid notes to offset shift. Returning None.") return None # Sample a random note @@ -794,7 +783,7 @@ def offset_shift( # Check if overlaps if overlaps(degraded, index): if tries == 1: - warnings.warn(TRIES_WARN_MSG) + logging.warning(TRIES_WARN_MSG) return None return offset_shift( excerpt, @@ -836,9 +825,7 @@ def remove_note(excerpt, tries=TRIES_DEFAULT): the degradations cannot be performed. """ if excerpt.shape[0] == 0: - warnings.warn( - "WARNING: No notes to remove. Returning None.", category=UserWarning - ) + logging.warning("No notes to remove. Returning None.") return None degraded = pre_process(excerpt) @@ -929,10 +916,7 @@ def add_note( pitch = excerpt["pitch"].between(min_pitch, max_pitch, inclusive=True) pitch = excerpt["pitch"][pitch].unique() if len(pitch) == 0: - warnings.warn( - "WARNING: No valid aligned pitch in given " "range.", - category=UserWarning, - ) + logging.warning("No valid aligned pitch in given range.") return None pitch = choice(pitch) else: @@ -941,10 +925,7 @@ def add_note( # Find onset and duration if align_time: if min_duration > excerpt["dur"].max() or max_duration < excerpt["dur"].min(): - warnings.warn( - "WARNING: No valid aligned duration in " "given range.", - category=UserWarning, - ) + logging.warning("No valid aligned duration in given range.") return None durations = excerpt["dur"].between(min_duration, max_duration, inclusive=True) @@ -983,7 +964,7 @@ def add_note( # Check if overlaps if overlaps(degraded, degraded.index[-1]): if tries == 1: - warnings.warn(TRIES_WARN_MSG) + logging.warning(TRIES_WARN_MSG) return None return add_note( excerpt, @@ -1036,9 +1017,7 @@ def split_note( the degradation cannot be performed. """ if excerpt.shape[0] == 0: - warnings.warn( - "WARNING: No notes to split. Returning None.", category=UserWarning - ) + logging.warning("No notes to split. Returning None.") return None excerpt = pre_process(excerpt) @@ -1048,9 +1027,7 @@ def split_note( valid_notes = list(long_enough.index[long_enough]) if not valid_notes: - warnings.warn( - "WARNING: No valid notes to split. Returning " "None.", category=UserWarning - ) + logging.warning("No valid notes to split. Returning None.") return None note_index = choice(valid_notes) @@ -1132,9 +1109,7 @@ def join_notes( the degradation cannot be performed. """ if excerpt.shape[0] < 2: - warnings.warn( - "WARNING: No notes to join. Returning None.", category=UserWarning - ) + logging.warning("No notes to join. Returning None.") return None excerpt = pre_process(excerpt, sort=True) @@ -1175,9 +1150,7 @@ def join_notes( valid_starts.extend(valid_starts_this) if not valid_starts: - warnings.warn( - "WARNING: No valid notes to join. Returning " "None.", category=UserWarning - ) + logging.warning("No valid notes to join. Returning None.") return None index = randint(len(valid_starts)) diff --git a/mdtk/tests/test_degradations.py b/mdtk/tests/test_degradations.py index 0043d3b..52f5ec0 100644 --- a/mdtk/tests/test_degradations.py +++ b/mdtk/tests/test_degradations.py @@ -1,5 +1,4 @@ import itertools -import re import numpy as np import pandas as pd @@ -36,6 +35,13 @@ def assert_none(res, msg=""): assert res is None, f"{msg}\nExpected None, but got:\n{res}" +def assert_warned(caplog, msg=None): + assert caplog.records[-1].levelname == "WARNING", "Warning not logged." + if msg: + assert msg in caplog.text, "Warning message incorrect." + caplog.clear() + + def test_pre_process(): basic_res = pd.DataFrame( { @@ -172,29 +178,25 @@ def test_overlaps(): ), f"Overlaps incorrectly returned False for:\n{fixed_basic}." -def test_unsorted(): +def test_unsorted(caplog): global BASIC_DF BASIC_DF = UNSORTED_DF - test_pitch_shift() - test_time_shift() - test_onset_shift() - test_offset_shift() - test_remove_note() - test_add_note() - test_split_note() + test_pitch_shift(caplog) + test_time_shift(caplog) + test_onset_shift(caplog) + test_offset_shift(caplog) + test_remove_note(caplog) + test_add_note(caplog) + test_split_note(caplog) BASIC_DF = BASIC_DF_FINAL -def test_pitch_shift(): - with pytest.warns( - UserWarning, - match=re.escape("WARNING: No notes to pitch" " shift. Returning None."), - ): - assert ( - deg.pitch_shift(EMPTY_DF) is None - ), "Pitch shifting with empty data frame did not return None." +def test_pitch_shift(caplog): + res = deg.pitch_shift(EMPTY_DF) + assert_none(res, msg="Pitch shifting with empty data frame did not return None.") + assert_warned(caplog) if BASIC_DF.equals(BASIC_DF_FINAL): # Deterministic testing @@ -219,9 +221,9 @@ def test_pitch_shift(): # Test if tries works df = pd.DataFrame({"onset": [0], "pitch": [10], "track": [0], "dur": [100]}) - with pytest.warns(UserWarning, match=re.escape(deg.TRIES_WARN_MSG)): - res = deg.pitch_shift(df, min_pitch=10, max_pitch=10) - assert_none(res, msg="Pitch shift should run out of tries.") + res = deg.pitch_shift(df, min_pitch=10, max_pitch=10) + assert_none(res, msg="Pitch shift should run out of tries.") + assert_warned(caplog, msg=deg.TRIES_WARN_MSG) # Truly random testing for i in range(10): @@ -275,27 +277,20 @@ def test_pitch_shift(): ) # Check for distribution warnings - with pytest.warns( - UserWarning, - match=re.escape( - "WARNING: distribution contains only 0s after " - "setting distribution[zero_idx] value to 0. " - "Returning None." - ), - ): - res = deg.pitch_shift(BASIC_DF, distribution=[0, 1, 0]) - assert res is None, "Pitch shifting with distribution of 0s returned something." + res = deg.pitch_shift(BASIC_DF, distribution=[0, 1, 0]) + assert_none(res, msg="Pitch shifting with distribution of 0s returned something.") + assert_warned( + caplog, + msg="distribution contains only 0s after " + "setting distribution[zero_idx] value to 0. " + "Returning None.", + ) - with pytest.warns( - UserWarning, - match=re.escape("WARNING: No valid pitches " "to shift given min_pitch"), - ): - res = deg.pitch_shift( - BASIC_DF, min_pitch=-50, max_pitch=-20, distribution=[1, 0, 1] - ) - assert ( - res is None - ), "Pitch shifting with invalid distribution returned something." + res = deg.pitch_shift( + BASIC_DF, min_pitch=-50, max_pitch=-20, distribution=[1, 0, 1] + ) + assert_none(res, msg="Pitch shifting with invalid distribution returned something.") + assert_warned(caplog, msg="No valid pitches to shift given min_pitch") res = deg.pitch_shift( BASIC_DF, @@ -305,17 +300,14 @@ def test_pitch_shift(): ) assert res is not None, "Valid shift down of 1 pitch returned None." - with pytest.warns( - UserWarning, - match=re.escape("WARNING: No valid pitches to shift " "given min_pitch"), - ): - res = deg.pitch_shift( - BASIC_DF, - min_pitch=BASIC_DF["pitch"].min() - 2, - max_pitch=BASIC_DF["pitch"].min() - 2, - distribution=[1, 0, 0], - ) - assert res is None, "Invalid shift down of 2 pitch returned something." + res = deg.pitch_shift( + BASIC_DF, + min_pitch=BASIC_DF["pitch"].min() - 2, + max_pitch=BASIC_DF["pitch"].min() - 2, + distribution=[1, 0, 0], + ) + assert_none(res, msg="Invalid shift down of 2 pitch returned something.") + assert_warned(caplog, msg="No valid pitches to shift given min_pitch") res = deg.pitch_shift( BASIC_DF, @@ -325,27 +317,22 @@ def test_pitch_shift(): ) assert res is not None, "Valid shift up of 1 pitch returned None." - with pytest.warns( - UserWarning, - match=re.escape("WARNING: No valid pitches to shift " "given min_pitch"), - ): - res = deg.pitch_shift( - BASIC_DF, - min_pitch=BASIC_DF["pitch"].max() + 2, - max_pitch=BASIC_DF["pitch"].max() + 2, - distribution=[0, 0, 1], - ) - assert res is None, "Invalid shift up of 2 pitch returned something." + res = deg.pitch_shift( + BASIC_DF, + min_pitch=BASIC_DF["pitch"].max() + 2, + max_pitch=BASIC_DF["pitch"].max() + 2, + distribution=[0, 0, 1], + ) + assert_none(res, msg="Invalid shift up of 2 pitch returned something.") + assert_warned(caplog, msg="No valid pitches to shift given min_pitch") -def test_time_shift(): - with pytest.warns( - UserWarning, - match=re.escape("WARNING: No valid notes to time " "shift. Returning None."), - ): - assert deg.time_shift(EMPTY_DF) is None, ( - "Time shifting with empty data " "frame did not return None." - ) +def test_time_shift(caplog): + assert_none( + deg.time_shift(EMPTY_DF), + msg="Time shifting with empty data frame did not return None.", + ) + assert_warned(caplog, "No valid notes to time shift. Returning None.") if BASIC_DF.equals(BASIC_DF_FINAL): # Deterministic testing @@ -436,23 +423,21 @@ def test_time_shift(): min_shift <= shift <= max_shift ), f"Shift {shift} outside of range [{min_shift}, {max_shift}]." else: - with pytest.warns(UserWarning, match=re.escape("WARNING:")): - res = deg.time_shift( - BASIC_DF, min_shift=min_shift, max_shift=max_shift, align_onset=True - ) + res = deg.time_shift( + BASIC_DF, min_shift=min_shift, max_shift=max_shift, align_onset=True + ) + assert_warned(caplog) # Check for range too large warning - with pytest.warns( - UserWarning, match=re.escape("WARNING: No valid notes to " "time shift.") - ): - res = deg.time_shift(BASIC_DF, min_shift=201, max_shift=202) - assert res is None, "Invalid time shift of 201 returned something." + res = deg.time_shift(BASIC_DF, min_shift=201, max_shift=202) + assert_none(res, msg="Invalid time shift of 201 returned something.") + assert_warned(caplog, msg="No valid notes to time shift.") res = deg.time_shift(BASIC_DF, min_shift=200, max_shift=201) assert res is not None, "Valid time shift of 200 returned None." -def test_onset_shift(): +def test_onset_shift(caplog): def check_onset_shift_result( df, res, min_shift, max_shift, min_duration, max_duration ): @@ -492,15 +477,11 @@ def check_onset_shift_result( changed_note.loc[0]["onset"] >= 0 ), "Changed note given negative onset time." - with pytest.warns( - UserWarning, - match=re.escape( - "WARNING: No valid notes to" " onset shift. Returning " "None." - ), - ): - assert ( - deg.onset_shift(EMPTY_DF) is None - ), "Onset shifting with empty data frame did not return None." + assert_none( + deg.onset_shift(EMPTY_DF), + msg="Onset shifting with empty data frame did not return None.", + ) + assert_warned(caplog, msg="No valid notes to onset shift. Returning None.") if BASIC_DF.equals(BASIC_DF_FINAL): # Deterministic testing @@ -548,22 +529,17 @@ def check_onset_shift_result( min_duration = 0 max_duration = 100 - max_shift - 1 - with pytest.warns( - UserWarning, - match=re.escape( - "WARNING: No valid notes to" " onset shift. Returning " "None." - ), - ): - res = deg.onset_shift( - BASIC_DF, - min_shift=min_shift, - max_shift=max_shift, - min_duration=min_duration, - max_duration=max_duration, - ) - assert ( - res is None - ), "Onset shift with max_duration too short didn't return None." + res = deg.onset_shift( + BASIC_DF, + min_shift=min_shift, + max_shift=max_shift, + min_duration=min_duration, + max_duration=max_duration, + ) + assert_none( + res, msg="Onset shift with max_duration too short didn't return None." + ) + assert_warned(caplog, msg="No valid notes to onset shift. Returning None.") # Duration is barely short enough min_duration = 0 @@ -583,22 +559,17 @@ def check_onset_shift_result( min_duration = 100 + max_shift + 1 max_duration = np.inf - with pytest.warns( - UserWarning, - match=re.escape( - "WARNING: No valid notes to" " onset shift. Returning " "None." - ), - ): - res = deg.onset_shift( - BASIC_DF, - min_shift=min_shift, - max_shift=max_shift, - min_duration=min_duration, - max_duration=max_duration, - ) - assert ( - res is None - ), "Onset shift with min_duration too long didn't return None." + res = deg.onset_shift( + BASIC_DF, + min_shift=min_shift, + max_shift=max_shift, + min_duration=min_duration, + max_duration=max_duration, + ) + assert_none( + res, msg="Onset shift with min_duration too long didn't return None." + ) + assert_warned(caplog, msg="No valid notes to onset shift. Returning None.") # Duration is barely short enough min_duration = 100 + max_shift @@ -661,18 +632,18 @@ def check_onset_shift_result( and res["dur"].isin([50, 100, 150]).all() ), "Onset with align_dur didn't align duration." - with pytest.warns(UserWarning, match=re.escape("WARNING:")): - res = deg.onset_shift(align_df, align_dur=True, min_shift=101) - assert_none(res) - with pytest.warns(UserWarning, match=re.escape("WARNING:")): - res = deg.onset_shift(align_df, align_dur=True, max_shift=49) - assert_none(res) - with pytest.warns(UserWarning, match=re.escape("WARNING:")): - res = deg.onset_shift(align_df, align_dur=True, min_duration=151) - assert_none(res) - with pytest.warns(UserWarning, match=re.escape("WARNING:")): - res = deg.onset_shift(align_df, align_dur=True, max_duration=49) - assert_none(res) + res = deg.onset_shift(align_df, align_dur=True, min_shift=101) + assert_none(res) + assert_warned(caplog) + res = deg.onset_shift(align_df, align_dur=True, max_shift=49) + assert_none(res) + assert_warned(caplog) + res = deg.onset_shift(align_df, align_dur=True, min_duration=151) + assert_none(res) + assert_warned(caplog) + res = deg.onset_shift(align_df, align_dur=True, max_duration=49) + assert_none(res) + assert_warned(caplog) # Test with align_onset res = deg.onset_shift(align_df, align_onset=True) @@ -683,18 +654,18 @@ def check_onset_shift_result( and len(set(res["onset"])) == 4 ), "Onset with align_onset didn't align onset." - with pytest.warns(UserWarning, match=re.escape("WARNING:")): - res = deg.onset_shift(align_df, align_dur=True, min_shift=201) - assert_none(res) - with pytest.warns(UserWarning, match=re.escape("WARNING:")): - res = deg.onset_shift(align_df, align_dur=True, max_shift=49) - assert_none(res) - with pytest.warns(UserWarning, match=re.escape("WARNING:")): - res = deg.onset_shift(align_df, align_dur=True, min_duration=301) - assert_none(res) - with pytest.warns(UserWarning, match=re.escape("WARNING:")): - res = deg.onset_shift(align_df, align_dur=True, max_duration=49) - assert_none(res) + res = deg.onset_shift(align_df, align_dur=True, min_shift=201) + assert_none(res) + assert_warned(caplog) + res = deg.onset_shift(align_df, align_dur=True, max_shift=49) + assert_none(res) + assert_warned(caplog) + res = deg.onset_shift(align_df, align_dur=True, min_duration=301) + assert_none(res) + assert_warned(caplog) + res = deg.onset_shift(align_df, align_dur=True, max_duration=49) + assert_none(res) + assert_warned(caplog) # Test with align both res = deg.onset_shift(align_df, align_onset=True, align_dur=True) @@ -710,33 +681,29 @@ def check_onset_shift_result( and len(set(res["onset"])) == 4 ), "Onset with align_dur and align_onset didn't align onset." - with pytest.warns(UserWarning, match=re.escape("WARNING:")): - res = deg.onset_shift(align_df, align_dur=True, min_shift=101) - assert_none(res) - with pytest.warns(UserWarning, match=re.escape("WARNING:")): - res = deg.onset_shift(align_df, align_dur=True, max_shift=49) - assert_none(res) - with pytest.warns(UserWarning, match=re.escape("WARNING:")): - res = deg.onset_shift(align_df, align_dur=True, min_duration=151) - assert_none(res) - with pytest.warns(UserWarning, match=re.escape("WARNING:")): - res = deg.onset_shift(align_df, align_dur=True, max_duration=49) - assert_none(res) - - with pytest.warns( - UserWarning, - match=re.escape( - "WARNING: No valid notes to" " onset shift. Returning " "None." - ), - ): - res = deg.onset_shift(BASIC_DF, min_shift=300) - assert res is None, ( - "Onset shifting with empty data min_shift greater than " - "possible additional duration did not return None." - ) + res = deg.onset_shift(align_df, align_dur=True, min_shift=101) + assert_none(res) + assert_warned(caplog) + res = deg.onset_shift(align_df, align_dur=True, max_shift=49) + assert_none(res) + assert_warned(caplog) + res = deg.onset_shift(align_df, align_dur=True, min_duration=151) + assert_none(res) + assert_warned(caplog) + res = deg.onset_shift(align_df, align_dur=True, max_duration=49) + assert_none(res) + assert_warned(caplog) + + res = deg.onset_shift(BASIC_DF, min_shift=300) + assert_none( + res, + msg="Onset shifting with empty data min_shift greater than " + "possible additional duration did not return None.", + ) + assert_warned(caplog, msg="No valid notes to onset shift. Returning None.") -def test_offset_shift(): +def test_offset_shift(caplog): def check_offset_shift_result( df, res, min_shift, max_shift, min_duration, max_duration ): @@ -776,15 +743,11 @@ def check_offset_shift_result( <= df[["onset", "dur"]].sum(axis=1).max() ), "Changed note offset shifted past previous last offset." - with pytest.warns( - UserWarning, - match=re.escape( - "WARNING: No valid notes to" " offset shift. Returning " "None." - ), - ): - assert ( - deg.offset_shift(EMPTY_DF) is None - ), "Offset shifting with empty data frame did not return None." + assert_none( + deg.offset_shift(EMPTY_DF), + msg="Offset shifting with empty data frame did not return None.", + ) + assert_warned(caplog, msg="No valid notes to offset shift. Returning None.") if BASIC_DF.equals(BASIC_DF_FINAL): # Deterministic testing @@ -805,12 +768,15 @@ def check_offset_shift_result( ) assert not BASIC_DF.equals(res), "Note_df was not copied." - with pytest.warns(UserWarning, match=re.escape("WARNING:")): - res = deg.offset_shift(BASIC_DF, seed=1, align_dur=True) - assert res is None, ( - "Offset shift with align_dur doesn't " - "fail on excerpt with only 1 duration." - ) + res = deg.offset_shift(BASIC_DF, seed=1, align_dur=True) + assert_none( + res, + msg=( + "Offset shift with align_dur doesn't fail on excerpt with " + "only 1 duration." + ), + ) + assert_warned(caplog) # Random testing for i in range(10): @@ -837,22 +803,17 @@ def check_offset_shift_result( min_duration = 0 max_duration = 100 - max_shift - 1 - with pytest.warns( - UserWarning, - match=re.escape( - "WARNING: No valid notes to" " offset shift. Returning " "None." - ), - ): - res = deg.offset_shift( - BASIC_DF, - min_shift=min_shift, - max_shift=max_shift, - min_duration=min_duration, - max_duration=max_duration, - ) - assert ( - res is None - ), "Offset shift with max_duration too short didn't return None." + res = deg.offset_shift( + BASIC_DF, + min_shift=min_shift, + max_shift=max_shift, + min_duration=min_duration, + max_duration=max_duration, + ) + assert_none( + res, msg="Offset shift with max_duration too short didn't return None." + ) + assert_warned(caplog, msg="No valid notes to offset shift. Returning None.") # Duration is barely short enough min_duration = 0 @@ -872,22 +833,17 @@ def check_offset_shift_result( min_duration = 100 + max_shift + 1 max_duration = np.inf - with pytest.warns( - UserWarning, - match=re.escape( - "WARNING: No valid notes to" " offset shift. Returning " "None." - ), - ): - res = deg.offset_shift( - BASIC_DF, - min_shift=min_shift, - max_shift=max_shift, - min_duration=min_duration, - max_duration=max_duration, - ) - assert ( - res is None - ), "Offset shift with min_duration too long didn't return None." + res = deg.offset_shift( + BASIC_DF, + min_shift=min_shift, + max_shift=max_shift, + min_duration=min_duration, + max_duration=max_duration, + ) + assert_none( + res, msg="Offset shift with min_duration too long didn't return None." + ) + assert_warned(caplog, msg="No valid notes to offset shift. Returning None.") # Duration is barely short enough min_duration = 100 + max_shift @@ -953,33 +909,33 @@ def check_offset_shift_result( ), "Offset shift with align_dur doesn't properly align duration." else: - with pytest.warns(UserWarning, match=re.escape("WARNING:")): - res = deg.offset_shift(BASIC_DF, min_shift=300) - assert res is None, ( - "Offset shifting with align_dur but all durs outside " - "valid range returns something." - ) - - with pytest.warns( - UserWarning, - match=re.escape( - "WARNING: No valid notes to" " offset shift. Returning " "None." + res = deg.offset_shift(BASIC_DF, min_shift=300) + assert_none( + res, + msg=( + "Offset shifting with align_dur but all durs outside valid " + "range returns something." + ), + ) + assert_warned(caplog) + + res = deg.offset_shift(BASIC_DF, min_shift=300) + assert_none( + res, + msg=( + "Offset shifting with empty data min_shift greater than possible " + "additional note duration did not return None." ), - ): - res = deg.offset_shift(BASIC_DF, min_shift=300) - assert res is None, ( - "Offset shifting with empty data min_shift greater than " - "possible additional note duration did not return None." - ) + ) + assert_warned(caplog, msg="No valid notes to offset shift. Returning None.") -def test_remove_note(): - with pytest.warns( - UserWarning, match=re.escape("WARNING: No notes to " "remove. Returning None.") - ): - assert ( - deg.remove_note(EMPTY_DF) is None - ), "Remove note with empty data frame did not return None." +def test_remove_note(caplog): + assert_none( + deg.remove_note(EMPTY_DF), + msg="Remove note with empty data frame did not return None.", + ) + assert_warned(caplog, "No notes to remove. Returning None.") if BASIC_DF.equals(BASIC_DF_FINAL): # Deterministic testing @@ -1014,7 +970,7 @@ def test_remove_note(): ), "Remove note did not remove exactly 1 note." -def test_add_note(): +def test_add_note(caplog): assert ( deg.add_note(EMPTY_DF) is not None ), "Add note to empty data frame returned None." @@ -1057,9 +1013,9 @@ def test_add_note(): ) diff = pd.concat([res, BASIC_DF]).drop_duplicates(keep=False) - assert diff.shape[0] == 1, ( - "Adding a note changed an existing note, or added note is a " "duplicate." - ) + assert ( + diff.shape[0] == 1 + ), "Adding a note changed an existing note, or added note is a duplicate." assert res.shape[0] == BASIC_DF.shape[0] + 1, "No note was added." note = diff.iloc[0] @@ -1087,16 +1043,16 @@ def test_add_note(): or min_duration > BASIC_DF["dur"].max() or max_duration < BASIC_DF["dur"].min() ): - with pytest.warns(UserWarning, match=re.escape("WARNING:")): - res = deg.add_note( - BASIC_DF, - min_pitch=min_pitch, - max_pitch=max_pitch, - min_duration=min_duration, - max_duration=max_duration, - align_pitch=True, - align_time=True, - ) + res = deg.add_note( + BASIC_DF, + min_pitch=min_pitch, + max_pitch=max_pitch, + min_duration=min_duration, + max_duration=max_duration, + align_pitch=True, + align_time=True, + ) + assert_warned(caplog) continue res = deg.add_note( @@ -1137,13 +1093,12 @@ def test_add_note(): ) -def test_split_note(): - with pytest.warns( - UserWarning, match=re.escape("WARNING: No notes to " "split. Returning None.") - ): - assert ( - deg.split_note(EMPTY_DF) is None - ), "Split note with empty data frame did not return None." +def test_split_note(caplog): + assert_none( + deg.split_note(EMPTY_DF), + msg="Split note with empty data frame did not return None.", + ) + assert_warned(caplog, msg="No notes to split. Returning None.") if BASIC_DF.equals(BASIC_DF_FINAL): # Deterministic testing @@ -1227,30 +1182,25 @@ def test_split_note(): ), "Duration changed when splitting." # Test min_duration too large for num_splits - with pytest.warns( - UserWarning, - match=re.escape("WARNING: No valid notes to" " split. Returning None."), - ): - assert ( - deg.split_note(BASIC_DF, min_duration=10, num_splits=10) is None - ), "Splitting note into too many pieces didn't return None." + assert_none( + deg.split_note(BASIC_DF, min_duration=10, num_splits=10), + msg="Splitting note into too many pieces didn't return None.", + ) + assert_warned(caplog, msg="No valid notes to split. Returning None.") -def test_join_notes(): - with pytest.warns( - UserWarning, match=re.escape("WARNING: No notes to " "join. Returning None.") - ): - assert ( - deg.join_notes(EMPTY_DF) is None - ), "Join notes with empty data frame did not return None." +def test_join_notes(caplog): + assert_none( + deg.join_notes(EMPTY_DF), + msg="Join notes with empty data frame did not return None.", + ) + assert_warned(caplog, msg="No notes to join. Returning None.") - with pytest.warns( - UserWarning, - match=re.escape("WARNING: No valid notes to" " join. Returning None."), - ): - assert ( - deg.join_notes(BASIC_DF) is None - ), "Joining notes with none back-to-back didn't return None." + assert_none( + deg.join_notes(BASIC_DF), + msg="Joining notes with none back-to-back didn't return None.", + ) + assert_warned(caplog, msg="No valid notes to join. Returning None.") # Create a garbled df with indices: [0, 2, 2, 4] join_df = pd.DataFrame( @@ -1297,23 +1247,19 @@ def test_join_notes(): # Check different pitch and track join_df.iloc[1]["pitch"] = 20 - with pytest.warns( - UserWarning, - match=re.escape("WARNING: No valid notes to" " join. Returning None."), - ): - assert ( - deg.join_notes(join_df) is None - ), "Joining notes with different pitches didn't return None." + assert_none( + deg.join_notes(join_df), + msg="Joining notes with different pitches didn't return None.", + ) + assert_warned(caplog, msg="No valid notes to join. Returning None.") join_df.iloc[1]["pitch"] = 10 join_df.iloc[1]["track"] = 1 - with pytest.warns( - UserWarning, - match=re.escape("WARNING: No valid notes to" " join. Returning None."), - ): - assert ( - deg.join_notes(join_df) is None - ), "Joining notes with different tracks didn't return None." + assert_none( + deg.join_notes(join_df), + msg="Joining notes with different tracks didn't return None.", + ) + assert_warned(caplog, msg="No valid notes to join. Returning None.") # Test real example which erred (because it had multiple possible notes) excerpt = pd.DataFrame( @@ -1543,10 +1489,8 @@ def test_join_notes(): join_df.iloc[1]["dur"] -= 1 # Gap too large - with pytest.warns( - UserWarning, - match=re.escape("WARNING: No valid notes to" " join. Returning None."), - ): - assert ( - deg.join_notes(join_df, max_gap=max_gap) is None - ), "Joining notes with too large of a gap didn't return None." + assert_none( + deg.join_notes(join_df, max_gap=max_gap), + msg="Joining notes with too large of a gap didn't return None.", + ) + assert_warned(caplog, msg="No valid notes to join. Returning None.")