diff --git a/README.rst b/README.rst index c34d10a..46b8ce7 100644 --- a/README.rst +++ b/README.rst @@ -27,7 +27,8 @@ Command line usage $ doc8 -h usage: doc8 [-h] [--config path] [--allow-long-titles] [--ignore code] - [--no-sphinx] [--ignore-path path] [--default-extension extension] + [--no-sphinx] [--ignore-path path] [--ignore-path-errors path] + [--default-extension extension] [--file-encoding encoding] [--max-line-length int] [-e extension] [-v] [--version] [path [path ...]] @@ -46,17 +47,20 @@ Command line usage - no newline at end of file - D005 positional arguments: - path path to scan for doc files (default: os.getcwd()) + path Path to scan for doc files (default: current + directory). optional arguments: -h, --help show this help message and exit - --config path user config file location (default: doc8.ini, tox.ini, - pep8.ini, setup.cfg) - --allow-long-titles allow long section titles (default: False) - --ignore code ignore the given errors code/codes - --no-sphinx do not ignore sphinx specific false positives - --ignore-path path ignore the given directory or file (globs are - supported) + --config path User config file location (default: doc8.ini, tox.ini, + pep8.ini, setup.cfg). + --allow-long-titles Allow long section titles (default: False). + --ignore code Ignore the given error code(s). + --no-sphinx Do not ignore sphinx specific false positives. + --ignore-path path Ignore the given directory or file (globs are + supported). + --ignore-path-errors path + Ignore the given specific errors in the provided file. --default-extension extension Default file extension to use when a file is found without a file extension. @@ -65,11 +69,11 @@ Command line usage an input files text encoding (providing this avoids using `chardet` to automatically detect encoding/s) --max-line-length int - maximum allowed line length (default: 79) + Maximum allowed line length (default: 79). -e extension, --extension extension - check file extensions of the given type (default: - .rst, .txt) - -v, --verbose run in verbose mode + Check file extensions of the given type (default: + .rst, .txt). + -v, --verbose Run in verbose mode. --version Show the version and exit. Ini file usage @@ -90,14 +94,14 @@ An example section that can be placed into one of these files:: [doc8] - ignore_path=/tmp/stuff,/tmp/other_stuff - max_line_length=99 + ignore-path=/tmp/stuff,/tmp/other_stuff + max-line-length=99 verbose=1 + ignore-path-errors=/tmp/other_thing.rst;D001;D002 -**Note:** The option names are the same as the command line ones but instead -of dashes underscores are used instead (with the only variation of this being -the ``no-sphinx`` option which from configuration file will be ``sphinx`` -instead). +**Note:** The option names are the same as the command line ones (with the +only variation of this being the ``no-sphinx`` option which from +configuration file will be ``sphinx`` instead). Option conflict resolution ************************** @@ -110,6 +114,7 @@ of conflicts. Option Overrides Merges ===================== =========== ======== ``allow-long-titles`` Yes No +``ignore-path-errors`` No Yes ``default-extension`` Yes No ``extension`` No Yes ``ignore-path`` No Yes diff --git a/doc8/main.py b/doc8/main.py index 19b5171..0196328 100644 --- a/doc8/main.py +++ b/doc8/main.py @@ -60,8 +60,8 @@ CONFIG_FILENAMES = [ ] -def split_set_type(text): - return set([i.strip() for i in text.split(",") if i.strip()]) +def split_set_type(text, delimiter=","): + return set([i.strip() for i in text.split(delimiter) if i.strip()]) def merge_sets(sets): @@ -71,6 +71,16 @@ def merge_sets(sets): return m +def parse_ignore_path_errors(entries): + ignore_path_errors = collections.defaultdict(set) + for path in entries: + path, ignored_errors = path.split(";", 1) + path = os.path.abspath(path.strip()) + ignored_errors = split_set_type(ignored_errors, delimiter=";") + ignore_path_errors[path].update(ignored_errors) + return dict(ignore_path_errors) + + def extract_config(args): parser = configparser.RawConfigParser() read_files = [] @@ -97,6 +107,13 @@ def extract_config(args): "ignore-path")) except (configparser.NoSectionError, configparser.NoOptionError): pass + try: + ignore_path_errors = parser.get("doc8", "ignore-path-errors") + ignore_path_errors = split_set_type(ignore_path_errors) + ignore_path_errors = parse_ignore_path_errors(ignore_path_errors) + cfg['ignore_path_errors'] = ignore_path_errors + except (configparser.NoSectionError, configparser.NoOptionError): + pass try: cfg['allow_long_titles'] = parser.getboolean("doc8", "allow-long-titles") @@ -186,10 +203,13 @@ def validate(cfg, files): print("Validating...") error_counts = {} ignoreables = frozenset(cfg.get('ignore', [])) + ignore_targeted = cfg.get('ignore_path_errors', {}) while files: f = files.popleft() if cfg.get('verbose'): print("Validating %s" % f) + targeted_ignoreables = set(ignore_targeted.get(f.filename, set())) + targeted_ignoreables.update(ignoreables) for c in fetch_checks(cfg): try: # http://legacy.python.org/dev/peps/pep-3155/ @@ -214,7 +234,7 @@ def validate(cfg, files): except AttributeError: pass else: - reports = reports - ignoreables + reports = reports - targeted_ignoreables if not reports: if cfg.get('verbose'): print(" Skipping check '%s', determined to only" @@ -224,7 +244,7 @@ def validate(cfg, files): print(" Running check '%s'" % check_name) if isinstance(c, checks.ContentCheck): for line_num, code, message in c.report_iter(f): - if code in ignoreables: + if code in targeted_ignoreables: continue if not isinstance(line_num, (float, int)): line_num = "?" @@ -238,7 +258,7 @@ def validate(cfg, files): elif isinstance(c, checks.LineCheck): for line_num, line in enumerate(f.lines_iter(), 1): for code, message in c.report_iter(line): - if code in ignoreables: + if code in targeted_ignoreables: continue if cfg.get('verbose'): print(' - %s:%s: %s %s' @@ -280,6 +300,9 @@ def main(): parser.add_argument("--ignore-path", action="append", default=[], help="Ignore the given directory or file (globs" " are supported).", metavar='path') + parser.add_argument("--ignore-path-errors", action="append", default=[], + help="Ignore the given specific errors in the" + " provided file.", metavar='path') parser.add_argument("--default-extension", action="store", help="Default file extension to use when a file is" " found without a file extension.", @@ -317,6 +340,16 @@ def main(): args['sphinx'] = cfg.pop("sphinx") args['extension'].extend(cfg.pop('extension', [])) args['ignore_path'].extend(cfg.pop('ignore_path', [])) + + cfg.setdefault('ignore_path_errors', {}) + for tmp_ignore_path_error in args.pop('ignore_path_errors', []): + tmp_ignores = parse_ignore_path_errors(tmp_ignore_path_error) + for path, ignores in six.iteritems(tmp_ignores): + if path in cfg['ignore_path_errors']: + cfg['ignore_path_errors'][path].update(ignores) + else: + cfg['ignore_path_errors'][path] = set(ignores) + args.update(cfg) setup_logging(args.get('verbose'))