Code Duplication    Length = 172-173 lines in 2 locations

pythonx/tests/markdown_parser.py 1 location

@@ 482-653 (lines=172) @@
479
        )
480
481
482
class InlineLexer(object):
483
    """Inline level lexer for inline grammars."""
484
    grammar_class = InlineGrammar
485
486
    default_rules = [
487
        'escape', 'inline_html', 'autolink', 'url',
488
        'footnote', 'link', 'reflink', 'nolink',
489
        'double_emphasis', 'emphasis', 'code',
490
        'linebreak', 'strikethrough', 'text',
491
    ]
492
    inline_html_rules = [
493
        'escape', 'autolink', 'url', 'link', 'reflink',
494
        'nolink', 'double_emphasis', 'emphasis', 'code',
495
        'linebreak', 'strikethrough', 'text',
496
    ]
497
498
    def __init__(self, renderer, rules=None, **kwargs):
499
        self.renderer = renderer
500
        self.links = {}
501
        self.footnotes = {}
502
        self.footnote_index = 0
503
504
        if not rules:
505
            rules = self.grammar_class()
506
507
        self.rules = rules
508
509
        self._in_link = False
510
        self._in_footnote = False
511
512
        kwargs.update(self.renderer.options)
513
        self._parse_inline_html = kwargs.get('parse_inline_html')
514
515
    def __call__(self, text, rules=None):
516
        return self.output(text, rules)
517
518
    def setup(self, links, footnotes):
519
        self.footnote_index = 0
520
        self.links = links or {}
521
        self.footnotes = footnotes or {}
522
523
    def output(self, text, rules=None):
524
        text = text.rstrip('\n')
525
        if not rules:
526
            rules = list(self.default_rules)
527
528
        if self._in_footnote and 'footnote' in rules:
529
            rules.remove('footnote')
530
531
        output = self.renderer.placeholder()
532
533
        def manipulate(text):
534
            for key in rules:
535
                pattern = getattr(self.rules, key)
536
                m = pattern.match(text)
537
                if not m:
538
                    continue
539
                self.line_match = m
540
                out = getattr(self, 'output_%s' % key)(m)
541
                if out is not None:
542
                    return m, out
543
            return False  # pragma: no cover
544
545
        self.line_started = False
546
        while text:
547
            ret = manipulate(text)
548
            self.line_started = True
549
            if ret is not False:
550
                m, out = ret
551
                output += out
552
                text = text[len(m.group(0)):]
553
                continue
554
            if text:  # pragma: no cover
555
                raise RuntimeError('Infinite loop at: %s' % text)
556
557
        return output
558
559
    def output_escape(self, m):
560
        return m.group(1)
561
562
    def output_autolink(self, m):
563
        link = m.group(1)
564
        if m.group(2) == '@':
565
            is_email = True
566
        else:
567
            is_email = False
568
        return self.renderer.autolink(link, is_email)
569
570
    def output_url(self, m):
571
        link = m.group(1)
572
        if self._in_link:
573
            return self.renderer.text(link)
574
        return self.renderer.autolink(link, False)
575
576
    def output_inline_html(self, m):
577
        tag = m.group(1)
578
        if self._parse_inline_html and tag in _inline_tags:
579
            text = m.group(3)
580
            if tag == 'a':
581
                self._in_link = True
582
                text = self.output(text, rules=self.inline_html_rules)
583
                self._in_link = False
584
            else:
585
                text = self.output(text, rules=self.inline_html_rules)
586
            extra = m.group(2) or ''
587
            html = '<%s%s>%s</%s>' % (tag, extra, text, tag)
588
        else:
589
            html = m.group(0)
590
        return self.renderer.inline_html(html)
591
592
    def output_footnote(self, m):
593
        key = _keyify(m.group(1))
594
        if key not in self.footnotes:
595
            return None
596
        if self.footnotes[key]:
597
            return None
598
        self.footnote_index += 1
599
        self.footnotes[key] = self.footnote_index
600
        return self.renderer.footnote_ref(key, self.footnote_index)
601
602
    def output_link(self, m):
603
        return self._process_link(m, m.group(3), m.group(4))
604
605
    def output_reflink(self, m):
606
        key = _keyify(m.group(2) or m.group(1))
607
        if key not in self.links:
608
            return None
609
        ret = self.links[key]
610
        return self._process_link(m, ret['link'], ret['title'])
611
612
    def output_nolink(self, m):
613
        key = _keyify(m.group(1))
614
        if key not in self.links:
615
            return None
616
        ret = self.links[key]
617
        return self._process_link(m, ret['link'], ret['title'])
618
619
    def _process_link(self, m, link, title=None):
620
        line = m.group(0)
621
        text = m.group(1)
622
        if line[0] == '!':
623
            return self.renderer.image(link, title, text)
624
625
        self._in_link = True
626
        text = self.output(text)
627
        self._in_link = False
628
        return self.renderer.link(link, title, text)
629
630
    def output_double_emphasis(self, m):
631
        text = m.group(2) or m.group(1)
632
        text = self.output(text)
633
        return self.renderer.double_emphasis(text)
634
635
    def output_emphasis(self, m):
636
        text = m.group(2) or m.group(1)
637
        text = self.output(text)
638
        return self.renderer.emphasis(text)
639
640
    def output_code(self, m):
641
        text = m.group(2)
642
        return self.renderer.codespan(text)
643
644
    def output_linebreak(self, m):
645
        return self.renderer.linebreak()
646
647
    def output_strikethrough(self, m):
648
        text = self.output(m.group(1))
649
        return self.renderer.strikethrough(text)
650
651
    def output_text(self, m):
652
        text = m.group(0)
653
        return self.renderer.text(text)
654
655
656
class Renderer(object):

pythonx/markdown_parser.py 1 location

@@ 493-665 (lines=173) @@
490
        )
491
492
493
class InlineLexer(object):
494
    """Inline level lexer for inline grammars."""
495
    grammar_class = InlineGrammar
496
497
    default_rules = [
498
        'escape', 'inline_html', 'autolink', 'url',
499
        'footnote', 'link', 'reflink', 'nolink',
500
        'double_emphasis', 'emphasis', 'code',
501
        'linebreak', 'strikethrough', 'text',
502
    ]
503
    inline_html_rules = [
504
        'escape', 'autolink', 'url', 'link', 'reflink',
505
        'nolink', 'double_emphasis', 'emphasis', 'code',
506
        'linebreak', 'strikethrough', 'text',
507
    ]
508
509
    def __init__(self, renderer, rules=None, **kwargs):
510
        self.renderer = renderer
511
        self.links = {}
512
        self.footnotes = {}
513
        self.footnote_index = 0
514
515
        if not rules:
516
            rules = self.grammar_class()
517
518
        kwargs.update(self.renderer.options)
519
        if kwargs.get('hard_wrap'):
520
            rules.hard_wrap()
521
522
        self.rules = rules
523
524
        self._in_link = False
525
        self._in_footnote = False
526
        self._parse_inline_html = kwargs.get('parse_inline_html')
527
528
    def __call__(self, text, rules=None):
529
        return self.output(text, rules)
530
531
    def setup(self, links, footnotes):
532
        self.footnote_index = 0
533
        self.links = links or {}
534
        self.footnotes = footnotes or {}
535
536
    def output(self, text, rules=None):
537
        text = text.rstrip('\n')
538
        if not rules:
539
            rules = list(self.default_rules)
540
541
        if self._in_footnote and 'footnote' in rules:
542
            rules.remove('footnote')
543
544
        output = self.renderer.placeholder()
545
546
        def manipulate(text):
547
            for key in rules:
548
                pattern = getattr(self.rules, key)
549
                m = pattern.match(text)
550
                if not m:
551
                    continue
552
                self.line_match = m
553
                out = getattr(self, 'output_%s' % key)(m)
554
                if out is not None:
555
                    return m, out
556
            return False  # pragma: no cover
557
558
        while text:
559
            ret = manipulate(text)
560
            if ret is not False:
561
                m, out = ret
562
                output += out
563
                text = text[len(m.group(0)):]
564
                continue
565
            if text:  # pragma: no cover
566
                raise RuntimeError('Infinite loop at: %s' % text)
567
568
        return output
569
570
    def output_escape(self, m):
571
        text = m.group(1)
572
        return self.renderer.escape(text)
573
574
    def output_autolink(self, m):
575
        link = m.group(1)
576
        if m.group(2) == '@':
577
            is_email = True
578
        else:
579
            is_email = False
580
        return self.renderer.autolink(link, is_email)
581
582
    def output_url(self, m):
583
        link = m.group(1)
584
        if self._in_link:
585
            return self.renderer.text(link)
586
        return self.renderer.autolink(link, False)
587
588
    def output_inline_html(self, m):
589
        tag = m.group(1)
590
        if self._parse_inline_html and tag in _inline_tags:
591
            text = m.group(3)
592
            if tag == 'a':
593
                self._in_link = True
594
                text = self.output(text, rules=self.inline_html_rules)
595
                self._in_link = False
596
            else:
597
                text = self.output(text, rules=self.inline_html_rules)
598
            extra = m.group(2) or ''
599
            html = '<%s%s>%s</%s>' % (tag, extra, text, tag)
600
        else:
601
            html = m.group(0)
602
        return self.renderer.inline_html(html)
603
604
    def output_footnote(self, m):
605
        key = _keyify(m.group(1))
606
        if key not in self.footnotes:
607
            return None
608
        if self.footnotes[key]:
609
            return None
610
        self.footnote_index += 1
611
        self.footnotes[key] = self.footnote_index
612
        return self.renderer.footnote_ref(key, self.footnote_index)
613
614
    def output_link(self, m):
615
        return self._process_link(m, m.group(3), m.group(4))
616
617
    def output_reflink(self, m):
618
        key = _keyify(m.group(2) or m.group(1))
619
        if key not in self.links:
620
            return None
621
        ret = self.links[key]
622
        return self._process_link(m, ret['link'], ret['title'])
623
624
    def output_nolink(self, m):
625
        key = _keyify(m.group(1))
626
        if key not in self.links:
627
            return None
628
        ret = self.links[key]
629
        return self._process_link(m, ret['link'], ret['title'])
630
631
    def _process_link(self, m, link, title=None):
632
        line = m.group(0)
633
        text = m.group(1)
634
        if line[0] == '!':
635
            return self.renderer.image(link, title, text)
636
637
        self._in_link = True
638
        text = self.output(text)
639
        self._in_link = False
640
        return self.renderer.link(link, title, text)
641
642
    def output_double_emphasis(self, m):
643
        text = m.group(2) or m.group(1)
644
        text = self.output(text)
645
        return self.renderer.double_emphasis(text)
646
647
    def output_emphasis(self, m):
648
        text = m.group(2) or m.group(1)
649
        text = self.output(text)
650
        return self.renderer.emphasis(text)
651
652
    def output_code(self, m):
653
        text = m.group(2)
654
        return self.renderer.codespan(text)
655
656
    def output_linebreak(self, m):
657
        return self.renderer.linebreak()
658
659
    def output_strikethrough(self, m):
660
        text = self.output(m.group(1))
661
        return self.renderer.strikethrough(text)
662
663
    def output_text(self, m):
664
        text = m.group(0)
665
        return self.renderer.text(text)
666
667
668
class Renderer(object):