From fd1bc024c117843e18a21f93a4b65010b5fef14e Mon Sep 17 00:00:00 2001 From: David Nicholson Date: Thu, 8 Oct 2026 22:17:08 -0400 Subject: [PATCH 1/2] ENH: Make Raven format work for BirdNet output, fix #301 Tell `pandera` to `coerce` the "Low Freq (Hz)" and "High Freq (Hz)" columns to float, instead of raising a SchemaError because those columns are int values. See linked issue for detail. --- src/crowsetta/formats/bbox/raven.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/crowsetta/formats/bbox/raven.py b/src/crowsetta/formats/bbox/raven.py index 7e28fc9..346c367 100644 --- a/src/crowsetta/formats/bbox/raven.py +++ b/src/crowsetta/formats/bbox/raven.py @@ -25,8 +25,8 @@ class RavenSchema(pandera.pandas.DataFrameModel): begin_time_s: Series[float] = pandera.pandas.Field() end_time_s: Series[float] = pandera.pandas.Field() - low_freq_hz: Series[float] = pandera.pandas.Field() - high_freq_hz: Series[float] = pandera.pandas.Field() + low_freq_hz: Series[float] = pandera.pandas.Field(coerce=True) + high_freq_hz: Series[float] = pandera.pandas.Field(coerce=True) annotation: Series[pd.StringDtype] = pandera.pandas.Field(coerce=True) class Config: From af7f7d475c632ea0bde248c52dd50dbbcb887ca3 Mon Sep 17 00:00:00 2001 From: David Nicholson Date: Fri, 9 Oct 2026 08:59:54 -0400 Subject: [PATCH 2/2] TST: Use pandera `SchemaErrors` (plural) to fix failures We're getting a bunch of spurious failures because `pandera` added a `errors.SchemaErrors` plural for the case where multiple rules of a schema fail. This is yet another time where it feels like `pandera` is more trouble than it's worth. What we want is a nice error message explaining something is wrong with the annotation file. What we get is a wall of text that will mean nothing to most users. --- tests/test_formats/test_bbox/test_audbbox.py | 2 +- tests/test_formats/test_seq/test_audseq.py | 2 +- tests/test_formats/test_seq/test_generic.py | 4 ++-- tests/test_formats/test_seq/test_simple.py | 2 +- tests/test_formats/test_seq/test_timit.py | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/test_formats/test_bbox/test_audbbox.py b/tests/test_formats/test_bbox/test_audbbox.py index a9a2ef9..33675dd 100644 --- a/tests/test_formats/test_bbox/test_audbbox.py +++ b/tests/test_formats/test_bbox/test_audbbox.py @@ -53,7 +53,7 @@ def test_raven_schema_bad_df(self, an_audbbox_path): # if we just load the csv directly, it will be invalid df = pd.read_csv(an_audbbox_path, sep="\t", header=None) - with pytest.raises(pandera.errors.SchemaError): + with pytest.raises(pandera.errors.SchemaErrors): crowsetta.formats.bbox.audbbox.AudBBoxSchema.validate(df) diff --git a/tests/test_formats/test_seq/test_audseq.py b/tests/test_formats/test_seq/test_audseq.py index d0d23da..1ee5daf 100644 --- a/tests/test_formats/test_seq/test_audseq.py +++ b/tests/test_formats/test_seq/test_audseq.py @@ -22,7 +22,7 @@ def test_audseq_schema_bad_df(self, an_audseq_path): audseq_df = pd.read_csv(an_audseq_path, sep="\t", header=None) # notice: wrong column name 'stop_time' audseq_df.columns = ["start_time", "stop_time", "label"] - with pytest.raises(pandera.errors.SchemaError): + with pytest.raises(pandera.errors.SchemaErrors): crowsetta.formats.seq.audseq.AudSeqSchema.validate(audseq_df) diff --git a/tests/test_formats/test_seq/test_generic.py b/tests/test_formats/test_seq/test_generic.py index d1fc70d..2b29641 100644 --- a/tests/test_formats/test_seq/test_generic.py +++ b/tests/test_formats/test_seq/test_generic.py @@ -62,7 +62,7 @@ def test_missing_column_raises(self, csv_missing_fields_in_header): def test_invalid_column_raises(self, csv_with_invalid_fields_in_header): """test that invalid column name 'invalid' raises a schema error""" invalid_df = pd.read_csv(csv_with_invalid_fields_in_header) - with pytest.raises(pandera.errors.SchemaError): + with pytest.raises(pandera.errors.SchemaErrors): crowsetta.formats.seq.generic.GenericSeqSchema.validate(invalid_df) def test_onset_s_with_no_offset_s_raises(self, csv_with_onset_s_but_no_offset_s): @@ -378,7 +378,7 @@ def test_csv2annot_missing_fields_raises(self, csv_missing_fields_in_header): crowsetta.formats.seq.generic.csv2annot(csv_path=csv_missing_fields_in_header) def test_csv2annot_invalid_fields_raises(self, csv_with_invalid_fields_in_header): - with pytest.raises(pandera.errors.SchemaError): + with pytest.raises(pandera.errors.SchemaErrors): crowsetta.formats.seq.generic.csv2annot(csv_path=csv_with_invalid_fields_in_header) diff --git a/tests/test_formats/test_seq/test_simple.py b/tests/test_formats/test_seq/test_simple.py index 2533b8a..6c5ddc2 100644 --- a/tests/test_formats/test_seq/test_simple.py +++ b/tests/test_formats/test_seq/test_simple.py @@ -22,7 +22,7 @@ def test_simple_seq_schema_bad_df(self, a_simple_csv_path): simple_df = pd.read_csv(a_simple_csv_path) # notice: wrong column names simple_df.columns = ["text", "begin_sample", "end_sample"] - with pytest.raises(pandera.errors.SchemaError): + with pytest.raises(pandera.errors.SchemaErrors): simple_df = crowsetta.formats.seq.simple.SimpleSeqSchema.validate(simple_df) diff --git a/tests/test_formats/test_seq/test_timit.py b/tests/test_formats/test_seq/test_timit.py index bcc833b..cc8602f 100644 --- a/tests/test_formats/test_seq/test_timit.py +++ b/tests/test_formats/test_seq/test_timit.py @@ -19,7 +19,7 @@ def test_timit_schema_bad_df(self, a_transcript_path): phn_df = pd.read_csv(a_transcript_path, sep=" ", header=None) # notice: wrong column names phn_df.columns = ["text", "begin_sample", "end_sample"] - with pytest.raises(pandera.errors.SchemaError): + with pytest.raises(pandera.errors.SchemaErrors): phn_df = crowsetta.formats.seq.timit.TimitTranscriptSchema.validate(phn_df)