Skip to content
Permalink
Browse files

Merge pull request #13386 from aeslaughter/sqa-12049

Improve sqa stats script and add links to source page headings
  • Loading branch information...
permcody committed May 9, 2019
2 parents 4ddac67 + 312b63b commit b8946869e8811d41f76f1c9dfaf7e86f2ff57722
@@ -85,6 +85,50 @@ Extensions:
shortcuts: !include framework/doc/globals.yml
MooseDocs.extensions.acronym:
acronyms: !include framework/doc/acronyms.yml
MooseDocs.extensions.content:
source_links:
action: source/actions/Action.md
actions: source/actions/Action.md
auxkernels: AuxKernels/index.md
bcs: syntax/BCs/index.md
constraints: syntax/Constraints/index.md
controls: syntax/Controls/index.md
dampers: syntax/Dampers/index.md
dgkernels: syntax/DGKernels/index.md
dirackernels: syntax/DiracKernels/index.md
distributions: syntax/Distributions/index.md
executioners: syntax/Executioner/index.md
functions: syntax/Functions/index.md
ics: syntax/ICs/index.md
indicators: syntax/Adaptivity/Indicators/index.md
interfacekernels: syntax/InterfaceKernels/index.md
interfaces: framework_development/interfaces/index.md
kernels: syntax/Kernels/index.md
markers: syntax/Adaptivity/Markers/index.md
materials: syntax/Materials/index.md
mesh: syntax/Mesh/index.md
meshgenerators: syntax/MeshGenerators/index.md
meshmodifiers: syntax/MeshModifiers/index.md
multiapps: syntax/MultiApps/index.md
nodalkernels: syntax/NodalKernels/index.md
outputs: syntax/Outputs/index.md
partitioner: syntax/Mesh/Partitioner/index.md
postprocessors: syntax/Postprocessors/index.md
preconditioners: syntax/Preconditioning/index.md
predictors: syntax/Executioner/Predictor/index.md
problems: syntax/Problem/index.md
restart: application_usage/restart_recover.md
samplers: syntax/Samplers/index.md
scalarkernels: syntax/ScalarKernels/index.md
splits: syntax/Preconditioning/index.md
timeintegrators: syntax/Executioner/TimeIntegrator/index.md
timesteppers: syntax/Executioner/TimeStepper/index.md
transfers: syntax/Transfers/index.md
userobject: syntax/UserObjects/index.md
userobjects: syntax/UserObjects/index.md
utils: framework_development/utils/index.md
variables: syntax/Variables/index.md
vectorpostprocessors: syntax/VectorPostprocessors/index.md
MooseDocs.extensions.sqa:
requirement-groups:
dgkernels: DGKernel Objects
@@ -40,6 +40,7 @@ class ContentExtension(command.CommandExtension):
@staticmethod
def defaultConfig():
config = command.CommandExtension.defaultConfig()
config['source_links'] = (dict(), "Dictionary of folder name to markdown links.")
return config

def extend(self, reader, renderer):
@@ -133,14 +134,21 @@ def createHTML(self, parent, token, page):
def createMaterialize(self, parent, token, page):

headings = self.extension.binContent(page, token['location'], ContentExtension.FOLDER)
links = self.extension.get('source_links')

# Build lists
for head in sorted(headings.keys()):
items = headings[head]
if head:
html.Tag(parent, 'h{:d}'.format(int(token['level'])),
class_='moose-a-to-z',
string=unicode(head))
h = html.Tag(parent, 'h{:d}'.format(int(token['level'])),
class_='moose-a-to-z')
if head in links:
p = self.translator.findPage(links[head])
dest = p.relativeDestination(page)
a = html.Tag(h, 'a', href=dest, string=unicode(head) + u' ')
html.Tag(a, 'i', string='link', class_='small material-icons moose-inline-icon')
else:
html.String(h, content=unicode(head))

row = html.Tag(parent, 'div', class_='row')
for chunk in mooseutils.make_chunks(list(items), 3):
@@ -16,6 +16,7 @@
from MooseException import MooseException
from eval_path import eval_path
from sqa_check import sqa_check, check_requirement
from compute_requirement_stats import compute_requirement_stats, SQAStats
from AutoPropertyMixin import AutoPropertyMixin, Property, addProperty
import parallel

@@ -0,0 +1,72 @@
import os
from mooseutils import colorText, git_ls_files, git_root_dir
try:
from hit_load import hit_load
except:
raise ImportError('hit package failed to load, but it is required.')

class SQAStats(object):
"""Data wrapper for SQA statistic information."""
def __init__(self, title):
self.title = title
self.files = 0
self.files_with_requirement = 0
self.tests = 0
self.tests_with_requirement = 0

@property
def complete(self):
return float(self.tests_with_requirement)/float(self.tests) if self.tests else 0

def __iadd__(self, other):
self.files += other.files
self.files_with_requirement += other.files_with_requirement
self.tests += other.tests
self.tests_with_requirement += other.tests_with_requirement
return self

def __str__(self):
"""Display requirement stats."""
out = []
out.append(colorText(self.title, 'LIGHT_YELLOW'))
out.append(' Complete: {:2.1f}%'.format(self.complete*100))
out.append(' Total Number of Files: {}'.format(self.files))
out.append(' Files with Requirements: {}'.format(self.files_with_requirement))
out.append(' Total Number of Tests: {}'.format(self.tests))
out.append(' Tests with Requirements: {}'.format(self.tests_with_requirement))
return '\n'.join(out)

def compute_requirement_stats(location, specs=['tests'], working_dir=None, show=True):
"""
Report requirement statistics for the test spec files with the supplied location.
Inputs:
location: Path to directory contain test specifications, the supplied path should be
relative to the cwd input.
specs: The filename(s) to consider
working_dir: The working directory, if not supplied the root directory of the repository is used
"""
working_dir = git_root_dir(os.getcwd()) if working_dir is None else working_dir
data = SQAStats(location)
location = os.path.join(working_dir, location)
for filename in git_ls_files(location):
if not os.path.isfile(filename):
continue
fname = os.path.basename(filename)
if fname in specs:
root = hit_load(filename)
has_requirement = False
for child in root.children[0]:
data.tests += 1
if child.get('requirement', None):
has_requirement = True
data.tests_with_requirement += 1

data.files += 1
if has_requirement:
data.files_with_requirement += 1

if show:
print(data)
return data
@@ -11,32 +11,38 @@
"""
Report statistics regarding the SQA documentation in MOOSE.
"""
import os
import mooseutils

def report_requirement_stats(location, specs):
"""
Report requirement statistics for the test spec files with the supplied location.
"""
requirements = 0
tests = 0
for filename in mooseutils.git_ls_files(location):
if not os.path.isfile(filename):
continue
fname = os.path.basename(filename)
if fname in specs:
root = mooseutils.hit_load(filename)
for child in root.children[0]:
tests += 1
if child.get('requirement', None):
requirements += 1

complete = float(requirements)/float(tests)
print 'Requirement Definitions ({:2.1f}% complete):'.format(complete*100)
print ' Location: {}'.format(location)
print ' Specs: {}'.format(' '.join(specs))
print ' Total Number of Tests: {}'.format(tests)
print ' Tests with Requirements: {}'.format(requirements)

if __name__ == '__main__':
report_requirement_stats(os.path.abspath(os.path.join('..', 'test', 'tests')), ['tests'])
data = mooseutils.SQAStats('Total')
data += mooseutils.compute_requirement_stats('test/tests')
data += mooseutils.compute_requirement_stats('stork')
data += mooseutils.compute_requirement_stats('tutorials')
data += mooseutils.compute_requirement_stats('examples')
data += mooseutils.compute_requirement_stats('scripts')
data += mooseutils.compute_requirement_stats('python')
data += mooseutils.compute_requirement_stats('modules/chemical_reactions')
data += mooseutils.compute_requirement_stats('modules/combined')
data += mooseutils.compute_requirement_stats('modules/contact')
data += mooseutils.compute_requirement_stats('modules/external_petsc_solver')
data += mooseutils.compute_requirement_stats('modules/fluid_properties')
data += mooseutils.compute_requirement_stats('modules/functional_expansion_tools')
data += mooseutils.compute_requirement_stats('modules/heat_conduction')
data += mooseutils.compute_requirement_stats('modules/level_set')
data += mooseutils.compute_requirement_stats('modules/misc')
data += mooseutils.compute_requirement_stats('modules/navier_stokes')
data += mooseutils.compute_requirement_stats('modules/phase_field')
data += mooseutils.compute_requirement_stats('modules/porous_flow')
data += mooseutils.compute_requirement_stats('modules/rdg')
data += mooseutils.compute_requirement_stats('modules/richards')
data += mooseutils.compute_requirement_stats('modules/solid_mechanics')
data += mooseutils.compute_requirement_stats('modules/stochastic_tools')
data += mooseutils.compute_requirement_stats('modules/tensor_mechanics')
data += mooseutils.compute_requirement_stats('modules/xfem')
print data

tdata = mooseutils.compute_requirement_stats('', show=False)
if tdata.files != data.files:
msg = 'ERROR: The total number of test files for the supplied directories does not match\n' \
' the number of test files in the repository.'
print mooseutils.colorText(msg, 'RED')

0 comments on commit b894686

Please sign in to comment.
You can’t perform that action at this time.