Skip to content

Instantly share code, notes, and snippets.

@kalmanolah
Last active August 29, 2015 14:06
Show Gist options
  • Save kalmanolah/b46de8369003640b6dc8 to your computer and use it in GitHub Desktop.
Save kalmanolah/b46de8369003640b6dc8 to your computer and use it in GitHub Desktop.
pdoc - a puppet documentation generator thingy
#!/usr/bin/env python3
# @python3
# @author Kalman Olah <[email protected]>
"""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='[email protected]', 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')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment