<commit_before># This source file is part of yaffel-py
# Main Developer : Dimitri Racordon (kyouko.taiga@gmail.com)
#
# Copyright 2014 Dimitri Racordon
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from collections import namedtuple
from funcparserlib.lexer import make_tokenizer, Token, LexerError
from funcparserlib.parser import some, a, many, maybe, finished, skip, with_forward_decls
from functools import reduce

import numbers, operator, sys

keywords = ['for', 'in', 'not in']

class EvaluationError(Exception):
    def __init__(self, message):
        Exception.__init__(self, message)

class Function(object):

    def __init__(self, head, expr=None):
        self.head = head
        self.expr = expr

    def __call__(self, **context):
        # retrieve the first term value
        a = self._value(self.head, context)

        # evaluate expression
        for f,b in self.expr:
            a = f(a, self._value(b, context))
        return a

    def _value(self, term, context):
        if isinstance(term, Token):
            try:
                return context[term.value]
            except KeyError:
                raise EvaluationError("unbound variable '%s'" % term.value) from None
        elif hasattr(term, '__call__'):
            return term(**context)
        else:
            return term

    def __repr__(self):
        return '%s(%s)' % (self.__class__, str(self))

    def __str__(self):
        # helper function to get the string representation of a term
        sym = lambda term: term.value if isinstance(term, Token) else str(term)

        # if the expression is simple a constant
        if not self.expr:
            return sym(self.head)

        ret = ''
        a = sym(self.head)
        for f,b in self.expr:
            a = '%(f)s(%(a)s, %(b)s)' % {'f': f, 'a': a, 'b': sym(b)}
        return a

class Set(object):

    def __init__(self, function, context):
        self.function = function
        self.context = context

    def __call__(self, **context):
        return Set(self.function, {k: v(**context) for k,v in self.context.items()})

    def __repr__(self):
        return '%s(%s)' % (self.__class__, str(self))

    def __str__(self):
        f = lambda c: '%s in %s' % (c[0], str(c[1]))
        return '{%s for %s}' % (self.function, ', '.join(f(c) for c in self.context.items()))

class Enumeration(Set):

    def __init__(self, *elements):
        self.elements = set(elements)

    def __call__(self, **context):
        return Enumeration(*{e(**context) for e in self.elements})

    def __repr__(self):
        return '%s(%s)' % (self.__class__, str(self))

    def __str__(self):
        return '{%s}' % ', '.join(str(e) for e in self.elements)

class Range(Set):

    def __init__(self, lower_bound, upper_bound):
        self.lower_bound = lower_bound
        self.upper_bound = upper_bound

    def __call__(self, **context):
        # evaluate lower and upper bounds
        lower = self.lower_bound(**context)
        upper = self.upper_bound(**context)

        # check type consistency
        if not isinstance(lower, numbers.Real) or not isinstance(upper, numbers.Real):
            raise TypeError('range defined for non-numeric lower or upper bounds')
        if not lower < upper:
            raise TypeError('range defined with unordered bounds')

        return Range(lower, upper)

    def __repr__(self):
        return '%s(%s)' % (self.__class__, str(self))

    def __str__(self):
        return '{%s:%s}' % (repr(self.lower_bound), self.upper_bound)

def tokenize(s):
    regexps = {
        'escaped':   r'\\(?P<standard>["\\/bfnrt])',
        'unescaped': r'[^"\\]' }
    grammar_specifications = [
        ('space',    (r'[ \t\r\n]+',)),
        ('number',   (r'-?(0|([1-9][0-9]*))(\.[0-9]+)?([Ee][+-][0-9]+)?',)),
        ('string',   (r'"[^"]*"',)),                                # unsupported escaped quotes
        ('operator', (r'(\*\*)|(and)|(or)|(in)|[{}\[\]\(\)\-\+\*/=><\.,:]',)),
        ('name',     (r'[A-Za-z_][A-Za-z_0-9]*',)),
    ]

    t = make_tokenizer(grammar_specifications)
    return [x for x in t(s) if x.type not in ['space']]

def parse(seq):
    # auxiliary helper functions
    const       = lambda x: lambda _: x
    uncurry     = lambda f: lambda x: f(*x)
    token_value = lambda t: t.value
    token_type  = lambda t: some(lambda x: x.type == t)

    # semantic actions
    def make_number(t):
        try:
            return int(t)
        except ValueError:
            return float(t)

    def eval_cst_expr(head, tail):
        return reduce(lambda s, p: p[0](s, p[1]), tail, head)

    def eval_expr(x):
        if hasattr(x[0], '__call__'):
            # Whenever an expression is parsed, an instance of Function is
            # created. Then, when we want to evaluate the result of the
            # expression for a given binding, this function will be called,
            # using the context bindings as the function parameters.
            context = x[1] or {}
            return x[0](**context)

        # If the expression is constant, we don't need to evaluate it.
        return x[0]

    def make_function(head, tail):
        # try to evaluate as a constant expression, if possible
        # terms = [head] + [t for _,t in tail]
        # if not any(isinstance(t, Token) or hasattr(t, '__call__') for t in terms):
        #     return eval_cst_expr(head, tail)

        # don't create an additional function if 'head' is the only term and is already callable
        if not tail and hasattr(head, '__call__'):
            return head

        # return a function that will take unbound variables as parameters
        return Function(head, tail)

    def make_binding(t):
        return (token_value(t[0]), t[1])

    def make_context(head, tail):
        context = {head[0]: head[1]}
        for k,v in tail:
            if k in context: raise EvaluationError("'%s' is already bound" % k)
            context[k] = v
        return context

    def make_enum(x):
        # check that the enumeration is not the empty set
        if x is not None:
            e = {x[0]} | {e for e in x[1]}
            return Enumeration(*e)

        # return the empty set
        return Enumeration()

    def make_range(x):
        return Range(x[0],x[1])

    def make_set(x):
        return Set(*x)

    # primitives
    op          = lambda s: a(Token('operator', s))
    op_         = lambda s: skip(op(s))

    kw          = lambda s: a(Token('name', s))
    kw_         = lambda s: skip(kw(s))

    add         = op('+') >> const(operator.add)
    sub         = op('-') >> const(operator.sub)
    mul         = op('*') >> const(operator.mul)
    div         = op('/') >> const(operator.truediv)
    power       = op('**') >> const(operator.pow)
    and_        = op('and') >> const(operator.and_)
    or_         = op('or') >> const(operator.or_)

    name        = token_type('name')
    number      = token_type('number') >> token_value >> make_number
    string      = token_type('string') >> token_value

    # grammar rules
    mul_op      = mul | div
    add_op      = add | sub
    bin_op      = or_ | and_

    atom        = with_forward_decls(lambda:
                    number | name | set_expr | (op_('(') + expr + op_(')')))
    factor      = atom + many(power + atom) >> uncurry(make_function)
    term        = factor + many(mul_op + factor) >> uncurry(make_function)
    expr        = term + many((add_op | bin_op) + term) >> uncurry(make_function)

    binding     = with_forward_decls(lambda: name + op_('=') + evaluation >> (make_binding))
    context     = binding + many(op_(',') + binding) >> uncurry(make_context)

    evaluable   = expr + maybe(kw_('for') + context) >> eval_expr
    evaluation  = evaluable | (op_('(') + evaluable + op_(')'))

    enumeration = op_('{') + maybe(expr + many(op_(',') + expr)) + op_('}') >> make_enum
    range_      = op_('{') + expr + op_(':') + expr  + op_('}') >> make_range
    set_        = with_forward_decls(lambda:
                    op_('{') + expr + maybe(kw_('for') + set_context) + op_('}') >> make_set)
    set_expr    = (enumeration | range_ | set_)

    set_binding = name + op_('in') + set_expr >> make_binding
    set_context = set_binding + many(op_(',') + set_binding) >> uncurry(make_context)

    yaffel      = evaluable + skip(finished)

    # tokenize and parse the given sequence
    parsed = yaffel.parse(tokenize(seq))
    return (type(parsed), parsed)

if __name__ == '__main__':
    #print(tokenize(sys.argv[1]))
    print( '%s %s' % parse(sys.argv[1]) )
    #print( parse(sys.argv[1])[1](**{'x':24}) )
<commit_msg>Comments<commit_after># This source file is part of yaffel-py
# Main Developer : Dimitri Racordon (kyouko.taiga@gmail.com)
#
# Copyright 2014 Dimitri Racordon
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from collections import namedtuple
from funcparserlib.lexer import make_tokenizer, Token, LexerError
from funcparserlib.parser import some, a, many, maybe, finished, skip, with_forward_decls
from functools import reduce

import numbers, operator, sys

keywords = ['for', 'in', 'not in']

class EvaluationError(Exception):
    def __init__(self, message):
        Exception.__init__(self, message)

class Function(object):
    """Represents an expression as an anonymous function.

    When parsed, yaffel expressions are recursively (actually the process is
    performed bottom-up) decomposed into smaller lazy-evaluated expressions, or
    anonymous functions, until no further decomposition is possible, i.e. when
    when they are reduced to atomic primitives such as numbers, strings, etc.
    """

    def __init__(self, head, expr=None):
        self.head = head
        self.expr = expr

    def __call__(self, **context):
        """Evaluates the function value.

        This method evaluates the function, using ``context`` to bind its free
        variables, if present.
        """
        # retrieve the first term value
        a = self._value(self.head, context)

        # evaluate expression
        for f,b in self.expr:
            a = f(a, self._value(b, context))
        return a

    def _value(self, term, context):
        if isinstance(term, Token):
            try:
                return context[term.value]
            except KeyError:
                raise EvaluationError("unbound variable '%s'" % term.value) from None
        elif hasattr(term, '__call__'):
            return term(**context)
        else:
            return term

    def __repr__(self):
        return '%s(%s)' % (self.__class__, str(self))

    def __str__(self):
        # helper function to get the string representation of a term
        sym = lambda term: term.value if isinstance(term, Token) else str(term)

        # if the expression is simple a constant
        if not self.expr:
            return sym(self.head)

        ret = ''
        a = sym(self.head)
        for f,b in self.expr:
            a = '%(f)s(%(a)s, %(b)s)' % {'f': f, 'a': a, 'b': sym(b)}
        return a

class Set(object):
    """Symbolic representation of a set.

    Sets are represented symbolically as a tuple (f,u) where f is a function
    and u another set. Let a set S be defined by (f,u), then elements of S are
    given by {f(x) | x \in u}.
    """

    def __init__(self, function, context):
        self.function = function
        self.context = context

    def __call__(self, **context):
        return Set(self.function, {k: v(**context) for k,v in self.context.items()})

    def __repr__(self):
        return '%s(%s)' % (self.__class__, str(self))

    def __str__(self):
        f = lambda c: '%s in %s' % (c[0], str(c[1]))
        return '{%s for %s}' % (self.function, ', '.join(f(c) for c in self.context.items()))

class Enumeration(Set):
    """Kind of set that simply enumerates values."""

    def __init__(self, *elements):
        self.elements = set(elements)

    def __call__(self, **context):
        return Enumeration(*{e(**context) for e in self.elements})

    def __repr__(self):
        return '%s(%s)' % (self.__class__, str(self))

    def __str__(self):
        return '{%s}' % ', '.join(str(e) for e in self.elements)

class Range(Set):
    """Numeric set that contains values from its lower to its upper bound."""

    def __init__(self, lower_bound, upper_bound):
        self.lower_bound = lower_bound
        self.upper_bound = upper_bound

    def __call__(self, **context):
        # evaluate lower and upper bounds
        lower = self.lower_bound(**context)
        upper = self.upper_bound(**context)

        # check type consistency
        if not isinstance(lower, numbers.Real) or not isinstance(upper, numbers.Real):
            raise TypeError('range defined for non-numeric lower or upper bounds')
        if not lower < upper:
            raise TypeError('range defined with unordered bounds')

        return Range(lower, upper)

    def __repr__(self):
        return '%s(%s)' % (self.__class__, str(self))

    def __str__(self):
        return '{%s:%s}' % (repr(self.lower_bound), self.upper_bound)

def tokenize(s):
    regexps = {
        'escaped':   r'\\(?P<standard>["\\/bfnrt])',
        'unescaped': r'[^"\\]' }
    grammar_specifications = [
        ('space',    (r'[ \t\r\n]+',)),
        ('number',   (r'-?(0|([1-9][0-9]*))(\.[0-9]+)?([Ee][+-][0-9]+)?',)),
        ('string',   (r'"[^"]*"',)),                                # unsupported escaped quotes
        ('operator', (r'(\*\*)|(and)|(or)|(in)|[{}\[\]\(\)\-\+\*/=><\.,:]',)),
        ('name',     (r'[A-Za-z_][A-Za-z_0-9]*',)),
    ]

    t = make_tokenizer(grammar_specifications)
    return [x for x in t(s) if x.type not in ['space']]

def parse(seq):
    # auxiliary helper functions
    const       = lambda x: lambda _: x
    uncurry     = lambda f: lambda x: f(*x)
    token_value = lambda t: t.value
    token_type  = lambda t: some(lambda x: x.type == t)

    # semantic actions
    def make_number(t):
        try:
            return int(t)
        except ValueError:
            return float(t)

    def eval_cst_expr(head, tail):
        return reduce(lambda s, p: p[0](s, p[1]), tail, head)

    def eval_expr(x):
        if hasattr(x[0], '__call__'):
            # Whenever an expression is parsed, an instance of Function is
            # created. Then, when we want to evaluate the result of the
            # expression for a given binding, this function will be called,
            # using the context bindings as the function parameters.
            context = x[1] or {}
            return x[0](**context)

        # If the expression is constant, we don't need to evaluate it.
        return x[0]

    def make_function(head, tail):
        # try to evaluate as a constant expression, if possible
        # terms = [head] + [t for _,t in tail]
        # if not any(isinstance(t, Token) or hasattr(t, '__call__') for t in terms):
        #     return eval_cst_expr(head, tail)

        # don't create an additional function if 'head' is the only term and is already callable
        if not tail and hasattr(head, '__call__'):
            return head

        # return a function that will take unbound variables as parameters
        return Function(head, tail)

    def make_binding(t):
        return (token_value(t[0]), t[1])

    def make_context(head, tail):
        context = {head[0]: head[1]}
        for k,v in tail:
            if k in context: raise EvaluationError("'%s' is already bound" % k)
            context[k] = v
        return context

    def make_enum(x):
        # check that the enumeration is not the empty set
        if x is not None:
            e = {x[0]} | {e for e in x[1]}
            return Enumeration(*e)

        # return the empty set
        return Enumeration()

    def make_range(x):
        return Range(x[0],x[1])

    def make_set(x):
        return Set(*x)

    # primitives
    op          = lambda s: a(Token('operator', s))
    op_         = lambda s: skip(op(s))

    kw          = lambda s: a(Token('name', s))
    kw_         = lambda s: skip(kw(s))

    add         = op('+') >> const(operator.add)
    sub         = op('-') >> const(operator.sub)
    mul         = op('*') >> const(operator.mul)
    div         = op('/') >> const(operator.truediv)
    power       = op('**') >> const(operator.pow)
    and_        = op('and') >> const(operator.and_)
    or_         = op('or') >> const(operator.or_)

    name        = token_type('name')
    number      = token_type('number') >> token_value >> make_number
    string      = token_type('string') >> token_value

    # grammar rules
    mul_op      = mul | div
    add_op      = add | sub
    bin_op      = or_ | and_

    atom        = with_forward_decls(lambda:
                    number | name | set_expr | (op_('(') + expr + op_(')')))
    factor      = atom + many(power + atom) >> uncurry(make_function)
    term        = factor + many(mul_op + factor) >> uncurry(make_function)
    expr        = term + many((add_op | bin_op) + term) >> uncurry(make_function)

    binding     = with_forward_decls(lambda: name + op_('=') + evaluation >> (make_binding))
    context     = binding + many(op_(',') + binding) >> uncurry(make_context)

    evaluable   = expr + maybe(kw_('for') + context) >> eval_expr
    evaluation  = evaluable | (op_('(') + evaluable + op_(')'))

    enumeration = op_('{') + maybe(expr + many(op_(',') + expr)) + op_('}') >> make_enum
    range_      = op_('{') + expr + op_(':') + expr  + op_('}') >> make_range
    set_        = with_forward_decls(lambda:
                    op_('{') + expr + maybe(kw_('for') + set_context) + op_('}') >> make_set)
    set_expr    = (enumeration | range_ | set_)

    set_binding = name + op_('in') + set_expr >> make_binding
    set_context = set_binding + many(op_(',') + set_binding) >> uncurry(make_context)

    yaffel      = evaluable + skip(finished)

    # tokenize and parse the given sequence
    parsed = yaffel.parse(tokenize(seq))
    return (type(parsed), parsed)

if __name__ == '__main__':
    #print(tokenize(sys.argv[1]))
    print( '%s %s' % parse(sys.argv[1]) )
    #print( parse(sys.argv[1])[1](**{'x':24}) )
<|endoftext|>


<commit_before># The MIT License (MIT)
#
# Copyright (c) 2013 CFEngine AS
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

import os
import sys
from os import listdir
from os.path import isfile, join
from string import ascii_letters, digits

def run(config):
	markdown_files =  config["markdown_files"]
	readLinkFile(config)
	for file in markdown_files:
		parseMarkdownForAnchors(file, config)

def apply(config):
	markdown_files =  config["markdown_files"]
	for file in markdown_files:
		applyLinkMap(file, config)

def readLinkFile(config):
	output_file = config["reference_path"]
	link_map = config.get("link_map", dict())

	link_file = open(output_file, 'r')
	link_lines = link_file.readlines()
	for line in link_lines:
		label = line[line.find('[') + 1:line.find(']')]
		link_map["`" + label + "`"] = "[" + label + "]"
	config["link_map"] = link_map

def addLinkToMap(keyword, anchor, html, config):
	link_map = config.get("link_map", dict())

	# don't overwrite
	if keyword in link_map:
		return

	link_map[keyword] = "[" + anchor + "]"

	output_file = config["reference_path"]
	out_file = open(output_file, "a")
	output_string = '[' + anchor + ']: ' + html
	out_file.write(output_string+"\n")
	out_file.close()

	config["link_map"] = link_map

def parseMarkdownForAnchors(file_name, config):
	in_file = open(file_name,"r")
	lines = in_file.readlines()
	in_file.close()

	current_file_name = ""
	current_file_label = ""
	current_title = ""
	header_list = []

	in_pre = False
	for line in lines:
		# ignore code blocks
		if line.find("    ") == 0:
			continue
		elif line.find("```") == 0:
			in_pre = not in_pre
		if in_pre:
			continue

		if line.find("title:") == 0:
			current_title = line.split('title: ')
			current_title = current_title[1].rstrip().rstrip('\"')
			current_title = current_title.lstrip().lstrip('\"')
		elif line.find("alias:") == 0:
			current_file_name = line.split('alias: ')
			current_file_name = current_file_name[1].rstrip()
		elif line.find("#") == 0:
			current_header = line.lstrip('#').rstrip().lstrip()
			header_list.append(current_header)

	current_file_label = current_title

	if current_file_label != "" and current_file_name != "":
		keyword = current_file_label
		# generate auto-link to functions via `function()`
		if current_file_name.find("reference-functions-") == 0:
			keyword += "()"
		addLinkToMap("`" + keyword + "`", current_file_label, current_file_name + ' \"' + current_title + '\"', config)
		# keep dictionary reasonably short by including at most three-word headers
		for header in header_list:
			if header == "":
				continue
			anchor = header.lower()
			anchor = anchor.replace(" ", "-")
			anchor = anchor.replace(":", "-")
			anchor = anchor.replace(".", "-")
			anchor = anchor.replace("`", "-")
			anchor = anchor.replace("/", "-")
			anchor = anchor.replace("$", "-")
			anchor = anchor.replace("(", "-")
			anchor = anchor.replace(")", "-")
			anchor = anchor.replace("\"", "")
			anchor = anchor.replace("--", "-")
			anchor = anchor.lstrip("-").rstrip("-")
			label = current_file_label+ '#' + header
			# prefer top-level anchors
			addLinkToMap("`" + header + "`", label, current_file_name + '#' + anchor + ' \"' + current_title + ' - ' + header + '\"', config)

def applyLinkMap(file_name, config):
	markdown_file = open(file_name,"r")
	markdown_lines = markdown_file.readlines()
	markdown_file.close()

	link_map = config["link_map"]

	new_lines = []
	write_changes = False
	in_pre = False
	previous_empty = True
	current_section = ""
	for markdown_line in markdown_lines:
		# we ignore everything in code blocks
		if previous_empty or in_pre:
			if markdown_line.lstrip()[:3] == '```':
				in_pre = not in_pre
			if markdown_line[:4] == "    ":
				new_lines.append(markdown_line)
				continue

		# don't link to the current section
		if markdown_line.find("title:") == 0:
			current_section = markdown_line.split('title: ')
			current_section = current_section[1].rstrip().rstrip('\"')
			current_section = current_section.lstrip().lstrip('\"')
			current_section = "`" + current_section + "`"
		elif markdown_line.find("#") == 0:
			current_section = "`" + markdown_line.lstrip('#').rstrip().lstrip() + "`"

		new_line = ""
		if not in_pre:
			while True:
				value = ""
				bracket_depth = 0
				index = -1
				candidate_start = -1
				i = 0
				# ignore existing links, ie everything in brackets
				while i < len(markdown_line):
					if markdown_line[i] == '[': bracket_depth += 1
					elif markdown_line[i] == ']': bracket_depth -= 1
					elif bracket_depth == 0:
						if markdown_line[i] == '`':
							if candidate_start == -1:
								candidate_start = i
							else:
								candidate = markdown_line[candidate_start:i+1]
								value = link_map.get(candidate)
								if not value == None and candidate != current_section:
									index = candidate_start
									break
								candidate_start = -1
					i += 1
				if index != -1:
					write_changes = True
					new_line += markdown_line[:index]
					new_line += "[" + candidate + "]" + value
					markdown_line = markdown_line[index + len(candidate):]
				else:
					break
		new_line += markdown_line
		new_lines.append(new_line)
		previous_empty = markdown_line.lstrip() == "\n"

	if write_changes:
		markdown_file = open(file_name + ".new", "w")
		for new_line in new_lines:
			markdown_file.write(new_line)
		markdown_file.close()
		os.rename(file_name + ".new", file_name)
<commit_msg>Don't overwrite unless existing entry is subheader<commit_after># The MIT License (MIT)
#
# Copyright (c) 2013 CFEngine AS
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

import os
import sys
from os import listdir
from os.path import isfile, join
from string import ascii_letters, digits

def run(config):
	markdown_files =  config["markdown_files"]
	readLinkFile(config)
	for file in markdown_files:
		parseMarkdownForAnchors(file, config)

def apply(config):
	markdown_files =  config["markdown_files"]
	for file in markdown_files:
		applyLinkMap(file, config)

def readLinkFile(config):
	output_file = config["reference_path"]
	link_map = config.get("link_map", dict())

	link_file = open(output_file, 'r')
	link_lines = link_file.readlines()
	for line in link_lines:
		label = line[line.find('[') + 1:line.find(']')]
		link_map["`" + label + "`"] = "[" + label + "]"
	config["link_map"] = link_map

def addLinkToMap(keyword, anchor, html, config):
	link_map = config.get("link_map", dict())

	# don't overwrite top level title with sub-header
	current_anchor = link_map.get(keyword)
	if current_anchor != None:
		if current_anchor.find("#") == -1:
			return

	link_map[keyword] = "[" + anchor + "]"

	output_file = config["reference_path"]
	out_file = open(output_file, "a")
	output_string = '[' + anchor + ']: ' + html
	out_file.write(output_string+"\n")
	out_file.close()

	config["link_map"] = link_map

def parseMarkdownForAnchors(file_name, config):
	in_file = open(file_name,"r")
	lines = in_file.readlines()
	in_file.close()

	current_file_name = ""
	current_file_label = ""
	current_title = ""
	header_list = []

	in_pre = False
	for line in lines:
		# ignore code blocks
		if line.find("    ") == 0:
			continue
		elif line.find("```") == 0:
			in_pre = not in_pre
		if in_pre:
			continue

		if line.find("title:") == 0:
			current_title = line.split('title: ')
			current_title = current_title[1].rstrip().rstrip('\"')
			current_title = current_title.lstrip().lstrip('\"')
		elif line.find("alias:") == 0:
			current_file_name = line.split('alias: ')
			current_file_name = current_file_name[1].rstrip()
		elif line.find("#") == 0:
			current_header = line.lstrip('#').rstrip().lstrip()
			header_list.append(current_header)

	current_file_label = current_title

	if current_file_label != "" and current_file_name != "":
		keyword = current_file_label
		# generate auto-link to functions via `function()`
		if current_file_name.find("reference-functions-") == 0:
			keyword += "()"
		addLinkToMap("`" + keyword + "`", current_file_label, current_file_name + ' \"' + current_title + '\"', config)
		# keep dictionary reasonably short by including at most three-word headers
		for header in header_list:
			if header == "":
				continue
			anchor = header.lower()
			anchor = anchor.replace(" ", "-")
			anchor = anchor.replace(":", "-")
			anchor = anchor.replace(".", "-")
			anchor = anchor.replace("`", "-")
			anchor = anchor.replace("/", "-")
			anchor = anchor.replace("$", "-")
			anchor = anchor.replace("(", "-")
			anchor = anchor.replace(")", "-")
			anchor = anchor.replace("\"", "")
			anchor = anchor.replace("--", "-")
			anchor = anchor.lstrip("-").rstrip("-")
			label = current_file_label+ '#' + header
			# prefer top-level anchors
			addLinkToMap("`" + header + "`", label, current_file_name + '#' + anchor + ' \"' + current_title + ' - ' + header + '\"', config)

def applyLinkMap(file_name, config):
	markdown_file = open(file_name,"r")
	markdown_lines = markdown_file.readlines()
	markdown_file.close()

	link_map = config["link_map"]

	new_lines = []
	write_changes = False
	in_pre = False
	previous_empty = True
	current_section = ""
	for markdown_line in markdown_lines:
		# we ignore everything in code blocks
		if previous_empty or in_pre:
			if markdown_line.lstrip()[:3] == '```':
				in_pre = not in_pre
			if markdown_line[:4] == "    ":
				new_lines.append(markdown_line)
				continue

		# don't link to the current section
		if markdown_line.find("title:") == 0:
			current_section = markdown_line.split('title: ')
			current_section = current_section[1].rstrip().rstrip('\"')
			current_section = current_section.lstrip().lstrip('\"')
			current_section = "`" + current_section + "`"
		elif markdown_line.find("#") == 0:
			current_section = "`" + markdown_line.lstrip('#').rstrip().lstrip() + "`"

		new_line = ""
		if not in_pre:
			while True:
				value = ""
				bracket_depth = 0
				index = -1
				candidate_start = -1
				i = 0
				# ignore existing links, ie everything in brackets
				while i < len(markdown_line):
					if markdown_line[i] == '[': bracket_depth += 1
					elif markdown_line[i] == ']': bracket_depth -= 1
					elif bracket_depth == 0:
						if markdown_line[i] == '`':
							if candidate_start == -1:
								candidate_start = i
							else:
								candidate = markdown_line[candidate_start:i+1]
								value = link_map.get(candidate)
								if not value == None and candidate != current_section:
									index = candidate_start
									break
								candidate_start = -1
					i += 1
				if index != -1:
					write_changes = True
					new_line += markdown_line[:index]
					new_line += "[" + candidate + "]" + value
					markdown_line = markdown_line[index + len(candidate):]
				else:
					break
		new_line += markdown_line
		new_lines.append(new_line)
		previous_empty = markdown_line.lstrip() == "\n"

	if write_changes:
		markdown_file = open(file_name + ".new", "w")
		for new_line in new_lines:
			markdown_file.write(new_line)
		markdown_file.close()
		os.rename(file_name + ".new", file_name)
<|endoftext|>


<commit_before># Copyright 2013 Hewlett-Packard Development Company, L.P.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

import os
import sys

from pbr import find_package
from pbr.hooks import base

def get_manpath():
    manpath = 'share/man'
    if os.path.exists(os.path.join(sys.prefix, 'man')):
        # This works around a bug with install where it expects every node
        # in the relative data directory to be an actual directory, since at
        # least Debian derivatives (and probably other platforms as well)
        # like to symlink Unixish /usr/local/man to /usr/local/share/man.
        manpath = 'man'
    return manpath

def get_man_section(section):
    return os.path.join(get_manpath(), 'man%s' % section)

class FilesConfig(base.BaseConfig):

    section = 'files'

    def __init__(self, config, name):
        super(FilesConfig, self).__init__(config)
        self.name = name
        self.data_files = self.config.get('data_files', '')

    def save(self):
        self.config['data_files'] = self.data_files
        super(FilesConfig, self).save()

    def expand_globs(self):
        finished = []
        for line in self.data_files.split("\n"):
            if line.rstrip().endswith('*') and '=' in line:
                (target, source_glob) = line.split('=')
                source_prefix = source_glob.strip()[:-1]
                target = target.strip()
                if not target.endswith(os.path.sep):
                    target += os.path.sep
                for (dirpath, dirnames, fnames) in os.walk(source_prefix):
                    finished.append(
                        "%s = " % dirpath.replace(source_prefix, target))
                    finished.extend(
                        [" %s" % os.path.join(dirpath, f) for f in fnames])
            else:
                finished.append(line)

        self.data_files = "\n".join(finished)

    def add_man_path(self, man_path):
        self.data_files = "%s\n%s =" % (self.data_files, man_path)

    def add_man_page(self, man_page):
        self.data_files = "%s\n  %s" % (self.data_files, man_page)

    def get_man_sections(self):
        man_sections = dict()
        manpages = self.pbr_config['manpages']
        for manpage in manpages.split():
            section_number = manpage.strip()[-1]
            section = man_sections.get(section_number, list())
            section.append(manpage.strip())
            man_sections[section_number] = section
        return man_sections

    def hook(self):
        package = self.config.get('packages', self.name).strip()
        if os.path.isdir(package):
            self.config['packages'] = find_package.smart_find_packages(package)

        self.expand_globs()

        if 'manpages' in self.pbr_config:
            man_sections = self.get_man_sections()
            for (section, pages) in man_sections.items():
                manpath = get_man_section(section)
                self.add_man_path(manpath)
                for page in pages:
                    self.add_man_page(page)
<commit_msg>"packages" might list multiple directories<commit_after># Copyright 2013 Hewlett-Packard Development Company, L.P.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

import os
import sys

from pbr import find_package
from pbr.hooks import base

def get_manpath():
    manpath = 'share/man'
    if os.path.exists(os.path.join(sys.prefix, 'man')):
        # This works around a bug with install where it expects every node
        # in the relative data directory to be an actual directory, since at
        # least Debian derivatives (and probably other platforms as well)
        # like to symlink Unixish /usr/local/man to /usr/local/share/man.
        manpath = 'man'
    return manpath

def get_man_section(section):
    return os.path.join(get_manpath(), 'man%s' % section)

class FilesConfig(base.BaseConfig):

    section = 'files'

    def __init__(self, config, name):
        super(FilesConfig, self).__init__(config)
        self.name = name
        self.data_files = self.config.get('data_files', '')

    def save(self):
        self.config['data_files'] = self.data_files
        super(FilesConfig, self).save()

    def expand_globs(self):
        finished = []
        for line in self.data_files.split("\n"):
            if line.rstrip().endswith('*') and '=' in line:
                (target, source_glob) = line.split('=')
                source_prefix = source_glob.strip()[:-1]
                target = target.strip()
                if not target.endswith(os.path.sep):
                    target += os.path.sep
                for (dirpath, dirnames, fnames) in os.walk(source_prefix):
                    finished.append(
                        "%s = " % dirpath.replace(source_prefix, target))
                    finished.extend(
                        [" %s" % os.path.join(dirpath, f) for f in fnames])
            else:
                finished.append(line)

        self.data_files = "\n".join(finished)

    def add_man_path(self, man_path):
        self.data_files = "%s\n%s =" % (self.data_files, man_path)

    def add_man_page(self, man_page):
        self.data_files = "%s\n  %s" % (self.data_files, man_page)

    def get_man_sections(self):
        man_sections = dict()
        manpages = self.pbr_config['manpages']
        for manpage in manpages.split():
            section_number = manpage.strip()[-1]
            section = man_sections.get(section_number, list())
            section.append(manpage.strip())
            man_sections[section_number] = section
        return man_sections

    def hook(self):
        packages = self.config.get('packages', self.name).strip()
        expanded = []
        for pkg in packages.split("\n"):
            if os.path.isdir(pkg.strip()):
                expanded.append(find_package.smart_find_packages(pkg.strip()))

        self.config['packages'] = "\n".join(expanded)

        self.expand_globs()

        if 'manpages' in self.pbr_config:
            man_sections = self.get_man_sections()
            for (section, pages) in man_sections.items():
                manpath = get_man_section(section)
                self.add_man_path(manpath)
                for page in pages:
                    self.add_man_page(page)
<|endoftext|>


<commit_before>"""Provides the repository macro to import Eigen."""

load("//third_party:repo.bzl", "tf_http_archive")

def repo():
    """Imports Eigen."""

    # Attention: tools parse and update these lines.
    EIGEN_COMMIT = "f612df273689a19d25b45ca4f8269463207c4fee"
    EIGEN_SHA256 = "e3fe5cac59763b7419af2de39840b5342d77624ddf8b181fb9f9f532615ec518"

    tf_http_archive(
        name = "eigen_archive",
        build_file = "//third_party/eigen3:eigen_archive.BUILD",
        sha256 = EIGEN_SHA256,
        strip_prefix = "eigen-{commit}".format(commit = EIGEN_COMMIT),
        urls = [
            "https://storage.googleapis.com/mirror.tensorflow.org/gitlab.com/libeigen/eigen/-/archive/{commit}/eigen-{commit}.tar.gz".format(commit = EIGEN_COMMIT),
            "https://gitlab.com/libeigen/eigen/-/archive/{commit}/eigen-{commit}.tar.gz".format(commit = EIGEN_COMMIT),
        ],
    )
<commit_msg>Update Eigen to: https://gitlab.com/libeigen/eigen/-/commit/fcb5106c6e16599eeabadf7d82a465d52229698f<commit_after>"""Provides the repository macro to import Eigen."""

load("//third_party:repo.bzl", "tf_http_archive")

def repo():
    """Imports Eigen."""

    # Attention: tools parse and update these lines.
    EIGEN_COMMIT = "fcb5106c6e16599eeabadf7d82a465d52229698f"
    EIGEN_SHA256 = "1d8c683cb8aa814499bd0254250937bebdc33146691a5d3c6b941af9d0303ea7"

    tf_http_archive(
        name = "eigen_archive",
        build_file = "//third_party/eigen3:eigen_archive.BUILD",
        sha256 = EIGEN_SHA256,
        strip_prefix = "eigen-{commit}".format(commit = EIGEN_COMMIT),
        urls = [
            "https://storage.googleapis.com/mirror.tensorflow.org/gitlab.com/libeigen/eigen/-/archive/{commit}/eigen-{commit}.tar.gz".format(commit = EIGEN_COMMIT),
            "https://gitlab.com/libeigen/eigen/-/archive/{commit}/eigen-{commit}.tar.gz".format(commit = EIGEN_COMMIT),
        ],
    )
<|endoftext|>


<commit_before>import numpy as np

def cnv_azel2latlon(az, el, site, ht=450):
    '''
    Function to convert from an azimuth/elevation grid to a
    latitude/longitude grid given an unwarping height and a site location.
    For elevations below the horizon, returns NaN.
    INPUTS:
        az - M x N array of azimuths to be converted [degrees]
        el - M x N array of elevation to be converted [degrees]
        site - 1 x 2 array containing [latitude, longitude] of the site
           [degrees]
        ht - scalar height to be used in the conversion [km] (default is
             450 [km])
    OUTPUTS:
        lat - M x N array of latitudes [degrees]
        lon - M x N array of longitudes [degrees]

    HISTORY:
        17-Oct-2006: Converted from IDL by Jonathan J. Makela
        (jmakela@uiuc.edu)
        03-Oct-2013: Converted from MATLAB to Python by Brian Harding
        (bhardin2@illinois.edu)
    '''
    Re = 6371.2 # radius of Earth in km

    # Convert inputs from degrees to radians
    el_r = np.radians(el)
    az_r = np.radians(az)
    lat_r = np.radias(site[0])
    lon_r = np.radians(site[1])

    # Calculate the differential angle, alpha
    temp = np.cos(el_r)/(1.+(ht/Re))
    alpha = np.arccos(temp) - el_r

    # Calculate the pierce point latitude
    temp = np.sin(lat_r) * np.cos(alpha) + np.cos(lat_r)*np.cos(az_r)*np.sin(alpha)
    lat_r = np.arcsin(temp)

    # Calculate the pierce point longitude
    temp = np.sin(alpha) * np.sin(az_r) / np.cos(lat_r)
    lon_r = np.arcsin(temp) + lon_r

    # Convert radian measurements to degrees
    lat = np.degrees(lat_r)
    lon = np.degrees(lon_r)

    return lat, lon
<commit_msg>Fixed a typo.<commit_after>import numpy as np

def cnv_azel2latlon(az, el, site, ht=450):
    '''
    Function to convert from an azimuth/elevation grid to a
    latitude/longitude grid given an unwarping height and a site location.
    For elevations below the horizon, returns NaN.
    INPUTS:
        az - M x N array of azimuths to be converted [degrees]
        el - M x N array of elevation to be converted [degrees]
        site - 1 x 2 array containing [latitude, longitude] of the site
           [degrees]
        ht - scalar height to be used in the conversion [km] (default is
             450 [km])
    OUTPUTS:
        lat - M x N array of latitudes [degrees]
        lon - M x N array of longitudes [degrees]

    HISTORY:
        17-Oct-2006: Converted from IDL by Jonathan J. Makela
        (jmakela@uiuc.edu)
        03-Oct-2013: Converted from MATLAB to Python by Brian Harding
        (bhardin2@illinois.edu)
    '''
    Re = 6371.2 # radius of Earth in km

    # Convert inputs from degrees to radians
    el_r = np.radians(el)
    az_r = np.radians(az)
    lat_r = np.radians(site[0])
    lon_r = np.radians(site[1])

    # Calculate the differential angle, alpha
    temp = np.cos(el_r)/(1.+(ht/Re))
    alpha = np.arccos(temp) - el_r

    # Calculate the pierce point latitude
    temp = np.sin(lat_r) * np.cos(alpha) + np.cos(lat_r)*np.cos(az_r)*np.sin(alpha)
    lat_r = np.arcsin(temp)

    # Calculate the pierce point longitude
    temp = np.sin(alpha) * np.sin(az_r) / np.cos(lat_r)
    lon_r = np.arcsin(temp) + lon_r

    # Convert radian measurements to degrees
    lat = np.degrees(lat_r)
    lon = np.degrees(lon_r)

    return lat, lon
<|endoftext|>


<commit_before># Giles: rps.py
# Copyright 2012 Phil Bordelon
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.

# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

from giles.state import State
from giles.games.game import Game
from giles.games.seat import Seat

class RockPaperScissors(Game):
    """A Rock-Paper-Scissors game table implementation.
    """

    def __init__(self, server, table_name):

        super(RockPaperScissors, self).__init__(server, table_name)

        self.game_display_name = "Rock-Paper-Scissors"
        self.game_name = "rps"
        self.seats = [
            Seat("Left"),
            Seat("Right"),
        ]
        self.min_players = 2
        self.max_players = 2
        self.state = State("need_players")
        self.plays = [None, None]
        self.prefix = "(^RRPS^~): "
        self.log_prefix = "%s/%s" % (self.game_display_name, self.game_name)

        # RPS requires both seats, so may as well mark them active.
        self.seats[0].active = True
        self.seats[1].active = True

    def handle(self, player, command_str):

        # Handle common commands.
        handled = self.handle_common_commands(player, command_str)

        state = self.state.get()

        if state == "need_moves":

            primary = command_str.split()[0].lower()
            if primary in ('r', 'p', 's', 'rock', 'paper', 'scissors'):
                self.move(player, primary)
                handled = True

            if self.plays[0] and self.plays[1] and self.active:

                # Got the moves!
                self.resolve()
                self.finish()

        if not handled:
            player.tell_cc(self.prefix + "Invalid command.\n")

    def tick(self):

        # If we were looking for players, check to see if both
        # seats are full and the game is active.  If so, autostart.
        if (self.state.get() == "need_players" and self.seats[0].player and
           self.seats[1].player and self.active):
            self.state.set("need_moves")
            self.channel.broadcast_cc(self.prefix + "Left: ^Y%s^~; Right: ^Y%s^~\n" %
               (self.seats[0].player.display_name, self.seats[1].player.display_name))
            self.channel.broadcast_cc(self.prefix + "Players, make your moves!\n")

    def show(self, player):

        state = self.state.get()
        if state == "need_players":
            player.tell_cc(self.prefix + "Everyone is hovering around the table, waiting for players.\n")
        elif state == "need_moves":
            for loc, color in ((0, "^Y"), (1, "^M")):
                if self.seats[loc].player:
                    name = self.seats[loc].player.display_name
                    if self.plays[loc]:
                        player.tell_cc(self.prefix + color + name + "^~'s hand is trembling with anticipation.\n")
                    else:
                        player.tell_cc(self.prefix + color + name + "^~ seems to be deep in thought.\n")
                else:
                    player.tell_cc(self.prefix + "^C%s^~ is strangely empty.\n" % self.seats[loc].display_name)
        else:
            player.tell_cc(self.prefix + "Nothing to see here.  Move along.\n")

    def show_help(self, player):

        super(RockPaperScissors, self).show_help(player)
        player.tell_cc("\nROCK-PAPER-SCISSORS:\n\n")
        player.tell_cc("                      ^!rock^., ^!r^.     Throw rock.\n")
        player.tell_cc("                     ^!paper^., ^!p^.     Throw paper.\n")
        player.tell_cc("                  ^!scissors^., ^!s^.     Throw scissors.\n")

    def move(self, player, play):

        seat = self.get_seat_of_player(player)
        if not seat:
            player.tell_cc(self.prefix + "You're not playing in this game!\n")
            return

        if play in ('r', 'rock'):
            this_move = "rock"
        elif play in ('p', 'paper'):
            this_move = "paper"
        elif play in ('s', 'scissors'):
            this_move = "scissors"
        else:
            player.tell_cc(self.prefix + "Invalid play.\n")
            return

        self.channel.broadcast_cc(self.prefix + "%s's hand twitches.\n" % player.display_name)

        if seat == self.seats[0]:
            self.plays[0] = this_move
        else:
            self.plays[1] = this_move

    def resolve(self):

        one = self.plays[0]
        two = self.plays[1]
        one_name = "^Y" + self.seats[0].player.display_name + "^~"
        two_name = "^M" + self.seats[1].player.display_name + "^~"
        self.channel.broadcast_cc(self.prefix + "Jan... ken... pon... Throwdown time!\n")
        self.channel.broadcast_cc(self.prefix + "%s throws ^!%s^.; %s throws ^!%s^.!\n" % (one_name, one, two_name, two))
        if one == two:
            msg = "It's a tie!\n"
        elif ((one == "rock" and two == "paper") or
           (one == "paper" and two == "scissors") or
           (one == "scissors" and two == "rock")):
            msg = two_name + " wins!\n"
        else:
            msg = one_name + " wins!\n"
        self.channel.broadcast_cc(msg)

    def remove_player(self, player):

        # Not only do we want to do the standard things, but if this person
        # really is a player, we want to invalidate their throw.  That way
        # you're not stuck with another player's throw mid-game.
        if self.seats[0].player == player:
            self.plays[0] = None
        elif self.seats[1].player == player:
            self.plays[1] = None
        super(RockPaperScissors, self).remove_player(player)
<commit_msg>rps: be nice and consume unneded move/play.<commit_after># Giles: rps.py
# Copyright 2012 Phil Bordelon
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.

# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

from giles.state import State
from giles.games.game import Game
from giles.games.seat import Seat

class RockPaperScissors(Game):
    """A Rock-Paper-Scissors game table implementation.
    """

    def __init__(self, server, table_name):

        super(RockPaperScissors, self).__init__(server, table_name)

        self.game_display_name = "Rock-Paper-Scissors"
        self.game_name = "rps"
        self.seats = [
            Seat("Left"),
            Seat("Right"),
        ]
        self.min_players = 2
        self.max_players = 2
        self.state = State("need_players")
        self.plays = [None, None]
        self.prefix = "(^RRPS^~): "
        self.log_prefix = "%s/%s" % (self.game_display_name, self.game_name)

        # RPS requires both seats, so may as well mark them active.
        self.seats[0].active = True
        self.seats[1].active = True

    def handle(self, player, command_str):

        # Handle common commands.
        handled = self.handle_common_commands(player, command_str)

        state = self.state.get()

        if state == "need_moves":

            command_bits = command_str.split()
            primary = command_bits[0].lower()

            # If this player is used to prefacing plays with 'move'/'play',
            # let's be polite and just chomp that away.
            if primary in ('move', 'play', 'mv', 'pl') and len(command_bits) > 1:
                primary = command_bits[1].lower()
            if primary in ('r', 'p', 's', 'rock', 'paper', 'scissors'):
                self.move(player, primary)
                handled = True

            if self.plays[0] and self.plays[1] and self.active:

                # Got the moves!
                self.resolve()
                self.finish()

        if not handled:
            player.tell_cc(self.prefix + "Invalid command.\n")

    def tick(self):

        # If we were looking for players, check to see if both
        # seats are full and the game is active.  If so, autostart.
        if (self.state.get() == "need_players" and self.seats[0].player and
           self.seats[1].player and self.active):
            self.state.set("need_moves")
            self.channel.broadcast_cc(self.prefix + "Left: ^Y%s^~; Right: ^Y%s^~\n" %
               (self.seats[0].player.display_name, self.seats[1].player.display_name))
            self.channel.broadcast_cc(self.prefix + "Players, make your moves!\n")

    def show(self, player):

        state = self.state.get()
        if state == "need_players":
            player.tell_cc(self.prefix + "Everyone is hovering around the table, waiting for players.\n")
        elif state == "need_moves":
            for loc, color in ((0, "^Y"), (1, "^M")):
                if self.seats[loc].player:
                    name = self.seats[loc].player.display_name
                    if self.plays[loc]:
                        player.tell_cc(self.prefix + color + name + "^~'s hand is trembling with anticipation.\n")
                    else:
                        player.tell_cc(self.prefix + color + name + "^~ seems to be deep in thought.\n")
                else:
                    player.tell_cc(self.prefix + "^C%s^~ is strangely empty.\n" % self.seats[loc].display_name)
        else:
            player.tell_cc(self.prefix + "Nothing to see here.  Move along.\n")

    def show_help(self, player):

        super(RockPaperScissors, self).show_help(player)
        player.tell_cc("\nROCK-PAPER-SCISSORS:\n\n")
        player.tell_cc("                      ^!rock^., ^!r^.     Throw rock.\n")
        player.tell_cc("                     ^!paper^., ^!p^.     Throw paper.\n")
        player.tell_cc("                  ^!scissors^., ^!s^.     Throw scissors.\n")

    def move(self, player, play):

        seat = self.get_seat_of_player(player)
        if not seat:
            player.tell_cc(self.prefix + "You're not playing in this game!\n")
            return

        if play in ('r', 'rock'):
            this_move = "rock"
        elif play in ('p', 'paper'):
            this_move = "paper"
        elif play in ('s', 'scissors'):
            this_move = "scissors"
        else:
            player.tell_cc(self.prefix + "Invalid play.\n")
            return

        self.channel.broadcast_cc(self.prefix + "%s's hand twitches.\n" % player.display_name)

        if seat == self.seats[0]:
            self.plays[0] = this_move
        else:
            self.plays[1] = this_move

    def resolve(self):

        one = self.plays[0]
        two = self.plays[1]
        one_name = "^Y" + self.seats[0].player.display_name + "^~"
        two_name = "^M" + self.seats[1].player.display_name + "^~"
        self.channel.broadcast_cc(self.prefix + "Jan... ken... pon... Throwdown time!\n")
        self.channel.broadcast_cc(self.prefix + "%s throws ^!%s^.; %s throws ^!%s^.!\n" % (one_name, one, two_name, two))
        if one == two:
            msg = "It's a tie!\n"
        elif ((one == "rock" and two == "paper") or
           (one == "paper" and two == "scissors") or
           (one == "scissors" and two == "rock")):
            msg = two_name + " wins!\n"
        else:
            msg = one_name + " wins!\n"
        self.channel.broadcast_cc(msg)

    def remove_player(self, player):

        # Not only do we want to do the standard things, but if this person
        # really is a player, we want to invalidate their throw.  That way
        # you're not stuck with another player's throw mid-game.
        if self.seats[0].player == player:
            self.plays[0] = None
        elif self.seats[1].player == player:
            self.plays[1] = None
        super(RockPaperScissors, self).remove_player(player)
<|endoftext|>


<commit_before><commit_msg>Fix slow front page and dataset page<commit_after><|endoftext|>


<commit_before>import re
from xbrowse import get_xpos
from utils import *

SEARCH_LIMIT = 10000
UNSUPPORTED_QUERIES = ['TTN', 'ENSG00000155657', 'CMD1G', 'CMH9', 'CMPD4', 'FLJ32040', 'LGMD2J', 'MYLK5', 'TMD',
                       u'ENST00000342175', u'ENST00000359218', u'ENST00000342992', u'ENST00000460472',
                       u'ENST00000589042', u'ENST00000591111']

def get_gene(db, gene_id):
    return db.genes.find_one({'gene_id': gene_id}, fields={'_id': False})

def get_gene_by_name(db, gene_name):
    # try gene_name field first
    gene = db.genes.find_one({'gene_name': gene_name}, fields={'_id': False})
    if gene:
        return gene
    # if not, try gene['other_names']
    return db.genes.find_one({'other_names': gene_name}, fields={'_id': False})

def get_transcript(db, transcript_id):
    transcript = db.transcripts.find_one({'transcript_id': transcript_id}, fields={'_id': False})
    if not transcript:
        return None
    transcript['exons'] = get_exons_in_transcript(db, transcript_id)
    return transcript

def get_variant(db, xpos, ref, alt):
    return db.variants.find_one({'xpos': xpos, 'ref': ref, 'alt': alt}, fields={'_id': False})

def get_variants_by_rsid(db, rsid):
    if not rsid.startswith('rs'):
        return None
    try:
        int(rsid.lstrip('rs'))
    except Exception, e:
        return None
    variants = list(db.variants.find({'rsid': rsid}, fields={'_id': False}))
    add_consequence_to_variants(variants)
    return variants

def get_coverage_for_bases(db, xstart, xstop=None):
    """
    Get the coverage for the list of bases given by xstart->xstop, inclusive
    Returns list of coverage dicts
    xstop can be None if just one base, but you'll still get back a list
    """
    if xstop is None:
        xstop = xstart
    coverages = {
        doc['xpos']: doc for doc in db.base_coverage.find(
            {'xpos': {'$gte': xstart, '$lte': xstop}},
            fields={'_id': False}
        )
    }
    ret = []
    for i in range(xstart, xstop+1):
        if i in coverages:
            ret.append(coverages[i])
        else:
            ret.append({'xpos': i, 'pos': xpos_to_pos(i)})
    for item in ret:
        item['has_coverage'] = 'mean' in item
        del item['xpos']
    return ret

def get_coverage_for_transcript(db, xstart, xstop=None):
    """

    :param db:
    :param genomic_coord_to_exon:
    :param xstart:
    :param xstop:
    :return:
    """
    coverage_array = get_coverage_for_bases(db, xstart, xstop)
    # only return coverages that have coverage (if that makes any sense?)
    # return coverage_array
    covered = [c for c in coverage_array if c['has_coverage']]
    for c in covered:
        del c['has_coverage']
    return covered

def get_awesomebar_suggestions(g, query):
    """
    This generates autocomplete suggestions when user
    query is the string that user types
    If it is the prefix for a gene, return list of gene names
    """
    regex = re.compile('^' + re.escape(query), re.IGNORECASE)
    results = [r for r in g.autocomplete_strings if regex.match(r)][:20]
    return results

# 1:1-1000
R1 = re.compile(r'^(\d+|X|Y|M|MT)\s*:\s*(\d+)-(\d+)$')
R2 = re.compile(r'^(\d+|X|Y|M|MT)\s*:\s*(\d+)$')
R3 = re.compile(r'^(\d+|X|Y|M|MT)$')
R4 = re.compile(r'^(\d+|X|Y|M|MT)\s*[-:]\s*(\d+)-([ATCG]+)-([ATCG]+)$')

def get_awesomebar_result(db, query):
    """
    Similar to the above, but this is after a user types enter
    We need to figure out what they meant - could be gene, variant, region

    Return tuple of (datatype, identifier)
    Where datatype is one of 'gene', 'variant', or 'region'
    And identifier is one of:
    - ensembl ID for gene
    - variant ID string for variant (eg. 1-1000-A-T)
    - region ID string for region (eg. 1-1000-2000)

    Follow these steps:
    - if query is an ensembl ID, return it
    - if a gene symbol, return that gene's ensembl ID
    - if an RSID, return that variant's string

    Finally, note that we don't return the whole object here - only it's identifier.
    This could be important for performance later

    """
    query = query.strip()
    print 'Query: %s' % query
    if query in UNSUPPORTED_QUERIES:
        return 'error', query

    # Variant
    variant = get_variants_by_rsid(db, query.lower())
    if variant:
        if len(variant) == 1:
            return 'variant', variant[0]['variant_id']
        else:
            return 'dbsnp_variant_set', variant[0]['rsid']
    # variant = get_variant(db, )
    # TODO - https://github.com/brettpthomas/exac_browser/issues/14

    # From here out, all should be uppercase (gene, tx, region, variant_id)
    query = query.upper()

    gene = get_gene_by_name(db, query)
    if gene:
        return 'gene', gene['gene_id']

    # Ensembl formatted queries
    if query.startswith('ENS'):
        # Gene
        gene = get_gene(db, query)
        if gene:
            return 'gene', gene['gene_id']

        # Transcript
        transcript = get_transcript(db, query)
        if transcript:
            return 'transcript', transcript['transcript_id']

    # From here on out, only region queries
    if query.startswith('CHR'):
        query = query.lstrip('CHR')
    # Region
    m = R1.match(query)
    if m:
        if int(m.group(3)) < int(m.group(2)):
            return 'region', 'invalid'
        return 'region', '{}-{}-{}'.format(m.group(1), m.group(2), m.group(3))
    m = R2.match(query)
    if m:
        return 'region', '{}-{}-{}'.format(m.group(1), m.group(2), m.group(2))
    m = R3.match(query)
    if m:
        return 'region', '{}'.format(m.group(1))
    m = R4.match(query)
    if m:
        return 'variant', '{}-{}-{}-{}'.format(m.group(1), m.group(2), m.group(3), m.group(4))

    return 'error', query

def get_genes_in_region(db, chrom, start, stop):
    """
    Genes that overlap a region
    """
    xstart = get_xpos(chrom, start)
    xstop = get_xpos(chrom, stop)
    genes = db.genes.find({
        'xstart': {'$lte': xstop},
        'xstop': {'$gte': xstart},
    }, fields={'_id': False})
    return list(genes)

def get_variants_in_region(db, chrom, start, stop):
    """
    Variants that overlap a region
    Unclear if this will include CNVs
    """
    xstart = get_xpos(chrom, start)
    xstop = get_xpos(chrom, stop)
    variants = list(db.variants.find({
        'xstart': {'$lte': xstop},  # start of variant should be before (or equal to) end of region
        'xstop': {'$gte': xstart},  # opposite of above
    }, fields={'_id': False}, limit=SEARCH_LIMIT))
    add_consequence_to_variants(variants)
    return list(variants)

def remove_extraneous_information(variant):
    del variant['genotype_depths']
    del variant['genotype_qualities']
    del variant['pop_acs']
    del variant['pop_ans']
    variant['hom_count'] = sum(variant['pop_homs'].values())
    del variant['pop_homs']
    del variant['transcripts']
    del variant['genes']
    del variant['orig_alt_alleles']
    del variant['xpos']
    del variant['xstart']
    del variant['xstop']
    del variant['site_quality']
    del variant['vep_annotations']

def get_variants_in_gene(db, gene_id):
    """
    """
    variants = []
    for variant in db.variants.find({'genes': gene_id}, fields={'_id': False}):
        variant['vep_annotations'] = [x for x in variant['vep_annotations'] if x['Gene'] == gene_id]
        add_consequence_to_variant(variant)
        remove_extraneous_information(variant)
        variants.append(variant)
    return variants

def get_transcripts_in_gene(db, gene_id):
    """
    """
    return list(db.transcripts.find({'gene_id': gene_id}, fields={'_id': False}))

def get_variants_in_transcript(db, transcript_id):
    """
    """
    variants = []
    for variant in db.variants.find({'transcripts': transcript_id}, fields={'_id': False}):
        variant['vep_annotations'] = [x for x in variant['vep_annotations'] if x['Feature'] == transcript_id]
        add_consequence_to_variant(variant)
        remove_extraneous_information(variant)
        variants.append(variant)
    return variants

def get_exons_in_transcript(db, transcript_id):
    # return sorted(
    #     [x for x in
    #      db.exons.find({'transcript_id': transcript_id}, fields={'_id': False})
    #      if x['feature_type'] != 'exon'],
    #     key=lambda k: k['start'])
    return sorted(list(db.exons.find({'transcript_id': transcript_id, 'feature_type': { "$in": ['CDS', 'UTR', 'exon'] }}, fields={'_id': False})), key=lambda k: k['start'])
<commit_msg>Sped up region search (Fixed #128)<commit_after>import re
from xbrowse import get_xpos
from utils import *

SEARCH_LIMIT = 10000
UNSUPPORTED_QUERIES = ['TTN', 'ENSG00000155657', 'CMD1G', 'CMH9', 'CMPD4', 'FLJ32040', 'LGMD2J', 'MYLK5', 'TMD',
                       u'ENST00000342175', u'ENST00000359218', u'ENST00000342992', u'ENST00000460472',
                       u'ENST00000589042', u'ENST00000591111']

def get_gene(db, gene_id):
    return db.genes.find_one({'gene_id': gene_id}, fields={'_id': False})

def get_gene_by_name(db, gene_name):
    # try gene_name field first
    gene = db.genes.find_one({'gene_name': gene_name}, fields={'_id': False})
    if gene:
        return gene
    # if not, try gene['other_names']
    return db.genes.find_one({'other_names': gene_name}, fields={'_id': False})

def get_transcript(db, transcript_id):
    transcript = db.transcripts.find_one({'transcript_id': transcript_id}, fields={'_id': False})
    if not transcript:
        return None
    transcript['exons'] = get_exons_in_transcript(db, transcript_id)
    return transcript

def get_variant(db, xpos, ref, alt):
    return db.variants.find_one({'xpos': xpos, 'ref': ref, 'alt': alt}, fields={'_id': False})

def get_variants_by_rsid(db, rsid):
    if not rsid.startswith('rs'):
        return None
    try:
        int(rsid.lstrip('rs'))
    except Exception, e:
        return None
    variants = list(db.variants.find({'rsid': rsid}, fields={'_id': False}))
    add_consequence_to_variants(variants)
    return variants

def get_coverage_for_bases(db, xstart, xstop=None):
    """
    Get the coverage for the list of bases given by xstart->xstop, inclusive
    Returns list of coverage dicts
    xstop can be None if just one base, but you'll still get back a list
    """
    if xstop is None:
        xstop = xstart
    coverages = {
        doc['xpos']: doc for doc in db.base_coverage.find(
            {'xpos': {'$gte': xstart, '$lte': xstop}},
            fields={'_id': False}
        )
    }
    ret = []
    for i in range(xstart, xstop+1):
        if i in coverages:
            ret.append(coverages[i])
        else:
            ret.append({'xpos': i, 'pos': xpos_to_pos(i)})
    for item in ret:
        item['has_coverage'] = 'mean' in item
        del item['xpos']
    return ret

def get_coverage_for_transcript(db, xstart, xstop=None):
    """

    :param db:
    :param genomic_coord_to_exon:
    :param xstart:
    :param xstop:
    :return:
    """
    coverage_array = get_coverage_for_bases(db, xstart, xstop)
    # only return coverages that have coverage (if that makes any sense?)
    # return coverage_array
    covered = [c for c in coverage_array if c['has_coverage']]
    for c in covered:
        del c['has_coverage']
    return covered

def get_awesomebar_suggestions(g, query):
    """
    This generates autocomplete suggestions when user
    query is the string that user types
    If it is the prefix for a gene, return list of gene names
    """
    regex = re.compile('^' + re.escape(query), re.IGNORECASE)
    results = [r for r in g.autocomplete_strings if regex.match(r)][:20]
    return results

# 1:1-1000
R1 = re.compile(r'^(\d+|X|Y|M|MT)\s*:\s*(\d+)-(\d+)$')
R2 = re.compile(r'^(\d+|X|Y|M|MT)\s*:\s*(\d+)$')
R3 = re.compile(r'^(\d+|X|Y|M|MT)$')
R4 = re.compile(r'^(\d+|X|Y|M|MT)\s*[-:]\s*(\d+)-([ATCG]+)-([ATCG]+)$')

def get_awesomebar_result(db, query):
    """
    Similar to the above, but this is after a user types enter
    We need to figure out what they meant - could be gene, variant, region

    Return tuple of (datatype, identifier)
    Where datatype is one of 'gene', 'variant', or 'region'
    And identifier is one of:
    - ensembl ID for gene
    - variant ID string for variant (eg. 1-1000-A-T)
    - region ID string for region (eg. 1-1000-2000)

    Follow these steps:
    - if query is an ensembl ID, return it
    - if a gene symbol, return that gene's ensembl ID
    - if an RSID, return that variant's string

    Finally, note that we don't return the whole object here - only it's identifier.
    This could be important for performance later

    """
    query = query.strip()
    print 'Query: %s' % query
    if query in UNSUPPORTED_QUERIES:
        return 'error', query

    # Variant
    variant = get_variants_by_rsid(db, query.lower())
    if variant:
        if len(variant) == 1:
            return 'variant', variant[0]['variant_id']
        else:
            return 'dbsnp_variant_set', variant[0]['rsid']
    # variant = get_variant(db, )
    # TODO - https://github.com/brettpthomas/exac_browser/issues/14

    # From here out, all should be uppercase (gene, tx, region, variant_id)
    query = query.upper()

    gene = get_gene_by_name(db, query)
    if gene:
        return 'gene', gene['gene_id']

    # Ensembl formatted queries
    if query.startswith('ENS'):
        # Gene
        gene = get_gene(db, query)
        if gene:
            return 'gene', gene['gene_id']

        # Transcript
        transcript = get_transcript(db, query)
        if transcript:
            return 'transcript', transcript['transcript_id']

    # From here on out, only region queries
    if query.startswith('CHR'):
        query = query.lstrip('CHR')
    # Region
    m = R1.match(query)
    if m:
        if int(m.group(3)) < int(m.group(2)):
            return 'region', 'invalid'
        return 'region', '{}-{}-{}'.format(m.group(1), m.group(2), m.group(3))
    m = R2.match(query)
    if m:
        return 'region', '{}-{}-{}'.format(m.group(1), m.group(2), m.group(2))
    m = R3.match(query)
    if m:
        return 'region', '{}'.format(m.group(1))
    m = R4.match(query)
    if m:
        return 'variant', '{}-{}-{}-{}'.format(m.group(1), m.group(2), m.group(3), m.group(4))

    return 'error', query

def get_genes_in_region(db, chrom, start, stop):
    """
    Genes that overlap a region
    """
    xstart = get_xpos(chrom, start)
    xstop = get_xpos(chrom, stop)
    genes = db.genes.find({
        'xstart': {'$lte': xstop},
        'xstop': {'$gte': xstart},
    }, fields={'_id': False})
    return list(genes)

def get_variants_in_region(db, chrom, start, stop):
    """
    Variants that overlap a region
    Unclear if this will include CNVs
    """
    xstart = get_xpos(chrom, start)
    xstop = get_xpos(chrom, stop)
    variants = list(db.variants.find({
        'xpos': {'$lte': xstop, '$gte': xstart}
    }, fields={'_id': False}, limit=SEARCH_LIMIT))
    add_consequence_to_variants(variants)
    return list(variants)

def remove_extraneous_information(variant):
    del variant['genotype_depths']
    del variant['genotype_qualities']
    del variant['pop_acs']
    del variant['pop_ans']
    variant['hom_count'] = sum(variant['pop_homs'].values())
    del variant['pop_homs']
    del variant['transcripts']
    del variant['genes']
    del variant['orig_alt_alleles']
    del variant['xpos']
    del variant['xstart']
    del variant['xstop']
    del variant['site_quality']
    del variant['vep_annotations']

def get_variants_in_gene(db, gene_id):
    """
    """
    variants = []
    for variant in db.variants.find({'genes': gene_id}, fields={'_id': False}):
        variant['vep_annotations'] = [x for x in variant['vep_annotations'] if x['Gene'] == gene_id]
        add_consequence_to_variant(variant)
        remove_extraneous_information(variant)
        variants.append(variant)
    return variants

def get_transcripts_in_gene(db, gene_id):
    """
    """
    return list(db.transcripts.find({'gene_id': gene_id}, fields={'_id': False}))

def get_variants_in_transcript(db, transcript_id):
    """
    """
    variants = []
    for variant in db.variants.find({'transcripts': transcript_id}, fields={'_id': False}):
        variant['vep_annotations'] = [x for x in variant['vep_annotations'] if x['Feature'] == transcript_id]
        add_consequence_to_variant(variant)
        remove_extraneous_information(variant)
        variants.append(variant)
    return variants

def get_exons_in_transcript(db, transcript_id):
    # return sorted(
    #     [x for x in
    #      db.exons.find({'transcript_id': transcript_id}, fields={'_id': False})
    #      if x['feature_type'] != 'exon'],
    #     key=lambda k: k['start'])
    return sorted(list(db.exons.find({'transcript_id': transcript_id, 'feature_type': { "$in": ['CDS', 'UTR', 'exon'] }}, fields={'_id': False})), key=lambda k: k['start'])
<|endoftext|>


<commit_before>from django.test import TestCase
from splinter import Browser

class TestBaseViews(TestCase):

    def setUp(self):
        self.browser = Browser('chrome')

    def tearDown(self):
        self.browser.quit()

    def test_home(self):
        self.browser.visit('http://localhost:8000')
        test_string = 'Hello, world!'
        if self.browser.is_text_present(test_string):
            self.assertTrue(True)

    def test_robots(self):
        self.browser.visit('http://localhost:8000/robots.txt')
        if self.browser.is_text_present('robotstxt'):
            self.assertTrue(True)

    def test_humans(self):
        self.browser.visit('http://localhost:8000/humans.txt')
        if self.browser.is_text_present('humanstxt'):
            self.assertTrue(True)
<commit_msg>Add the proper tests for the base app<commit_after>from django.contrib.staticfiles.testing import StaticLiveServerTestCase
from django.urls import reverse
from splinter import Browser

class TestBaseViews(StaticLiveServerTestCase):
    """Integration test suite for testing the views in the app: base.

    Test the url for home and the basefiles like robots.txt and humans.txt

    Attributes
    ----------
    browser : Browser
        Driver to navigate through websites and to run integration tests.
    """

    def setUp(self):
        """Initialize the browser, before running the tests.
        """
        self.browser = Browser('chrome')

    def tearDown(self):
        """At the end of tests, close the browser
        """
        self.browser.quit()

    def test_home(self):
        """Test for url 'base:home'.

        Visit the url of name 'home' and check it loads the content
        """
        self.browser.visit(self.live_server_url + reverse('home'))
        self.assertTrue(self.browser.is_text_present('Hello, world!'))

    def test_robots(self):
        """Test for url 'base:base_files(robots.txt)'.

        Visit the url of robots.txt and check it loads the file
        """
        self.browser.visit(self.live_server_url + reverse('base_files',
                           kwargs={'filename': 'robots.txt'}))
        self.assertTrue(self.browser.is_text_present('robotstxt'))

    def test_humans(self):
        """Test for url 'base:base_files(humans.txt)'.

        Visit the url of humans.txt and check it loads the file
        """
        self.browser.visit(self.live_server_url + reverse('base_files',
                           kwargs={'filename': 'humans.txt'}))
        self.assertTrue(self.browser.is_text_present('humanstxt'))
<|endoftext|>


<commit_before>import fileinput
import os
import re
from lxml import etree as ET
import sys

from cumulusci.core.tasks import BaseTask

class MetaXmlBaseTask(BaseTask):

    def _init_options(self, kwargs):
        super(MetaXmlBaseTask, self)._init_options(kwargs)
        if 'dir' not in self.options or not self.options['dir']:
            self.options['dir'] = os.path.join(
                self.project_config.repo_root,
                'src',
            )

    def _run_task(self):
        for root, dirs, files in os.walk(self.options['dir']):
            for filename in files:
                if filename.endswith('-meta.xml'):
                    self._process_file(os.path.join(root, filename))

    def _write_file(self, tree, filename):
        tree.write(
            filename,
            xml_declaration=True,
            encoding='UTF-8',
            pretty_print=True,
        )
        # change back to double quotes in header to minimize diffs
        for line in fileinput.input(filename, inplace=1):
            if line.startswith('<?xml'):
                sys.stdout.write(line.replace("'", '"'))
            else:
                sys.stdout.write(line)

class UpdateApi(MetaXmlBaseTask):
    task_options = {
        'dir': {
            'description': 'Base directory to search for *-meta.xml files',
        },
        'version': {
            'description': 'API version number e.g. 37.0',
            'required': True,
        },
    }

    def _process_file(self, filename):
        tree = ET.parse(filename)
        root = tree.getroot()
        xmlns = re.search('({.+}).+', root.tag).group(1)
        changed = False
        api_version = root.find('{}apiVersion'.format(xmlns))
        if (api_version is not None and
                api_version.text != self.options['version']):
            api_version.text = self.options['version']
            changed = True
        if changed:
            self._write_file(tree, filename)
            self.logger.info('Processed file %s', filename)
        else:
            self.logger.info('No changes for file %s', filename)

class UpdateDependencies(MetaXmlBaseTask):
    task_options = {
        'dir': {
            'description': 'Base directory to search for *-meta.xml files',
        },
        'namespace': {
            'description': 'Package namespace e.g. npe01',
            'required': True,
        },
        'version': {
            'description': 'Package version number e.g. 1.2',
            'required': True,
        },
    }

    def _process_file(self, filename):
        tree = ET.parse(filename)
        root = tree.getroot()
        xmlns = re.search('({.+}).+', root.tag).group(1)
        changed = False
        v_major, v_minor = self.options['version'].split('.')
        for package_version in root.findall('{}packageVersions'.format(xmlns)):
            namespace = package_version.find('{}namespace'.format(xmlns)).text
            if namespace != self.options['namespace']:
                continue
            major = package_version.find('{}majorNumber'.format(xmlns))
            if major.text != v_major:
                major.text = v_major
                changed = True
            minor = package_version.find('{}minorNumber'.format(xmlns))
            if minor.text != v_minor:
                minor.text = v_minor
                changed = True
        if changed:
            self._write_file(tree, filename)
            self.logger.info('Processed file %s', filename)
        else:
            self.logger.info('No changes for file %s', filename)
<commit_msg>cleanup<commit_after>import fileinput
import os
import re
from lxml import etree as ET
import sys

from cumulusci.core.tasks import BaseTask

class MetaXmlBaseTask(BaseTask):

    def _init_options(self, kwargs):
        super(MetaXmlBaseTask, self)._init_options(kwargs)
        if 'dir' not in self.options or not self.options['dir']:
            self.options['dir'] = os.path.join(
                self.project_config.repo_root,
                'src',
            )

    def _run_task(self):
        for root, dirs, files in os.walk(self.options['dir']):
            for filename in files:
                filename = os.path.join(root, filename)
                if filename.endswith('-meta.xml'):
                    tree = ET.parse(filename)
                    if self._process_xml(tree.getroot()):
                        self._write_file(tree, filename)
                        self.logger.info('Processed file %s', filename)
                    else:
                        self.logger.info('No changes for file %s', filename)

    def _write_file(self, tree, filename):
        tree.write(
            filename,
            xml_declaration=True,
            encoding='UTF-8',
            pretty_print=True,
        )
        # change back to double quotes in header to minimize diffs
        for line in fileinput.input(filename, inplace=1):
            if line.startswith('<?xml'):
                sys.stdout.write(line.replace("'", '"'))
            else:
                sys.stdout.write(line)

class UpdateApi(MetaXmlBaseTask):
    task_options = {
        'dir': {
            'description': 'Base directory to search for *-meta.xml files',
        },
        'version': {
            'description': 'API version number e.g. 37.0',
            'required': True,
        },
    }

    def _process_xml(self, root):
        changed = False
        xmlns = re.search('({.+}).+', root.tag).group(1)
        api_version = root.find('{}apiVersion'.format(xmlns))
        if (api_version is not None and
                api_version.text != self.options['version']):
            api_version.text = self.options['version']
            changed = True
        return changed

class UpdateDependencies(MetaXmlBaseTask):
    task_options = {
        'dir': {
            'description': 'Base directory to search for *-meta.xml files',
        },
        'namespace': {
            'description': 'Package namespace e.g. npe01',
            'required': True,
        },
        'version': {
            'description': 'Package version number e.g. 1.2',
            'required': True,
        },
    }

    def _process_xml(self, root):
        changed = False
        xmlns = re.search('({.+}).+', root.tag).group(1)
        v_major, v_minor = self.options['version'].split('.')
        for package_version in root.findall('{}packageVersions'.format(xmlns)):
            namespace = package_version.find('{}namespace'.format(xmlns)).text
            if namespace != self.options['namespace']:
                continue
            major = package_version.find('{}majorNumber'.format(xmlns))
            if major.text != v_major:
                major.text = v_major
                changed = True
            minor = package_version.find('{}minorNumber'.format(xmlns))
            if minor.text != v_minor:
                minor.text = v_minor
                changed = True
        return changed
<|endoftext|>


<commit_before>"""Let's Encrypt tests"""
<commit_msg>Remove tests/__init__.py.<commit_after><|endoftext|>


<commit_before>__version__ = "1.0.0"
<commit_msg>Bump to v1.1.0 (#427)<commit_after>__version__ = "1.1.0"
<|endoftext|>


<commit_before>'''
Compatibility module for Python 2.7 and > 3.3
=============================================
'''

__all__ = ('PY2', 'string_types', 'queue', 'iterkeys',
           'itervalues', 'iteritems')

import sys
try:
    import queue
except ImportError:
    import Queue as queue

#: True if Python 2 intepreter is used
PY2 = sys.version_info[0] == 2

#: String types that can be used for checking if a object is a string
string_types = None
text_type = None
if PY2:
    string_types = basestring
    text_type = unicode
else:
    string_types = text_type = str

#: unichr is just chr in py3, since all strings are unicode
if PY2:
    unichr = unichr
else:
    unichr = chr

if PY2:
    iterkeys = lambda d: d.iterkeys()
    itervalues = lambda d: d.itervalues()
    iteritems = lambda d: d.iteritems()
else:
    iterkeys = lambda d: iter(d.keys())
    itervalues = lambda d: iter(d.values())
    iteritems = lambda d: iter(d.items())
<commit_msg>Add clock to compat.<commit_after>'''
Compatibility module for Python 2.7 and > 3.3
=============================================
'''

__all__ = ('PY2', 'string_types', 'queue', 'iterkeys',
           'itervalues', 'iteritems')

import sys
import time
try:
    import queue
except ImportError:
    import Queue as queue

#: True if Python 2 intepreter is used
PY2 = sys.version_info[0] == 2
'''True, if the version of python running is 2.x. '''

clock = None
'''A clock with the highest available resolution. '''

#: String types that can be used for checking if a object is a string
string_types = None
text_type = None
if PY2:
    string_types = basestring
    text_type = unicode
else:
    string_types = text_type = str

#: unichr is just chr in py3, since all strings are unicode
if PY2:
    unichr = unichr
else:
    unichr = chr

if PY2:
    iterkeys = lambda d: d.iterkeys()
    itervalues = lambda d: d.itervalues()
    iteritems = lambda d: d.iteritems()
else:
    iterkeys = lambda d: iter(d.keys())
    itervalues = lambda d: iter(d.values())
    iteritems = lambda d: iter(d.items())

if PY2:
    if sys.platform in ('win32', 'cygwin'):
        clock = time.clock
    else:
        clock = time.time
else:
    clock = time.perf_counter
<|endoftext|>