2025-10-14 17:04:58 -04:00

115 lines
3.4 KiB
Python
Executable File

#!/usr/bin/env python3
import os
import re
import yaml
def read_features(filename):
'''Get a list of string feature names from a test file's YAML-formatted
frontmatter.'''
with open(filename, 'r') as handle:
frontmatter = None
for line in handle:
if frontmatter is not None:
if line.strip() == '---*/':
break
frontmatter += line
if line.strip() == '/*---':
frontmatter = ''
assert frontmatter is not None, f'File has frontmatter: {filename}'
return yaml.safe_load(frontmatter).get('features', [])
def file_is_test(filename):
return not (filename.endswith('FIXTURE.js') or filename.endswith('.json'))
def pattern_from_path_spec(path_spec):
return re.compile(re.sub('\*', '.*', path_spec) + '(/|$)')
def get_filenames(path_spec):
pattern = pattern_from_path_spec(path_spec)
# path_spec is a literal path, not a pattern
if pattern.pattern == path_spec + '(/|$)':
if os.path.isfile(path_spec):
yield path_spec
elif os.path.isdir(path_spec):
for root, _, files in os.walk(path_spec):
test_files = filter(file_is_test, files)
yield from [os.path.join(root, file) for file in test_files]
else:
raise AssertionError(f'No such file/directory: "{path_spec}"')
return
# Choose the optimal directory from which to conduct the search by using
# all available static directory names in the path spec (e.g. `a/b/c` in
# the path spec `a/b/c/*/d`)
search_root = '.'
for part in path_spec.split('/'):
if '*' in part:
break
search_root = f'{search_root}/{part}'
matched = False
for root, _, files in os.walk(search_root):
for file in files:
file = os.path.join(root, file)
if pattern.search(file):
matched = True
yield file
assert matched, f'At least one matching file for "{path_spec}"'
def get_filenames_from_path_specs(path_specs):
filenames = set()
for path_spec in path_specs:
if path_spec.startswith('!'):
pattern = pattern_from_path_spec(path_spec[1:])
used = False
for filename in list(filenames):
if pattern.search(filename):
filenames.remove(filename)
used = True
assert used, f'Pathspec used at least once: "{path_spec}"'
else:
filenames.update(get_filenames(path_spec))
return filenames
def match(file_path, tag_specs):
tags = read_features(file_path)
for tag_filter in tag_specs:
if tag_filter.startswith('!'):
if tag_filter[1:] in tags:
return False
else:
if tag_filter not in tags:
return False
return True
def main(web_features_filename):
with open(web_features_filename, 'r') as handle:
features = yaml.safe_load(handle)['features']
for feature in features:
name = feature['name']
path_specs = feature['files']
tag_specs = feature.get('tags', [])
tests = [*filter(
lambda candidate: match(candidate, tag_specs),
get_filenames_from_path_specs(path_specs)
)]
print(f'{name},{len(tests)}')
print(f'{web_features_filename} is conformant')
if __name__ == '__main__':
main('./WEB_FEATURES.yml')