Changeset - d8507a1a35a7
[Not reviewed]
0 4 0
Brett Smith - 4 years ago 2020-04-23 14:27:47
brettcsmith@brettcsmith.org
rtutil: Add RTUtil.metadata_regexp() classmethod.

The accruals check script wants to be able to search RT links in
all kinds of metadata, not just rt-id as the filter currently
handles.
4 files changed with 55 insertions and 3 deletions:
0 comments (0 inline, 0 general)
conservancy_beancount/filters.py
Show inline comments
...
 
@@ -19,2 +19,3 @@ import re
 
from . import data
 
from . import rtutil
 

	
...
 
@@ -55,3 +56,3 @@ def filter_for_rt_id(postings: Postings, ticket_id: Union[int, str]) -> Postings
 
    """
 
    regexp = r'^\s*rt:(?://ticket/)?{}\b'.format(re.escape(str(ticket_id)))
 
    regexp = rtutil.RT.metadata_regexp(ticket_id, first_link_only=True)
 
    return filter_meta_match(postings, 'rt-id', regexp)
conservancy_beancount/rtutil.py
Show inline comments
...
 
@@ -268,2 +268,31 @@ class RT:
 

	
 
    @classmethod
 
    def metadata_regexp(self,
 
                        ticket_id: RTId,
 
                        attachment_id: Optional[RTId]=None,
 
                        *,
 
                        first_link_only: bool=False
 
    ) -> str:
 
        """Return a pattern to find RT links in metadata
 

	
 
        Given a ticket ID and optional attachment ID, this method returns a
 
        regular expression pattern that will find matching RT links in a
 
        metadata value string, written in any format.
 

	
 
        If the keyword-only argument first_link_only is true, the pattern will
 
        only match the first link in a metadata string. Otherwise the pattern
 
        matches any link in the string (the default).
 
        """
 
        if first_link_only:
 
            prolog = r'^\s*'
 
        else:
 
            prolog = r'(?:^|\s)'
 
        if attachment_id is None:
 
            attachment = ''
 
        else:
 
            attachment = r'/(?:attachments?/)?{}'.format(attachment_id)
 
        ticket = r'rt:(?://ticket/)?{}'.format(ticket_id)
 
        epilog = r'/?(?:$|\s)'
 
        return f'{prolog}{ticket}{attachment}{epilog}'
 

	
 
    @classmethod
tests/test_filters.py
Show inline comments
...
 
@@ -113,3 +113,2 @@ def test_filter_for_rt_id(cc_txn_pair, ticket_id, expected_indexes):
 
    'rt:450/',
 
    'rt:450/678',
 
    ' rt:450 rt:540',
...
 
@@ -117,3 +116,2 @@ def test_filter_for_rt_id(cc_txn_pair, ticket_id, expected_indexes):
 
    'rt://ticket/450/',
 
    'rt://ticket/450/678',
 
    ' rt://ticket/450',
tests/test_rtutil.py
Show inline comments
...
 
@@ -17,2 +17,4 @@
 
import contextlib
 
import itertools
 
import re
 

	
...
 
@@ -64,2 +66,24 @@ def test_url(rt, ticket_id, attachment_id, expected):
 

	
 
@pytest.mark.parametrize('attachment_id,first_link_only', itertools.product(
 
    [245, None],
 
    [True, False],
 
))
 
def test_metadata_regexp(rt, attachment_id, first_link_only):
 
    if attachment_id is None:
 
        match_links = ['rt:220', 'rt://ticket/220']
 
    else:
 
        match_links = [f'rt:220/{attachment_id}',
 
                       f'rt://ticket/220/attachments/{attachment_id}']
 
    regexp = rt.metadata_regexp(220, attachment_id, first_link_only=first_link_only)
 
    for link in match_links:
 
        assert re.search(regexp, link)
 
        assert re.search(regexp, link + ' link2')
 
        assert re.search(regexp, link + '0') is None
 
        assert re.search(regexp, 'a' + link) is None
 
        end_match = re.search(regexp, 'link0 ' + link)
 
        if first_link_only:
 
            assert end_match is None
 
        else:
 
            assert end_match
 

	
 
@pytest.mark.parametrize('attachment_id', [
0 comments (0 inline, 0 general)