import re import subprocess from collections import defaultdict from dataclasses import dataclass, field from pprint import pprint TEMPLATE = """## {code} ({text_code}) ### :x: Problematic code: ```python # to be addded ``` ### :heavy_check_mark: Correct code: ```python # to be added ``` ### Rationale: {description} ### Related resources: - [Testcases](#) - [Issue Tracker](https://github.com/PyCQA/pylint/issues?q=is%3Aissue+%22{text_code}%22+OR+%22{code}%22) """ CHECKS_TO_DIRS = { 'Async Checker Messages': 'async', 'Basic Checker Messages': 'basic', 'Broad Try Clause Checker Messages': 'broad-try-clause', 'Classes Checker Messages': 'classes', 'Compare-To-Empty-String Checker Messages': 'compare-to-empty-string', 'Compare-To-Zero Checker Messages': 'compare-to-zero', 'Deprecated Builtins Checker Messages': 'deprecated-builtins', 'Design Checker Messages': 'design', 'Docstyle Checker Messages': 'docstyle', 'Else If Used Checker Messages': 'else-if-used', 'Exceptions Checker Messages': 'exceptions', 'Format Checker Messages': 'format', 'Imports Checker Messages': 'imports', 'Logging Checker Messages': 'logging', 'Miscellaneous Checker Messages': 'miscellaneous', 'Multiple Types Checker Messages': 'multiple-types', 'Newstyle Checker Messages': 'newstyle', 'Overlap-Except Checker Messages': 'overlap-except', 'Parameter Documentation Checker Messages': 'parameter-documentation', 'Python3 Checker Messages': 'python3', 'Refactoring Checker Messages': 'refactoring', 'Similarities Checker Messages': 'similarities', 'Spelling Checker Messages': 'spelling', 'Stdlib Checker Messages': 'stdlib', 'String Checker Messages': 'string', 'Typecheck Checker Messages': 'typecheck', 'Variables Checker Messages': 'variables' } CHECK = re.compile(r'^\#\#\# .* checker Messages$') ERROR = re.compile(r'^[a-z-]+ \([\w]+\)$') @dataclass class PylintError: code: str text_code: str description: list = field(repr=False, default=None) def capitalise_key(words): """Capitalises a key and preserves dashes.""" capitalised_key = [] for word in words: sub_words = [] for sub_word in word.split('-'): sub_words.append(sub_word.capitalize()) capitalised_key.append('-'.join(sub_words)) return ' '.join(capitalised_key) def extract_errors(): check = None checks_to_errors = defaultdict(list) with open('pylint.md', 'r') as fh: for line in fh.readlines(): if CHECK.search(line): # [1:] to skip ### check = capitalise_key(line.split()[1:]) # Add an error to check's array if ERROR.search(line): checks_to_errors[check].append(line[:-1]) return checks_to_errors def parse_errors(mapping): errors = defaultdict(list) for key, values in mapping.items(): for error in values: text_error = error.split(' ') error_code = text_error[-1].split('(') error_code = error_code[-1].split(')') errors[key].append(PylintError(error_code[0], text_error[0])) return errors def sort_errors(mapping): sorted_errors = {} for key, errors in mapping.items(): sorted_errors[key] = sorted(errors, key=lambda e: e.code) return sorted_errors def set_errors_description(mapping): for key, errors in mapping.items(): for error in errors: p = subprocess.Popen( ['pylint', '--help-msg', error.code], stdout=subprocess.PIPE, stderr=subprocess.PIPE ) stdout, stderr = p.communicate() stdout = stdout.decode().split(':')[2:] error.description = ''.join(stdout) def write_errors(mapping): for key, errors in mapping.items(): for error in errors: path = '{}/{}.md'.format(CHECKS_TO_DIRS[key], error.code) with open(path, 'w') as fh: fh.write( TEMPLATE.format( code=error.code, text_code=error.text_code, description=error.description ) ) def render_tree(mapping): for key, errors in mapping.items(): print(f'### {key}') print() for error in errors: print( '- [{} ({})](errors/{}/{}.md)'.format( error.code, error.text_code, CHECKS_TO_DIRS[key], error.code ) ) print() if __name__ == '__main__': # Get errors from a .md doc raw_errors = extract_errors() # Parse errors parsed_errors = parse_errors(raw_errors) # Sort errors sorted_errors = sort_errors(parsed_errors) render_tree(sorted_errors) #set_errors_description(sorted_errors) # Write errors #write_errors(sorted_errors)