Example #1
0
 def test_2_matches(self):
     sub1 = substitution.Substitution(
         matched_spans={'x': (0, 1)},
         replacements={'x': u'x'},
         primary_label='x',
     )
     sub2 = substitution.Substitution(
         matched_spans={'x': (2, 3)},
         replacements={'x': u'x'},
         primary_label='x',
     )
     self.assertEqual(
         formatting.apply_substitutions('abc', [sub1, sub2]),
         'xbx',
     )
Example #2
0
 def test_swapped_order_empty(self):
     """Test what 'shouldn't happen'."""
     with self.assertRaises(AssertionError):
         list(
             substitution.labeled_spans(
                 substitution.Substitution(matched_spans={'a': (10, 5)},
                                           primary_label='a')))
Example #3
0
 def test_validate_category_failure(self, category):
     with self.assertRaises(ValueError):
         substitution.Substitution(
             primary_label='label',
             matched_spans={'label': (0, 0)},
             category=category,
         )
Example #4
0
def _substitution_with_span(start, end, **kwargs):
    kwargs.setdefault('message', '')
    kwargs.setdefault('url', '')
    return substitution.Substitution(matched_spans={'label': (start, end)},
                                     primary_label='label',
                                     replacements={'label': u''},
                                     **kwargs)
Example #5
0
 def find_iter_parsed(
     self, parsed: _matcher.PythonParsedFile
 ) -> Iterable[substitution.Substitution]:
     for match_dict, templates in self.find_dicts_parsed(parsed):
         try:
             replacements = formatting.rewrite_templates(
                 parsed, match_dict, templates)
         except formatting.RewriteError as e:
             # TODO: Forward this up somehow.
             print('Skipped rewrite:', e, file=sys.stderr)
             continue
         yield substitution.Substitution(
             matched_spans={
                 label: s.span
                 for label, s in match_dict.items()
                 if s.span not in (None, (-1, -1))
             },
             replacements=replacements,
             primary_label=ROOT_LABEL,
             key_span=self.key_span_for_dict(parsed, match_dict),
             message=replacements.pop(MESSAGE_LABEL, None),
             url=replacements.pop(URL_LABEL, None),
             category=replacements.pop(CATEGORY_LABEL, None),
             significant=bool(replacements.pop(SIGNIFICANT_LABEL, '')),
         )
Example #6
0
 def test_empty_range(self):
     self.assertEqual(
         list(
             substitution.labeled_spans(
                 substitution.Substitution(matched_spans={'a': (0, 0)},
                                           primary_label='a'))),
         [substitution.LabeledSpan(labels={'a'}, span=(0, 0))])
Example #7
0
 def next_out(label):
     sub = substitution.Substitution(
         matched_spans={label: (0, 3)},
         primary_label=label,
     )
     is_diff, out = renderer.render('abc', sub, {})
     self.assertFalse(is_diff)
     return out
Example #8
0
 def test_noreplacements(self):
     sub = substitution.Substitution(
         matched_spans={'x': (1, 2)},
         primary_label='x',
     )
     self.assertEqual(
         formatting.apply_substitutions('abc', [sub]),
         'abc',
     )
Example #9
0
 def test_validate_span_replacements(self):
     with self.assertRaises(ValueError):
         substitution.Substitution(
             message='',
             matched_spans={'label': (0, 0)},
             primary_label='label',
             replacements={'label_dne': u''},
             url='',
         )
Example #10
0
 def test_validate_span_not_in_replacements(self):
     """It is OK to only replace a subset of matched spans."""
     # does not raise:
     substitution.Substitution(
         message='',
         matched_spans={'label': (0, 0)},
         primary_label='label',
         replacements={},
         url='',
     )
Example #11
0
 def test_total_overlap(self):
     self.assertEqual(
         list(
             substitution.labeled_spans(
                 substitution.Substitution(matched_spans={
                     'a': (0, 10),
                     'b': (0, 10)
                 },
                                           primary_label='a'))),
         [substitution.LabeledSpan(labels={'a', 'b'}, span=(0, 10))])
Example #12
0
    def test_empty_style(self):
        """Tests that the empty string is unstyled.

    We want to preserve colors for the _non_ empty spans.
    """
        sub = substitution.Substitution(
            matched_spans={'primary': (0, 0)},
            primary_label='primary',
        )
        self.assertEqual(
            formatting.Renderer(match_format='{match}').render('abc', sub, {}),
            (False, '\n'))
Example #13
0
    def test_diff(self):
        """Tests a basic diff rendering."""
        sub = substitution.Substitution(
            matched_spans={'primary': (0, 3)},
            replacements={'primary': u'new'},
            primary_label='primary',
        )

        renderer = formatting.Renderer(match_format='{match}', color=False)
        is_diff, out = renderer.render('old', sub, {})
        self.assertTrue(is_diff)
        self.assertEqual(out, '-old\n+new\n')
Example #14
0
    def test_saves_style(self):
        """Tests that the same style is reused for the same label."""
        renderer = formatting.Renderer(match_format='{match}')
        sub_x = substitution.Substitution(
            matched_spans={'x': (0, 3)},
            primary_label='x',
        )
        is_diff, out_1 = renderer.render('abc', sub_x, {})
        self.assertFalse(is_diff)
        is_diff, out_2 = renderer.render('abc', sub_x, {})
        self.assertFalse(is_diff)

        # The same labels always get the same styling:
        self.assertEqual(out_1, out_2)
        # But a different label gets a new styling:
        sub_y = substitution.Substitution(
            matched_spans={'y': (0, 3)},
            primary_label='y',
        )
        is_diff, out_3 = renderer.render('abc', sub_y, {})
        self.assertFalse(is_diff)
        self.assertNotEqual(out_1, out_3)
Example #15
0
 def test_gap(self):
     self.assertEqual(
         list(
             substitution.labeled_spans(
                 substitution.Substitution(matched_spans={
                     'a': (0, 10),
                     'b': (20, 30)
                 },
                                           primary_label='a'))),
         [
             substitution.LabeledSpan(labels={'a'}, span=(0, 10)),
             substitution.LabeledSpan(labels=set(), span=(10, 20)),
             substitution.LabeledSpan(labels={'b'}, span=(20, 30))
         ])
Example #16
0
 def test_nonsolo_primary_style(self):
     # exploit a weird edge case for testing: if the other label has zero-width,
     # it is not styled, but this still affects how the primary label is treated.
     sub = substitution.Substitution(
         matched_spans={
             'primary': (0, 3),
             'other': (3, 3)
         },
         primary_label='primary',
     )
     self.assertEqual(
         formatting.Renderer(match_format='{match}').render('abc', sub, {}),
         (False,
          '{colorama.Style.BRIGHT}abc{colorama.Style.RESET_ALL}\n'.format(
              colorama=colorama)))
Example #17
0
 def test_fixedpoint_drop_insignificant(self):
     fx = fixer.CombiningPythonFixer([
         _search_replace_fixer('a', 'b', url='url_a', significant=False),
         _search_replace_fixer('b', 'c', url='url_b', significant=True),
     ])
     self.assertEqual(
         list(search.find_iter(fx, 'a', 'foo.py', max_iterations=10)), [
             substitution.Substitution(
                 message='b',
                 matched_spans={'fixedpoint': (0, 1)},
                 primary_label='fixedpoint',
                 replacements={'fixedpoint': 'c'},
                 url='url_b',
                 significant=True,
                 category='refex.merged.significant',
             )
         ])
Example #18
0
def _substitution(**kwargs):
    """Match with a substitution that shares the provided fields.

  The rest are replaced with mock.ANY.

  Args:
    **kwargs: The arguments to Substitution().

  Returns:
    A Substitution.
  """
    for attribute in attr.fields(substitution.Substitution):
        if attribute.name not in kwargs:
            kwargs[attribute.name] = mock.ANY
    # temporarily disable input validation:
    with mock.patch.object(substitution.Substitution, '_validate',
                           lambda self: None):
        return substitution.Substitution(**kwargs)
Example #19
0
 def test_fixedpoint_keep_insignificant(self):
     fx = fixer.CombiningPythonFixer([
         _search_replace_fixer('a', 'b', url='url_a', significant=False),
         _search_replace_fixer('b', 'c', url='url_b', significant=False),
     ])
     self.assertEqual(
         list(search.find_iter(fx, 'a', 'foo.py', max_iterations=10)), [
             substitution.Substitution(
                 message=
                 'There are a few findings here:\n\na\n(url_a)\n\nb\n(url_b)',
                 matched_spans={'fixedpoint': (0, 1)},
                 primary_label='fixedpoint',
                 replacements={'fixedpoint': 'c'},
                 url=
                 'https://refex.readthedocs.io/en/latest/guide/fixers/merged.html',
                 significant=False,
                 category='refex.merged.not-significant',
             )
         ])
Example #20
0
def _compile_substitutions(substitutions: Iterable[substitution.Substitution],
                           primary_start: int, primary_end: int,
                           new_primary_contents: Text):
    """Create one substitution out of many that were composed together."""
    if not substitutions:
        return None
    significant = True
    significant_subs = [sub for sub in substitutions if sub.significant]
    if not significant_subs:
        significant_subs = substitutions
        significant = False  # all subs were insignificant
    message_header = 'There are a few findings here:\n\n'
    urls = {sub.url for sub in significant_subs}
    if len(urls) == 1:
        [url] = urls
        messages = [sub.message for sub in significant_subs if sub.message]
        if len(set(messages)) == 1:
            # Present only one message, with no header.
            message_header = ''
            del messages[1:]
    else:
        # Can't give a better URL here :/
        url = 'https://refex.readthedocs.io/en/latest/guide/fixers/merged.html'
        messages = [
            '{message}\n({url})'.format(message=sub.message or '(no message)',
                                        url=sub.url)
            for sub in significant_subs
        ]
    if messages:
        message = message_header + '\n\n'.join(m for m in messages)
    else:
        message = None
    primary_label = 'fixedpoint'
    return substitution.Substitution(
        message=message,
        url=url,
        matched_spans={primary_label: (primary_start, primary_end)},
        primary_label=primary_label,
        replacements={primary_label: new_primary_contents},
        significant=significant,
        category='refex.merged.{}'.format(
            'significant' if significant else 'not-significant'),
    )
Example #21
0
 def test_validate_no_replacements(self):
     substitution.Substitution(
         primary_label='label',
         matched_spans={'label': (0, 0)},
         replacements=None,
     )
Example #22
0
 def test_validate_category_success(self, category):
     substitution.Substitution(
         primary_label='label',
         matched_spans={'label': (0, 0)},
         category=category,
     )