@@ -149,6 +149,62 @@ def test_chinese_word_swap_hownet():
149149 assert augmented_s or s in augmented_text_list
150150
151151
152+ def test_zip_flair_result_annotation_layer_key_independent ():
153+ # zip_flair_result used to hardcode the annotation layer's key name
154+ # ("upos"), the same failure class as #727 (which hardcoded "pos" and
155+ # broke when flair started using "upos"). The actual CI failure this was
156+ # investigating turned out to be caused by a different bug (flair_tag's
157+ # single-slot tagger cache getting poisoned by a different tag_type, see
158+ # test_pos_of_word_index_after_ner_of_word_index in test_attacked_text.py
159+ # for the real regression test), but hardcoding the annotation key name
160+ # is still fragile on its own, so keep this as a defense-in-depth check
161+ # that zip_flair_result doesn't assume one specific key name.
162+ from flair .data import Sentence
163+
164+ from textattack .shared .utils import zip_flair_result
165+
166+ sentence = Sentence ("cats run" )
167+ for token , tag in zip (sentence .tokens , ["NOUN" , "VERB" ]):
168+ token .add_label ("pos" , tag )
169+
170+ word_list , pos_list = zip_flair_result (sentence , tag_type = "upos-fast" )
171+ assert word_list == ["cats" , "run" ]
172+ assert pos_list == ["NOUN" , "VERB" ]
173+
174+
175+ def test_word_swap_inflections_pos_matching ():
176+ # Regression test for https://github.com/QData/TextAttack/issues/713 and
177+ # https://github.com/QData/TextAttack/issues/727: AttackedText.pos_of_word_index
178+ # returns flair's upos-fast tags (e.g. "NOUN", "VERB"), so
179+ # WordSwapInflections's POS-to-lemma mapping must have entries for those
180+ # tags, not just legacy fine-grained en-ptb tags (e.g. "NN", "VBD"), or it
181+ # silently returns zero candidates for ordinary words.
182+ import textattack
183+ from textattack .transformations .word_swaps import WordSwapInflections
184+
185+ transformation = WordSwapInflections ()
186+ attacked_text = textattack .shared .AttackedText ("The cats were running quickly." )
187+
188+ # Confirm the tagger is actually giving us the upos-fast tag, not a
189+ # legacy en-ptb one, so this test exercises the real mismatch and isn't
190+ # trivially passing for the wrong reason.
191+ cats_index = attacked_text .words .index ("cats" )
192+ cats_pos = attacked_text .pos_of_word_index (cats_index )
193+ assert cats_pos == "NOUN"
194+ # Before the fix, "NOUN" wasn't a key in the mapping (only "NN" was), so
195+ # this lookup missed and _get_replacement_words returned [] for every
196+ # ordinary noun.
197+ noun_candidates = transformation ._get_replacement_words ("cats" , cats_pos )
198+ assert "cat" in noun_candidates
199+
200+ were_index = attacked_text .words .index ("were" )
201+ were_pos = attacked_text .pos_of_word_index (were_index )
202+ assert were_pos == "VERB"
203+ # Same failure mode as above, for verbs ("VERB" vs. the legacy "VBD").
204+ verb_candidates = transformation ._get_replacement_words ("were" , were_pos )
205+ assert "was" in verb_candidates
206+
207+
152208def test_chinese_word_swap_masked ():
153209 from textattack .augmentation import Augmenter
154210 from textattack .transformations .word_swaps .chn_transformations import (
0 commit comments