Source code for flakeheaven.parsers._rst

# built-in
from pathlib import Path
from types import MappingProxyType
from typing import List, Optional

# app
from ._base import BaseParser
from ._markdown import CODE_TYPES, CodeType


[docs]class RSTParser(BaseParser): ignore = MappingProxyType({ 'pycodestyle': ('E302', 'E303', 'E305', 'E402'), })
[docs] @classmethod def parse(cls, path: Path) -> List[str]: code_found = False code_type = None indent = None lines = [] with path.open(encoding='utf8') as stream: for line in stream: # leave empty lines as-is if not line.strip(): lines.append('\n') continue if code_type is None: # detect code block start new_code_type = cls._get_code_type(line=line) if new_code_type: code_type = new_code_type indent = None # ignore rst and code block starts lines.append('# {}\n'.format(line[:40].strip())) continue # detect code block end current_indent = len(line) - len(line.lstrip()) if indent is not None and current_indent < indent: code_type = None lines.append('# {}\n'.format(line[:40].strip())) continue # For the first line of code check indentation. if indent is None: indent = current_indent if line.lstrip()[:4] == '>>> ': code_type = CodeType.PYCON # Remove this identation from every line of the code block line = line[indent:] # remove repl chars and comment-out output if code_type == CodeType.PYCON: if line.startswith('>>> ') or line.startswith('... '): line = line[4:] else: line = '# ' + line # save code line as-is lines.append(line) code_found = True if not code_found: return [] return lines
[docs] @staticmethod def _get_code_type(line: str) -> Optional[CodeType]: line = line.lstrip() if line[:2] != '..': return None line = line[2:].lstrip() block, sep, lang = line.partition('::') if not sep: return None if block.strip() not in ('code-block', 'code', 'sourcecode', 'ipython'): return None lang = lang.strip().lower() return CODE_TYPES.get(lang, None)