Пример #1
0
def do_summary(conf, env, options):

    limit = options.max if options.max > 0 else 5
    entrylist, pages, translations, drafts = readers.load(conf)

    entrylist = sorted(entrylist + translations + drafts,
                       key=lambda k: k.date,
                       reverse=True)

    print()
    print('Acrylamid', blue(env['version']) + ',', end=' ')
    print('cache size:', blue('%0.2f' % (cache.size / 1024.0**2)) + ' mb')
    print()

    for entry in entrylist[:limit]:
        print('  ',
              green(ago(entry.date.replace(tzinfo=None)).ljust(13)),
              end=' ')
        print(white(entry.title) if entry.draft else normal(entry.title))

    print()
    print('%s published,' % blue(len([e for e in entrylist if not e.draft])),
          end=' ')
    print('%s drafted articles' % blue(len([e for e in entrylist if e.draft])))

    if not isfile(join(conf.get('cache_dir', '.cache/'), 'info')):
        return

    time = localtime(getmtime(join(conf.get('cache_dir', '.cache/'), 'info')))
    print('last compilation at %s' %
          blue(u(strftime(u'%d. %B %Y, %H:%M', time))))
Пример #2
0
def run(conf, env, options):
    """Subcommand: info -- a short overview of a blog."""

    limit = options.max if options.max > 0 else 5
    entrylist = sorted(
        [
            Entry(e, conf)
            for e in utils.filelist(conf["content_dir"], conf.get("entries_ignore", []))
            if utils.istext(e)
        ],
        key=lambda k: k.date,
        reverse=True,
    )

    print
    print "acrylamid", blue(env["version"]) + ",",
    print "cache size:", blue("%0.2f" % (cache.size / 1024.0 ** 2)) + " mb"
    print

    for entry in entrylist[:limit]:
        print "  ", green(ago(entry.date).ljust(13)),
        print white(entry.title) if entry.draft else entry.title

    print
    print "%s published," % blue(len([e for e in entrylist if not e.draft])),
    print "%s drafted articles" % blue(len([e for e in entrylist if e.draft]))

    time = localtime(getmtime(join(conf.get("cache_dir", ".cache/"), "info")))
    print "last compilation at %s" % blue(strftime("%d. %B %Y, %H:%M", time))
Пример #3
0
def do_summary(conf, env, options):

    limit = options.max if options.max > 0 else 5
    entrylist, pages, translations, drafts = readers.load(conf)

    entrylist = sorted(entrylist + translations + drafts,
        key=lambda k: k.date, reverse=True)

    print()
    print('Acrylamid', blue(env['version']) + ',', end=' ')
    print('cache size:', blue('%0.2f' % (cache.size / 1024.0**2)) + ' mb')
    print()

    for entry in entrylist[:limit]:
        print('  ', green(ago(entry.date.replace(tzinfo=None)).ljust(13)), end=' ')
        print(white(entry.title) if entry.draft else normal(entry.title))

    print()
    print('%s published,' % blue(len([e for e in entrylist if not e.draft])), end=' ')
    print('%s drafted articles' % blue(len([e for e in entrylist if e.draft])))

    if not isfile(join(conf.get('cache_dir', '.cache/'), 'info')):
        return

    time = localtime(getmtime(join(conf.get('cache_dir', '.cache/'), 'info')))
    print('last compilation at %s' % blue(u(strftime(u'%d. %B %Y, %H:%M', time))))
Пример #4
0
def breaks(env, firstrun):
    """Return whether the new version may break current configuration and print
    all changes between the current and new version."""

    version = memoize('version') or (0, 4)
    if version >= (env.version.major, env.version.minor):
        return False

    memoize('version', (env.version.major, env.version.minor, env.version.patch))

    if firstrun:
        return False

    broken = False
    print

    for major in range(version[0], env.version.major or 1):
        for minor in range(version[1], env.version.minor):
            rv, hints = changesfor('%i.%i' % (major, minor + 1))
            broken = broken or rv

            print (blue('Acrylamid') + ' %i.%s' % (major, minor+1) + u' – changes').encode('utf-8'),

            if broken:
                print (u'– ' + red('may break something.')).encode('utf-8')
            else:
                print

            print
            print colorize(hints).encode('utf-8')
            print

    return broken
Пример #5
0
def pingback(src, dest, dryrun=False):
    """Makes a pingback request to dest on behalf of src, i.e. effectively
    saying to dest that "the page at src is linking to you"."""
    def search_link(content):
        match = re.search(b'<link rel="pingback" href="([^"]+)" ?/?>', content)
        return match and match.group(1)

    try:
        r = head(dest)
    except (URLError, HTTPError) as e:
        return

    try:
        server_url = r.info().get('X-Pingback', '') or search_link(
            r.read(512 * 1024))
        if server_url:

            print("Pingback", blue(urlparse(server_url).netloc), end='')
            print("from", green(''.join(urlparse(src)[1:3])) + ".")

            if not dryrun:
                server = xmlrpc.client.ServerProxy(server_url)
                server.pingback.ping(src, dest)

    except xmlrpc.client.ProtocolError as e:
        raise AcrylamidException(e.args[0])
Пример #6
0
def pingback(src, dest, dryrun=False):
    """Makes a pingback request to dest on behalf of src, i.e. effectively
    saying to dest that "the page at src is linking to you"."""

    def search_link(content):
        match = re.search(b'<link rel="pingback" href="([^"]+)" ?/?>', content)
        return match and match.group(1)

    try:
        r = head(dest)
    except (URLError, HTTPError) as e:
        return

    try:
        server_url = r.info().get('X-Pingback', '') or search_link(r.read(512 * 1024))
        if server_url:

            print("Pingback", blue(urlparse(server_url).netloc), end='')
            print("from", green(''.join(urlparse(src)[1:3])) + ".")

            if not dryrun:
                server = xmlrpc.client.ServerProxy(server_url)
                server.pingback.ping(src, dest)
    except xmlrpclib.Fault as e:
        log.warn("XML-RPC fault: %d (%s)", e.faultCode, e.faultString)
    except xmlrpc.client.ProtocolError as e:
        raise AcrylamidException(e.args[0])
Пример #7
0
def tweet(entry, conf, dryrun=False):
    """Send a tweet with the title, link and tags from an entry. The first time you
    need to authorize Acrylamid but than it works without any interaction."""

    key = "6k00FRe6w4SZfqEzzzyZVA"
    secret = "fzRfQcqQX4gcZziyLeoI5wSbnFb7GGj2oEh10hnjPUo"

    creds = os.path.expanduser('~/.twitter_oauth')
    if not os.path.exists(creds):
        twitter.oauth_dance("Acrylamid", key, secret, creds)

    oauth_token, oauth_token_secret = twitter.read_token_file(creds)
    t = twitter.Twitter(auth=twitter.OAuth(oauth_token, oauth_token_secret, key, secret))

    tweet = u"New Blog Entry: {0} {1} {2}".format(entry.title,
        helpers.joinurl(conf['www_root'], entry.permalink),
        ' '.join([u'#' + helpers.safeslug(tag) for tag in entry.tags]))

    print('     ', bold(blue("tweet ")), end='')
    print('\n'.join(wrap(tweet.encode('utf8'), subsequent_indent=' '*13)))

    if not dryrun:
        try:
            t.statuses.update(status=tweet.encode('utf8'))
        except twitter.api.TwitterError as e:
            try:
                log.warn("%s" % json.loads(e.response_data)['error'])
            except (ValueError, TypeError):
                log.warn("Twitter: something went wrong...")
Пример #8
0
def tweet(entry, conf, dryrun=False):
    """Send a tweet with the title, link and tags from an entry. The first time you
    need to authorize Acrylamid but than it works without any interaction."""

    key = "6k00FRe6w4SZfqEzzzyZVA"
    secret = "fzRfQcqQX4gcZziyLeoI5wSbnFb7GGj2oEh10hnjPUo"

    creds = os.path.expanduser('~/.twitter_oauth')
    if not os.path.exists(creds):
        twitter.oauth_dance("Acrylamid", key, secret, creds)

    oauth_token, oauth_token_secret = twitter.read_token_file(creds)
    t = twitter.Twitter(
        auth=twitter.OAuth(oauth_token, oauth_token_secret, key, secret))

    tweet = u"New Blog Entry: {0} {1} {2}".format(
        entry.title, helpers.joinurl(conf['www_root'], entry.permalink),
        ' '.join([u'#' + helpers.safeslug(tag) for tag in entry.tags]))

    print('     ', bold(blue("tweet ")), end='')
    print('\n'.join(wrap(tweet.encode('utf8'), subsequent_indent=' ' * 13)))

    if not dryrun:
        try:
            t.statuses.update(status=tweet.encode('utf8'))
        except twitter.api.TwitterError as e:
            try:
                log.warn("%s" % json.loads(e.response_data)['error'])
            except (ValueError, TypeError):
                log.warn("Twitter: something went wrong...")
Пример #9
0
def do_tags(conf, env, options):

    limit = options.max if options.max > 0 else 100
    entrylist = readers.load(conf)[0]

    if options.coverage:
        for tag, entries in sorted(fetch(entrylist).iteritems()):
            if len(entries) <= options.coverage:
                print blue(tag).encode('utf-8'),
                print ', '.join(e.filename.encode('utf-8') for e in entries)
        return

    tags = ['%i %s' % (len(value), key) for key, value in
        sorted(fetch(entrylist).iteritems(), key=lambda k: len(k[1]), reverse=True)]

    colprint(
        list(izip(*list(batch(tags[:limit], ceil(len(tags)/4.0))), fillvalue='')),
        os.popen('stty size', 'r').read().split()[1]
    )
Пример #10
0
def validate(paths, jobs):
    """Validates a list of urls using up to N threads.

    :param paths: a list of HTML files where we search for a-href's
    :param jobs: numbers of threads used to send I/O requests"""

    ahref = re.compile(r'<a [^>]*href="([^"]+)"[^>]*>.*?</a>')
    visited, urls = set(), collections.defaultdict(list)

    def check(url, path):
        """A HEAD request to URL.  If HEAD is not allowed, we try GET."""

        try:
            get(url, timeout=10)
        except HTTPError as e:
            if e.code == 405:
                try:
                    get(url, path, 'GET', True)
                except URLError as e:
                    print '  ' + yellow(e.reason), url
                    print white('  -- ' + path)
            else:
                print '  ' + red(e.code), url
                print white('  -- ' + path)
        except URLError as e:
            print '  ' + yellow(e.reason), url
            print white('  -- ' + path)

    # -- validation
    for path in paths:

        with io.open(path, 'r') as fp:
            data = fp.read()

        for match in ahref.finditer(data):
            a = match.group(1)
            if a.startswith(('http://', 'https://')):
                if a not in visited:
                    visited.add(a)
                    urls[path].append(a)

    print
    print "Trying", blue(len(visited)), "links..."
    print

    pool = Threadpool(jobs)
    for path in urls:
        for url in urls[path]:
            pool.add_task(check, *[unescape(url), path])

    try:
        pool.wait_completion()
    except KeyboardInterrupt:
        sys.exit(1)
Пример #11
0
def do_summary(conf, env, options):

    limit = options.max if options.max > 0 else 5
    entrylist, pages = readers.load(conf)

    print
    print 'acrylamid', blue(env['version']) + ',',
    print 'cache size:', blue('%0.2f' % (cache.size / 1024.0**2)) + ' mb'
    print

    for entry in entrylist[:limit]:
        print '  ', green(ago(entry.date.replace(tzinfo=None)).ljust(13)),
        print white(entry.title) if entry.draft else normal(entry.title)

    print
    print '%s published,' % blue(len([e for e in entrylist if not e.draft])),
    print '%s drafted articles' % blue(len([e for e in entrylist if e.draft]))

    time = localtime(getmtime(join(conf.get('cache_dir', '.cache/'), 'info')))
    print 'last compilation at %s' % blue(strftime('%d. %B %Y, %H:%M', time))
Пример #12
0
def validate(paths, jobs):
    """Validates a list of urls using up to N threads.

    :param paths: a list of HTML files where we search for a-href's
    :param jobs: numbers of threads used to send I/O requests"""

    ahref = re.compile(r'<a [^>]*href="([^"]+)"[^>]*>.*?</a>')
    visited, urls = set(), collections.defaultdict(list)

    def check(url, path):
        """A HEAD request to URL.  If HEAD is not allowed, we try GET."""

        try:
            get(url, timeout=10)
        except HTTPError as e:
            if e.code == 405:
                try:
                    get(url, path, 'GET', True)
                except URLError as e:
                    print('  ' + yellow(e.reason), url)
                    print(white('  -- ' + path))
            else:
                print('  ' + red(e.code), url)
                print(white('  -- ' + path))
        except URLError as e:
            print('  ' + yellow(e.reason), url)
            print(white('  -- ' + path))

    # -- validation
    for path in paths:

        with io.open(path, 'r', encoding='utf-8') as fp:
            data = fp.read()

        for match in ahref.finditer(data):
            a = match.group(1)
            if a.startswith(('http://', 'https://')):
                if a not in visited:
                    visited.add(a)
                    urls[path].append(a)

    print()
    print("Trying", blue(len(visited)), "links...")
    print()

    pool = Threadpool(jobs)
    for path in urls:
        for url in urls[path]:
            pool.add_task(check, *[unescape(url), path])

    try:
        pool.wait_completion()
    except KeyboardInterrupt:
        sys.exit(1)
Пример #13
0
def run(conf, env, options):
    """Subcommand: info -- a short overview of a blog."""

    limit = options.max if options.max > 0 else 5
    commands.initialize(conf, env)
    entrylist, pages = readers.load(conf)

    print
    print "acrylamid", blue(env["version"]) + ",",
    print "cache size:", blue("%0.2f" % (cache.size / 1024.0 ** 2)) + " mb"
    print

    for entry in entrylist[:limit]:
        print "  ", green(ago(entry.date.replace(tzinfo=None)).ljust(13)),
        print white(entry.title) if entry.draft else normal(entry.title)

    print
    print "%s published," % blue(len([e for e in entrylist if not e.draft])),
    print "%s drafted articles" % blue(len([e for e in entrylist if e.draft]))

    time = localtime(getmtime(join(conf.get("cache_dir", ".cache/"), "info")))
    print "last compilation at %s" % blue(strftime("%d. %B %Y, %H:%M", time))
Пример #14
0
def run(conf, env, options):
    """Subcommand: info -- a short overview of a blog."""

    limit = options.max if options.max > 0 else 5
    commands.initialize(conf, env)
    entrylist, pages = readers.load(conf)

    print
    print 'acrylamid', blue(env['version']) + ',',
    print 'cache size:', blue('%0.2f' % (cache.size / 1024.0**2)) + ' mb'
    print

    for entry in entrylist[:limit]:
        print '  ', green(ago(entry.date.replace(tzinfo=None)).ljust(13)),
        print white(entry.title) if entry.draft else entry.title

    print
    print '%s published,' % blue(len([e for e in entrylist if not e.draft])),
    print '%s drafted articles' % blue(len([e for e in entrylist if e.draft]))

    time = localtime(getmtime(join(conf.get('cache_dir', '.cache/'), 'info')))
    print 'last compilation at %s' % blue(strftime('%d. %B %Y, %H:%M', time))
Пример #15
0
def do_tags(conf, env, options):

    limit = options.max if options.max > 0 else 100
    entrylist = readers.load(conf)[0]

    if options.coverage:
        for tag, entries in sorted(iteritems(fetch(entrylist))):
            if len(entries) <= options.coverage:
                print(blue(tag).encode('utf-8'), end=' ')
                print(', '.join(e.filename.encode('utf-8') for e in entries))
        return

    tags = [
        '%i %s' % (len(value), key) for key, value in sorted(
            iteritems(fetch(entrylist)), key=lambda k: len(k[1]), reverse=True)
    ]

    colprint(
        list(
            izip(*list(batch(tags[:limit], ceil(len(tags) / 4.0))),
                 fillvalue='')),
        os.popen('stty size', 'r').read().split()[1])
Пример #16
0
def breaks(env, firstrun):
    """Return whether the new version may break current configuration and print
    all changes between the current and new version."""

    version = memoize("version") or (0, 4)
    if version >= (env.version.major, env.version.minor):
        return False

    memoize("version", (env.version.major, env.version.minor))

    if firstrun:
        return False

    broken = False

    for major in range(version[0], env.version.major or 1):
        for minor in range(version[1], env.version.minor):
            rv, hints = changesfor("%i.%i" % (major, minor + 1))
            broken = broken or rv

            if not hints:
                continue

            print()
            print((blue("Acrylamid") + " %i.%s" % (major, minor + 1) + u" – changes").encode("utf-8"), end="")

            if broken:
                print((u"– " + red("may break something.")).encode("utf-8"))
            else:
                print()

            print()
            print(colorize(hints).encode("utf-8"))
            print()

    return broken
Пример #17
0
def breaks(env, firstrun):
    """Return whether the new version may break current configuration and print
    all changes between the current and new version."""

    version = memoize('version') or (0, 4)
    if version >= (env.version.major, env.version.minor):
        return False

    memoize('version', (env.version.major, env.version.minor))

    if firstrun:
        return False

    broken = False

    for major in range(version[0], env.version.major or 1):
        for minor in range(version[1], env.version.minor):
            rv, hints = changesfor('%i.%i' % (major, minor + 1))
            broken = broken or rv

            if not hints:
                continue

            print()
            print((blue('Acrylamid') + ' %i.%s' % (major, minor+1) + u' – changes').encode('utf-8'), end="")

            if broken:
                print((u'– ' + red('may break something.')).encode('utf-8'))
            else:
                print()

            print()
            print(colorize(hints).encode('utf-8'))
            print()

    return broken
Пример #18
0
                continue

            if section and line.startswith('### '):
                paragraph = 'changes' in line
                continue

            if section and paragraph:
                rv.append(line)
                if 'break' in line:
                    safe = False

    return not safe, '\n'.join(rv)


colorize = lambda text: \
    re.sub('`([^`]+)`', lambda m: bold(blue(m.group(1))).encode('utf-8'),
    re.sub('`([A-Z_*]+)`', lambda m: bold(m.group(1)).encode('utf-8'),
    re.sub('(#\d+)', lambda m: underline(m.group(1)).encode('utf-8'),
    re.sub('(breaks?)', lambda m: red(bold(m.group(1))).encode('utf-8'), text))))


def breaks(env, firstrun):
    """Return whether the new version may break current configuration and print
    all changes between the current and new version."""

    version = memoize('version') or (0, 4)
    if version >= (env.version.major, env.version.minor):
        return False

    memoize('version', (env.version.major, env.version.minor))
Пример #19
0
            if section and line.startswith("### "):
                paragraph = "changes" in line
                continue

            if section and paragraph:
                rv.append(line)
                if "break" in line:
                    safe = False

    return not safe, "\n".join(rv)


colorize = lambda text: re.sub(
    "`([^`]+)`",
    lambda m: bold(blue(m.group(1))).encode("utf-8"),
    re.sub(
        "`([A-Z_*]+)`",
        lambda m: bold(m.group(1)).encode("utf-8"),
        re.sub(
            "(#\d+)",
            lambda m: underline(m.group(1)).encode("utf-8"),
            re.sub("(breaks?)", lambda m: red(bold(m.group(1))).encode("utf-8"), text),
        ),
    ),
)


def breaks(env, firstrun):
    """Return whether the new version may break current configuration and print
    all changes between the current and new version."""
Пример #20
0
                continue

            if section and line.startswith('### '):
                paragraph = 'changes' in line
                continue

            if section and paragraph:
                rv.append(line)
                if 'break' in line:
                    safe = False

    return not safe, '\n'.join(rv)


colorize = lambda text: \
    re.sub('`([^`]+)`', lambda m: bold(blue(m.group(1))).encode('utf-8'),
    re.sub('`([A-Z_*]+)`', lambda m: bold(m.group(1)).encode('utf-8'),
    re.sub('(#\d+)', lambda m: underline(m.group(1)).encode('utf-8'),
    re.sub('(breaks?)', lambda m: red(bold(m.group(1))).encode('utf-8'), text))))


def breaks(env, firstrun):
    """Return whether the new version may break current configuration and print
    all changes between the current and new version."""

    version = memoize('version') or (0, 4)
    if version >= (env.version.major, env.version.minor):
        return False

    memoize('version', (env.version.major, env.version.minor))
Пример #21
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)
Пример #22
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)
Пример #23
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)
Пример #24
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)