data: Add Metadata.report_links() method.

This is just a variant of get_links() that eats TypeError.
Higher-level reporting code often wants it.
This commit is contained in:
Brett Smith 2020-06-15 14:19:10 -04:00
parent 72f58d80d7
commit 582316ae85
3 changed files with 40 additions and 16 deletions

View file

@ -252,6 +252,19 @@ class Metadata(MutableMapping[MetaKey, MetaValue]):
key, type(value).__name__,
))
def report_links(self, key: MetaKey) -> Sequence[str]:
"""Return a sequence of link strings under the named metadata key
get_links raises a TypeError if the metadata is not a string.
This method simply returns the empty sequence.
Validation code (like in the plugin) usually uses get_links()
while reporting code uses report_links().
"""
try:
return self.get_links(key)
except TypeError:
return ()
@overload
def first_link(self, key: MetaKey, default: None=None) -> Optional[str]: ...

View file

@ -335,15 +335,10 @@ class RelatedPostings(Sequence[data.Posting]):
def __len__(self) -> int:
return len(self._postings)
def _all_meta_links(self, key: MetaKey) -> Iterator[str]:
for post in self:
try:
yield from post.meta.get_links(key)
except TypeError:
pass
def all_meta_links(self, key: MetaKey) -> Iterator[str]:
return filters.iter_unique(self._all_meta_links(key))
return filters.iter_unique(
link for post in self for link in post.meta.report_links(key)
)
@overload
def first_meta_links(self, key: MetaKey, default: str='') -> Iterator[str]: ...

View file

@ -28,6 +28,15 @@ def simple_txn(index=None, key=None):
])
SIMPLE_TXN_METAKEYS = frozenset(['filename', 'lineno', 'note'])
LINK_STRINGS = [
'',
'link',
' link',
'link ',
'link1 link2',
' link1 link2 link3 ',
]
def test_metadata_transforms_source():
source = {'1': 'one'}
meta = data.Metadata(source)
@ -36,14 +45,7 @@ def test_metadata_transforms_source():
del meta['1']
assert set(source) == {'2'}
@pytest.mark.parametrize('value', [
'',
'link',
' link',
'link ',
'link1 link2',
' link1 link2 link3 ',
])
@pytest.mark.parametrize('value', LINK_STRINGS)
def test_get_links(value):
meta = data.Metadata({'key': value})
assert list(meta.get_links('key')) == value.split()
@ -58,6 +60,20 @@ def test_get_links_bad_type(value):
with pytest.raises(TypeError):
meta.get_links('key')
@pytest.mark.parametrize('value', LINK_STRINGS)
def test_report_links(value):
meta = data.Metadata({'key': value})
assert list(meta.report_links('key')) == value.split()
def test_report_links_missing():
meta = data.Metadata({})
assert not meta.report_links('key')
@pytest.mark.parametrize('value', testutil.NON_STRING_METADATA_VALUES)
def test_report_links_bad_type(value):
meta = data.Metadata({'key': value})
assert not meta.report_links('key')
def test_first_link_from_txn(simple_txn):
meta = data.PostingMeta(simple_txn, 0)
assert meta.first_link('note') == 'txn'