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))))
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))
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
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])
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])
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...")
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...")
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] )
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)
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))
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)
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))
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))
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])
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
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
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))
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."""
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)
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)
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)
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)