Пример #1
0
def Acryl():
    """The main function that dispatches the CLI.  We use :class:`AcrylFormatter`
    as custom help formatter that ommits the useless list of available subcommands
    and their aliases.

    All flags from acrylamid --help are also available in subcommands altough not
    explicitely printed in their help."""

    parser = argparse.ArgumentParser(
        parents=[], formatter_class=AcrylFormatter
    )
    parser.add_argument("-v", "--verbose", action="store_const", dest="verbosity",
        help="more verbose", const=log.SKIP, default=log.INFO)
    parser.add_argument("-q", "--quiet", action="store_const", dest="verbosity",
        help="less verbose", const=log.WARN)
    parser.add_argument("-C", "--no-color", action="store_false", dest="colors",
        help="disable color", default=True)
    parser.add_argument("--conf", dest="conf", help="alternate conf.py",
        default="conf.py", metavar="/path/to/conf")
    parser.add_argument("--version", action="version",
        version=colors.blue('Acrylamid ') + dist.version)

    subparsers = parser.add_subparsers(dest="parser")

    # a repeat yourself of default arguments but not visible on subcommand --help
    default = argparse.ArgumentParser(add_help=False)
    default.add_argument("-v", "--verbose", action="store_const", dest="verbosity",
        help=argparse.SUPPRESS, const=log.SKIP, default=log.INFO)
    default.add_argument("-q", "--quiet", action="store_const", dest="verbosity",
        help=argparse.SUPPRESS, const=log.WARN)
    default.add_argument("-C", "--no-color", action="store_false", dest="colors",
        help=argparse.SUPPRESS, default=True)

    # --- gen params --- #
    generate = subparsers.add_parser('compile', help='compile blog', parents=[default])
    generate.add_argument("-f", "--force", action="store_true", dest="force",
        help="clear cache before compilation", default=False)
    generate.add_argument("-n", "--dry-run", dest="dryrun", action='store_true',
        help="show what would have been compiled", default=False)
    generate.add_argument("--ignore", dest="ignore", action="store_true",
        help="ignore critical errors", default=False)
    generate.add_argument("--search", dest="search", action="store_true",
        help="build search index", default=False)

    # --- webserver params --- #
    view = subparsers.add_parser('view', help="fire up built-in webserver", parents=[default])
    view.add_argument("-p", "--port", dest="port", type=int, default=8000,
        help="webserver port")

    # --- aco params --- #
    autocompile = subparsers.add_parser('autocompile', help="automatic compilation and serving",
        parents=[default])
    autocompile.add_argument("-f", "--force", action="store_true", dest="force",
        help="clear cache before compilation", default=False)
    autocompile.add_argument("-n", "--dry-run", dest="dryrun", action='store_true',
        help="show what would have been compiled", default=False)
    autocompile.add_argument("--ignore", dest="ignore", action="store_true",
        help="ignore critical errors", default=False)
    autocompile.add_argument("--search", dest="search", action="store_true",
        help="build search index", default=False)
    autocompile.add_argument("-p", "--port", dest="port", type=int, default=8000,
        help="webserver port")

    for alias in ('co', 'gen', 'generate'):
        subparsers._name_parser_map[alias] = generate

    for alias in ('serve', 'srv'):
        subparsers._name_parser_map[alias] = view

    subparsers._name_parser_map['aco'] = autocompile

    # temporary log to catch issues during task initialization
    log.init('temporary', level=log.WARN, colors=False)

    # initialize other tasks
    tasks.initialize(subparsers, default)

    # parse args
    options = parser.parse_args()

    # initialize colored logger
    log.init('acrylamid', level=options.verbosity, colors=options.colors)

    env = core.Environment({'author': __author__, 'url': __url__,
        'options': options, 'globals': Struct()})

    try:
        conf = core.load(options.conf)
    except IOError:
        log.critical('no conf.py found. Are you inside your blog?')
        sys.exit(1)
    except Exception as e:
        log.critical("%s in `conf.py`" % e.__class__.__name__)
        traceback.print_exc(file=sys.stdout)
        sys.exit(1)


    # -- run -- #
    if options.parser in ('gen', 'generate', 'co', 'compile'):
        log.setLevel(options.verbosity)
        try:
            commands.compile(conf, env)
        except AcrylamidException as e:
            log.exception(e.args[0])
            sys.exit(1)

    elif options.parser in ('srv', 'serve', 'view'):
        from acrylamid.lib.httpd import Webserver
        ws = partial(Webserver, options.port, conf['output_dir'])
        ws = ws(log.info) if options.verbosity < 20 else ws(); ws.start()
        log.info(' * Running on http://127.0.0.1:%i/' % options.port)

        try:
            while True:
                time.sleep(1)
        except (SystemExit, KeyboardInterrupt) as e:
            ws.kill_received = True
            sys.exit(0)

    elif options.parser in ('aco', 'autocompile'):
        from acrylamid.lib.httpd import Webserver
        # XXX compile on request _or_ use inotify/fsevent
        ws = Webserver(options.port, conf['output_dir']); ws.start()
        log.info(' * Running on http://127.0.0.1:%i/' % options.port)

        try:
            commands.autocompile(ws, conf, env)
        except (SystemExit, KeyboardInterrupt) as e:
            ws.kill_received = True
            log.error(e.args[0])
            traceback.print_exc(file=sys.stdout)
            sys.exit(0)

    elif options.parser in tasks.collected:
        try:
            tasks.collected[options.parser](conf, env, options)
        except AcrylamidException as e:
            log.exception('uncaught exception')
            sys.exit(1)
    else:
        log.critical('No such command!')
        sys.exit(2)

    sys.exit(0)
Пример #2
0
def Acryl():
    """The main function that dispatches the CLI.  We use :class:`AcrylFormatter`
    as custom help formatter that ommits the useless list of available subcommands
    and their aliases.

    All flags from acrylamid --help are also available in subcommands altough not
    explicitely printed in their help."""

    parser = argparse.ArgumentParser(
        parents=[], formatter_class=AcrylFormatter
    )
    parser.add_argument("-v", "--verbose", action="store_const", dest="verbosity",
        help="more verbose", const=log.SKIP, default=log.INFO)
    parser.add_argument("-q", "--quiet", action="store_const", dest="verbosity",
        help="less verbose", const=log.WARN)
    parser.add_argument("-C", "--no-color", action="store_false", dest="colors",
        help="disable color", default=True)
    parser.add_argument("--version", action="version",
        version=colors.blue('acrylamid ') + __version__)

    subparsers = parser.add_subparsers(dest="parser")

    # a repeat yourself of default arguments but not visible on subcommand --help
    default = argparse.ArgumentParser(add_help=False)
    default.add_argument("-v", "--verbose", action="store_const", dest="verbosity",
        help=argparse.SUPPRESS, const=log.SKIP, default=log.INFO)
    default.add_argument("-q", "--quiet", action="store_const", dest="verbosity",
        help=argparse.SUPPRESS, const=log.WARN)
    default.add_argument("-C", "--no-color", action="store_false", dest="colors",
        help=argparse.SUPPRESS, default=True)

    # --- gen params --- #
    generate = subparsers.add_parser('compile', help='compile blog', parents=[default])
    generate.add_argument("-f", "--force", action="store_true", dest="force",
        help="clear cache before compilation", default=False)
    generate.add_argument("-n", "--dry-run", dest="dryrun", action='store_true',
        help="show what would have been compiled", default=False)
    generate.add_argument("-i", "--ignore", dest="ignore", action="store_true",
        help="ignore critical errors", default=False)

    # --- webserver params --- #
    view = subparsers.add_parser('view', help="fire up built-in webserver", parents=[default])
    view.add_argument("-p", "--port", dest="port", type=int, default=8000,
        help="webserver port")

    # --- aco params --- #
    autocompile = subparsers.add_parser('autocompile', help="automatic compilation and serving",
        parents=[default])
    autocompile.add_argument("-f", "--force", action="store_true", dest="force",
        help="clear cache before compilation", default=False)
    autocompile.add_argument("-n", "--dry-run", dest="dryrun", action='store_true',
        help="show what would have been compiled", default=False)
    autocompile.add_argument("-i", "--ignore", dest="ignore", action="store_true",
        help="ignore critical errors", default=False)
    autocompile.add_argument("-p", "--port", dest="port", type=int, default=8000,
        help="webserver port")

    for alias in ('co', 'gen', 'generate'):
        subparsers._name_parser_map[alias] = generate

    for alias in ('serve', 'srv'):
        subparsers._name_parser_map[alias] = view

    subparsers._name_parser_map['aco'] = autocompile

    new = subparsers.add_parser('new', help="create a new entry", parents=[default],
        epilog=("Takes all leading [args] as title or prompt if none given. creates "
                "a new entry based on your PERMALINK_FORMAT and opens it with your "
                "favourite $EDITOR."))
    new.add_argument("title", nargs="*", default='')

    # initialize other tasks
    tasks.initialize(subparsers, default)

    # parse args
    options = parser.parse_args()

    # initialize colored logger
    log.init('acrylamid', level=options.verbosity, colors=options.colors)

    env = Struct({'version': __version__, 'author': __author__, 'url': __url__})

    env['options'] = options
    env['globals'] = Struct()

    # -- init -- #
    # TODO: acrylamid init --layout_dir=somedir to overwrite defaults
    if options.parser in ('init', ):
        tasks.collected[options.parser](env, options)
        sys.exit(0)

    # -- teh real thing -- #
    conf = Struct(defaults.conf)

    try:
        ns = dict([(k.upper(), v) for k, v in defaults.conf.iteritems()])
        os.chdir(os.path.dirname(find('conf.py', os.getcwd())))
        execfile('conf.py', ns)
        conf.update(dict([(k.lower(), ns[k]) for k in ns if k.upper() == k]))
    except IOError:
        log.critical('no conf.py found. Try "acrylamid init".')
        sys.exit(1)
    except Exception as e:
        log.critical("%s in `conf.py`" % e.__class__.__name__)
        traceback.print_exc(file=sys.stdout)
        sys.exit(1)

    conf['output_dir'] = conf.get('output_dir', 'output/')
    conf['content_dir'] = conf.get('content_dir', 'content/')
    conf['layout_dir'] = conf.get('layout_dir', 'layouts/')

    # -- run -- #
    if options.parser in ('gen', 'generate', 'co', 'compile'):
        log.setLevel(options.verbosity)
        try:
            commands.compile(conf, env, **options.__dict__)
        except AcrylamidException as e:
            log.fatal(e.args[0])
            sys.exit(1)

    elif options.parser in ('new', 'create'):
        try:
            commands.new(conf, env, title=' '.join(options.title), prompt=log.level()<log.WARN)
        except AcrylamidException as e:
            log.fatal(e.args[0])
            sys.exit(1)

    elif options.parser in ('srv', 'serve', 'view'):
        from acrylamid.lib.httpd import Webserver
        ws = Webserver(options.port, conf['output_dir']); ws.start()
        log.info(' * Running on http://127.0.0.1:%i/' % options.port)

        try:
            while True:
                time.sleep(1)
        except (SystemExit, KeyboardInterrupt, Exception) as e:
            ws.kill_received = True
            sys.exit(0)

    elif options.parser in ('aco', 'autocompile'):
        from acrylamid.lib.httpd import Webserver
        # XXX compile on request _or_ use inotify/fsevent
        ws = Webserver(options.port, conf['output_dir']); ws.start()
        log.info(' * Running on http://127.0.0.1:%i/' % options.port)

        try:
            commands.autocompile(ws, conf, env, **options.__dict__)
        except (SystemExit, KeyboardInterrupt, Exception) as e:
            ws.kill_received = True
            log.error(e.args[0])
            traceback.print_exc(file=sys.stdout)
            sys.exit(0)

    elif options.parser in tasks.collected:
        try:
            tasks.collected[options.parser](conf, env, options)
        except AcrylamidException as e:
            log.critical(e.args[0])
            sys.exit(1)
    else:
        log.critical('No such command!')
        sys.exit(2)

    sys.exit(0)
Пример #3
0
def init(env, options):
    """Subcommand: init -- creates the base structure of an Acrylamid blog
    or restores individual files."""

    root = options.dest

    if not options.engine:
        try:
            import jinja2
            options.engine = 'jinja2'
        except ImportError:
            options.engine = 'mako'

    def create(directory, path):
        """A shortcut for check if exists and shutil.copy to."""

        dest = join(root, directory, basename(path))
        if not isfile(dest) or options.overwrite == True:
            try:
                shutil.copy(path, dest)
                log.info('create  %s', dest)
            except IOError as e:
                log.fatal(unicode(e))
        else:
            log.info('skip  %s already exists', dest)

    default = defaults.conf

    default['output_dir'] = default['output_dir'].rstrip('/')
    default['content_dir'] = default['content_dir'].rstrip('/')
    default['layout_dir'] = default['layout_dir'].rstrip('/')

    dirs = [
        '%(content_dir)s/', '%(layout_dir)s/', '%(output_dir)s/', '.cache/'
    ]

    files = [
        p % {
            'engine': options.engine,
            'theme': options.theme
        } for p in [
            '%(engine)s/%(theme)s/base.html', '%(engine)s/%(theme)s/main.html',
            '%(engine)s/%(theme)s/entry.html',
            '%(engine)s/%(theme)s/articles.html', '%(engine)s/rss.xml',
            '%(engine)s/atom.xml', 'misc/%(theme)s/style.css',
            'misc/sample-entry.txt'
        ]
    ]
    files = [join(dirname(defaults.__file__), path) for path in files]

    # restore a given file from defaults
    # XXX restore folders, too
    if filter(lambda p: basename(p) == basename(root), files):

        for path in files:
            if basename(path) == basename(root):
                break
        if isfile(root) and (options.overwrite or raw_input(
                're-initialize %r? [yn]: ' % root) == 'y'):
            shutil.copy(path, root)
            log.info('re-initialized %s' % root)
        else:
            shutil.copy(path, root)
            log.info('create %s' % root)
        sys.exit(0)

    # re-initialize conf.py
    if root == 'conf.py':
        if options.overwrite or raw_input(
                're-initialize %r? [yn]: ' % root) == 'y':
            with io.open('conf.py', 'w') as fp:
                fp.write(confstring % {'engine': options.engine})
            log.info('re-initialized %s' % root)
        sys.exit(0)

    # YO DAWG I HERD U LIEK BLOGS SO WE PUT A BLOG IN UR BLOG -- ask user before
    if isfile('conf.py') and not options.overwrite:
        q = raw_input("Create blog inside a blog? [yn]: ")
        if q != 'y':
            sys.exit(1)

    if exists(root) and len(os.listdir(root)) > 0 and not options.overwrite:
        if raw_input(
                "Destination directory not empty! Continue? [yn]: ") != 'y':
            sys.exit(1)

    if root != '.' and not exists(root):
        os.mkdir(root)

    for directory in dirs:
        directory = join(root, directory % default)
        if exists(directory) and not isdir(directory):
            log.critical('Unable to create %r. Please remove this file',
                         directory)
            sys.exit(1)
        elif not exists(directory):
            os.mkdir(directory)

    with io.open(join(root, 'conf.py'), 'w') as fp:
        fp.write(confstring % {'engine': options.engine})
        log.info('create  %s', join(root, 'conf.py'))

    for path in files:
        if path.endswith(('.html', '.xml')):
            create(default['layout_dir'], path)
        elif path.endswith('.txt'):
            create(default['content_dir'], path)
        else:
            create(default['output_dir'], path)

    log.info('Created your fresh new blog at %r. Enjoy!', root)
Пример #4
0
    def __init__(self, conf=None):
        """Sets configuration and environment and creates the Request
        object"""

        global sys

        usage = "usage: %prog <subcommand> [options] [args]"
        epilog = None

        options, constants = (
            [],
            [
                make_option("-h", "--help", action="store_true", help=SUPPRESS_HELP),
                make_option(
                    "-v", "--verbose", action="store_const", dest="verbosity", help=SUPPRESS_HELP, const=log.SKIP
                ),
                make_option(
                    "-q",
                    "--quit",
                    action="store_const",
                    dest="verbosity",
                    help=SUPPRESS_HELP,
                    const=log.WARN,
                    default=log.INFO,
                ),
                make_option("-C", "--no-color", action="store_false", dest="colors", default=True, help=SUPPRESS_HELP),
                make_option("--version", action="store_true", dest="version", help=SUPPRESS_HELP, default=False),
            ],
        )

        # reorder `prog help foo` and `prog --help foo`
        if len(sys.argv) > 2 and sys.argv[1] in ("--help", "help"):
            sys.argv[1], sys.argv[2] = sys.argv[2], "--help"

        if len(sys.argv) <= 1 or sys.argv[1] in ("-h", "--help", "help"):
            options, constants = (
                [],
                [
                    make_option(
                        "-q",
                        "--quiet",
                        action="store_const",
                        dest="verbosity",
                        help="less verbose",
                        const=log.WARN,
                        default=log.INFO,
                    ),
                    make_option(
                        "-v", "--verbose", action="store_const", dest="verbosity", help="more verbose", const=log.SKIP
                    ),
                    make_option(
                        "-C", "--no-color", action="store_false", dest="colors", default=True, help="disable color"
                    ),
                    make_option("-h", "--help", action="store_true", help="show this help message and exit"),
                    make_option(
                        "--version", action="store_true", dest="version", help="print version details", default=False
                    ),
                ],
            )
            epilog = (
                "Commands:\n"
                "  init           initializes base structure in DIR\n"
                "  create  (new)  creates a new entry\n"
                "  compile (co)   compile blog\n"
                "  view           fire up built-in webserver\n"
                "  autocompile    automatic compilation and serving (short aco)\n"
                "  clean   (rm)   remove abandoned files\n"
                "  import         import content from URL\n"
                "  deploy         run a given TASK\n"
                "\nAll subcommands except `init` require a conf.py file.\n"
            )

        # --- init params --- #
        elif sys.argv[1] in ("init", "initialize"):
            usage = "%prog " + sys.argv[1] + " [DEST|FILE] [-p]"
            options = [
                make_option(
                    "-f", "--force", action="store_true", dest="force", help="don't ask, just overwrite", default=False
                ),
                make_option(
                    "--xhtml",
                    action="store_const",
                    dest="theme",
                    const="xhtml",
                    help="use XHTML theme",
                    default="html5",
                ),
                make_option("--html5", action="store_const", dest="theme", const="html5", help="use HTML5 theme"),
            ]
        # --- init params --- #
        elif sys.argv[1] in ("new",):
            usage = "%prog " + sys.argv[1] + " [args]"
            epilog = (
                "Takes all leading [args] as title or prompt if none given. creates "
                "a new entry based on your PERMALINK_FORMAT and opens it with your "
                "favourite EDITOR."
            )
            epilog = fill(epilog) + "\n"
        # --- gen params --- #
        elif sys.argv[1] in ("compile", "co", "generate", "gen"):
            usage = "%prog " + sys.argv[1] + " [-fn]"
            options = [
                make_option(
                    "-f",
                    "--force",
                    action="store_true",
                    dest="force",
                    help="clear cache before compilation",
                    default=False,
                ),
                make_option(
                    "-n",
                    "--dry-run",
                    dest="dryrun",
                    action="store_true",
                    default=False,
                    help="show what would have been compiled",
                ),
                make_option(
                    "-i", "--ignore", dest="ignore", action="store_true", default=False, help="ignore critical errors"
                ),
            ]
        # --- webserver params --- #
        elif sys.argv[1] in ("view", "serve", "srv"):
            usage = "%prog " + sys.argv[1] + " [-p]"
            options = [make_option("-p", "--port", dest="port", type=int, default=8000, help="webserver port")]
        # --- autocompile params --- #
        elif sys.argv[1] in ("autocompile", "aco"):
            usage = "%prog " + sys.argv[1] + " [-pf]"
            options = [
                make_option(
                    "-f",
                    "--force",
                    action="store_true",
                    dest="force",
                    help="clear cache before compilation",
                    default=False,
                ),
                make_option(
                    "-i", "--ignore", dest="ignore", action="store_true", default=False, help="ignore critical errors"
                ),
                make_option("-p", "--port", dest="port", type=int, default=8000, help="webserver port"),
            ]
        # --- import params --- #
        elif sys.argv[1] in ("import",):
            usage = "%prog " + sys.argv[1] + " [-mk]"
            options = [
                make_option("-m", dest="import_fmt", default="Markdown", help="reconvert HTML to MARKUP"),
                make_option("-k", "--keep-links", dest="keep_links", action="store_true", help="keep permanent links"),
            ]

        else:
            tasks = get_tasks()
            if sys.argv[1] in tasks:
                usage = tasks[sys.argv[1]].usage
                options = tasks[sys.argv[1]].options

        class AcrylParser(OptionParser):
            # -- http://stackoverflow.com/q/1857346
            def format_epilog(self, formatter):
                if epilog is None:
                    return ""
                return "\n" + self.epilog

        parser = AcrylParser(option_list=options + constants, usage=usage, add_help_option=False, epilog=epilog)
        (options, args) = parser.parse_args()

        if len(sys.argv) <= 1 or sys.argv[1] == "help" or options.help:
            parser.print_help()
            sys.exit(0)

        # initialize colored logger
        log.init("acrylamid", level=options.verbosity, colors=options.colors)

        env = Environment({"version": __version__, "author": __author__, "url": __url__})
        env["options"] = options

        if options.version:
            print "acrylamid " + env.version
            sys.exit(0)

        # -- init -- #
        # TODO: acrylamid init --layout_dir=somedir to overwrite defaults

        if "init" in args:
            if len(args) == 2:
                defaults.init(args[1], options.theme, options.force)
            else:
                defaults.init(".", options.theme, options.force)
            sys.exit(0)

        # -- teh real thing -- #
        conf = defaults.conf

        try:
            ns = dict([(k.upper(), v) for k, v in defaults.conf.iteritems()])
            execfile("conf.py", ns)
            conf.update(dict([(k.lower(), ns[k]) for k in ns if k.upper() == k]))
        except OSError:
            log.critical('no config file found: %s. Try "acrylamid init".', options.conf)
            sys.exit(1)
        except Exception, e:
            log.critical("%s in `conf.py`" % e.__class__.__name__)
            traceback.print_exc(file=sys.stdout)
            sys.exit(1)
Пример #5
0
def Acryl():
    """The main function that dispatches the CLI.  We use :class:`AcrylFormatter`
    as custom help formatter that ommits the useless list of available subcommands
    and their aliases.

    All flags from acrylamid --help are also available in subcommands altough not
    explicitely printed in their help."""

    parser = argparse.ArgumentParser(
        parents=[], formatter_class=AcrylFormatter
    )
    parser.add_argument("-v", "--verbose", action="store_const", dest="verbosity",
        help="more verbose", const=log.SKIP, default=log.INFO)
    parser.add_argument("-q", "--quiet", action="store_const", dest="verbosity",
        help="less verbose", const=log.WARN)
    parser.add_argument("-C", "--no-color", action="store_false", dest="colors",
        help="disable color", default=True)
    parser.add_argument("--version", action="version",
        version=colors.blue('acrylamid ') + __version__)

    subparsers = parser.add_subparsers(dest="parser")

    # a repeat yourself of default arguments but not visible on subcommand --help
    default = argparse.ArgumentParser(add_help=False)
    default.add_argument("-v", "--verbose", action="store_const", dest="verbosity",
        help=argparse.SUPPRESS, const=log.SKIP, default=log.INFO)
    default.add_argument("-q", "--quiet", action="store_const", dest="verbosity",
        help=argparse.SUPPRESS, const=log.WARN)
    default.add_argument("-C", "--no-color", action="store_false", dest="colors",
        help=argparse.SUPPRESS, default=True)

    # --- init params --- #
    init = subparsers.add_parser('init', help='initializes base structure in DIR',
        parents=[default, ])
    init.add_argument("dest", metavar="DEST|FILE", nargs="?")
    init.add_argument("-f", "--force", action="store_true", dest="force",
        help="don't ask, just overwrite", default=False)
    init.add_argument("--xhtml", action="store_const", dest="theme", const="xhtml",
        help="use XHTML theme", default="html5")
    init.add_argument("--html5", action="store_const", dest="theme", const="html5",
        help="use HTML5 theme (default)")
    init.add_argument("--mako", action="store_const", dest="engine", const="mako",
        help="use the Mako template engine", default="jinja2")
    init.add_argument("--jinja2", action="store_const", dest="engine", const="jinja2",
        help="use the Jinja2 template engine (default)")

    # --- gen params --- #
    generate = subparsers.add_parser('compile', help='compile blog', parents=[default])
    generate.add_argument("-f", "--force", action="store_true", dest="force",
        help="clear cache before compilation", default=False)
    generate.add_argument("-n", "--dry-run", dest="dryrun", action='store_true',
        help="show what would have been compiled", default=False)
    generate.add_argument("-i", "--ignore", dest="ignore", action="store_true",
        help="ignore critical errors", default=False)

    # --- webserver params --- #
    view = subparsers.add_parser('view', help="fire up built-in webserver", parents=[default])
    view.add_argument("-p", "--port", dest="port", type=int, default=8000,
        help="webserver port")

    # --- aco params --- #
    autocompile = subparsers.add_parser('autocompile', help="automatic compilation and serving",
        parents=[default])
    autocompile.add_argument("-f", "--force", action="store_true", dest="force",
        help="clear cache before compilation", default=False)
    autocompile.add_argument("-n", "--dry-run", dest="dryrun", action='store_true',
        help="show what would have been compiled", default=False)
    autocompile.add_argument("-i", "--ignore", dest="ignore", action="store_true",
        help="ignore critical errors", default=False)
    autocompile.add_argument("-p", "--port", dest="port", type=int, default=8000,
        help="webserver port")

    # --- import params --- #
    importer = subparsers.add_parser('import', help="import content from URL or FILE",
        parents=[default])
    importer.add_argument("src", metavar="FILE|URL")
    importer.add_argument("-f", "--force", dest="force", action="store_true",
        help="overwrite existing entries", default=False)
    importer.add_argument("-m", dest="fmt", default="Markdown", help="reconvert HTML to FMT")
    importer.add_argument("-k", "--keep-links", dest="keep", action="store_true",
        help="keep permanent links", default=False)
    importer.add_argument("-p", "--pandoc", dest="pandoc", action="store_true",
        help="use pandoc first", default=False)
    importer.add_argument("-a", dest="args", nargs="+", action="store", type=str,
        help="add argument to header section", default=[])

    for alias in ('co', 'gen', 'generate'):
        subparsers._name_parser_map[alias] = generate

    for alias in ('serve', 'srv'):
        subparsers._name_parser_map[alias] = view

    subparsers._name_parser_map['aco'] = autocompile

    new = subparsers.add_parser('new', help="create a new entry", parents=[default],
        epilog=("Takes all leading [args] as title or prompt if none given. creates "
                "a new entry based on your PERMALINK_FORMAT and opens it with your "
                "favourite $EDITOR."))
    new.add_argument("title", nargs="*", default='')

    # initialize other tasks
    tasks.initialize(subparsers, default)

    # parse args
    options = parser.parse_args()

    # initialize colored logger
    log.init('acrylamid', level=options.verbosity, colors=options.colors)

    env = Struct({'version': __version__, 'author': __author__, 'url': __url__})

    env['options'] = options
    env['globals'] = Struct()

    # -- init -- #
    # TODO: acrylamid init --layout_dir=somedir to overwrite defaults
    if options.parser in ('init', ):
        defaults.init(options.dest if options.dest else '.', options.theme, options.engine, options.force)
        sys.exit(0)

    # -- teh real thing -- #
    conf = Struct(defaults.conf)

    try:
        ns = dict([(k.upper(), v) for k, v in defaults.conf.iteritems()])
        execfile('conf.py', ns)
        conf.update(dict([(k.lower(), ns[k]) for k in ns if k.upper() == k]))
    except OSError:
        log.critical('no config file found: %s. Try "acrylamid init".', options.conf)
        sys.exit(1)
    except Exception, e:
        log.critical("%s in `conf.py`" % e.__class__.__name__)
        traceback.print_exc(file=sys.stdout)
        sys.exit(1)
Пример #6
0
        # XXX compile on request _or_ use inotify/fsevent
        ws = Webserver(options.port, conf['output_dir']); ws.start()
        log.info(' * Running on http://127.0.0.1:%i/' % options.port)

        try:
            commands.autocompile(ws, conf, env, **options.__dict__)
        except (SystemExit, KeyboardInterrupt, Exception) as e:
            ws.kill_received = True
            log.error(e.args[0])
            traceback.print_exc(file=sys.stdout)
            sys.exit(0)

    elif options.parser in ('import', ):
        try:
            commands.imprt(conf, env, options)
        except AcrylamidException as e:
            log.critical(e.args[0])
            sys.exit(1)

    elif options.parser in tasks.collected:
        try:
            tasks.collected[options.parser](conf, env, options)
        except AcrylamidException as e:
            log.critical(e.args[0])
            sys.exit(1)
    else:
        log.critical('No such command!')
        sys.exit(2)

    sys.exit(0)
Пример #7
0
def Acryl():
    """The main function that dispatches the CLI.  We use :class:`AcrylFormatter`
    as custom help formatter that ommits the useless list of available subcommands
    and their aliases.

    All flags from acrylamid --help are also available in subcommands altough not
    explicitely printed in their help."""

    parser = argparse.ArgumentParser(parents=[], formatter_class=AcrylFormatter)
    parser.add_argument(
        "-v", "--verbose", action="store_const", dest="verbosity", help="more verbose", const=log.SKIP, default=log.INFO
    )
    parser.add_argument("-q", "--quiet", action="store_const", dest="verbosity", help="less verbose", const=log.WARN)
    parser.add_argument("-C", "--no-color", action="store_false", dest="colors", help="disable color", default=True)
    parser.add_argument("--version", action="version", version=colors.blue("acrylamid ") + __version__)

    subparsers = parser.add_subparsers(dest="parser")

    # a repeat yourself of default arguments but not visible on subcommand --help
    default = argparse.ArgumentParser(add_help=False)
    default.add_argument(
        "-v",
        "--verbose",
        action="store_const",
        dest="verbosity",
        help=argparse.SUPPRESS,
        const=log.SKIP,
        default=log.INFO,
    )
    default.add_argument(
        "-q", "--quiet", action="store_const", dest="verbosity", help=argparse.SUPPRESS, const=log.WARN
    )
    default.add_argument("-C", "--no-color", action="store_false", dest="colors", help=argparse.SUPPRESS, default=True)

    # --- gen params --- #
    generate = subparsers.add_parser("compile", help="compile blog", parents=[default])
    generate.add_argument(
        "-f", "--force", action="store_true", dest="force", help="clear cache before compilation", default=False
    )
    generate.add_argument(
        "-n", "--dry-run", dest="dryrun", action="store_true", help="show what would have been compiled", default=False
    )
    generate.add_argument(
        "-i", "--ignore", dest="ignore", action="store_true", help="ignore critical errors", default=False
    )

    # --- webserver params --- #
    view = subparsers.add_parser("view", help="fire up built-in webserver", parents=[default])
    view.add_argument("-p", "--port", dest="port", type=int, default=8000, help="webserver port")

    # --- aco params --- #
    autocompile = subparsers.add_parser("autocompile", help="automatic compilation and serving", parents=[default])
    autocompile.add_argument(
        "-f", "--force", action="store_true", dest="force", help="clear cache before compilation", default=False
    )
    autocompile.add_argument(
        "-n", "--dry-run", dest="dryrun", action="store_true", help="show what would have been compiled", default=False
    )
    autocompile.add_argument(
        "-i", "--ignore", dest="ignore", action="store_true", help="ignore critical errors", default=False
    )
    autocompile.add_argument("-p", "--port", dest="port", type=int, default=8000, help="webserver port")

    for alias in ("co", "gen", "generate"):
        subparsers._name_parser_map[alias] = generate

    for alias in ("serve", "srv"):
        subparsers._name_parser_map[alias] = view

    subparsers._name_parser_map["aco"] = autocompile

    # initialize other tasks
    tasks.initialize(subparsers, default)

    # parse args
    options = parser.parse_args()

    # initialize colored logger
    log.init("acrylamid", level=options.verbosity, colors=options.colors)

    env = Struct({"version": __version__, "author": __author__, "url": __url__})

    env["options"] = options
    env["globals"] = Struct()

    # -- init -- #
    try:
        if options.parser in ("init",):
            tasks.collected[options.parser](env, options)
            sys.exit(0)
    except AcrylamidException as e:
        log.fatal(e.args[0])
        sys.exit(1)

    # -- teh real thing -- #
    conf = Struct(defaults.conf)

    try:
        ns = dict([(k.upper(), v) for k, v in defaults.conf.iteritems()])
        os.chdir(os.path.dirname(find("conf.py", os.getcwd())))
        execfile("conf.py", ns)
        conf.update(dict([(k.lower(), ns[k]) for k in ns if k.upper() == k]))
    except IOError:
        log.critical('no conf.py found. Try "acrylamid init".')
        sys.exit(1)
    except Exception as e:
        log.critical("%s in `conf.py`" % e.__class__.__name__)
        traceback.print_exc(file=sys.stdout)
        sys.exit(1)

    # -- run -- #
    if options.parser in ("gen", "generate", "co", "compile"):
        log.setLevel(options.verbosity)
        try:
            commands.compile(conf, env, **options.__dict__)
        except AcrylamidException as e:
            log.fatal(e.args[0])
            sys.exit(1)

    elif options.parser in ("srv", "serve", "view"):
        from acrylamid.lib.httpd import Webserver

        ws = partial(Webserver, options.port, conf["output_dir"])
        ws = ws(log.info) if options.verbosity < 20 else ws()
        ws.start()
        log.info(" * Running on http://127.0.0.1:%i/" % options.port)

        try:
            while True:
                time.sleep(1)
        except (SystemExit, KeyboardInterrupt, Exception) as e:
            ws.kill_received = True
            sys.exit(0)

    elif options.parser in ("aco", "autocompile"):
        from acrylamid.lib.httpd import Webserver

        # XXX compile on request _or_ use inotify/fsevent
        ws = Webserver(options.port, conf["output_dir"])
        ws.start()
        log.info(" * Running on http://127.0.0.1:%i/" % options.port)

        try:
            commands.autocompile(ws, conf, env, **options.__dict__)
        except (SystemExit, KeyboardInterrupt, Exception) as e:
            ws.kill_received = True
            log.error(e.args[0])
            traceback.print_exc(file=sys.stdout)
            sys.exit(0)

    elif options.parser in tasks.collected:
        try:
            tasks.collected[options.parser](conf, env, options)
        except AcrylamidException as e:
            log.critical(e.args[0])
            sys.exit(1)
    else:
        log.critical("No such command!")
        sys.exit(2)

    sys.exit(0)
Пример #8
0
def init(env, options):
    """Subcommand: init -- creates the base structure of an Acrylamid blog
    or restores individual files."""

    root = options.dest

    if not options.engine:
        try:
            import jinja2
            options.engine = 'jinja2'
        except ImportError:
            options.engine = 'mako'

    def create(directory, path):
        """A shortcut for check if exists and shutil.copy to."""

        dest = join(root, directory, basename(path))
        if not isfile(dest) or options.overwrite == True:
            try:
                shutil.copy(path, dest)
                log.info('create  %s', dest)
            except IOError as e:
                log.fatal(unicode(e))
        else:
            log.info('skip  %s already exists', dest)

    default = defaults.conf

    default['output_dir'] = default['output_dir'].rstrip('/')
    default['content_dir'] = default['content_dir'].rstrip('/')
    default['layout_dir'] = default['layout_dir'].rstrip('/')

    dirs = ['%(content_dir)s/', '%(layout_dir)s/', '%(output_dir)s/', '.cache/']

    files = [p % {'engine': options.engine, 'theme': options.theme} for p in [
        '%(engine)s/%(theme)s/base.html', '%(engine)s/%(theme)s/main.html',
        '%(engine)s/%(theme)s/entry.html', '%(engine)s/%(theme)s/articles.html',
        '%(engine)s/rss.xml', '%(engine)s/atom.xml',
        'misc/%(theme)s/style.css', 'misc/sample-entry.txt']]
    files = [join(dirname(defaults.__file__), path) for path in files]

    # restore a given file from defaults
    # XXX restore folders, too
    if filter(lambda p: basename(p) == basename(root), files):

        for path in files:
            if basename(path) == basename(root):
                break
        if isfile(root) and (options.overwrite or raw_input('re-initialize %r? [yn]: ' % root) == 'y'):
            shutil.copy(path, root)
            log.info('re-initialized %s' % root)
        else:
            shutil.copy(path, root)
            log.info('create %s' % root)
        sys.exit(0)

    # re-initialize conf.py
    if root == 'conf.py':
        if options.overwrite or raw_input('re-initialize %r? [yn]: ' % root) == 'y':
            with io.open('conf.py', 'w') as fp:
                fp.write(confstring % {'engine': options.engine})
            log.info('re-initialized %s' % root)
        sys.exit(0)

    # YO DAWG I HERD U LIEK BLOGS SO WE PUT A BLOG IN UR BLOG -- ask user before
    if isfile('conf.py') and not options.overwrite:
        q = raw_input("Create blog inside a blog? [yn]: ")
        if q != 'y':
            sys.exit(1)

    if exists(root) and len(os.listdir(root)) > 0 and not options.overwrite:
        if raw_input("Destination directory not empty! Continue? [yn]: ") != 'y':
            sys.exit(1)

    if root != '.' and not exists(root):
        os.mkdir(root)

    for directory in dirs:
        directory = join(root, directory % default)
        if exists(directory) and not isdir(directory):
            log.critical('Unable to create %r. Please remove this file', directory)
            sys.exit(1)
        elif not exists(directory):
            os.mkdir(directory)

    with io.open(join(root, 'conf.py'), 'w') as fp:
        fp.write(confstring % {'engine': options.engine})
        log.info('create  %s', join(root, 'conf.py'))

    for path in files:
        if path.endswith(('.html', '.xml')):
            create(default['layout_dir'], path)
        elif path.endswith('.txt'):
            create(default['content_dir'], path)
        else:
            create(default['output_dir'], path)

    log.info('Created your fresh new blog at %r. Enjoy!', root)