wpt_lint_rules.py (2635B)
1 from docutils.parsers.rst import Directive, nodes 2 from docutils.utils import new_document 3 from recommonmark.parser import CommonMarkParser 4 import importlib 5 import textwrap 6 7 class WPTLintRules(Directive): 8 """A docutils directive to generate documentation for the 9 web-platform-test-test's linting tool from its source code. Requires a 10 single argument: a Python module specifier for a file which declares 11 linting rules.""" 12 has_content = True 13 required_arguments = 1 14 optional_arguments = 0 15 _md_parser = CommonMarkParser() 16 17 @staticmethod 18 def _parse_markdown(markdown): 19 WPTLintRules._md_parser.parse(markdown, new_document("<string>")) 20 return WPTLintRules._md_parser.document.children[0] 21 22 @property 23 def module_specifier(self): 24 return self.arguments[0] 25 26 def _get_rules(self): 27 try: 28 module = importlib.import_module(self.module_specifier) 29 except ImportError: 30 raise ImportError( 31 """wpt-lint-rules: unable to resolve the module at "{}".""".format(self.module_specifier) 32 ) 33 34 for binding_name, value in module.__dict__.items(): 35 if hasattr(value, "__abstractmethods__") and len(value.__abstractmethods__): 36 continue 37 38 description = getattr(value, "description", None) 39 name = getattr(value, "name", None) 40 to_fix = getattr(value, "to_fix", None) 41 42 if description is None: 43 continue 44 45 if to_fix is not None: 46 to_fix = textwrap.dedent(to_fix) 47 48 yield { 49 "name": name, 50 "description": textwrap.dedent(description), 51 "to_fix": to_fix 52 } 53 54 55 def run(self): 56 definition_list = nodes.definition_list() 57 58 for rule in sorted(self._get_rules(), key=lambda rule: rule['name']): 59 item = nodes.definition_list_item() 60 definition = nodes.definition() 61 term = nodes.term() 62 item += term 63 item += definition 64 definition_list += item 65 66 term += nodes.literal(text=rule["name"]) 67 definition += WPTLintRules._parse_markdown(rule["description"]) 68 69 if rule["to_fix"]: 70 definition += nodes.strong(text="To fix:") 71 definition += WPTLintRules._parse_markdown(rule["to_fix"]) 72 73 if len(definition_list.children) == 0: 74 raise Exception( 75 """wpt-lint-rules: no linting rules found at "{}".""".format(self.module_specifier) 76 ) 77 78 return [definition_list]