11import unittest
2+ import os
3+ from typing import Dict , List
4+
25from bibtex_linter .parser import EntryType , BibTeXEntry , split_entries , parse_bibtex_file
36
7+
48class TestBibTeXEntry (unittest .TestCase ):
5- def test_parse_field_value (self ):
9+ def test_parse_field_value (self ) -> None :
610 test_cases = [
711 ("{John Doe}" , "John Doe" ),
812 ("{{John Doe}}" , "John Doe" ),
@@ -31,7 +35,7 @@ def test_parse_field_value(self):
3135 result = BibTeXEntry ._parse_field_value (raw_value )
3236 self .assertEqual (expected , result )
3337
34- def test_split_fields_basic (self ):
38+ def test_split_fields_basic (self ) -> None :
3539 entry = """@article{doe2020,
3640 author = {John Doe},
3741 title = {A Study},
@@ -45,7 +49,7 @@ def test_split_fields_basic(self):
4549 result = BibTeXEntry ._split_fields (entry )
4650 self .assertEqual (expected , result )
4751
48- def test_split_fields_with_trailing_comma_and_newline (self ):
52+ def test_split_fields_with_trailing_comma_and_newline (self ) -> None :
4953 entry = """@book{smith2021,
5054 author = {Jane Smith},
5155 title = {The Book of Testing},
@@ -59,7 +63,7 @@ def test_split_fields_with_trailing_comma_and_newline(self):
5963 result = BibTeXEntry ._split_fields (entry )
6064 self .assertEqual (expected , result )
6165
62- def test_split_fields_multiline_values (self ):
66+ def test_split_fields_multiline_values (self ) -> None :
6367 entry = """@misc{nested2022,
6468 author = {{Industrial Digital Twin Association e. V.}},
6569 url = {https://example.com},
@@ -74,12 +78,11 @@ def test_split_fields_multiline_values(self):
7478 result = BibTeXEntry ._split_fields (entry )
7579 self .assertEqual (expected , result )
7680
77- def test_split_fields_with_extra_whitespace (self ):
78- entry = """@misc{id123,
79- author = {Someone} ,
80- title= { Extra Spaces } ,
81- year= {2023}
82- }"""
81+ def test_split_fields_with_extra_whitespace (self ) -> None :
82+ entry = ("@misc{id123, \n "
83+ "author = {Someone} , \n "
84+ "title= { Extra Spaces } , \n "
85+ "year= {2023} }" )
8386 expected = [
8487 " author = {Someone} " ,
8588 " title= { Extra Spaces } " ,
@@ -88,7 +91,7 @@ def test_split_fields_with_extra_whitespace(self):
8891 result = BibTeXEntry ._split_fields (entry )
8992 self .assertEqual (expected , result )
9093
91- def test_split_fields_with_linebreak_after_entry_type (self ):
94+ def test_split_fields_with_linebreak_after_entry_type (self ) -> None :
9295 entry = """@misc
9396{
9497id456,
@@ -102,14 +105,14 @@ def test_split_fields_with_linebreak_after_entry_type(self):
102105 result = BibTeXEntry ._split_fields (entry )
103106 self .assertEqual (expected , result )
104107
105- def test_split_fields_missing_open_brace (self ):
108+ def test_split_fields_missing_open_brace (self ) -> None :
106109 entry = "article, author = {John Doe}, title = {Oops}"
107110 with self .assertRaises (KeyError ):
108111 BibTeXEntry ._split_fields (entry )
109112
110113
111114class TestSplitEntries (unittest .TestCase ):
112- def test_single_entry (self ):
115+ def test_single_entry (self ) -> None :
113116 raw = """@article{key1,
114117 author = {John Doe},
115118 title = {Example},
@@ -119,7 +122,7 @@ def test_single_entry(self):
119122 self .assertEqual (1 , len (entries ))
120123 self .assertIn ("key1" , entries [0 ])
121124
122- def test_multiple_entries (self ):
125+ def test_multiple_entries (self ) -> None :
123126 raw = """@article{key1,
124127 author = {John Doe},
125128 title = {Example 1},
@@ -136,15 +139,15 @@ def test_multiple_entries(self):
136139 self .assertIn ("key1" , entries [0 ])
137140 self .assertIn ("key2" , entries [1 ])
138141
139- def test_entry_with_nested_braces (self ):
142+ def test_entry_with_nested_braces (self ) -> None :
140143 raw = """@misc{key3,
141144 note = {Something with {nested} braces}
142145}"""
143146 entries = split_entries (raw )
144147 self .assertEqual (1 , len (entries ))
145148 self .assertIn ("nested" , entries [0 ])
146149
147- def test_entry_with_line_breaks (self ):
150+ def test_entry_with_line_breaks (self ) -> None :
148151 raw = """@online{key4,
149152 author = {Someone},
150153 title = {Line
@@ -155,7 +158,7 @@ def test_entry_with_line_breaks(self):
155158 self .assertEqual (1 , len (entries ))
156159 self .assertIn ("Line\n Break" , entries [0 ])
157160
158- def test_incomplete_entry (self ):
161+ def test_incomplete_entry (self ) -> None :
159162 raw = """@article{key5,
160163 title = {Missing closing brace}
161164"""
@@ -164,8 +167,9 @@ def test_incomplete_entry(self):
164167
165168
166169class TestParseBibtexFile (unittest .TestCase ):
167- def test_parse_all_entries (self ):
168- entries = parse_bibtex_file ("./test_refs.bib" )
170+ def test_parse_all_entries (self ) -> None :
171+ bib_path = os .path .join (os .path .dirname (__file__ ), "test_refs.bib" )
172+ entries = parse_bibtex_file (bib_path )
169173 self .assertEqual (17 , len (entries ))
170174
171175 expected_types = {
@@ -185,8 +189,8 @@ def test_parse_all_entries(self):
185189 actual_count = sum (1 for e in entries if e .entry_type == entry_type )
186190 self .assertEqual (expected_count , actual_count )
187191
188- def test_entry_fields_and_values (self ):
189- expected_entries = [
192+ def test_entry_fields_and_values (self ) -> None :
193+ expected_entries : List [ Dict [ str , EntryType | Dict [ str , str ]]] = [
190194 {
191195 "type" : EntryType .ARTICLE ,
192196 "fields" : {
@@ -309,12 +313,16 @@ def test_entry_fields_and_values(self):
309313 },
310314 ]
311315
312- parsed_entries = parse_bibtex_file ("./test_refs.bib" )
316+ bib_path = os .path .join (os .path .dirname (__file__ ), "test_refs.bib" )
317+ parsed_entries = parse_bibtex_file (bib_path )
313318
314319 for expected in expected_entries :
315320 with self .subTest (expected = expected ["fields" ]):
321+ # (2025-04-24, s-heppner)
322+ # We can safely ignore the mypy warning here, since we wrote the `expected_entries` this way just above.
323+ expected_fields : Dict [str , str ] = expected ["fields" ] # type: ignore
316324 match = next (
317- (e for e in parsed_entries if all (e .fields .get (k ) == v for k , v in expected [ "fields" ] .items ())),
325+ (e for e in parsed_entries if all (e .fields .get (k ) == v for k , v in expected_fields .items ())),
318326 None
319327 )
320328 all_field_sets = [e .fields for e in parsed_entries ]
@@ -323,7 +331,10 @@ def test_entry_fields_and_values(self):
323331 f"Missing or incorrect entry for:\n Expected Fields: { expected ['fields' ]} \n "
324332 f"Parsed Entries:\n { all_field_sets } "
325333 )
326- self .assertEqual (expected ["type" ], match .entry_type )
334+ # (2025-04-24, s-heppner)
335+ # We can safely ignore the mypy warning here, since we already asserted that `match` is not `None` in
336+ # the line above.
337+ self .assertEqual (expected ["type" ], match .entry_type ) # type: ignore
327338
328339
329340if __name__ == "__main__" :
0 commit comments