From 863d6ba2644b02176ef939b697e66c94568f4424 Mon Sep 17 00:00:00 2001 From: Michael Weiss Date: Fri, 24 Nov 2023 07:25:36 +0100 Subject: [PATCH] :sparkles: Optionally raise an exception when adding duplicate blocks --- bibtexparser/library.py | 20 +++++++++++++++++++- tests/test_library.py | 9 +++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/bibtexparser/library.py b/bibtexparser/library.py index db01748..2f6a425 100644 --- a/bibtexparser/library.py +++ b/bibtexparser/library.py @@ -24,7 +24,9 @@ def __init__(self, blocks: Union[List[Block], None] = None): if blocks is not None: self.add(blocks) - def add(self, blocks: Union[List[Block], Block]): + def add( + self, blocks: Union[List[Block], Block], fail_on_duplicate_key: bool = False + ): """Add blocks to library. The adding is key-safe, i.e., it is made sure that no duplicate keys are added. @@ -32,14 +34,30 @@ def add(self, blocks: Union[List[Block], Block]): a DuplicateKeyBlock. :param blocks: Block or list of blocks to add. + :param fail_on_duplicate_key: If True, raises ValueError if a block was replaced with a DuplicateKeyBlock. """ if isinstance(blocks, Block): blocks = [blocks] + _added_blocks = [] for block in blocks: # This may replace block with a DuplicateEntryKeyBlock block = self._add_to_dicts(block) self._blocks.append(block) + _added_blocks.append(block) + + if fail_on_duplicate_key: + duplicate_keys = [] + for original, added in zip(blocks, _added_blocks): + if not original is added and isinstance(added, DuplicateBlockKeyBlock): + duplicate_keys.append(added.key) + + if len(duplicate_keys) > 0: + raise ValueError( + f"Duplicate keys found: {duplicate_keys}. " + f"Duplicate entries have been added to the library as DuplicateBlockKeyBlock." + f"Use `library.failed_blocks` to access them. " + ) def remove(self, blocks: Union[List[Block], Block]): """Remove blocks from library. diff --git a/tests/test_library.py b/tests/test_library.py index 239f76f..e02597e 100644 --- a/tests/test_library.py +++ b/tests/test_library.py @@ -64,3 +64,12 @@ def test_replace_fail_on_duplicate(): assert len(library.failed_blocks) == 0 assert library.entries[0].key == "Just a regular entry, to be replaced" assert library.entries[1].key == "duplicateKey" + + +def test_fail_on_duplicate_add(): + library = Library() + library.add(get_dummy_entry()) + with pytest.raises(ValueError): + library.add(get_dummy_entry(), fail_on_duplicate_key=True) + assert len(library.blocks) == 2 + assert len(library.failed_blocks) == 1