Browse Source

Allow ignore specific error codes in files

Instead of only ignoring full files or ignoring full
codes for all files, allow for ignoring specific errors
for certain files.

Change-Id: I0ebfbe1d2dc68990c84bc0b47d872e44e19b5b2a
Joshua Harlow 4 years ago
parent
commit
b2adee882b
2 changed files with 62 additions and 24 deletions
  1. 24
    19
      README.rst
  2. 38
    5
      doc8/main.py

+ 24
- 19
README.rst View File

@@ -27,7 +27,8 @@ Command line usage
27 27
     $ doc8  -h
28 28
 
29 29
     usage: doc8 [-h] [--config path] [--allow-long-titles] [--ignore code]
30
-                [--no-sphinx] [--ignore-path path] [--default-extension extension]
30
+                [--no-sphinx] [--ignore-path path] [--ignore-path-errors path]
31
+                [--default-extension extension] [--file-encoding encoding]
31 32
                 [--max-line-length int] [-e extension] [-v] [--version]
32 33
                 [path [path ...]]
33 34
 
@@ -46,17 +47,20 @@ Command line usage
46 47
         - no newline at end of file - D005
47 48
 
48 49
     positional arguments:
49
-      path                  path to scan for doc files (default: os.getcwd())
50
+      path                  Path to scan for doc files (default: current
51
+                            directory).
50 52
 
51 53
     optional arguments:
52 54
       -h, --help            show this help message and exit
53
-      --config path         user config file location (default: doc8.ini, tox.ini,
54
-                            pep8.ini, setup.cfg)
55
-      --allow-long-titles   allow long section titles (default: False)
56
-      --ignore code         ignore the given errors code/codes
57
-      --no-sphinx           do not ignore sphinx specific false positives
58
-      --ignore-path path    ignore the given directory or file (globs are
59
-                            supported)
55
+      --config path         User config file location (default: doc8.ini, tox.ini,
56
+                            pep8.ini, setup.cfg).
57
+      --allow-long-titles   Allow long section titles (default: False).
58
+      --ignore code         Ignore the given error code(s).
59
+      --no-sphinx           Do not ignore sphinx specific false positives.
60
+      --ignore-path path    Ignore the given directory or file (globs are
61
+                            supported).
62
+      --ignore-path-errors path
63
+                            Ignore the given specific errors in the provided file.
60 64
       --default-extension extension
61 65
                             Default file extension to use when a file is found
62 66
                             without a file extension.
@@ -65,11 +69,11 @@ Command line usage
65 69
                             an input files text encoding (providing this avoids
66 70
                             using `chardet` to automatically detect encoding/s)
67 71
       --max-line-length int
68
-                            maximum allowed line length (default: 79)
72
+                            Maximum allowed line length (default: 79).
69 73
       -e extension, --extension extension
70
-                            check file extensions of the given type (default:
71
-                            .rst, .txt)
72
-      -v, --verbose         run in verbose mode
74
+                            Check file extensions of the given type (default:
75
+                            .rst, .txt).
76
+      -v, --verbose         Run in verbose mode.
73 77
       --version             Show the version and exit.
74 78
 
75 79
 Ini file usage
@@ -90,14 +94,14 @@ An example section that can be placed into one of these files::
90 94
 
91 95
     [doc8]
92 96
 
93
-    ignore_path=/tmp/stuff,/tmp/other_stuff
94
-    max_line_length=99
97
+    ignore-path=/tmp/stuff,/tmp/other_stuff
98
+    max-line-length=99
95 99
     verbose=1
100
+    ignore-path-errors=/tmp/other_thing.rst;D001;D002
96 101
 
97
-**Note:** The option names are the same as the command line ones but instead
98
-of dashes underscores are used instead (with the only variation of this being
99
-the ``no-sphinx`` option which from configuration file will be ``sphinx``
100
-instead).
102
+**Note:** The option names are the same as the command line ones (with the
103
+only variation of this being the ``no-sphinx`` option which from
104
+configuration file will be ``sphinx`` instead).
101 105
 
102 106
 Option conflict resolution
103 107
 **************************
@@ -110,6 +114,7 @@ of conflicts.
110 114
 Option                 Overrides    Merges
111 115
 =====================  ===========  ========
112 116
 ``allow-long-titles``  Yes          No
117
+``ignore-path-errors`` No           Yes
113 118
 ``default-extension``  Yes          No
114 119
 ``extension``          No           Yes
115 120
 ``ignore-path``        No           Yes

+ 38
- 5
doc8/main.py View File

@@ -60,8 +60,8 @@ CONFIG_FILENAMES = [
60 60
 ]
61 61
 
62 62
 
63
-def split_set_type(text):
64
-    return set([i.strip() for i in text.split(",") if i.strip()])
63
+def split_set_type(text, delimiter=","):
64
+    return set([i.strip() for i in text.split(delimiter) if i.strip()])
65 65
 
66 66
 
67 67
 def merge_sets(sets):
@@ -71,6 +71,16 @@ def merge_sets(sets):
71 71
     return m
72 72
 
73 73
 
74
+def parse_ignore_path_errors(entries):
75
+    ignore_path_errors = collections.defaultdict(set)
76
+    for path in entries:
77
+        path, ignored_errors = path.split(";", 1)
78
+        path = os.path.abspath(path.strip())
79
+        ignored_errors = split_set_type(ignored_errors, delimiter=";")
80
+        ignore_path_errors[path].update(ignored_errors)
81
+    return dict(ignore_path_errors)
82
+
83
+
74 84
 def extract_config(args):
75 85
     parser = configparser.RawConfigParser()
76 86
     read_files = []
@@ -97,6 +107,13 @@ def extract_config(args):
97 107
                                                        "ignore-path"))
98 108
     except (configparser.NoSectionError, configparser.NoOptionError):
99 109
         pass
110
+    try:
111
+        ignore_path_errors = parser.get("doc8", "ignore-path-errors")
112
+        ignore_path_errors = split_set_type(ignore_path_errors)
113
+        ignore_path_errors = parse_ignore_path_errors(ignore_path_errors)
114
+        cfg['ignore_path_errors'] = ignore_path_errors
115
+    except (configparser.NoSectionError, configparser.NoOptionError):
116
+        pass
100 117
     try:
101 118
         cfg['allow_long_titles'] = parser.getboolean("doc8",
102 119
                                                      "allow-long-titles")
@@ -186,10 +203,13 @@ def validate(cfg, files):
186 203
     print("Validating...")
187 204
     error_counts = {}
188 205
     ignoreables = frozenset(cfg.get('ignore', []))
206
+    ignore_targeted = cfg.get('ignore_path_errors', {})
189 207
     while files:
190 208
         f = files.popleft()
191 209
         if cfg.get('verbose'):
192 210
             print("Validating %s" % f)
211
+        targeted_ignoreables = set(ignore_targeted.get(f.filename, set()))
212
+        targeted_ignoreables.update(ignoreables)
193 213
         for c in fetch_checks(cfg):
194 214
             try:
195 215
                 # http://legacy.python.org/dev/peps/pep-3155/
@@ -214,7 +234,7 @@ def validate(cfg, files):
214 234
             except AttributeError:
215 235
                 pass
216 236
             else:
217
-                reports = reports - ignoreables
237
+                reports = reports - targeted_ignoreables
218 238
                 if not reports:
219 239
                     if cfg.get('verbose'):
220 240
                         print("  Skipping check '%s', determined to only"
@@ -224,7 +244,7 @@ def validate(cfg, files):
224 244
                 print("  Running check '%s'" % check_name)
225 245
             if isinstance(c, checks.ContentCheck):
226 246
                 for line_num, code, message in c.report_iter(f):
227
-                    if code in ignoreables:
247
+                    if code in targeted_ignoreables:
228 248
                         continue
229 249
                     if cfg.get('verbose'):
230 250
                         print('    - %s:%s: %s %s'
@@ -236,7 +256,7 @@ def validate(cfg, files):
236 256
             elif isinstance(c, checks.LineCheck):
237 257
                 for line_num, line in enumerate(f.lines_iter(), 1):
238 258
                     for code, message in c.report_iter(line):
239
-                        if code in ignoreables:
259
+                        if code in targeted_ignoreables:
240 260
                             continue
241 261
                         if cfg.get('verbose'):
242 262
                             print('    - %s:%s: %s %s'
@@ -278,6 +298,9 @@ def main():
278 298
     parser.add_argument("--ignore-path", action="append", default=[],
279 299
                         help="Ignore the given directory or file (globs"
280 300
                              " are supported).", metavar='path')
301
+    parser.add_argument("--ignore-path-errors", action="append", default=[],
302
+                        help="Ignore the given specific errors in the"
303
+                             " provided file.", metavar='path')
281 304
     parser.add_argument("--default-extension", action="store",
282 305
                         help="Default file extension to use when a file is"
283 306
                              " found without a file extension.",
@@ -315,6 +338,16 @@ def main():
315 338
         args['sphinx'] = cfg.pop("sphinx")
316 339
     args['extension'].extend(cfg.pop('extension', []))
317 340
     args['ignore_path'].extend(cfg.pop('ignore_path', []))
341
+
342
+    cfg.setdefault('ignore_path_errors', {})
343
+    for tmp_ignore_path_error in args.pop('ignore_path_errors', []):
344
+        tmp_ignores = parse_ignore_path_errors(tmp_ignore_path_error)
345
+        for path, ignores in six.iteritems(tmp_ignores):
346
+            if path in cfg['ignore_path_errors']:
347
+                cfg['ignore_path_errors'][path].update(ignores)
348
+            else:
349
+                cfg['ignore_path_errors'][path] = set(ignores)
350
+
318 351
     args.update(cfg)
319 352
     setup_logging(args.get('verbose'))
320 353
 

Loading…
Cancel
Save