131
131
except NameError :
132
132
unichr = chr
133
133
134
+
134
135
class CustomHTMLParser (HTMLParser ):
135
136
"""simplified HTML parser.
136
137
@@ -169,21 +170,25 @@ def close(self):
169
170
HTMLParser .close (self )
170
171
return self .__builder .close ()
171
172
173
+
172
174
Command = namedtuple ('Command' , 'negated cmd args lineno context' )
173
175
176
+
174
177
class FailedCheck (Exception ):
175
178
pass
176
179
180
+
177
181
class InvalidCheck (Exception ):
178
182
pass
179
183
184
+
180
185
def concat_multi_lines (f ):
181
186
"""returns a generator out of the file object, which
182
187
- removes `\\ ` then `\n ` then a shared prefix with the previous line then
183
188
optional whitespace;
184
189
- keeps a line number (starting from 0) of the first line being
185
190
concatenated."""
186
- lastline = None # set to the last line when the last line has a backslash
191
+ lastline = None # set to the last line when the last line has a backslash
187
192
firstlineno = None
188
193
catenated = ''
189
194
for lineno , line in enumerate (f ):
@@ -208,6 +213,7 @@ def concat_multi_lines(f):
208
213
if lastline is not None :
209
214
print_err (lineno , line , 'Trailing backslash at the end of the file' )
210
215
216
+
211
217
LINE_PATTERN = re .compile (r'''
212
218
(?<=(?<!\S)@)(?P<negated>!?)
213
219
(?P<cmd>[A-Za-z]+(?:-[A-Za-z]+)*)
@@ -252,7 +258,7 @@ def flatten(node):
252
258
253
259
def normalize_xpath (path ):
254
260
if path .startswith ('//' ):
255
- return '.' + path # avoid warnings
261
+ return '.' + path # avoid warnings
256
262
elif path .startswith ('.//' ):
257
263
return path
258
264
else :
@@ -316,7 +322,7 @@ def get_dir(self, path):
316
322
317
323
def check_string (data , pat , regexp ):
318
324
if not pat :
319
- return True # special case a presence testing
325
+ return True # special case a presence testing
320
326
elif regexp :
321
327
return re .search (pat , data , flags = re .UNICODE ) is not None
322
328
else :
@@ -353,7 +359,7 @@ def check_tree_text(tree, path, pat, regexp):
353
359
ret = check_string (value , pat , regexp )
354
360
if ret :
355
361
break
356
- except Exception as e :
362
+ except Exception :
357
363
print ('Failed to get path "{}"' .format (path ))
358
364
raise
359
365
return ret
@@ -363,6 +369,7 @@ def get_tree_count(tree, path):
363
369
path = normalize_xpath (path )
364
370
return len (tree .findall (path ))
365
371
372
+
366
373
def stderr (* args ):
367
374
if sys .version_info .major < 3 :
368
375
file = codecs .getwriter ('utf-8' )(sys .stderr )
@@ -371,6 +378,7 @@ def stderr(*args):
371
378
372
379
print (* args , file = file )
373
380
381
+
374
382
def print_err (lineno , context , err , message = None ):
375
383
global ERR_COUNT
376
384
ERR_COUNT += 1
@@ -381,48 +389,50 @@ def print_err(lineno, context, err, message=None):
381
389
if context :
382
390
stderr ("\t {}" .format (context ))
383
391
392
+
384
393
ERR_COUNT = 0
385
394
395
+
386
396
def check_command (c , cache ):
387
397
try :
388
398
cerr = ""
389
- if c .cmd == 'has' or c .cmd == 'matches' : # string test
399
+ if c .cmd == 'has' or c .cmd == 'matches' : # string test
390
400
regexp = (c .cmd == 'matches' )
391
- if len (c .args ) == 1 and not regexp : # @has <path> = file existence
401
+ if len (c .args ) == 1 and not regexp : # @has <path> = file existence
392
402
try :
393
403
cache .get_file (c .args [0 ])
394
404
ret = True
395
405
except FailedCheck as err :
396
406
cerr = str (err )
397
407
ret = False
398
- elif len (c .args ) == 2 : # @has/matches <path> <pat> = string test
408
+ elif len (c .args ) == 2 : # @has/matches <path> <pat> = string test
399
409
cerr = "`PATTERN` did not match"
400
410
ret = check_string (cache .get_file (c .args [0 ]), c .args [1 ], regexp )
401
- elif len (c .args ) == 3 : # @has/matches <path> <pat> <match> = XML tree test
411
+ elif len (c .args ) == 3 : # @has/matches <path> <pat> <match> = XML tree test
402
412
cerr = "`XPATH PATTERN` did not match"
403
413
tree = cache .get_tree (c .args [0 ])
404
414
pat , sep , attr = c .args [1 ].partition ('/@' )
405
- if sep : # attribute
415
+ if sep : # attribute
406
416
tree = cache .get_tree (c .args [0 ])
407
417
ret = check_tree_attr (tree , pat , attr , c .args [2 ], regexp )
408
- else : # normalized text
418
+ else : # normalized text
409
419
pat = c .args [1 ]
410
420
if pat .endswith ('/text()' ):
411
421
pat = pat [:- 7 ]
412
422
ret = check_tree_text (cache .get_tree (c .args [0 ]), pat , c .args [2 ], regexp )
413
423
else :
414
424
raise InvalidCheck ('Invalid number of @{} arguments' .format (c .cmd ))
415
425
416
- elif c .cmd == 'count' : # count test
417
- if len (c .args ) == 3 : # @count <path> <pat> <count> = count test
426
+ elif c .cmd == 'count' : # count test
427
+ if len (c .args ) == 3 : # @count <path> <pat> <count> = count test
418
428
expected = int (c .args [2 ])
419
429
found = get_tree_count (cache .get_tree (c .args [0 ]), c .args [1 ])
420
430
cerr = "Expected {} occurrences but found {}" .format (expected , found )
421
431
ret = expected == found
422
432
else :
423
433
raise InvalidCheck ('Invalid number of @{} arguments' .format (c .cmd ))
424
- elif c .cmd == 'has-dir' : # has-dir test
425
- if len (c .args ) == 1 : # @has-dir <path> = has-dir test
434
+ elif c .cmd == 'has-dir' : # has-dir test
435
+ if len (c .args ) == 1 : # @has-dir <path> = has-dir test
426
436
try :
427
437
cache .get_dir (c .args [0 ])
428
438
ret = True
@@ -448,11 +458,13 @@ def check_command(c, cache):
448
458
except InvalidCheck as err :
449
459
print_err (c .lineno , c .context , str (err ))
450
460
461
+
451
462
def check (target , commands ):
452
463
cache = CachedFiles (target )
453
464
for c in commands :
454
465
check_command (c , cache )
455
466
467
+
456
468
if __name__ == '__main__' :
457
469
if len (sys .argv ) != 3 :
458
470
stderr ('Usage: {} <doc dir> <template>' .format (sys .argv [0 ]))
0 commit comments