<commit_before>#!/usr/bin/env python
import sys
import os
# requires support lib:
# 	https://raw.githubusercontent.com/parrt/bild/master/src/python/bilder.py
sys.path.append(os.path.abspath("/Users/parrt/github/bild/src/python"))
import string

from bilder import *

VERSION = "4.4"
JAVA_TARGET	= "."
PYTHON2_TARGET	= "../antlr4-python2"
PYTHON3_TARGET	= "../antlr4-python3"
CSHARP_TARGET	= "../antlr4cs"

# Properties needed to run Python[23] tests
test_properties = {
	"antlr-python2-python":"/usr/local/Cellar/python/2.7.5/bin/python2.7",
	"antlr-python2-runtime":uniformpath(PYTHON2_TARGET)+"/src",
	"antlr-python3-python":"/usr/local/Cellar/python3/3.4.1/bin/python3",
	"antlr-python3-runtime":uniformpath(PYTHON3_TARGET)+"/src",
}

# TARGETS			= {"Java":JAVA_TARGET, "Python2":PYTHON2_TARGET, "Python3":PYTHON3_TARGET, "CSharp":CSHARP_TARGET}
TARGETS	= {"Java":uniformpath(JAVA_TARGET),
		   "Python2":uniformpath(PYTHON2_TARGET),
		   "Python3":uniformpath(PYTHON3_TARGET),
		   "CSharp":uniformpath(CSHARP_TARGET)}

def parsers():
	antlr3("tool/src/org/antlr/v4/parse", "gen", package="org.antlr.v4.parse")
	antlr3("tool/src/org/antlr/v4/codegen", "gen", package="org.antlr.v4.codegen", args=["-lib","tool/src/org/antlr/v4/parse"])
	antlr4("runtime/Java/src/org/antlr/v4/runtime/tree/xpath", "gen", package="org.antlr.v4.runtime.tree.xpath")

def compile():
	require(parsers)
	cp = uniformpath("out")+os.pathsep+ \
		 os.path.join(JARCACHE,"antlr-3.5.1-complete.jar")+os.pathsep+ \
		 "runtime/Java/lib/org.abego.treelayout.core.jar"
	args = ["-Xlint", "-Xlint:-serial", "-g"]
	javac("runtime/JavaAnnotations/src/", "out", version="1.6", cp=cp, args=args)
	javac("runtime/Java/src", "out", version="1.6", cp=cp, args=args)
	javac("tool/src", "out", version="1.6", cp=cp, args=args)
	javac("gen", "out", version="1.6", cp=cp, args=args)
	# pull in targets
	for t in TARGETS:
		javac(TARGETS[t]+"/tool/src", "out", version="1.6", cp=cp, args=args)

def mkjar():
	require(compile)
	copytree(src="tool/resources", dst="out")
	manifest = \
"""Version: %s
Main-Class: org.antlr.v4.Tool
""" % VERSION
	# unjar required libraries
	unjar("runtime/Java/lib/org.abego.treelayout.core.jar", trgdir="out")
	unjar(os.path.join(JARCACHE,"antlr-3.5.1-complete.jar"), trgdir="out")
	# pull in target templates
	for t in TARGETS:
		copyfile(TARGETS[t]+"/tool/resources/org/antlr/v4/tool/templates/codegen/"+t+"/"+t+".stg",
				 "out/org/antlr/v4/tool/templates/codegen/"+t)
	jar("dist/antlr-"+VERSION+"-complete.jar", srcdir="out", manifest=manifest)

def tests():
	require(mkjar)
	junit_jar, hamcrest_jar = load_junitjars()
	cp = "dist/antlr-"+VERSION+"-complete.jar"+os.pathsep+ \
		 uniformpath("out/test/Java")+os.pathsep+ \
		 string.join([uniformpath(TARGETS[t]+"/tool/test") for t in TARGETS],os.pathsep)+os.pathsep+ \
		 junit_jar+os.pathsep+hamcrest_jar
	properties = ["-D%s=%s" % (p, test_properties[p]) for p in test_properties]
	args = ["-Xlint", "-Xlint:-serial", "-g"]
	javac("tool/test", "out/test/Java", version="1.6", cp=cp, args=args) # all targets can use org.antlr.v4.test.*
	for t in TARGETS:
		print "Test %7s --------------" % t
		javac(TARGETS[t]+"/tool/test", "out/test/"+t, version="1.6", cp=cp, args=args)
		copytree(src=TARGETS[t]+"/tool/resources", dst="out/test/"+t)
		junit("out/test/"+t, cp=cp, verbose=False, args=properties)

def all():
	mkjar()
	tests()
	mkdoc()

def clean():
	rmdir("out")
	rmdir("gen")
	rmdir("doc")

def mkdoc():
	mkdir("doc/Java")
	mkdir("doc/JavaTool")
	javadoc(srcdir="runtime/Java/src", trgdir="doc/Java", packages="org.antlr.v4.runtime")
	toolsrc = [TARGETS[t]+"/tool/src" for t in TARGETS]
	toolsrc = string.join(toolsrc, ":")
	javadoc(srcdir=toolsrc, trgdir="doc/JavaTool", packages="org.antlr.v4")
	# build stack merge PredictionContext and ATNState images from DOT
	# DOT Images are in runtime/Java/src/main/dot/org/antlr/v4/runtime/atn/images/
	# Gen into E.g., doc/Java/org/antlr/v4/runtime/atn/images/SingletonMerge_DiffRootSamePar.svg
	mkdir("doc/Java/org/antlr/v4/runtime/atn/images")
	for f in glob.glob("runtime/Java/src/main/dot/org/antlr/v4/runtime/atn/images/*.dot"):
		dot(f, "doc/Java/org/antlr/v4/runtime/atn/images", format="svg")
	zip("doc/antlr4-runtime.zip", "doc/Java")
	zip("doc/antlr4-tool.zip", "doc/JavaTool")

processargs(globals()) # E.g., "python bild.py all"
<commit_msg>expand path to jar.<commit_after>#!/usr/bin/env python
import sys
import os
# requires support lib:
# 	https://raw.githubusercontent.com/parrt/bild/master/src/python/bilder.py
sys.path.append(os.path.abspath("/Users/parrt/github/bild/src/python"))
import string

from bilder import *

VERSION = "4.4"
JAVA_TARGET	= "."
PYTHON2_TARGET	= "../antlr4-python2"
PYTHON3_TARGET	= "../antlr4-python3"
CSHARP_TARGET	= "../antlr4cs"

# Properties needed to run Python[23] tests
test_properties = {
	"antlr-python2-python":"/usr/local/Cellar/python/2.7.5/bin/python2.7",
	"antlr-python2-runtime":uniformpath(PYTHON2_TARGET)+"/src",
	"antlr-python3-python":"/usr/local/Cellar/python3/3.4.1/bin/python3",
	"antlr-python3-runtime":uniformpath(PYTHON3_TARGET)+"/src",
}

# TARGETS			= {"Java":JAVA_TARGET, "Python2":PYTHON2_TARGET, "Python3":PYTHON3_TARGET, "CSharp":CSHARP_TARGET}
TARGETS	= {"Java":uniformpath(JAVA_TARGET),
		   "Python2":uniformpath(PYTHON2_TARGET),
		   "Python3":uniformpath(PYTHON3_TARGET),
		   "CSharp":uniformpath(CSHARP_TARGET)}

def parsers():
	antlr3("tool/src/org/antlr/v4/parse", "gen", package="org.antlr.v4.parse")
	antlr3("tool/src/org/antlr/v4/codegen", "gen", package="org.antlr.v4.codegen", args=["-lib","tool/src/org/antlr/v4/parse"])
	antlr4("runtime/Java/src/org/antlr/v4/runtime/tree/xpath", "gen", package="org.antlr.v4.runtime.tree.xpath")

def compile():
	require(parsers)
	cp = uniformpath("out")+os.pathsep+ \
		 os.path.join(JARCACHE,"antlr-3.5.1-complete.jar")+os.pathsep+ \
		 "runtime/Java/lib/org.abego.treelayout.core.jar"
	args = ["-Xlint", "-Xlint:-serial", "-g"]
	javac("runtime/JavaAnnotations/src/", "out", version="1.6", cp=cp, args=args)
	javac("runtime/Java/src", "out", version="1.6", cp=cp, args=args)
	javac("tool/src", "out", version="1.6", cp=cp, args=args)
	javac("gen", "out", version="1.6", cp=cp, args=args)
	# pull in targets
	for t in TARGETS:
		javac(TARGETS[t]+"/tool/src", "out", version="1.6", cp=cp, args=args)

def mkjar():
	require(compile)
	copytree(src="tool/resources", dst="out")
	manifest = \
"""Version: %s
Main-Class: org.antlr.v4.Tool
""" % VERSION
	# unjar required libraries
	unjar("runtime/Java/lib/org.abego.treelayout.core.jar", trgdir="out")
	unjar(os.path.join(JARCACHE,"antlr-3.5.1-complete.jar"), trgdir="out")
	# pull in target templates
	for t in TARGETS:
		copyfile(TARGETS[t]+"/tool/resources/org/antlr/v4/tool/templates/codegen/"+t+"/"+t+".stg",
				 "out/org/antlr/v4/tool/templates/codegen/"+t)
	jar("dist/antlr-"+VERSION+"-complete.jar", srcdir="out", manifest=manifest)

def tests():
	require(mkjar)
	junit_jar, hamcrest_jar = load_junitjars()
	cp = uniformpath("dist/antlr-"+VERSION+"-complete.jar")+os.pathsep+ \
		 uniformpath("out/test/Java")+os.pathsep+ \
		 string.join([uniformpath(TARGETS[t]+"/tool/test") for t in TARGETS],os.pathsep)+os.pathsep+ \
		 junit_jar+os.pathsep+hamcrest_jar
	properties = ["-D%s=%s" % (p, test_properties[p]) for p in test_properties]
	args = ["-Xlint", "-Xlint:-serial", "-g"]
	javac("tool/test", "out/test/Java", version="1.6", cp=cp, args=args) # all targets can use org.antlr.v4.test.*
	for t in TARGETS:
		print "Test %7s --------------" % t
		javac(TARGETS[t]+"/tool/test", "out/test/"+t, version="1.6", cp=cp, args=args)
		copytree(src=TARGETS[t]+"/tool/resources", dst="out/test/"+t)
		junit("out/test/"+t, cp=cp, verbose=False, args=properties)

def all():
	mkjar()
	tests()
	mkdoc()

def clean():
	rmdir("out")
	rmdir("gen")
	rmdir("doc")

def mkdoc():
	mkdir("doc/Java")
	mkdir("doc/JavaTool")
	javadoc(srcdir="runtime/Java/src", trgdir="doc/Java", packages="org.antlr.v4.runtime")
	toolsrc = [TARGETS[t]+"/tool/src" for t in TARGETS]
	toolsrc = string.join(toolsrc, ":")
	javadoc(srcdir=toolsrc, trgdir="doc/JavaTool", packages="org.antlr.v4")
	# build stack merge PredictionContext and ATNState images from DOT
	# DOT Images are in runtime/Java/src/main/dot/org/antlr/v4/runtime/atn/images/
	# Gen into E.g., doc/Java/org/antlr/v4/runtime/atn/images/SingletonMerge_DiffRootSamePar.svg
	mkdir("doc/Java/org/antlr/v4/runtime/atn/images")
	for f in glob.glob("runtime/Java/src/main/dot/org/antlr/v4/runtime/atn/images/*.dot"):
		dot(f, "doc/Java/org/antlr/v4/runtime/atn/images", format="svg")
	zip("doc/antlr4-runtime.zip", "doc/Java")
	zip("doc/antlr4-tool.zip", "doc/JavaTool")

processargs(globals()) # E.g., "python bild.py all"
<|endoftext|>


<commit_before>import numpy as np
import argparse

parser = argparse.ArgumentParser(description='Generate bins.')
parser.add_argument('beginning', help='Beginning of the first bin.', type=int)
parser.add_argument('end', help='End of the last bin.', type=int)
parser.add_argument('-interval', help='Size of the bin.', type=int)
parser.add_argument('-n', help='Number of bins.', type=int)
parser.add_argument('outputFile', type=str, help='Set the output file.')
args = parser.parse_args()

bins = np.array([0, 0])
i = args.beginning
if args.interval is not None:
    interval = args.interval
    outputFormat = '%.4d'
    while i + interval <= args.end:
        bins = np.vstack([bins, [i, i + interval]])
        i += interval
elif args.n is not None:
    interval = 1. / args.n
    outputFormat = '%.4f'
    for j in range(0, args.n):
        bins = np.vstack([bins, [i, i + interval]])
        i += interval

bins = np.delete(bins, (0), axis=0)
np.savetxt(args.outputFile, bins, fmt=outputFormat)
<commit_msg>rewrite bins.py<commit_after>import numpy as np
import argparse

parser = argparse.ArgumentParser(description='Generate bins.')
parser.add_argument('beginning', help='Beginning of the first bin.', type=str)
parser.add_argument('end', help='End of the last bin.', type=str)
parser.add_argument('-interval', help='Size of the bin.', type=int)
parser.add_argument('-n', help='Number of bins.', type=int)
parser.add_argument('outputFile', type=str, help='Set the output file.')
parser.add_argument('-sb', type=bool, default=False, help='Use when \
                    creating sub-bins.')
args = parser.parse_args()

args.beginning = np.float(args.beginning)
args.end = np.float(args.end)

if (args.interval is not None) and (args.n is not None):
    parser.error('-n and -interval are mutually exclusive')

bins = []
i = args.beginning
if args.interval is not None:
    interval = args.interval
    while i < args.end:
        if i + interval > args.end:
            bins.append([i, args.end])
        else:
            bins.append([i, i + interval])
        i += interval
elif args.n is not None:
    if args.sb:
        interval = 1.
    else:
        interval = (args.end - args.beginning) / args.n
    for j in range(args.n):
        bins.append([i, i + interval])
        i += interval

np.savetxt(args.outputFile, bins)
<|endoftext|>


<commit_before>#!/usr/bin/python3
import os
import json
import shutil
import datetime
import argparse
import http.server
import socketserver
from subprocess import call

import jinja2
from bs4 import BeautifulSoup

class Command(type):
    def __init__(cls, *args, **kwargs):
        if not hasattr(cls, 'commands'):
            cls.commands = {}
        else:
            cls.commands[cls._command] = cls()

class BlgrCommand(metaclass=Command):
    def __init__(self):
        super().__init__()
        self.parser = None
        self.config = None

    def add_args(self):
        raise NotImplementedError

    def prepare(self):
        raise NotImplementedError

    def execute(self):
        raise NotImplementedError

class Create(BlgrCommand):
    _command = 'create'

    def add_args(self):
        pass

    def prepare(self):
        self.post_data = {}
        resp = None
        while resp not in ('y', 'n', ''):
            resp = input('Would you like to provide post metadata now {y/[n]}')

        if resp == 'y':
            self._ask_post_meta()

    def _ask_post_meta(self):
        post_data = {}
        post_data['title'] = input('Post title: ')
        post_data['slug'] = input('Post slug: ')
        post_data['category'] = input('Post category: ')
        sl = None
        while sl not in ('y', 'n', ''):
            sl = input('Set post link in menu {y/[n]}')
        if sl == 'y':
            post_data['set_link'] = True
        elif sl in ('', 'n'):
            post_data['set_link'] = False

        comments = None
        while comments not in ('y', 'n', ''):
            comments = input('Allow comments {[y]/n}')
        if comments == 'n':
            post_data['comments'] = False
        elif comments in ('', 'y'):
            post_data['comments'] = True
        self.post_data = post_data

    def execute(self):
        dt = datetime.datetime.now()
        ts = dt.strftime('%Y-%m-%d-%H')
        slug = self.post_data.setdefault('slug', 'post')
        post_dir = os.path.join(self.config['posts']['path'],
                                '-'.join((ts, slug)))
        post_name = '{}{}.{}'.format(slug, ts, 'ipynb')

        if not os.path.exists(post_dir):
            os.makedirs(post_dir)

        shutil.copyfile('./data/empty.ipynb', os.path.join(post_dir, post_name))
        with open(os.path.join(post_dir, 'meta.json'), 'w') as meta:
            json.dump({'title': self.post_data.setdefault('title', ''),
                       'slug': self.post_data.setdefault('slug', ''),
                       'category': self.post_data.setdefault('category', ''),
                       'dt': dt.isoformat(),
                       'comments': self.post_data.setdefault('comments', False),
                       'set_link': self.post_data.setdefault('set_link', False)},
                      meta)

class Generate(BlgrCommand):
    _command = 'generate'

    def add_args(self):
        pass

    def prepare(self):
        self.prj_path = os.path.abspath(os.path.dirname(__file__))
        jinja_loader = jinja2.FileSystemLoader(searchpath=os.path.join(self.prj_path, 'data/'))
        self.tmpl_env = jinja2.Environment(loader=jinja_loader)
        out_path = self.config['output']['path']
        if os.path.exists(out_path):
            shutil.rmtree(out_path)
        os.makedirs(out_path)

        posts_path = self.config['posts']['path']

        self.posts = {}
        post_dirs = (d for d in os.listdir(posts_path) if os.path.isdir(os.path.join(posts_path, d)))
        for pd in post_dirs:
            pp = os.path.join(posts_path, pd)
            with open(os.path.join(pp, 'meta.json'), 'r') as meta_file:
                meta = json.load(meta_file)
            self.posts[pp] = meta

        self.dts = {}
        self.pages = []
        for pp, data in self.posts.items():
            if not data['set_link']:
                dt = datetime.datetime.strptime(data['dt'], '%Y-%m-%dT%H:%M:%S.%f')
                self.dts.setdefault(dt.year, {}).setdefault(dt.month, {}).setdefault(dt.day, []).append(pp)
            else:
                self.pages.append(pp)

    def _generate_pages(self):
        out_path = self.config['output']['path']
        for page in self.pages:
            page_path = os.path.join(out_path, self.posts[page]['slug'])
            if not os.path.exists(page_path):
                os.mkdir(page_path)

            fls = os.listdir(page)
            psts = [pst for pst in fls if pst.endswith('.ipynb')]
            pp = os.path.join(self.prj_path, page, psts[0])
            self._process_ipynb(page_path, pp)

    def _generate_comments(self):
        tmpl = self.tmpl_env.get_or_select_template('comments.html')
        self.comments = tmpl.render({'disqus': self.config['disqus']})

    def _generate_menu(self):
        pages = []
        for page in self.pages:
            pd = self.posts[page]
            pd['url'] = '/{}/'.format(pd['slug'])
            pages.append(pd)
        tmpl = self.tmpl_env.get_or_select_template('menu.html')
        self.menu = tmpl.render({'pages': pages})

    def _generate_year_index(self, year_path, posts, year):
        indx_path = os.path.join(year_path, 'index.html')
        tmpl = self.tmpl_env.get_or_select_template('index.html')
        indx = tmpl.render({'header': 'Year {}'.format(year), 'posts': posts})
        with open(indx_path, 'w') as cindex:
            cindex.write(indx)

    def _generate_month_index(self, month_path, posts, year_month):
        indx_path = os.path.join(month_path, 'index.html')
        tmpl = self.tmpl_env.get_or_select_template('index.html')
        indx = tmpl.render({'header': 'Year {} Month {}'.format(year_month[0], year_month[1]),
                            'posts': posts})
        with open(indx_path, 'w') as cindex:
            cindex.write(indx)

    def _generate_day_index(self, day_path, posts, year_month_day):
        indx_path = os.path.join(day_path, 'index.html')
        tmpl = self.tmpl_env.get_or_select_template('index.html')
        indx = tmpl.render({'header': 'Year {} Month {} Day {}'.format(year_month_day[0], year_month_day[1],
                                                                       year_month_day[2]), 'posts': posts})
        with open(indx_path, 'w') as cindex:
            cindex.write(indx)

    def _generate_category_index(self, category, cat_path, posts):
        indx_path = os.path.join(cat_path, 'index.html')
        tmpl = self.tmpl_env.get_or_select_template('index.html')
        indx = tmpl.render({'header': category, 'posts': posts})
        with open(indx_path, 'w') as cindex:
            cindex.write(indx)

    def _generate_categories(self, categories):
        for cat in categories:
            cat_path = os.path.join(self.config['output']['path'], cat)
            if not os.path.exists(cat_path):
                os.mkdir(cat_path)

            self._generate_category_index(cat, cat_path, categories[cat])

    def _process_ipynb(self, out_path, post_path, comments=False):
        os.chdir(out_path)
        call(['ipython', 'nbconvert', '--to', 'html', post_path])
        psts_html = os.listdir('./')
        if psts_html:
            os.rename(psts_html[0], 'index.html')

        os.chdir(self.prj_path)
        self._append_html(os.path.join(out_path, 'index.html'), comments)

    def _append_html(self, path, comments):
        soup = BeautifulSoup(open(path))

        menu = BeautifulSoup(self.menu)
        comments_div = soup.find(id='notebook-container')
        soup.body.insert(0, menu)
        if comments:
            comments = BeautifulSoup(self.comments)
            comments_div.append(comments)
        res = soup.prettify()
        with open(path, 'w') as pg:
            pg.write(res)

    def _generate_posts(self):
        out_path = self.config['output']['path']
        categories = {}
        for year in self.dts:
            year_posts = []
            year_path = os.path.join(out_path, str(year))
            if not os.path.exists(year_path):
                os.mkdir(year_path)

            for month in self.dts[year]:
                month_posts = []
                month_path = os.path.join(year_path, str(month))
                if not os.path.exists(month_path):
                    os.mkdir(month_path)

                for day in self.dts[year][month]:
                    day_posts = []
                    day_path = os.path.join(month_path, str(day))
                    if not os.path.exists(day_path):
                        os.mkdir(day_path)

                    for post in self.dts[year][month][day]:
                        slug = self.posts[post]['slug']
                        slug_path = os.path.join(day_path, slug)
                        cat = self.posts[post]['category'] if self.posts[post]['category'] else 'uncategorized'
                        pd = {'url': '/{}/{}/{}/{}/'.format(year, month, day, slug)}
                        pd.update(self.posts[post])
                        categories.setdefault(cat, []).append(pd)
                        if not os.path.exists(slug_path):
                            os.mkdir(slug_path)

                        fls = os.listdir(post)
                        psts = [pst for pst in fls if pst.endswith('.ipynb')]
                        pp = os.path.join(self.prj_path, post, psts[0])
                        self._process_ipynb(slug_path, pp, pd['comments'])

                    day_posts.append(pd)
                    month_posts.append(pd)
                    year_posts.append(pd)

                    self._generate_day_index(day_path, day_posts, (year, month, day))
                self._generate_month_index(month_path, month_posts, (year, month))
            self._generate_year_index(year_path, year_posts, year)
        self._generate_categories(categories)

    def execute(self):
        self._generate_menu()
        self._generate_comments()
        self._generate_pages()
        self._generate_posts()

class Serve(BlgrCommand):
    _command = 'serve'

    def add_args(self):
        self.parser.add_argument('-p', '--port', type=int, default=8080,
                                 required=False, help='port on which to start '
                                                      'serving')

    def prepare(self):
        os.chdir(self.config['output']['path'])

    def execute(self):
        handler = http.server.SimpleHTTPRequestHandler
        httpd = socketserver.TCPServer(('', self.port), handler)
        print('serving at port {}'.format(self.port))
        httpd.serve_forever()

class BlgrCli():
    def __init__(self):
        self._read_config()
        self._process()

    def _read_config(self):
        config = None
        with open('config.json', 'r') as conf:
            config = json.load(conf)

        self.config = config

    def _process(self):
        parser = argparse.ArgumentParser(description='blgr cli')

        subparsers = parser.add_subparsers(help='command')
        for name, cmd in BlgrCommand.commands.items():
            cmd.parser = subparsers.add_parser(name)
            cmd.add_args()
            cmd.parser.set_defaults(cmd=cmd)
        args = parser.parse_args()
        cmd = args.cmd
        parser.parse_args(namespace=cmd)

        cmd.config = self.config
        cmd.prepare()
        cmd.execute()

if __name__ == '__main__':
    blgr = BlgrCli()
<commit_msg>generates main index file<commit_after>#!/usr/bin/python3
import os
import json
import shutil
import datetime
import argparse
import http.server
import socketserver
from subprocess import call

import jinja2
from bs4 import BeautifulSoup

class Command(type):
    def __init__(cls, *args, **kwargs):
        if not hasattr(cls, 'commands'):
            cls.commands = {}
        else:
            cls.commands[cls._command] = cls()

class BlgrCommand(metaclass=Command):
    def __init__(self):
        super().__init__()
        self.parser = None
        self.config = None

    def add_args(self):
        raise NotImplementedError

    def prepare(self):
        raise NotImplementedError

    def execute(self):
        raise NotImplementedError

class Create(BlgrCommand):
    _command = 'create'

    def add_args(self):
        pass

    def prepare(self):
        self.post_data = {}
        resp = None
        while resp not in ('y', 'n', ''):
            resp = input('Would you like to provide post metadata now {y/[n]}')

        if resp == 'y':
            self._ask_post_meta()

    def _ask_post_meta(self):
        post_data = {}
        post_data['title'] = input('Post title: ')
        post_data['slug'] = input('Post slug: ')
        post_data['category'] = input('Post category: ')
        sl = None
        while sl not in ('y', 'n', ''):
            sl = input('Set post link in menu {y/[n]}')
        if sl == 'y':
            post_data['set_link'] = True
        elif sl in ('', 'n'):
            post_data['set_link'] = False

        comments = None
        while comments not in ('y', 'n', ''):
            comments = input('Allow comments {[y]/n}')
        if comments == 'n':
            post_data['comments'] = False
        elif comments in ('', 'y'):
            post_data['comments'] = True
        self.post_data = post_data

    def execute(self):
        dt = datetime.datetime.now()
        ts = dt.strftime('%Y-%m-%d-%H')
        slug = self.post_data.setdefault('slug', 'post')
        post_dir = os.path.join(self.config['posts']['path'],
                                '-'.join((ts, slug)))
        post_name = '{}{}.{}'.format(slug, ts, 'ipynb')

        if not os.path.exists(post_dir):
            os.makedirs(post_dir)

        shutil.copyfile('./data/empty.ipynb', os.path.join(post_dir, post_name))
        with open(os.path.join(post_dir, 'meta.json'), 'w') as meta:
            json.dump({'title': self.post_data.setdefault('title', ''),
                       'slug': self.post_data.setdefault('slug', ''),
                       'category': self.post_data.setdefault('category', ''),
                       'dt': dt.isoformat(),
                       'comments': self.post_data.setdefault('comments', False),
                       'set_link': self.post_data.setdefault('set_link', False)},
                      meta)

class Generate(BlgrCommand):
    _command = 'generate'

    def add_args(self):
        pass

    def prepare(self):
        self.prj_path = os.path.abspath(os.path.dirname(__file__))
        self.out_path = self.config['output']['path']
        jinja_loader = jinja2.FileSystemLoader(searchpath=os.path.join(self.prj_path, 'data/'))
        self.tmpl_env = jinja2.Environment(loader=jinja_loader)
        if os.path.exists(self.out_path):
            shutil.rmtree(self.out_path)
        os.makedirs(self.out_path)

        posts_path = self.config['posts']['path']

        self.posts = {}
        post_dirs = (d for d in os.listdir(posts_path) if os.path.isdir(os.path.join(posts_path, d)))
        for pd in post_dirs:
            pp = os.path.join(posts_path, pd)
            with open(os.path.join(pp, 'meta.json'), 'r') as meta_file:
                meta = json.load(meta_file)
            self.posts[pp] = meta

        self.dts = {}
        self.pages = []
        for pp, data in self.posts.items():
            if not data['set_link']:
                dt = datetime.datetime.strptime(data['dt'], '%Y-%m-%dT%H:%M:%S.%f')
                self.dts.setdefault(dt.year, {}).setdefault(dt.month, {}).setdefault(dt.day, []).append(pp)
            else:
                self.pages.append(pp)

    def _generate_main_indices(self, posts):
        tmpl = self.tmpl_env.get_template('index.html')
        main_indx_path = os.path.join(self.out_path, 'index.html')
        main_indx = tmpl.render({'header': 'Main index', 'posts': posts, 'pages': self.menu_pages})
        with open(main_indx_path, 'w') as indx:
            indx.write(main_indx)

    def _generate_pages(self):
        for page in self.pages:
            page_path = os.path.join(self.out_path, self.posts[page]['slug'])
            if not os.path.exists(page_path):
                os.mkdir(page_path)

            fls = os.listdir(page)
            psts = [pst for pst in fls if pst.endswith('.ipynb')]
            pp = os.path.join(self.prj_path, page, psts[0])
            self._process_ipynb(page_path, pp)

    def _generate_comments(self):
        tmpl = self.tmpl_env.get_template('comments.html')
        self.comments = tmpl.render({'disqus': self.config['disqus']})

    def _generate_menu(self):
        self.menu_pages = []
        for page in self.pages:
            pd = self.posts[page]
            pd['url'] = '/{}/'.format(pd['slug'])
            self.menu_pages.append(pd)
        tmpl = self.tmpl_env.get_template('menu.html')
        self.menu = tmpl.render({'pages': self.menu_pages})

    def _generate_year_index(self, year_path, posts, year):
        indx_path = os.path.join(year_path, 'index.html')
        tmpl = self.tmpl_env.get_template('index.html')
        indx = tmpl.render({'header': 'Year {}'.format(year), 'posts': posts})
        with open(indx_path, 'w') as cindex:
            cindex.write(indx)

    def _generate_month_index(self, month_path, posts, year_month):
        indx_path = os.path.join(month_path, 'index.html')
        tmpl = self.tmpl_env.get_template('index.html')
        indx = tmpl.render({'header': 'Year {} Month {}'.format(year_month[0], year_month[1]),
                            'posts': posts, 'pages': self.menu_pages})
        with open(indx_path, 'w') as cindex:
            cindex.write(indx)

    def _generate_day_index(self, day_path, posts, year_month_day):
        indx_path = os.path.join(day_path, 'index.html')
        tmpl = self.tmpl_env.get_template('index.html')
        indx = tmpl.render({'header': 'Year {} Month {} Day {}'.format(year_month_day[0], year_month_day[1],
                                                                       year_month_day[2]),
                            'posts': posts, 'pages': self.menu_pages})
        with open(indx_path, 'w') as cindex:
            cindex.write(indx)

    def _generate_category_index(self, category, cat_path, posts):
        indx_path = os.path.join(cat_path, 'index.html')
        tmpl = self.tmpl_env.get_template('index.html')
        indx = tmpl.render({'header': category, 'posts': posts, 'pages': self.menu_pages})
        with open(indx_path, 'w') as cindex:
            cindex.write(indx)

    def _generate_categories(self, categories):
        for cat in categories:
            cat_path = os.path.join(self.config['output']['path'], cat)
            if not os.path.exists(cat_path):
                os.mkdir(cat_path)

            self._generate_category_index(cat, cat_path, categories[cat])

    def _process_ipynb(self, out_path, post_path, comments=False):
        os.chdir(out_path)
        call(['ipython', 'nbconvert', '--to', 'html', post_path])
        psts_html = os.listdir('./')
        if psts_html:
            os.rename(psts_html[0], 'index.html')

        os.chdir(self.prj_path)
        self._append_html(os.path.join(out_path, 'index.html'), comments)

    def _append_html(self, path, comments):
        soup = BeautifulSoup(open(path))

        menu = BeautifulSoup(self.menu)
        comments_div = soup.find(id='notebook-container')
        soup.body.insert(0, menu)
        if comments:
            comments = BeautifulSoup(self.comments)
            comments_div.append(comments)
        res = soup.prettify()
        with open(path, 'w') as pg:
            pg.write(res)

    def _generate_posts(self):
        all_posts = []
        categories = {}
        for year in self.dts:
            year_posts = []
            year_path = os.path.join(self.out_path, str(year))
            if not os.path.exists(year_path):
                os.mkdir(year_path)

            for month in self.dts[year]:
                month_posts = []
                month_path = os.path.join(year_path, str(month))
                if not os.path.exists(month_path):
                    os.mkdir(month_path)

                for day in self.dts[year][month]:
                    day_posts = []
                    day_path = os.path.join(month_path, str(day))
                    if not os.path.exists(day_path):
                        os.mkdir(day_path)

                    for post in self.dts[year][month][day]:
                        slug = self.posts[post]['slug']
                        slug_path = os.path.join(day_path, slug)
                        cat = self.posts[post]['category'] if self.posts[post]['category'] else 'uncategorized'
                        pd = {'url': '/{}/{}/{}/{}/'.format(year, month, day, slug)}
                        pd.update(self.posts[post])
                        categories.setdefault(cat, []).append(pd)
                        if not os.path.exists(slug_path):
                            os.mkdir(slug_path)

                        fls = os.listdir(post)
                        psts = [pst for pst in fls if pst.endswith('.ipynb')]
                        pp = os.path.join(self.prj_path, post, psts[0])
                        self._process_ipynb(slug_path, pp, pd['comments'])
                        all_posts.append(pd)

                    day_posts.append(pd)
                    month_posts.append(pd)
                    year_posts.append(pd)

                    self._generate_day_index(day_path, day_posts, (year, month, day))
                self._generate_month_index(month_path, month_posts, (year, month))
            self._generate_year_index(year_path, year_posts, year)
        self._generate_categories(categories)
        self._generate_main_indices(all_posts)

    def execute(self):
        self._generate_menu()
        self._generate_comments()
        self._generate_pages()
        self._generate_posts()

class Serve(BlgrCommand):
    _command = 'serve'

    def add_args(self):
        self.parser.add_argument('-p', '--port', type=int, default=8080,
                                 required=False, help='port on which to start '
                                                      'serving')

    def prepare(self):
        os.chdir(self.config['output']['path'])

    def execute(self):
        handler = http.server.SimpleHTTPRequestHandler
        httpd = socketserver.TCPServer(('', self.port), handler)
        print('serving at port {}'.format(self.port))
        httpd.serve_forever()

class BlgrCli():
    def __init__(self):
        self._read_config()
        self._process()

    def _read_config(self):
        config = None
        with open('config.json', 'r') as conf:
            config = json.load(conf)

        self.config = config

    def _process(self):
        parser = argparse.ArgumentParser(description='blgr cli')

        subparsers = parser.add_subparsers(help='command')
        for name, cmd in BlgrCommand.commands.items():
            cmd.parser = subparsers.add_parser(name)
            cmd.add_args()
            cmd.parser.set_defaults(cmd=cmd)
        args = parser.parse_args()
        cmd = args.cmd
        parser.parse_args(namespace=cmd)

        cmd.config = self.config
        cmd.prepare()
        cmd.execute()

if __name__ == '__main__':
    blgr = BlgrCli()
<|endoftext|>


<commit_before>import os
import glob
import socket
import ruamel.yaml
import tempfile

from setup_app import paths
from setup_app.static import AppType, InstallOption, fapolicyd_rule_tmp
from setup_app.utils import base
from setup_app.config import Config
from setup_app.utils.setup_utils import SetupUtils, SetupProfiles
from setup_app.installers.base import BaseInstaller

class OxdInstaller(SetupUtils, BaseInstaller):

    def __init__(self):
        setattr(base.current_app, self.__class__.__name__, self)
        self.service_name = 'oxd-server'
        self.oxd_root = '/opt/oxd-server/'
        self.needdb = False # we don't need backend connection in this class
        self.app_type = AppType.SERVICE
        self.install_type = InstallOption.OPTONAL
        self.install_var = 'installOxd'
        self.register_progess()

        self.oxd_server_yml_fn = os.path.join(self.oxd_root, 'conf/oxd-server.yml')
        self.oxd_server_keystore_fn = os.path.join(self.oxd_root, 'conf/oxd-server.{}'.format(Config.default_store_type))
        self.oxd_jwks_keystore_fn = os.path.join(self.oxd_root, 'conf/oxd-jwks.{}'.format(Config.default_store_type))

        self.oxd_keystore_passw = 'example'
        self.fips_provider = self.get_keytool_provider()
        self.ks_type_bcfks = 'bcfks'
        self.ks_type_pkcs12 = 'pkcs12'

    def install(self):
        self.logIt("Installing {}".format(self.service_name.title()), pbar=self.service_name)
        self.run(['tar', '-zxf', Config.oxd_package, '--no-same-owner', '--strip-components=1', '-C', self.oxd_root])

        oxd_user = 'oxd-server' if Config.profile == SetupProfiles.DISA_STIG else Config.jetty_user
        Config.templateRenderingDict['service_user'] = oxd_user
        self.render_unit_file(self.service_name)

        if Config.profile == SetupProfiles.DISA_STIG:
            self.create_service_user(oxd_user)

        self.log_dir = '/var/log/oxd-server'
        service_file = os.path.join(self.oxd_root, 'oxd-server.service')
        if os.path.exists(service_file):
            self.run(['cp', service_file, '/lib/systemd/system'])
        else:
            self.run([Config.cmd_ln, service_file, '/etc/init.d/oxd-server'])

        if not os.path.exists(self.log_dir):
            self.run([paths.cmd_mkdir, self.log_dir])

        oxd_default = self.readFile(os.path.join(Config.install_dir, 'static/oxd/oxd-server.default'))
        rendered_oxd_default = self.fomatWithDict(oxd_default, self.merge_dicts(Config.__dict__, Config.templateRenderingDict))
        self.writeFile(os.path.join(Config.osDefault, 'oxd-server'), rendered_oxd_default)

        self.log_file = os.path.join(self.log_dir, 'oxd-server.log')
        if not os.path.exists(self.log_file):
            open(self.log_file, 'w').close()

        self.run([paths.cmd_chown, '-R', '{0}:{0}'.format(oxd_user), self.log_dir])

        for fn in glob.glob(os.path.join(self.oxd_root,'bin/*')):
            self.run([paths.cmd_chmod, '+x', fn])

        if not base.argsp.dummy:
            self.modify_config_yml()
            self.generate_keystore()

        self.run([paths.cmd_chown, '-R', '{0}:{0}'.format(oxd_user), self.oxd_root])

        if Config.profile == SetupProfiles.DISA_STIG:
            log_dir = '/var/log/oxd-server/'
            oxd_fapolicyd_rules = [
                    fapolicyd_rule_tmp.format(oxd_user, Config.jre_home),
                    fapolicyd_rule_tmp.format(oxd_user, log_dir),
                    fapolicyd_rule_tmp.format(oxd_user, self.oxd_root),
                    '# give access to oxd-server',
                    ]

            self.apply_fapolicyd_rules(oxd_fapolicyd_rules)
            # Restore SELinux Context
            self.run(['restorecon', '-rv', os.path.join(self.oxd_root, 'bin')])

            self.run([paths.cmd_chown, '{}:{}'.format(oxd_user, Config.gluu_group), os.path.join(Config.osDefault, self.service_name)])

        self.enable()

    def modify_config_yml(self):
        self.logIt("Configuring", pbar=self.service_name)
        yml_str = self.readFile(self.oxd_server_yml_fn)
        oxd_yaml = ruamel.yaml.load(yml_str, ruamel.yaml.RoundTripLoader)

        if 'bind_ip_addresses' in oxd_yaml:
            oxd_yaml['bind_ip_addresses'].append(Config.ip)
        else:
            for i, k in enumerate(oxd_yaml):
                if k == 'storage':
                    break
            else:
                i = 1
            addr_list = [Config.ip]
            if Config.profile == SetupProfiles.DISA_STIG:
                addr_list.append('127.0.0.1')
            oxd_yaml.insert(i, 'bind_ip_addresses',  addr_list)

        if Config.get('oxd_use_gluu_storage'):

            if 'dbFileLocation' in oxd_yaml['storage_configuration']:
                oxd_yaml['storage_configuration'].pop('dbFileLocation')
            oxd_yaml['storage'] = 'gluu_server_configuration'
            oxd_yaml['storage_configuration']['baseDn'] = 'o=gluu'
            oxd_yaml['storage_configuration']['type'] = Config.gluu_properties_fn
            if Config.mappingLocations['default'] == 'ldap':
                oxd_yaml['storage_configuration']['connection'] = Config.ox_ldap_properties
            elif Config.mappingLocations['default'] == 'rdbm':
                if Config.rdbm_type in ('mysql', 'pgsql'):
                    oxd_yaml['storage_configuration']['connection'] = Config.gluuRDBMProperties
                elif Config.rdbm_type == 'spanner':
                    oxd_yaml['storage_configuration']['connection'] = Config.gluuSpannerProperties
            elif Config.mappingLocations['default'] == 'couchbase':
                oxd_yaml['storage_configuration']['connection'] = Config.gluuCouchebaseProperties
            oxd_yaml['storage_configuration']['salt'] = os.path.join(Config.configFolder, "salt")

        if Config.profile == SetupProfiles.DISA_STIG:
            application_connectors = oxd_yaml['server']['applicationConnectors'][0]
            application_connectors['type'] = 'https'
            application_connectors['port'] = '8443'
            application_connectors['keyStorePath'] = self.oxd_server_keystore_fn
            application_connectors['keyStorePassword'] = self.oxd_keystore_passw
            application_connectors['keyStoreType'] = Config.default_store_type
            application_connectors['keyStoreProvider'] = self.fips_provider['-providername']
            application_connectors['trustStoreType'] = Config.default_store_type
            application_connectors['jceProvider'] = self.fips_provider['-providerclass']
            application_connectors['validateCerts'] = 'false'

            admin_connectors = oxd_yaml['server']['adminConnectors'][0]
            admin_connectors['type'] = 'https'
            admin_connectors['port'] = '8444'
            admin_connectors['keyStorePath'] = self.oxd_server_keystore_fn
            admin_connectors['keyStorePassword'] = self.oxd_keystore_passw
            admin_connectors['keyStoreType'] = Config.default_store_type
            admin_connectors['keyStoreProvider'] = self.fips_provider['-providername']
            admin_connectors['trustStoreType'] = Config.default_store_type
            admin_connectors['jceProvider'] = self.fips_provider['-providerclass']
            admin_connectors['validateCerts'] = 'false'

            oxd_yaml['crypt_provider_key_store_path']=self.oxd_jwks_keystore_fn
            oxd_yaml['crypt_provider_key_store_password']=self.oxd_keystore_passw

        yml_str = ruamel.yaml.dump(oxd_yaml, Dumper=ruamel.yaml.RoundTripDumper)
        self.writeFile(self.oxd_server_yml_fn, yml_str)

    def generate_keystore(self):
        self.logIt("Generating certificate", pbar=self.service_name)
        # generate oxd-server.keystore for the hostname

        keystore_tmp = '{}/oxd.{}'.format(tempfile.gettempdir(), Config.default_store_type)

        if Config.profile == SetupProfiles.DISA_STIG:

            cmd_cert_gen = [
                Config.cmd_keytool, '-genkey',
                '-alias', Config.hostname,
                '-keyalg', 'rsa',
                '-dname', 'CN={},O=OXD RSA Self-Signed Certificate'.format(Config.hostname),
                '-keystore', keystore_tmp,
                '-storetype', self.ks_type_bcfks,
                '-validity', '3650',
                ]

            cmd_cert_gen += [
                '-providername', self.fips_provider['-providername'],
                '-provider', self.fips_provider['-providerclass'],
                '-providerpath',  self.fips_provider['-providerpath'],
                '-keypass', self.oxd_keystore_passw,
                '-storepass', self.oxd_keystore_passw,
                '-keysize', '2048',
                '-sigalg', 'SHA256WITHRSA',
                    ]

            self.run(cmd_cert_gen)

            cmd_cert_gen = [
                Config.cmd_keytool, '-selfcert',
                '-alias', Config.hostname,
                '-keystore', keystore_tmp,
                '-storetype', self.ks_type_bcfks,
                '-validity', '3650',
                ]

            cmd_cert_gen += [
                '-providername', self.fips_provider['-providername'],
                '-provider', self.fips_provider['-providerclass'],
                '-providerpath', self.fips_provider['-providerpath'],
                '-storepass', 'pass:{}'.format(self.oxd_keystore_passw),
                ]

            self.run(cmd_cert_gen)

        else:
            oxd_key_tmp = '{}/{}'.format(tempfile.gettempdir(),'oxd.key')
            oxd_crt_tmp = '{}/{}'.format(tempfile.gettempdir(),'oxd.crt')
            oxd_p12_tmp = '{}/{}'.format(tempfile.gettempdir(),'oxd.p12')

            self.run([
                paths.cmd_openssl,
                'req', '-x509', '-newkey', 'rsa:4096', '-nodes',
                '-out', oxd_crt_tmp,
                '-keyout', oxd_key_tmp,
                '-days', '3650',
                '-subj', '/C={}/ST={}/L={}/O={}/CN={}/emailAddress={}'.format(Config.countryCode, Config.state, Config.city, Config.orgName, Config.hostname, Config.admin_email),
                ])

            self.run([
                paths.cmd_openssl,
                'pkcs12', '-export',
                '-in', oxd_crt_tmp,
                '-inkey', oxd_key_tmp,
                '-out', oxd_p12_tmp,
                '-name', Config.hostname,
                '-passout', 'pass:{}'.format(self.oxd_keystore_passw)
                ])

            self.run([
                Config.cmd_keytool,
                '-importkeystore',
                '-deststorepass', self.oxd_keystore_passw,
                '-destkeypass', self.oxd_keystore_passw,
                '-destkeystore', keystore_tmp,
                '-srckeystore', oxd_p12_tmp,
                '-srcstoretype', self.ks_type_pkcs12,
                '-srcstorepass', self.oxd_keystore_passw,
                '-alias', Config.hostname,
                ])

            for f in (oxd_key_tmp, oxd_crt_tmp, oxd_p12_tmp):
                self.run([paths.cmd_rm, '-f', f])

        self.run([paths.cmd_rm, '-f', os.path.join(self.oxd_root,'conf/oxd-server.keystore')])

        self.run(['cp', '-f', keystore_tmp, self.oxd_server_keystore_fn])
        self.run([paths.cmd_chown, 'jetty:jetty', self.oxd_server_keystore_fn])

        self.run([paths.cmd_rm, '-f', keystore_tmp])

        self.import_oxd_certificate()

    def installed(self):
        return os.path.exists(self.oxd_server_yml_fn)

    def download_files(self, force=False):
        oxd_url = Config.maven_root + '/maven/org/gluu/oxd-server/{0}/oxd-server-{0}-distribution.zip'.format(Config.oxVersion)

        self.logIt("Downloading {} and preparing package".format(os.path.basename(oxd_url)))

        oxd_zip_fn = os.path.join(Config.outputFolder, 'oxd-server.zip')
        oxd_tgz_fn = os.path.join(Config.distGluuFolder, 'oxd-server.tgz')
        tmp_dir = os.path.join('/tmp', os.urandom(5).hex())
        oxd_tmp_dir = os.path.join(tmp_dir, 'oxd-server')

        self.run([paths.cmd_mkdir, '-p', oxd_tmp_dir])
        self.download_file(oxd_url, oxd_zip_fn)
        self.run([paths.cmd_unzip, '-qqo', oxd_zip_fn, '-d', oxd_tmp_dir])
        self.run([paths.cmd_mkdir, os.path.join(oxd_tmp_dir, 'data')])

        service_file = 'oxd-server.init.d' if base.deb_sysd_clone else 'oxd-server.service'
        service_url = 'https://raw.githubusercontent.com/GluuFederation/community-edition-package/master/package/systemd/oxd-server.service'.format(Config.oxVersion, service_file)
        self.download_file(service_url, os.path.join(oxd_tmp_dir, service_file))

        oxd_server_sh_url = 'https://raw.githubusercontent.com/GluuFederation/oxd/master/debian/oxd-server'
        self.download_file(oxd_server_sh_url, os.path.join(oxd_tmp_dir, 'bin/oxd-server'))

        self.run(['tar', '-zcf', oxd_tgz_fn, 'oxd-server'], cwd=tmp_dir)
        #self.run(['rm', '-r', '-f', tmp_dir])
        Config.oxd_package = oxd_tgz_fn

    def import_oxd_certificate(self):

        oxd_hostname, oxd_port = self.parse_url(Config.oxd_server_https)
        oxd_alias = 'oxd_' + oxd_hostname.replace('.','_')
        oxd_cert_fn = os.path.join(Config.outputFolder, '{}.pem'.format(oxd_alias))
        # let's delete if alias exists
        self.delete_key(oxd_alias)
        self.export_cert_from_store(Config.hostname, self.oxd_server_keystore_fn, self.oxd_keystore_passw, oxd_cert_fn)
        self.import_cert_to_java_truststore(oxd_alias, oxd_cert_fn)

    def create_folders(self):
        if not os.path.exists(self.oxd_root):
            self.run([paths.cmd_mkdir, self.oxd_root])

<commit_msg>fix: stig - remove selfcert for oxd<commit_after>import os
import glob
import socket
import ruamel.yaml
import tempfile

from setup_app import paths
from setup_app.static import AppType, InstallOption, fapolicyd_rule_tmp
from setup_app.utils import base
from setup_app.config import Config
from setup_app.utils.setup_utils import SetupUtils, SetupProfiles
from setup_app.installers.base import BaseInstaller

class OxdInstaller(SetupUtils, BaseInstaller):

    def __init__(self):
        setattr(base.current_app, self.__class__.__name__, self)
        self.service_name = 'oxd-server'
        self.oxd_root = '/opt/oxd-server/'
        self.needdb = False # we don't need backend connection in this class
        self.app_type = AppType.SERVICE
        self.install_type = InstallOption.OPTONAL
        self.install_var = 'installOxd'
        self.register_progess()

        self.oxd_server_yml_fn = os.path.join(self.oxd_root, 'conf/oxd-server.yml')
        self.oxd_server_keystore_fn = os.path.join(self.oxd_root, 'conf/oxd-server.{}'.format(Config.default_store_type))
        self.oxd_jwks_keystore_fn = os.path.join(self.oxd_root, 'conf/oxd-jwks.{}'.format(Config.default_store_type))

        self.oxd_keystore_passw = 'example'
        self.fips_provider = self.get_keytool_provider()
        self.ks_type_bcfks = 'bcfks'
        self.ks_type_pkcs12 = 'pkcs12'

    def install(self):
        self.logIt("Installing {}".format(self.service_name.title()), pbar=self.service_name)
        self.run(['tar', '-zxf', Config.oxd_package, '--no-same-owner', '--strip-components=1', '-C', self.oxd_root])

        oxd_user = 'oxd-server' if Config.profile == SetupProfiles.DISA_STIG else Config.jetty_user
        Config.templateRenderingDict['service_user'] = oxd_user
        self.render_unit_file(self.service_name)

        if Config.profile == SetupProfiles.DISA_STIG:
            self.create_service_user(oxd_user)

        self.log_dir = '/var/log/oxd-server'
        service_file = os.path.join(self.oxd_root, 'oxd-server.service')
        if os.path.exists(service_file):
            self.run(['cp', service_file, '/lib/systemd/system'])
        else:
            self.run([Config.cmd_ln, service_file, '/etc/init.d/oxd-server'])

        if not os.path.exists(self.log_dir):
            self.run([paths.cmd_mkdir, self.log_dir])

        oxd_default = self.readFile(os.path.join(Config.install_dir, 'static/oxd/oxd-server.default'))
        rendered_oxd_default = self.fomatWithDict(oxd_default, self.merge_dicts(Config.__dict__, Config.templateRenderingDict))
        self.writeFile(os.path.join(Config.osDefault, 'oxd-server'), rendered_oxd_default)

        self.log_file = os.path.join(self.log_dir, 'oxd-server.log')
        if not os.path.exists(self.log_file):
            open(self.log_file, 'w').close()

        self.run([paths.cmd_chown, '-R', '{0}:{0}'.format(oxd_user), self.log_dir])

        for fn in glob.glob(os.path.join(self.oxd_root,'bin/*')):
            self.run([paths.cmd_chmod, '+x', fn])

        if not base.argsp.dummy:
            self.modify_config_yml()
            self.generate_keystore()

        self.run([paths.cmd_chown, '-R', '{0}:{0}'.format(oxd_user), self.oxd_root])

        if Config.profile == SetupProfiles.DISA_STIG:
            log_dir = '/var/log/oxd-server/'
            oxd_fapolicyd_rules = [
                    fapolicyd_rule_tmp.format(oxd_user, Config.jre_home),
                    fapolicyd_rule_tmp.format(oxd_user, log_dir),
                    fapolicyd_rule_tmp.format(oxd_user, self.oxd_root),
                    '# give access to oxd-server',
                    ]

            self.apply_fapolicyd_rules(oxd_fapolicyd_rules)
            # Restore SELinux Context
            self.run(['restorecon', '-rv', os.path.join(self.oxd_root, 'bin')])

            self.run([paths.cmd_chown, '{}:{}'.format(oxd_user, Config.gluu_group), os.path.join(Config.osDefault, self.service_name)])

        self.enable()

    def modify_config_yml(self):
        self.logIt("Configuring", pbar=self.service_name)
        yml_str = self.readFile(self.oxd_server_yml_fn)
        oxd_yaml = ruamel.yaml.load(yml_str, ruamel.yaml.RoundTripLoader)

        if 'bind_ip_addresses' in oxd_yaml:
            oxd_yaml['bind_ip_addresses'].append(Config.ip)
        else:
            for i, k in enumerate(oxd_yaml):
                if k == 'storage':
                    break
            else:
                i = 1
            addr_list = [Config.ip]
            if Config.profile == SetupProfiles.DISA_STIG:
                addr_list.append('127.0.0.1')
            oxd_yaml.insert(i, 'bind_ip_addresses',  addr_list)

        if Config.get('oxd_use_gluu_storage'):

            if 'dbFileLocation' in oxd_yaml['storage_configuration']:
                oxd_yaml['storage_configuration'].pop('dbFileLocation')
            oxd_yaml['storage'] = 'gluu_server_configuration'
            oxd_yaml['storage_configuration']['baseDn'] = 'o=gluu'
            oxd_yaml['storage_configuration']['type'] = Config.gluu_properties_fn
            if Config.mappingLocations['default'] == 'ldap':
                oxd_yaml['storage_configuration']['connection'] = Config.ox_ldap_properties
            elif Config.mappingLocations['default'] == 'rdbm':
                if Config.rdbm_type in ('mysql', 'pgsql'):
                    oxd_yaml['storage_configuration']['connection'] = Config.gluuRDBMProperties
                elif Config.rdbm_type == 'spanner':
                    oxd_yaml['storage_configuration']['connection'] = Config.gluuSpannerProperties
            elif Config.mappingLocations['default'] == 'couchbase':
                oxd_yaml['storage_configuration']['connection'] = Config.gluuCouchebaseProperties
            oxd_yaml['storage_configuration']['salt'] = os.path.join(Config.configFolder, "salt")

        if Config.profile == SetupProfiles.DISA_STIG:
            application_connectors = oxd_yaml['server']['applicationConnectors'][0]
            application_connectors['type'] = 'https'
            application_connectors['port'] = '8443'
            application_connectors['keyStorePath'] = self.oxd_server_keystore_fn
            application_connectors['keyStorePassword'] = self.oxd_keystore_passw
            application_connectors['keyStoreType'] = Config.default_store_type
            application_connectors['keyStoreProvider'] = self.fips_provider['-providername']
            application_connectors['trustStoreType'] = Config.default_store_type
            application_connectors['jceProvider'] = self.fips_provider['-providerclass']
            application_connectors['validateCerts'] = 'false'

            admin_connectors = oxd_yaml['server']['adminConnectors'][0]
            admin_connectors['type'] = 'https'
            admin_connectors['port'] = '8444'
            admin_connectors['keyStorePath'] = self.oxd_server_keystore_fn
            admin_connectors['keyStorePassword'] = self.oxd_keystore_passw
            admin_connectors['keyStoreType'] = Config.default_store_type
            admin_connectors['keyStoreProvider'] = self.fips_provider['-providername']
            admin_connectors['trustStoreType'] = Config.default_store_type
            admin_connectors['jceProvider'] = self.fips_provider['-providerclass']
            admin_connectors['validateCerts'] = 'false'

            oxd_yaml['crypt_provider_key_store_path']=self.oxd_jwks_keystore_fn
            oxd_yaml['crypt_provider_key_store_password']=self.oxd_keystore_passw

        yml_str = ruamel.yaml.dump(oxd_yaml, Dumper=ruamel.yaml.RoundTripDumper)
        self.writeFile(self.oxd_server_yml_fn, yml_str)

    def generate_keystore(self):
        self.logIt("Generating certificate", pbar=self.service_name)
        # generate oxd-server.keystore for the hostname

        keystore_tmp = '{}/oxd.{}'.format(tempfile.gettempdir(), Config.default_store_type)

        if Config.profile == SetupProfiles.DISA_STIG:

            cmd_cert_gen = [
                Config.cmd_keytool, '-genkey',
                '-alias', Config.hostname,
                '-keyalg', 'rsa',
                '-dname', 'CN={},O=OXD RSA Self-Signed Certificate'.format(Config.hostname),
                '-keystore', keystore_tmp,
                '-storetype', self.ks_type_bcfks,
                '-validity', '3650',
                ]

            cmd_cert_gen += [
                '-providername', self.fips_provider['-providername'],
                '-provider', self.fips_provider['-providerclass'],
                '-providerpath',  self.fips_provider['-providerpath'],
                '-keypass', self.oxd_keystore_passw,
                '-storepass', self.oxd_keystore_passw,
                '-keysize', '2048',
                '-sigalg', 'SHA256WITHRSA',
                    ]

            self.run(cmd_cert_gen)

        else:
            oxd_key_tmp = '{}/{}'.format(tempfile.gettempdir(),'oxd.key')
            oxd_crt_tmp = '{}/{}'.format(tempfile.gettempdir(),'oxd.crt')
            oxd_p12_tmp = '{}/{}'.format(tempfile.gettempdir(),'oxd.p12')

            self.run([
                paths.cmd_openssl,
                'req', '-x509', '-newkey', 'rsa:4096', '-nodes',
                '-out', oxd_crt_tmp,
                '-keyout', oxd_key_tmp,
                '-days', '3650',
                '-subj', '/C={}/ST={}/L={}/O={}/CN={}/emailAddress={}'.format(Config.countryCode, Config.state, Config.city, Config.orgName, Config.hostname, Config.admin_email),
                ])

            self.run([
                paths.cmd_openssl,
                'pkcs12', '-export',
                '-in', oxd_crt_tmp,
                '-inkey', oxd_key_tmp,
                '-out', oxd_p12_tmp,
                '-name', Config.hostname,
                '-passout', 'pass:{}'.format(self.oxd_keystore_passw)
                ])

            self.run([
                Config.cmd_keytool,
                '-importkeystore',
                '-deststorepass', self.oxd_keystore_passw,
                '-destkeypass', self.oxd_keystore_passw,
                '-destkeystore', keystore_tmp,
                '-srckeystore', oxd_p12_tmp,
                '-srcstoretype', self.ks_type_pkcs12,
                '-srcstorepass', self.oxd_keystore_passw,
                '-alias', Config.hostname,
                ])

            for f in (oxd_key_tmp, oxd_crt_tmp, oxd_p12_tmp):
                self.run([paths.cmd_rm, '-f', f])

        self.run([paths.cmd_rm, '-f', os.path.join(self.oxd_root,'conf/oxd-server.keystore')])

        self.run(['cp', '-f', keystore_tmp, self.oxd_server_keystore_fn])
        self.run([paths.cmd_chown, 'jetty:jetty', self.oxd_server_keystore_fn])

        self.run([paths.cmd_rm, '-f', keystore_tmp])

        self.import_oxd_certificate()

    def installed(self):
        return os.path.exists(self.oxd_server_yml_fn)

    def download_files(self, force=False):
        oxd_url = Config.maven_root + '/maven/org/gluu/oxd-server/{0}/oxd-server-{0}-distribution.zip'.format(Config.oxVersion)

        self.logIt("Downloading {} and preparing package".format(os.path.basename(oxd_url)))

        oxd_zip_fn = os.path.join(Config.outputFolder, 'oxd-server.zip')
        oxd_tgz_fn = os.path.join(Config.distGluuFolder, 'oxd-server.tgz')
        tmp_dir = os.path.join('/tmp', os.urandom(5).hex())
        oxd_tmp_dir = os.path.join(tmp_dir, 'oxd-server')

        self.run([paths.cmd_mkdir, '-p', oxd_tmp_dir])
        self.download_file(oxd_url, oxd_zip_fn)
        self.run([paths.cmd_unzip, '-qqo', oxd_zip_fn, '-d', oxd_tmp_dir])
        self.run([paths.cmd_mkdir, os.path.join(oxd_tmp_dir, 'data')])

        service_file = 'oxd-server.init.d' if base.deb_sysd_clone else 'oxd-server.service'
        service_url = 'https://raw.githubusercontent.com/GluuFederation/community-edition-package/master/package/systemd/oxd-server.service'.format(Config.oxVersion, service_file)
        self.download_file(service_url, os.path.join(oxd_tmp_dir, service_file))

        oxd_server_sh_url = 'https://raw.githubusercontent.com/GluuFederation/oxd/master/debian/oxd-server'
        self.download_file(oxd_server_sh_url, os.path.join(oxd_tmp_dir, 'bin/oxd-server'))

        self.run(['tar', '-zcf', oxd_tgz_fn, 'oxd-server'], cwd=tmp_dir)
        #self.run(['rm', '-r', '-f', tmp_dir])
        Config.oxd_package = oxd_tgz_fn

    def import_oxd_certificate(self):

        oxd_hostname, oxd_port = self.parse_url(Config.oxd_server_https)
        oxd_alias = 'oxd_' + oxd_hostname.replace('.','_')
        oxd_cert_fn = os.path.join(Config.outputFolder, '{}.pem'.format(oxd_alias))
        # let's delete if alias exists
        self.delete_key(oxd_alias)
        self.export_cert_from_store(Config.hostname, self.oxd_server_keystore_fn, self.oxd_keystore_passw, oxd_cert_fn)
        self.import_cert_to_java_truststore(oxd_alias, oxd_cert_fn)

    def create_folders(self):
        if not os.path.exists(self.oxd_root):
            self.run([paths.cmd_mkdir, self.oxd_root])

<|endoftext|>


<commit_before>import functools
import operator
import itertools

from .extern.jaraco.text import yield_lines
from .extern.jaraco.functools import pass_none
from ._importlib import metadata
from ._itertools import ensure_unique
from .extern.more_itertools import consume

def ensure_valid(ep):
    """
    Exercise one of the dynamic properties to trigger
    the pattern match.
    """
    ep.extras

def load_group(value, group):
    """
    Given a value of an entry point or series of entry points,
    return each as an EntryPoint.
    """
    # normalize to a single sequence of lines
    lines = yield_lines(value)
    text = f'[{group}]\n' + '\n'.join(lines)
    return metadata.EntryPoints._from_text(text)

def by_group_and_name(ep):
    return ep.group, ep.name

def validate(eps: metadata.EntryPoints):
    """
    Ensure entry points are unique by group and name and validate each.
    """
    consume(map(ensure_valid, ensure_unique(eps, key=by_group_and_name)))
    return eps

@functools.singledispatch
def load(eps):
    """
    Given a Distribution.entry_points, produce EntryPoints.
    """
    groups = itertools.chain.from_iterable(
        load_group(value, group)
        for group, value in eps.items())
    return validate(metadata.EntryPoints(groups))

@load.register(str)
def _(eps):
    return validate(metadata.EntryPoints._from_text(eps))

load.register(type(None), lambda x: x)

@pass_none
def render(eps: metadata.EntryPoints):
    by_group = operator.attrgetter('group')
    groups = itertools.groupby(sorted(eps, key=by_group), by_group)

    return '\n'.join(
        f'[{group}]\n{render_items(items)}\n'
        for group, items in groups
    )

def render_items(eps):
    return '\n'.join(
        f'{ep.name} = {ep.value}'
        for ep in sorted(eps)
    )
<commit_msg>Add test for loading entry points from a string. Ref #3103.<commit_after>import functools
import operator
import itertools

from .extern.jaraco.text import yield_lines
from .extern.jaraco.functools import pass_none
from ._importlib import metadata
from ._itertools import ensure_unique
from .extern.more_itertools import consume

def ensure_valid(ep):
    """
    Exercise one of the dynamic properties to trigger
    the pattern match.
    """
    ep.extras

def load_group(value, group):
    """
    Given a value of an entry point or series of entry points,
    return each as an EntryPoint.
    """
    # normalize to a single sequence of lines
    lines = yield_lines(value)
    text = f'[{group}]\n' + '\n'.join(lines)
    return metadata.EntryPoints._from_text(text)

def by_group_and_name(ep):
    return ep.group, ep.name

def validate(eps: metadata.EntryPoints):
    """
    Ensure entry points are unique by group and name and validate each.
    """
    consume(map(ensure_valid, ensure_unique(eps, key=by_group_and_name)))
    return eps

@functools.singledispatch
def load(eps):
    """
    Given a Distribution.entry_points, produce EntryPoints.
    """
    groups = itertools.chain.from_iterable(
        load_group(value, group)
        for group, value in eps.items())
    return validate(metadata.EntryPoints(groups))

@load.register(str)
def _(eps):
    r"""
    >>> ep, = load('[console_scripts]\nfoo=bar')
    >>> ep.group
    'console_scripts'
    >>> ep.name
    'foo'
    >>> ep.value
    'bar'
    """
    return validate(metadata.EntryPoints._from_text(eps))

load.register(type(None), lambda x: x)

@pass_none
def render(eps: metadata.EntryPoints):
    by_group = operator.attrgetter('group')
    groups = itertools.groupby(sorted(eps, key=by_group), by_group)

    return '\n'.join(
        f'[{group}]\n{render_items(items)}\n'
        for group, items in groups
    )

def render_items(eps):
    return '\n'.join(
        f'{ep.name} = {ep.value}'
        for ep in sorted(eps)
    )
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-

import logging
import os
import os.path as p

__version__ = '0.4.2'
static_dir = p.join(p.dirname(__file__), 'static')
default_static_dir = p.join(static_dir, 'default-static')
default_template_dir = p.join(static_dir, 'default-templates')

if not hasattr(p, 'relpath'):
    def relpath(path, start=p.curdir):
        """Return a relative version of a path"""

        if not path:
            raise ValueError("no path specified")

        start_list = p.abspath(start).split(p.sep)
        path_list = p.abspath(path).split(p.sep)

        # Work out how much of the filepath is shared by start and path.
        i = len(p.commonprefix([start_list, path_list]))

        rel_list = [p.pardir] * (len(start_list)-i) + path_list[i:]
        if not rel_list:
            return p.curdir
        return p.join(*rel_list)
    p.relpath = relpath

default_formatter = logging.Formatter(
    u'%(name)s: %(levelname)s: %(message)s')

console_handler = logging.StreamHandler() # By default, outputs to stderr.
console_handler.setFormatter(default_formatter)
console_handler.setLevel(logging.DEBUG)

logging.getLogger('markdoc').addHandler(console_handler)
logging.getLogger('markdoc').setLevel(logging.INFO) # Default level.

# These modules all initialize various default config values, so need to be
# imported straight away.
import markdoc.builder
import markdoc.directories
import markdoc.render
import markdoc.server
import markdoc.templates
<commit_msg>Bumped to v0.4.3.<commit_after># -*- coding: utf-8 -*-

import logging
import os
import os.path as p

__version__ = '0.4.3'
static_dir = p.join(p.dirname(__file__), 'static')
default_static_dir = p.join(static_dir, 'default-static')
default_template_dir = p.join(static_dir, 'default-templates')

if not hasattr(p, 'relpath'):
    def relpath(path, start=p.curdir):
        """Return a relative version of a path"""

        if not path:
            raise ValueError("no path specified")

        start_list = p.abspath(start).split(p.sep)
        path_list = p.abspath(path).split(p.sep)

        # Work out how much of the filepath is shared by start and path.
        i = len(p.commonprefix([start_list, path_list]))

        rel_list = [p.pardir] * (len(start_list)-i) + path_list[i:]
        if not rel_list:
            return p.curdir
        return p.join(*rel_list)
    p.relpath = relpath

default_formatter = logging.Formatter(
    u'%(name)s: %(levelname)s: %(message)s')

console_handler = logging.StreamHandler() # By default, outputs to stderr.
console_handler.setFormatter(default_formatter)
console_handler.setLevel(logging.DEBUG)

logging.getLogger('markdoc').addHandler(console_handler)
logging.getLogger('markdoc').setLevel(logging.INFO) # Default level.

# These modules all initialize various default config values, so need to be
# imported straight away.
import markdoc.builder
import markdoc.directories
import markdoc.render
import markdoc.server
import markdoc.templates
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-

from pint import UnitRegistry

#Update schema
__url__ = "https://raw.githubusercontent.com/KittyHawkIrc/modules/production/" + __name__ + ".py"
__version__ = 2.0

# declare() sets the strings that trigger this module.
# declare: None -> Dict{Str: Str}
def declare():
    declares = ['bmi', 'weight', 'mass', 'height', 'setbmi', 'clear_bmi2']
    return {command: 'privmsg' for command in declares}

def callback(self):
    channel = self.channel
    command = self.command.lower()
    user = self.user.split('!')[0]
    msg = self.msg
    isop = self.isop
    message = self.message.split(command, 1)[1].strip()
    words = message.split()

    ureg = UnitRegistry()
    ureg.define('bmi = kilogram / meter **2')

    try:
        mass, height, bmi = parse_input(message)
    except AttributeError:
        pass

    if command == 'clear_bmi2':
        if self.isowner:
            self.locker.bmi2 = None
            self.cache_save()   #persist cache post-restarts
            return msg(channel, 'All stored values cleared.')
        else:
            return msg(channel, 'Operation only permitted by bot owner.')
    elif command == 'setbmi':
        if bmi:
            set_other = is_nick(words[0]) and isop
            set_self = bool(not is_nick(words[0]) and bmi.magnitude < 25)

            if set_other or set_self:
                if set_other:
                    user = words[0]
                try:
                    self.locker.bmi2[user.lower()] = (mass, height, bmi)
                except:
                    self.locker.bmi2 = {user.lower(): (mass, height, bmi)}

                self.cache_save()   #persist cache post-restarts

                output = 'BMI for user [{u}] set to {b:.4g~P} / {b_c}'
            elif set_self:
                output = 'BMI [{b:.4g~P}] out of range settable by [{u}]'
            else:
                output = 'BMI for user [{w[0]}] cannot be set by user [{u}]'
        else:
            output = '{c}: <magnitude> <unit>...'
    elif command in ['bmi', 'weight', 'mass', 'height']:
        if mass and height and bmi:
            output = '{u} / {m:.4g~P} / {h:.4g~P} / {b:.4g~P} / {b_c}'
        elif len(words) < 1 or is_nick(words[0]):
            if len(words) > 0 and is_nick(words[0]):
                user = words[0]
            try:
                mass, height, bmi = self.locker.bmi2[user.lower()]
                if command == 'bmi':
                    output = '{u} / {b:.4g~P} / {b_c}'
                elif command == 'height' and height:
                    output = '{u} / {h:.4g~P}'
                elif mass:
                    output = '{u} / {m:.4g~P}'
                else:
                    raise
            except:
                if command == 'bmi':
                    try:
                        bmi = self.locker.bmi[user.lower()]
                        if is_quantity(bmi):
                            bmi = bmi.magnitude
                        bmi = bmi * ureg.bmi
                        output = '{u} / {b:.4g~P} / {b_c}'
                    except:
                        output = 'BMI not found for user [{u}]'
                else:
                    output = '{c} for [{u}] has not been updated for bmi2.'
        else:
            output = '{c}: <empty> | <nick> | <magnitude> <unit>...'

    if height and height.units == ureg.foot:
        output = output.replace('h:.4g~P', 'i_h')

    return msg(channel, output.format(w = words,   b = bmi,
                                      u = user,    m = mass,
                                      c = command, h = height,
                                      i_h = to_feet_inches(height),
                                      b_c = classify_bmi(bmi)))

# parse_input(message) takes string 'message' and attempts to extract and return
#   heights, masses, and BMIs from the string.
# parse_input: Str -> (Quantity None), (Quantity None), (Quantity None)
def parse_input(message):
    # replace ' and " with inch and feet before splitting message
    words = replace_foot_inch_symbol(message).split()

    # create variables
    heights = []
    masses = []
    bmi = 0

    for i, word in enumerate(words):
        # only allow numbers to be processed
        if not word[0].isdigit():
            continue

        # allow for spaces between magnitudes and units by concatenating word
        #   with following word
        if is_float(word) and (i+1 < len(words) and not is_float(words[i+1])):
            word = ' '.join((word, words.pop(i+1)))

        # check for bmi values included
        if len(word) > 3 and is_float(word[:-3]) and word[-3:].lower() == 'bmi':
            bmi = float(word[:-3]) * (ureg.bmi)
            continue

        # otherwise, check for quantities recognized by ureg
        quantity = ureg.Quantity(word)
        if is_quantity(quantity):
            if str(quantity.dimensionality) == '[length]':
                heights.append(quantity)
            elif str(quantity.dimensionality) == '[mass]':
                masses.append(quantity)

    # sum quantities recognized by ureg
    height = sum(heights)
    mass = sum(masses)

    # fill in missing quantity with maths
    if is_quantity(height) and is_quantity(mass):
        bmi = (mass / height ** 2).to(ureg.bmi)
    elif is_quantity(bmi) and is_quantity(height):
        mass = (bmi * height ** 2).to_base_units()
    elif is_quantity(bmi) and is_quantity(mass):
        height = ((mass / bmi) ** 0.5).to_base_units()

    # return tuple in order of mass, height (as mass/height^2=bmi)
    return mass, height, bmi

# classify_bmi(bmi) takes quantity 'bmi' and returns string for whether a bmi of
#   'bmi' is one of underweight, normal, obese, or overweight, with IRC control
#   codes to colour those results.
# classify_bmi: Quantity -> (Str None)
# requires: bmi.dimensionality == {'[length]': -2.0, '[mass]': 1.0}
def classify_bmi(bmi):
    try:
        if bmi.magnitude < 18.5:
            return '\002\00308underweight\017'
        if bmi.magnitude < 25.0:
            return '\002\00309normal\017'
        if bmi.magnitude < 30.0:
            return '\002\00307overweight\017'
        else:
            return '\002\00304obese\017'
    except:
        return None

# to_feet_inches(quantity) takes length 'quantity' and returns a tuple of the
#   length in feet and inches.
# to_feet_inches: Quantity -> (Str None)
# requires: quantity.dimensionality == {'[length]': 1.0}
def to_feet_inches(quantity):
    try:
        imperial_height_str = '{.magnitude:.0f}\'{.magnitude:.4g}"'
        feet = int(quantity.to(ureg.foot).magnitude) * ureg.foot
        inches = (quantity - feet).to(ureg.inch)
        return imperial_height_str.format(feet, inches)
    except:
        return None

# replace_foot_inch_symbol(string) takes string and replaces all instances of
#   quotation marks with their respective unit (foot or inch).
# replace_foot_inch_symbol: Str -> Str
def replace_foot_inch_symbol(string):
    foot_symbols = ["'", "‘", "’"]
    inch_symbols = ['"', '“', '”']

    for symbol in foot_symbols:
        string = string.replace(symbol, 'foot ')

    for symbol in inch_symbols:
        string = string.replace(symbol, 'inch ')

    return string

# is_imperial(quantity) returns whether 'quantity' is an imperial unit or not.
# is_imperial: Quantity -> Bool
def is_imperial(quantity):
    if (quantity.units in dir(ureg.sys.US) or
        quantity.units in dir(ureg.sys.imperial)):
        return True
    return False

# is_nick(string) takes 'string' and determines if it is a valid IRC nickname
# is_nick: Str -> Bool
# requires: isinstance(string, str)
def is_nick(string):
    for i, char in enumerate(string):
        if ((i > 0 and (char.isdigit() or char == '-')) or
            char.isalpha() or char in '_-\[]{}^`|'):
            continue
        else:
            return False
    return True

# is_float(object_) takes any object 'object_' and returns a boolean for
#   whether it can be converted into a float
# is_float: Any -> Bool
def is_float(object_):
    try:
        float(object_)
        return True
    except:
        return False

# is_quantity(object_) takes any object 'object_' and returns a boolean for
#   whether it is of the type 'Quantity'
# is_quantity: Any -> Bool
def is_quantity(object_):
    return type(object_).__name__ == 'Quantity'

################################ START: Testing ################################
class api:
    def msg(self, channel, text):
        return "[%s] %s" % (channel, text)

class empty:
    pass

if __name__ == "__main__":
    def cache_save():
        print 'Cache saved'
    api = api()
    declares = declare().keys()
    setattr(api, 'cache_save', cache_save)
    setattr(api, 'type', 'privmsg')
    setattr(api, 'channel', "#channel")
    setattr(api, 'locker', empty)
    setattr(api, 'user', 'nick!ident@host')
    setattr(api, 'isop', False)
    setattr(api, 'isowner', False)
###############nick########### START: Interactive Testing ##########################
'''
    while(True):
        _input = raw_input('Enter message here: ')
        input_split = _input.split()
        if input_split[0] == 'op':
            setattr(api, 'isop', True)
            print 'User opped'
            continue
        elif input_split[0] == 'deop':
            setattr(api, 'isop', False)
            print 'User deopped'
            continue
        elif input_split[0] == 'owner':
            setattr(api, 'isowner', True)
            setattr(api, 'isop', True)
            print 'User ownered'
            continue
        elif input_split[0] == 'deowner':
            setattr(api, 'isowner', False)
            print 'User deownered'
            continue
        elif input_split[0] == 'user' and len(input_split) > 1:
            setattr(api, 'user', input_split[1])
            print 'User changed to {}'.format(input_split[1])
            continue
        elif input_split[0] == 'quit':
            break
        elif len(_input) > 0 and input_split[0][1:] in declares:
            setattr(api, 'command', _input.split()[0][1:])
            setattr(api, 'message', _input)
            print callback(api)
            continue
'''
########################### END: Interactive Testing ###########################
################################# END: Testing #################################
<commit_msg>Revert "Update bmi2.py"<commit_after># -*- coding: utf-8 -*-

from pint import UnitRegistry

ureg = UnitRegistry()
ureg.define('bmi = kilogram / meter **2')

#Update schema
__url__ = "https://raw.githubusercontent.com/KittyHawkIrc/modules/production/" + __name__ + ".py"
__version__ = 2.0

# declare() sets the strings that trigger this module.
# declare: None -> Dict{Str: Str}
def declare():
    declares = ['bmi', 'weight', 'mass', 'height', 'setbmi', 'clear_bmi2']
    return {command: 'privmsg' for command in declares}

def callback(self):
    channel = self.channel
    command = self.command.lower()
    user = self.user.split('!')[0]
    msg = self.msg
    isop = self.isop
    message = self.message.split(command, 1)[1].strip()
    words = message.split()

    try:
        mass, height, bmi = parse_input(message)
    except AttributeError:
        pass

    if command == 'clear_bmi2':
        if self.isowner:
            self.locker.bmi2 = None
            self.cache_save()   #persist cache post-restarts
            return msg(channel, 'All stored values cleared.')
        else:
            return msg(channel, 'Operation only permitted by bot owner.')
    elif command == 'setbmi':
        if bmi:
            set_other = is_nick(words[0]) and isop
            set_self = bool(not is_nick(words[0]) and bmi.magnitude < 25)

            if set_other or set_self:
                if set_other:
                    user = words[0]
                try:
                    self.locker.bmi2[user.lower()] = (mass, height, bmi)
                except:
                    self.locker.bmi2 = {user.lower(): (mass, height, bmi)}

                self.cache_save()   #persist cache post-restarts

                output = 'BMI for user [{u}] set to {b:.4g~P} / {b_c}'
            elif set_self:
                output = 'BMI [{b:.4g~P}] out of range settable by [{u}]'
            else:
                output = 'BMI for user [{w[0]}] cannot be set by user [{u}]'
        else:
            output = '{c}: <magnitude> <unit>...'
    elif command in ['bmi', 'weight', 'mass', 'height']:
        if mass and height and bmi:
            output = '{u} / {m:.4g~P} / {h:.4g~P} / {b:.4g~P} / {b_c}'
        elif len(words) < 1 or is_nick(words[0]):
            if len(words) > 0 and is_nick(words[0]):
                user = words[0]
            try:
                mass, height, bmi = self.locker.bmi2[user.lower()]
                if command == 'bmi':
                    output = '{u} / {b:.4g~P} / {b_c}'
                elif command == 'height' and height:
                    output = '{u} / {h:.4g~P}'
                elif mass:
                    output = '{u} / {m:.4g~P}'
                else:
                    raise
            except:
                if command == 'bmi':
                    try:
                        bmi = self.locker.bmi[user.lower()]
                        if is_quantity(bmi):
                            bmi = bmi.magnitude
                        bmi = bmi * ureg.bmi
                        output = '{u} / {b:.4g~P} / {b_c}'
                    except:
                        output = 'BMI not found for user [{u}]'
                else:
                    output = '{c} for [{u}] has not been updated for bmi2.'
        else:
            output = '{c}: <empty> | <nick> | <magnitude> <unit>...'

    if height and height.units == ureg.foot:
        output = output.replace('h:.4g~P', 'i_h')

    return msg(channel, output.format(w = words,   b = bmi,
                                      u = user,    m = mass,
                                      c = command, h = height,
                                      i_h = to_feet_inches(height),
                                      b_c = classify_bmi(bmi)))

# parse_input(message) takes string 'message' and attempts to extract and return
#   heights, masses, and BMIs from the string.
# parse_input: Str -> (Quantity None), (Quantity None), (Quantity None)
def parse_input(message):
    # replace ' and " with inch and feet before splitting message
    words = replace_foot_inch_symbol(message).split()

    # create variables
    heights = []
    masses = []
    bmi = 0

    for i, word in enumerate(words):
        # only allow numbers to be processed
        if not word[0].isdigit():
            continue

        # allow for spaces between magnitudes and units by concatenating word
        #   with following word
        if is_float(word) and (i+1 < len(words) and not is_float(words[i+1])):
            word = ' '.join((word, words.pop(i+1)))

        # check for bmi values included
        if len(word) > 3 and is_float(word[:-3]) and word[-3:].lower() == 'bmi':
            bmi = float(word[:-3]) * (ureg.bmi)
            continue

        # otherwise, check for quantities recognized by ureg
        quantity = ureg.Quantity(word)
        if is_quantity(quantity):
            if str(quantity.dimensionality) == '[length]':
                heights.append(quantity)
            elif str(quantity.dimensionality) == '[mass]':
                masses.append(quantity)

    # sum quantities recognized by ureg
    height = sum(heights)
    mass = sum(masses)

    # fill in missing quantity with maths
    if is_quantity(height) and is_quantity(mass):
        bmi = (mass / height ** 2).to(ureg.bmi)
    elif is_quantity(bmi) and is_quantity(height):
        mass = (bmi * height ** 2).to_base_units()
    elif is_quantity(bmi) and is_quantity(mass):
        height = ((mass / bmi) ** 0.5).to_base_units()

    # return tuple in order of mass, height (as mass/height^2=bmi)
    return mass, height, bmi

# classify_bmi(bmi) takes quantity 'bmi' and returns string for whether a bmi of
#   'bmi' is one of underweight, normal, obese, or overweight, with IRC control
#   codes to colour those results.
# classify_bmi: Quantity -> (Str None)
# requires: bmi.dimensionality == {'[length]': -2.0, '[mass]': 1.0}
def classify_bmi(bmi):
    try:
        if bmi.magnitude < 18.5:
            return '\002\00308underweight\017'
        if bmi.magnitude < 25.0:
            return '\002\00309normal\017'
        if bmi.magnitude < 30.0:
            return '\002\00307overweight\017'
        else:
            return '\002\00304obese\017'
    except:
        return None

# to_feet_inches(quantity) takes length 'quantity' and returns a tuple of the
#   length in feet and inches.
# to_feet_inches: Quantity -> (Str None)
# requires: quantity.dimensionality == {'[length]': 1.0}
def to_feet_inches(quantity):
    try:
        imperial_height_str = '{.magnitude:.0f}\'{.magnitude:.4g}"'
        feet = int(quantity.to(ureg.foot).magnitude) * ureg.foot
        inches = (quantity - feet).to(ureg.inch)
        return imperial_height_str.format(feet, inches)
    except:
        return None

# replace_foot_inch_symbol(string) takes string and replaces all instances of
#   quotation marks with their respective unit (foot or inch).
# replace_foot_inch_symbol: Str -> Str
def replace_foot_inch_symbol(string):
    foot_symbols = ["'", "‘", "’"]
    inch_symbols = ['"', '“', '”']

    for symbol in foot_symbols:
        string = string.replace(symbol, 'foot ')

    for symbol in inch_symbols:
        string = string.replace(symbol, 'inch ')

    return string

# is_imperial(quantity) returns whether 'quantity' is an imperial unit or not.
# is_imperial: Quantity -> Bool
def is_imperial(quantity):
    if (quantity.units in dir(ureg.sys.US) or
        quantity.units in dir(ureg.sys.imperial)):
        return True
    return False

# is_nick(string) takes 'string' and determines if it is a valid IRC nickname
# is_nick: Str -> Bool
# requires: isinstance(string, str)
def is_nick(string):
    for i, char in enumerate(string):
        if ((i > 0 and (char.isdigit() or char == '-')) or
            char.isalpha() or char in '_-\[]{}^`|'):
            continue
        else:
            return False
    return True

# is_float(object_) takes any object 'object_' and returns a boolean for
#   whether it can be converted into a float
# is_float: Any -> Bool
def is_float(object_):
    try:
        float(object_)
        return True
    except:
        return False

# is_quantity(object_) takes any object 'object_' and returns a boolean for
#   whether it is of the type 'Quantity'
# is_quantity: Any -> Bool
def is_quantity(object_):
    return type(object_).__name__ == 'Quantity'

################################ START: Testing ################################
class api:
    def msg(self, channel, text):
        return "[%s] %s" % (channel, text)

class empty:
    pass

if __name__ == "__main__":
    def cache_save():
        print 'Cache saved'
    api = api()
    declares = declare().keys()
    setattr(api, 'cache_save', cache_save)
    setattr(api, 'type', 'privmsg')
    setattr(api, 'channel', "#channel")
    setattr(api, 'locker', empty)
    setattr(api, 'user', 'nick!ident@host')
    setattr(api, 'isop', False)
    setattr(api, 'isowner', False)
###############nick########### START: Interactive Testing ##########################
'''
    while(True):
        _input = raw_input('Enter message here: ')
        input_split = _input.split()
        if input_split[0] == 'op':
            setattr(api, 'isop', True)
            print 'User opped'
            continue
        elif input_split[0] == 'deop':
            setattr(api, 'isop', False)
            print 'User deopped'
            continue
        elif input_split[0] == 'owner':
            setattr(api, 'isowner', True)
            setattr(api, 'isop', True)
            print 'User ownered'
            continue
        elif input_split[0] == 'deowner':
            setattr(api, 'isowner', False)
            print 'User deownered'
            continue
        elif input_split[0] == 'user' and len(input_split) > 1:
            setattr(api, 'user', input_split[1])
            print 'User changed to {}'.format(input_split[1])
            continue
        elif input_split[0] == 'quit':
            break
        elif len(_input) > 0 and input_split[0][1:] in declares:
            setattr(api, 'command', _input.split()[0][1:])
            setattr(api, 'message', _input)
            print callback(api)
            continue
'''
########################### END: Interactive Testing ###########################
################################# END: Testing #################################
<|endoftext|>