#!/usr/bin/env python3 # @python3 # @author Kalman Olah """pdoc - a puppet documentation generator thingy.""" import os import re import fnmatch import click from datetime import datetime __VERSION__ = '0.0.1' __DOC_TEMPLATE__ = """ # == {type}: {name} # # Full description of {type} {name} here. # # === Parameters #{parameters} # === Examples # # class {{ 'ntp': # servers => [ 'pool.ntp.org', 'ntp.local.company.com' ], # }} # # === Authors # # {author} <{email}> # # === Copyright # # Copyright {year} {author}, unless otherwise noted. # """ __PARAM_TEMPLATE__ = """ # [*{key}*] # Explanation of what this parameter affects. # Defaults to {value}. # """ def show_version(ctx, value): """Print version information and exit.""" if not value: return click.echo('pdoc %s' % __VERSION__) ctx.exit() @click.command() @click.option('--version', '-v', is_flag=True, help='Print version information and exit.', callback=show_version, expose_value=False, is_eager=True) @click.option('--really', '-r', is_flag=True, help='Really apply changes.') @click.option('--author', '-a', default='John Doe', help='Author name to use in generated documentation.') @click.option('--email', '-e', default='john.doe@domain.com', help='Author email to use in generated documentation.') @click.argument('path', type=click.Path(exists=False, file_okay=True, dir_okay=True, writable=True, readable=True, resolve_path=True), default='./') @click.pass_context def pdoc(ctx, really, author, email, path): """pdoc - a puppet documentation generator thingy.""" # If path if a file stick it into a paths list, if not perform some mad # globbing if os.path.isfile(path): paths = (path) if path.endswith('.pp') else () else: paths = [os.path.join(dirpath, f) for dirpath, dirnames, files in os.walk(path) for f in fnmatch.filter(files, '*.pp')] click.echo('Found %s puppet manifests; iterating..' % click.style(str(len(paths)), fg='green', bold=True)) for p in paths: # Read first character of the file: if it's a hashtag it means we have # docs; if it's not, we should add docs with open(p, 'r') as file: first = file.read(1) # If the first character is a hashtag, do nothing if first is '#': continue click.echo('Adding documentation to %s' % click.style(p, fg='blue', bold=True)) # Grab file contents so we can do matching and stuff with open(p, 'r') as file: content = file.read() # Try to extract type, name and parameters pattern = re.compile(r"\s*(\w+)\s+([\w:]+)[\s\w:]*([\"'\w\s,=\$\(\):]*)\s*{.*}\s*", re.DOTALL) matches = re.match(pattern, content) type = 'type' if matches.group(1) is 'define' else matches.group(1) name = matches.group(2) parameters = '' params = re.sub(r"[\s\(\)]", '', matches.group(3)) params = re.split(',', params) for param in params: split = re.split('=', param) value = split[1] if len(split) > 1 else 'undef' parameters += __PARAM_TEMPLATE__.rstrip().format(key=split[0], value=value) docs = __DOC_TEMPLATE__.strip().format( type=type, name=name, parameters=parameters, author=author, email=email, year=datetime.utcnow().year ) if really: with open(p, 'w') as file: file.write(docs + '\n' + content) click.echo(click.style('Done!', fg='green', bold=True)) """Standard import guard.""" if __name__ == '__main__': pdoc(obj={}, auto_envvar_prefix='PDOC')