コード例 #1
0
class ExternalFieldExpression(ExternalField):
    def __init__(self, name, electric_or_magnetic, expression_x, expression_y,
                 expression_z):
        super().__init__(name, electric_or_magnetic)
        self.expression_x = expression_x
        self.expression_y = expression_y
        self.expression_z = expression_z
        self._ev = SimpleEval(functions={
            "sin": math.sin,
            "cos": math.cos,
            "sqrt": math.sqrt
        })
        # todo: inherit SimpleEval and define math functions inside
        # todo: add r, theta, phi names

    def _field_at_position(self, pos):
        self._ev.names["x"] = pos[0]
        self._ev.names["y"] = pos[1]
        self._ev.names["z"] = pos[2]
        fx = self._ev.eval(self.expression_x)
        fy = self._ev.eval(self.expression_y)
        fz = self._ev.eval(self.expression_z)
        return fx, fy, fz

    def get_at_points(self, positions, time):
        positions = np.asarray(positions)
        self._ev.names["t"] = time
        if positions.shape == (3, ):
            return np.array(self._field_at_position(positions))
        else:
            return np.array(
                [self._field_at_position(pos) for pos in positions])
コード例 #2
0
class FieldExpression(Field):
    @safe_default_inject
    @inject.params(xp=numpy)
    def __init__(self,
                 name,
                 electric_or_magnetic,
                 expression_x,
                 expression_y,
                 expression_z,
                 xp=numpy):
        super().__init__(name, electric_or_magnetic)
        self._xp = xp
        self.expression_x = expression_x
        self.expression_y = expression_y
        self.expression_z = expression_z
        self._ev = SimpleEval(functions={
            "sin": xp.sin,
            "cos": xp.cos,
            "sqrt": xp.sqrt
        },
                              operators={
                                  ast.Add: op.add,
                                  ast.Sub: op.sub,
                                  ast.Mult: op.mul,
                                  ast.Div: op.truediv,
                                  ast.FloorDiv: op.floordiv,
                                  ast.Pow: op.pow,
                                  ast.Mod: op.mod,
                                  ast.Eq: op.eq,
                                  ast.NotEq: op.ne,
                                  ast.Gt: op.gt,
                                  ast.Lt: op.lt,
                                  ast.GtE: op.ge,
                                  ast.LtE: op.le,
                                  ast.Not: op.not_,
                                  ast.USub: op.neg,
                                  ast.UAdd: op.pos,
                                  ast.In: lambda x, y: op.contains(y, x),
                                  ast.NotIn:
                                  lambda x, y: not op.contains(y, x),
                                  ast.Is: lambda x, y: x is y,
                                  ast.IsNot: lambda x, y: x is not y,
                              })
        # todo: inherit SimpleEval and define math functions inside
        # todo: add r, theta, phi names

    def get_at_points(self, positions, time: float) -> numpy.ndarray:
        positions = self._xp.asarray(positions)
        self._ev.names["t"] = time
        self._ev.names["x"] = positions[:, 0]
        self._ev.names["y"] = positions[:, 1]
        self._ev.names["z"] = positions[:, 2]
        result = self._xp.empty_like(positions)
        result[:, 0] = self._ev.eval(self.expression_x)
        result[:, 1] = self._ev.eval(self.expression_y)
        result[:, 2] = self._ev.eval(self.expression_z)
        return result
コード例 #3
0
 def test_no_names(self):
     # does not work on current Py3, True et al. are keywords now
     self.s.eval('True')
     # with self.assertRaises(NameNotDefined):
     s = SimpleEval(names={})
     if sys.version_info < (3, ):
         with self.assertRaises(NameNotDefined):
             s.eval('True')
     else:
         s.eval('True')
コード例 #4
0
    def visit_typedecl(self, node):
        """
        Visit a node.
        """
        if node.declname in self.names:
            c_gen = c_generator.CGenerator()
            pins = {}

            operators = DEFAULT_OPERATORS
            operators[ast.BitOr] = lambda a, b: a | b
            operators[ast.LShift] = lambda a, b: a << b
            operators[ast.RShift] = lambda a, b: a << b
            evaluator = SimpleEval(DEFAULT_OPERATORS)

            for pin in node.type.values.enumerators:
                expr = c_gen.visit(pin.value)

                if "(int)" in expr:
                    expr = expr.replace('(int)', '')

                if expr in pins:
                    pins[pin.name] = pins[expr]
                else:
                    pins[pin.name] = evaluator.eval(expr.strip())

            return pins
コード例 #5
0
    def evaluate_context(self, context, verbose=True, allowed_missing=()):
        evaluator = SimpleEval(
            functions={
                **DEFAULT_FUNCTIONS,
                'log': np.log,
                'log2': np.log2,
                'log10': np.log10,
                'sqrt': np.sqrt,
                'abs': np.abs,
                'ord': ord,
            })
        evaluator.names.update(context)
        evaluator.names.update(self._constants)
        allowed_missing = set(allowed_missing)

        for name, code in self._evaluables.items():
            try:
                result = evaluator.eval(code) if isinstance(code,
                                                            str) else code
            except NameNotDefined as error:
                if error.name in allowed_missing:
                    allowed_missing.add(name)
                    log.debug(f'Skipped evaluating: {name}')
                    continue
                else:
                    raise
            if verbose:
                log.debug(f'Evaluated: {name} = {repr(result)}')
            evaluator.names[name] = context[name] = result
コード例 #6
0
 def parse_entry(self, parsed_data):
     if parsed_data[0] == 0:  # concatenation
         if len(parsed_data) == 1:
             return
         element = parsed_data[1]
         remainder = parsed_data[2:]
         remainder.insert(0, 0)
         if type(element) is str:
             result = None
             for result in self.parse_entry(remainder):
                 yield element + result
             if result is None:
                 yield element
         else:
             element_result = None
             for element_result in self.parse_entry(element):
                 remainder_result = None
                 for remainder_result in self.parse_entry(remainder):
                     yield element_result + remainder_result
                 if remainder_result is None:
                     yield element_result
             if element_result is None:
                 for remainder_result in self.parse_entry(remainder):
                     yield remainder_result
     elif parsed_data[0] == 1:  # random choice [a,b,c]
         element = parsed_data[random.randint(1, len(parsed_data) - 1)]
         if type(element) is not str:
             for result in self.parse_entry(element):
                 yield result
         else:
             yield element
     elif parsed_data[0] == 2:  # multiple response {a,b,c}
         for element in parsed_data[1:]:
             if type(element) is str:
                 yield element
             else:
                 for result in self.parse_entry(element):
                     yield result
     elif parsed_data[0] == 3:  # dynamic variable ${variable}
         variable_name = parsed_data[1]
         if type(variable_name) is not str:
             variable_name = next(self.parse_entry(variable_name), '')
         evaluator = SimpleEval(names=self.variables.copy(),
                                functions=EVAL_FUNCTIONS,
                                operators=EVAL_OPERATORS)
         evaluator.names['variables'] = evaluator.names
         evaluator.functions['eval'] = evaluator.eval
         try:
             yield str(evaluator.eval(variable_name))
         except GeneratorExit:
             pass
         except:
             yield '[Error: {0}]'.format(''.join(
                 traceback.format_exception_only(
                     sys.exc_info()[0],
                     sys.exc_info()[1])).strip())
コード例 #7
0
class DRYTest(unittest.TestCase):
    ''' Stuff we need to do every test, let's do here instead..
        Don't Repeat Yourself. '''
    def setUp(self):
        ''' initialize a SimpleEval '''
        self.s = SimpleEval()

    def t(self, expr, shouldbe):  #pylint: disable=invalid-name
        ''' test an evaluation of an expression against an expected answer '''
        return self.assertEqual(self.s.eval(expr), shouldbe)
コード例 #8
0
    def test_functions_are_disallowed_in_expressions(self):
        DISALLOWED = [type, isinstance, eval, getattr, setattr, help, repr, compile, open]

        if simpleeval.PYTHON3:
            exec('DISALLOWED.append(exec)') # exec is not a function in Python2...

        for f in simpleeval.DISALLOW_FUNCTIONS:
            assert f in DISALLOWED


        DF = simpleeval.DEFAULT_FUNCTIONS.copy()

        for x in DISALLOWED:
            simpleeval.DEFAULT_FUNCTIONS = DF.copy()
            with self.assertRaises(FeatureNotAvailable):
                s = SimpleEval()
                s.functions['foo'] = x
                s.eval('foo(42)')

        simpleeval.DEFAULT_FUNCTIONS = DF.copy()
コード例 #9
0
class DRYTest(unittest.TestCase):
    """ Stuff we need to do every test, let's do here instead..
        Don't Repeat Yourself. """

    def setUp(self):
        """ initialize a SimpleEval """
        self.s = SimpleEval()

    def t(self, expr, shouldbe):  # pylint: disable=invalid-name
        """ test an evaluation of an expression against an expected answer """
        return self.assertEqual(self.s.eval(expr), shouldbe)
コード例 #10
0
    def test_functions_are_disallowed_in_expressions(self):
        DISALLOWED = [type, isinstance, eval, getattr, setattr, help, repr, compile, open]

        if simpleeval.PYTHON3:
            exec('DISALLOWED.append(exec)') # exec is not a function in Python2...

        for f in simpleeval.DISALLOW_FUNCTIONS:
            assert f in DISALLOWED


        DF = simpleeval.DEFAULT_FUNCTIONS.copy()

        for x in DISALLOWED:
            simpleeval.DEFAULT_FUNCTIONS = DF.copy()
            with self.assertRaises(FeatureNotAvailable):
                s = SimpleEval()
                s.functions['foo'] = x
                s.eval('foo(42)')

        simpleeval.DEFAULT_FUNCTIONS = DF.copy()
コード例 #11
0
ファイル: botparser.py プロジェクト: ArkaneMoose/BotBot
 def parse_entry(self, parsed_data):
     if parsed_data[0] == 0: # concatenation
         if len(parsed_data) == 1:
             return
         element = parsed_data[1]
         remainder = parsed_data[2:]
         remainder.insert(0, 0)
         if type(element) is str:
             result = None
             for result in self.parse_entry(remainder):
                 yield element + result
             if result is None:
                 yield element
         else:
             element_result = None
             for element_result in self.parse_entry(element):
                 remainder_result = None
                 for remainder_result in self.parse_entry(remainder):
                     yield element_result + remainder_result
                 if remainder_result is None:
                     yield element_result
             if element_result is None:
                 for remainder_result in self.parse_entry(remainder):
                     yield remainder_result
     elif parsed_data[0] == 1: # random choice [a,b,c]
         element = parsed_data[random.randint(1, len(parsed_data) - 1)]
         if type(element) is not str:
             for result in self.parse_entry(element):
                 yield result
         else:
             yield element
     elif parsed_data[0] == 2: # multiple response {a,b,c}
         for element in parsed_data[1:]:
             if type(element) is str:
                 yield element
             else:
                 for result in self.parse_entry(element):
                     yield result
     elif parsed_data[0] == 3: # dynamic variable ${variable}
         variable_name = parsed_data[1]
         if type(variable_name) is not str:
             variable_name = next(self.parse_entry(variable_name), '')
         evaluator = SimpleEval(names=self.variables.copy(), functions=EVAL_FUNCTIONS, operators=EVAL_OPERATORS)
         evaluator.names['variables'] = evaluator.names
         evaluator.functions['eval'] = evaluator.eval
         try:
             yield str(evaluator.eval(variable_name))
         except GeneratorExit:
             pass
         except:
             yield '[Error: {0}]'.format(''.join(traceback.format_exception_only(sys.exc_info()[0], sys.exc_info()[1])).strip())
コード例 #12
0
def eval_statements(statement, variable_context):
    """Evaluates math statements and returns the value

    args
        statement: a simple python-like math statement
        variable_context: a dict with variable names as key and assigned values as dict values
    """
    # variable values should be numbers
    var_types = set(type(value) for value in variable_context.values())
    if not var_types.issubset({int, float, long, Decimal, date, datetime, NoneType, bool}):
        raise InvalidExpression

    evaluator = SimpleEval(operators=SAFE_OPERATORS, names=variable_context, functions=FUNCTIONS)
    return evaluator.eval(statement)
コード例 #13
0
ファイル: utils.py プロジェクト: tlwakwella/commcare-hq
def eval_statements(statement, variable_context):
    """Evaluates math statements and returns the value

    args
        statement: a simple python-like math statement
        variable_context: a dict with variable names as key and assigned values as dict values
    """
    # variable values should be numbers
    var_types = set(type(value) for value in variable_context.values())
    if not var_types.issubset(set([int, float, long])):
        raise InvalidExpression

    evaluator = SimpleEval(operators=SAFE_OPERATORS, names=variable_context)
    return evaluator.eval(statement)
コード例 #14
0
class BooleanQueryType(click.ParamType):

    name = "query"

    def __init__(self):
        super().__init__()
        # Create a sandboxed evaluator allowing to use the Q object,
        # and the "|", "&" and "~" operators.
        # See: https://github.com/danthedeckie/simpleeval
        self.evaluator = SimpleEval(
            functions={"Q": Q},
            operators={
                ast.BitOr: operator.or_,
                ast.BitAnd: operator.and_,
                ast.Invert: operator.invert,
            },
        )

    def convert(self, value, param, ctx) -> Q:
        try:
            return self.evaluator.eval(value)  # 🤯
        except Exception as exc:
            raise click.BadParameter(str(exc))
コード例 #15
0
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

__author__ = 'ipetrash'

# pip install simpleeval
from simpleeval import SimpleEval


def get_from_file(file_name):
    with open(file_name) as f:
        return f.read()


my_eval = SimpleEval()
my_eval.functions['get'] = get_from_file

print(my_eval.eval("get('a_value.txt') + get('b_value.txt')"))  # '12345'
print(my_eval.eval("int(get('a_value.txt')) + int(get('b_value.txt'))"))  # 168
コード例 #16
0
class CardDeck(CardPile):
    def __init__(
            self,
            card_pile_id,
            mat_center,
            mat_size,
            mat_boundary,
            card_size,
            card_offset,
            mat_color,
            size_scaler,
            update_event_handle,
            per_deck_cards,  #initial_num_of_decks=None,
            face_down=True,
            enable_generation=None,
            num_of_decks_per_generation=1,
            enable_auto_distribution=None,
            destination_piles_and_cards=None,
            title_property=None,
            other_properties=None,
            *args,
            **kwargs):
        super().__init__(card_pile_id,
                         mat_center,
                         mat_size,
                         mat_boundary,
                         card_size,
                         card_offset,
                         mat_color,
                         size_scaler,
                         sorting_rule=None,
                         auto_sort_setting=None,
                         enable_sort_button=False,
                         enable_recover_last_removed_cards=False,
                         update_event_handle=update_event_handle,
                         title_property=title_property,
                         other_properties=other_properties,
                         *args,
                         **kwargs)
        self._simple_eval = SimpleEval()
        self.enable_auto_distribution = enable_auto_distribution
        self._destination_piles_and_cards = destination_piles_and_cards
        self._ui_destination_piles_and_cards = {}
        self.per_deck_cards = per_deck_cards
        #self.initial_num_of_decks=initial_num_of_decks
        self._enable_generation = enable_generation
        self._num_of_decks_per_generation = num_of_decks_per_generation
        self._ui_num_of_decks_per_generation = None
        self._enable_auto_distribution = enable_auto_distribution
        self._per_deck_cards = per_deck_cards
        self.face_down = face_down
        self._generation_button = None
        self._auto_distribution_button = None
        self.setup_vertical_ui_elements()

    @property
    def num_of_decks_per_generation(self):
        if self._ui_num_of_decks_per_generation is None:
            return None
        else:
            c_value = self._ui_num_of_decks_per_generation.text
            if not c_value.isdigit():
                return None
            else:
                return int(c_value)

    @num_of_decks_per_generation.setter
    def num_of_decks_per_generation(self, value):
        if value is not None:
            #if self._ui_num_of_decks_per_generation.text!=str(value):
            self._ui_num_of_decks_per_generation.sync_text(str(value))

    @property
    def destination_piles_and_cards(self):
        output_dict = {}
        for key, ui_input in self._ui_destination_piles_and_cards.items():
            c_value = ui_input.text
            if not c_value.isdigit():
                return None
            else:
                output_dict[key] = int(c_value)
        return output_dict

    @destination_piles_and_cards.setter
    def destination_piles_and_cards(self, value: dict):
        for key, val in value.items():
            #c_value =self._ui_destination_piles_and_cards[key].text
            #if c_value != str(val):
            self._ui_destination_piles_and_cards[key].sync_text(str(val))

    def update_ui_property(self, ui_property):
        if 'num_of_decks_per_generation' in ui_property:
            self.num_of_decks_per_generation = ui_property[
                'num_of_decks_per_generation']
        if 'destination_piles_and_cards' in ui_property:
            self.destination_piles_and_cards = ui_property[
                'destination_piles_and_cards']

    def deal_cards(self):
        if 'pile_tag_to_pile_id' in self.other_properties:
            card_values = self.to_valuelist()
            destination_piles_and_cards = self.destination_piles_and_cards
            if destination_piles_and_cards is not None:
                all_cards_to_distribute_count = sum([
                    len(self.other_properties['pile_tag_to_pile_id'][key]) *
                    self._eval_expression(val)
                    for key, val in destination_piles_and_cards.items()
                ])
                if all_cards_to_distribute_count <= len(card_values):
                    starting_index = 0
                    for key, val in destination_piles_and_cards.items():
                        n_cards = self._eval_expression(val)
                        for card_pile_id in self.other_properties[
                                'pile_tag_to_pile_id'][key]:
                            new_event = gamestate.Event(
                                type='Move',
                                src_pile=self.card_pile_id,
                                dst_pile=card_pile_id,
                                cards=card_values[
                                    starting_index:starting_index + n_cards])
                            self._update_event_handle(new_event,
                                                      local_fast_update=False)
                            starting_index += n_cards

    def _eval_expression(self, x):
        if isinstance(x, str):
            temp_str = x
            for key, val in self.other_properties['constants'].items():
                temp_str = temp_str.replace(key, str(val))
            return self._simple_eval.eval(temp_str)
        else:
            return x

    def generate_cards(self):
        """ Send gnerate new cards event

        :return:
        """

        random.seed(a=None)
        n_deck_per_generation = self.num_of_decks_per_generation
        if n_deck_per_generation is not None:
            new_cards = [
                j * MAX_DECK_SIZE + w for j in range(n_deck_per_generation)
                for w in self.per_deck_cards
            ]
            face_value = 'D' if self.face_down else 'U'
            card_status = {w: face_value for w in new_cards}
            random.shuffle(new_cards)
            new_event = gamestate.EventAddNewCards(type='AddNewCards',
                                                   dst_pile=self.card_pile_id,
                                                   cards=new_cards,
                                                   cards_status=card_status)
            self._update_event_handle(new_event, local_fast_update=False)

    def _on_change_num_of_decks_per_generation(self, value):
        num_of_decks_per_generation = self.num_of_decks_per_generation
        if num_of_decks_per_generation is not None:
            new_event = gamestate.Event(type='UIElementChange',
                                        dst_pile=self.card_pile_id,
                                        property={
                                            'num_of_decks_per_generation':
                                            num_of_decks_per_generation
                                        })
            self._update_event_handle(new_event, local_fast_update=False)

    def _on_change_destination_piles_and_cards(self, value):
        destination_piles_and_cards = self.destination_piles_and_cards
        if destination_piles_and_cards is not None:
            new_event = gamestate.Event(type='UIElementChange',
                                        dst_pile=self.card_pile_id,
                                        property={
                                            'destination_piles_and_cards':
                                            destination_piles_and_cards
                                        })
            self._update_event_handle(new_event, local_fast_update=False)

    def setup_vertical_ui_elements(self):
        #num_vertical_button = 0
        if self._enable_generation:
            if self._generation_button is None:
                text_label = ResizableGameTextLabel(
                    width=self._vertical_button_width / 2,
                    height=self._vertical_button_height,
                    center_x=self._mat_center[0] + self._mat_size[0] / 2 +
                    self._vertical_button_width / 4,
                    center_y=self._mat_center[1] + self._mat_size[1] / 2 -
                    (self._vertical_button_count * 2 + 1) / 2 *
                    self._vertical_button_height,
                    size_scaler=self._size_scaler,
                    font_size=height_to_font_size(
                        self._vertical_button_height),
                    text=str('#decks'))
                c_text_input = SyncedResizableUIInputBox(
                    width=self._vertical_button_width / 2,
                    height=self._vertical_button_height,
                    center_x=self._mat_center[0] + self._mat_size[0] / 2 +
                    self._vertical_button_width / 4 * 3,
                    center_y=self._mat_center[1] + self._mat_size[1] / 2 -
                    (self._vertical_button_count * 2 + 1) / 2 *
                    self._vertical_button_height,
                    size_scaler=self._size_scaler,
                    font_size=height_to_font_size(
                        self._vertical_button_height),
                    text=str(
                        self._eval_expression(
                            self._num_of_decks_per_generation)),
                    on_text_update_hanlder=self.
                    _on_change_num_of_decks_per_generation)
                self._ui_num_of_decks_per_generation = c_text_input
                self._vertical_button_count += 1
                self._ui_elements.append(text_label)
                self._ui_elements.append(c_text_input)

                self._generation_button = self._add_vertical_buttons(
                    self.generate_cards, 'GENERATE')

        if self._enable_auto_distribution:
            if self._auto_distribution_button is None:
                for key, val in self._destination_piles_and_cards.items():
                    text_label = ResizableGameTextLabel(
                        width=self._vertical_button_width / 2,
                        height=self._vertical_button_height,
                        center_x=self._mat_center[0] + self._mat_size[0] / 2 +
                        self._vertical_button_width / 4,
                        center_y=self._mat_center[1] + self._mat_size[1] / 2 -
                        (self._vertical_button_count * 2 + 1) / 2 *
                        self._vertical_button_height,
                        size_scaler=self._size_scaler,
                        font_size=height_to_font_size(
                            self._vertical_button_height),
                        text=str(key))

                    c_text_input = SyncedResizableUIInputBox(
                        width=self._vertical_button_width / 2,
                        height=self._vertical_button_height,
                        center_x=self._mat_center[0] + self._mat_size[0] / 2 +
                        self._vertical_button_width / 4 * 3,
                        center_y=self._mat_center[1] + self._mat_size[1] / 2 -
                        (self._vertical_button_count * 2 + 1) / 2 *
                        self._vertical_button_height,
                        size_scaler=self._size_scaler,
                        font_size=height_to_font_size(
                            self._vertical_button_height),
                        text=str(self._eval_expression(val)),
                        on_text_update_hanlder=self.
                        _on_change_destination_piles_and_cards)
                    self._ui_destination_piles_and_cards[key] = c_text_input
                    self._vertical_button_count += 1
                    self._ui_elements.append(text_label)
                    self._ui_elements.append(c_text_input)
                self._auto_distribution_button = self._add_vertical_buttons(
                    self.deal_cards, 'DEAL')
コード例 #17
0
ファイル: __init__.py プロジェクト: Zetison/badger
 def evaluate_context(self, context):
     evaluator = SimpleEval()
     evaluator.names.update(context)
     for name, code in self._evaluables.items():
         result = evaluator.eval(code) if isinstance(code, str) else code
         evaluator.names[name] = context[name] = result
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

__author__ = 'ipetrash'

# pip install simpleeval
from simpleeval import SimpleEval


def get_from_url(value):
    import requests
    rs = requests.get('https://httpbin.org/get', params={'value': value})
    return rs.json()['args']['value']


my_eval = SimpleEval()
my_eval.functions['get'] = get_from_url

print(my_eval.eval("get('123') + get('45')"))  # '12345'
print(my_eval.eval("int(get('123')) + int(get('45'))"))  # 168
コード例 #19
0
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

__author__ = 'ipetrash'

# SOURCE: https://github.com/danthedeckie/simpleeval#operators

# pip install simpleeval
from simpleeval import SimpleEval

import ast
import operator as op

s = SimpleEval()
s.operators[ast.BitXor] = op.xor
# # OR:
# s.operators[ast.BitXor] = lambda a, b: a ^ b

print(s.eval("2 ^ 10"))  # 8
コード例 #20
0
ファイル: launcher.py プロジェクト: wezu/p3d_launcher
class Launcher (DirectObject):
    def __init__(self, app, setup_data, custom_functions={}):         
        #we keep the 'main' application class to call some functions there
        self.app=app            
        #load the config
        self.setup_data=setup_data
        self.cfg=Configer(path+self.setup_data['basic']['config_file'])        
        
        #setup the window for the launcher
        wp = WindowProperties.getDefault() 
        wp.setFixedSize(True)  
        wp.setFullscreen(False)
        wp.setUndecorated(self.setup_data['basic']['undecorated'])
        wp.setOrigin(-2,-2)  
        wp.setTitle(self.setup_data['basic']['title'])  
        wp.setSize(self.setup_data['basic']['window_size'][0],self.setup_data['basic']['window_size'][1])        
        base.openMainWindow(props = wp)
        base.win.setCloseRequestEvent('exit_program')
        
        #a root node for ell the widgets
        self.root=pixel2d.attachNewNode('launcher_root')
        
        #set the bacground image
        self.background=DirectFrame(frameSize=_rec2d(self.setup_data['basic']['window_size'][0],self.setup_data['basic']['window_size'][1]),
                                 frameColor=(1,1,1, 1), 
                                 frameTexture=path+self.setup_data['basic']['background'],                    
                                 parent=self.root)
        _resetPivot(self.background) 
        self.background.setPos(_pos2d(0,0))                         
        
        #some vars used later
        self.last_click_time=0.0
        self.shouldExit =False
        self.last_button=None
        self.last_select_button=None
        self.last_select=None
        self.last_button_group=0            
        self.fonts={}        
        self.buttons=[]
        self.last_slider_config_name=None
        self.last_slider_name=None
        #make the needed buttons
        #needed for the updater part...
        self.update_label=self.makeLabel("", 'wait')   
        x=self.setup_data['basic']["window_size"][0]/2
        x-=self.setup_data['style']['default']["size"][0]/2  
        y=self.setup_data['basic']["window_size"][1]-self.setup_data['style']['default']["size"][1]*1.5
        pos=[x,y]   
        self.update_done_button=self.makeButton(self.setup_data['basic']['msg']['ok'], {"style": "default","pos": pos,"func": "updateDone()"})
        self.update_done_button.hide()
        #needed for the loadscreen
        self.loading_label=self.makeLabel(self.setup_data['basic']['msg']['loading'], 'loading') 
        #needed for the slider screen
        self.slider = DirectSlider(frameSize=_rec2d(self.setup_data['style']['slider']["size"][0]*0.8, self.setup_data['style']['slider']["size"][1]),
                                range=(0.0,1.0),
                                value=0.5,
                                thumb_relief=DGG.FLAT,
                                thumb_frameTexture=path+self.setup_data['style']['slider']['thumb_img'],
                                thumb_frameSize=(self.setup_data['style']['slider']['thumb_size'][0]/2,
                                                -self.setup_data['style']['slider']['thumb_size'][0]/2,
                                                -self.setup_data['style']['slider']['thumb_size'][1]/2,
                                                 self.setup_data['style']['slider']['thumb_size'][1]/2),
                                frameTexture=path+self.setup_data['style']['slider']['img'],
                                frameVisibleScale=(1.25,1), 
                                command=self.setSliderValue,
                                parent=self.root)
        x=self.setup_data['basic']["window_size"][0]/2
        x+=(self.setup_data['style']['slider']["size"][0]*0.8)/2  
        y=self.setup_data['basic']["window_size"][1]/2
        y+=self.setup_data['style']['slider']["size"][1]/2
        self.slider.setPos(_pos2d(x,y))                        
        self.slider.setTransparency(TransparencyAttrib.MDual)
        self.slider.hide()
        self.slider_done_button=self.makeButton(self.setup_data['basic']['msg']['ok'], {"style": "default","pos": pos,"func": "sliderDone()"})
        self.slider_done_button.hide()
        self.slider_label=self.makeLabel("")
        #needed for key input
        self.key_input_label=self.makeLabel("")
        self.key_input_current_label=self.makeLabel("", "key_input")
        self.key_input_done=self.makeButton(self.setup_data['basic']['msg']['ok'], {"style": "default","pos": pos,"func": "keyInputDone()"})
        self.key_input_done.hide()
        #the rest
        self.select_screens={}        
        self.select_names={}
        self.select_labels={}
        for select_group in self.setup_data["select"]:
            self.select_screens[select_group]=[]
            self.select_names[select_group]={}
            for label in self.setup_data["select"][select_group]:                
                self.select_names[select_group][self.setup_data["select"][select_group][label]]=label
                self.select_screens[select_group].append(self.makeSelectButton(label))                
            self.packSelectButtons(self.select_screens[select_group])
        i=0
        for button_group in self.setup_data["buttons"]:
            self.buttons.append({})
            for button_name in button_group:
                self.buttons[i][button_name]=self.makeButton(button_name, button_group[button_name])
                if i != 0:
                    self.buttons[i][button_name].hide()
            i+=1       
        #SimpleEval stuff
        names={'None': None}
        functions={ 
                    'Vec3':Vec3,
                    'startGame':self.startGame,
                    'exitGame':self.exitGame,
                    'updateGame':self.updateGame,
                    'updateDone':self.updateDone,
                    'toggleButtonGroup':self.toggleButtonGroup,
                    'showButton':self.showButton,
                    'select':self.showSelectScreen,
                    'slide':self.showSlideScreen,
                    'key':self.showKeyInputScreen,
                    'keyInputDone':self.keyInputDone,
                    'sliderDone':self.sliderDone,
                    'selectItem':self.selectItem,
                    'saveConfig':self.saveConfig                    
                    }   
        for key in  custom_functions:
            functions[key]=custom_functions[key]                
        self.simple_eval = SimpleEval(names=names, functions=functions)   
         
        #events 
        self.accept('exit_program',self.exitGame) 
        base.buttonThrowers[0].node().setButtonDownEvent('buttonDown')
        self.accept('buttonDown', self.getKey)
        
        #tasks
        taskMgr.add(self.update, 'launcher_update')
    
    def disable(self):
        #destroy all buttons
        for button_group in self.buttons:            
            for button_name in button_group:
                button_group[button_name].destroy()
        for button_group in  self.select_screens:       
            for button in self.select_screens[button_group]:            
                button.destroy()        
        for label in self.select_labels:
            self.select_labels[label].destroy()        
        self.key_input_label.destroy()
        self.key_input_current_label.destroy()
        self.key_input_done.destroy()
        self.update_done_button.destroy()
        self.loading_label.destroy()
        self.update_label.destroy()
        self.background.destroy() 
               
        #ignore all events
        self.ignoreAll()
        #remove task
        taskMgr.remove('launcher_update')
        #remove root node
        self.root.removeNode()
        #clear data
        del self.select_names
        del self.setup_data
        del self.last_click_time
        del self.shouldExit
        del self.last_button
        del self.last_select_button
        del self.last_select
        del self.last_button_group
        del self.fonts
        del self.buttons
        del self.last_slider_config_name
        del self.last_slider_name
        
    def getKey(self, keyname):
        self.last_key=keyname
        self.key_input_current_label['text']=keyname
        
    def renderSomeFrames(self, frames=1):
        for i in range(frames):
            base.graphicsEngine.renderFrame() 
            
    def startGame(self):
        self.toggleButtonGroup(-1)
        self.loading_label.show()
        #print "starting game"
        self.app.startGame()
    
    def hide(self):
        self.root.hide()
   
    def updateDone(self):
        self.toggleButtonGroup(0)
        self.update_done_button.hide()
        self.update_label['text']=""
        self.update_label.hide()
        
    def updateGame(self, wait_txt):
        url=self.setup_data['basic']['update_url']
        self.downloadUpdates(url)
        self.toggleButtonGroup(-1)
        self.update_label.show()
        self.update_label['text']
        
    def downloadUpdates(self, url):
        self.files_to_download=[]
                
        self.http = HTTPClient()
        self.channel = self.http.makeChannel(True)        
        
        self.files_to_download.append({'url':url, 'target':path+'update.json'})
        self.channel.beginGetDocument(DocumentSpec(url))
        self.channel.downloadToFile(Filename(path+'update.json')) 
        self.update_label['text']+=self.setup_data['basic']['msg']['collect']
        
        #add a task that will do the lifting
        taskMgr.add(self.downloadTask, 'downloadTask')    
            
    def downloadTask(self, task):
        if self.files_to_download:
            if self.channel.run():
                #print 'running...'
                return task.cont
            else:    
                if not self.channel.isDownloadComplete():      
                    #print "Error downloading file."
                    self.update_label['text']+=self.setup_data['basic']['msg']['download_error']
                    self.update_label['text']+="\n"+str(self.channel.getStatusString())
                else:
                    #if the downloaded file is named 'update.json'
                    #we get the files and urls there and add them to
                    #the download quene
                    last_file=self.files_to_download[0]['target']
                    #print "downloaded", last_file
                    self.update_label['text']+=self.setup_data['basic']['msg']['download_ok'] +last_file
                    self.renderSomeFrames(8)
                    if last_file == path+'update.json':
                        with open(path+'update.json') as f: 
                            try: 
                                file_list=json.load(f)
                                #print "loaded json file"
                            except:
                                #print "Error reading file" 
                                self.update_label['text']+=self.setup_data['basic']['msg']['read_error']   
                        #we only download files on the list that we don't have (by name)    
                        for f in file_list:
                            #print f 
                            if not os.path.exists(path+f['target']):
                                self.files_to_download.append({'url':f['url'], 'target':path+f['target']})
                    #if it's a zipfile we extract
                    elif is_zipfile(last_file):
                        #print "extracting"
                        self.update_label['text']+=self.setup_data['basic']['msg']['unzip']
                        self.renderSomeFrames(8)
                        with ZipFile(last_file) as zf:
                            zf.extractall(Filename(path).toOsSpecific())   
                        #remove zero sized files
                        self.update_label['text']+=self.setup_data['basic']['msg']['clean_up']
                        self.renderSomeFrames(8)                                               
                        for dirpath, dirs, files in os.walk(path):
                            for file in files: 
                                full_path = Filename(os.path.join(dirpath, file)).toOsSpecific()
                                #print full_path
                                if os.stat(full_path).st_size == 0:
                                    os.remove(full_path)
                    else:
                        self.update_label['text']+=path+last_file               
                        self.update_label['text']+="\n - not a zip file!"
                    #remove the last file from the list and get a next one        
                    self.files_to_download.pop(0) 
                    if self.files_to_download:
                        next_file=self.files_to_download[0]
                        #print "next_file", next_file
                        self.channel.beginGetDocument(DocumentSpec(next_file['url']))
                        self.channel.downloadToFile(Filename(next_file['target']))    
                        return task.cont                    
        #print "done" 
        self.update_label['text']+=self.setup_data['basic']['msg']['done']
        self.update_done_button.show()               
        return task.done
    
        
    def update(self, task):
        #calling exit from a sequence will crash the game
        if self.shouldExit:
            self.app.exit()
        return task.cont 
              
    def exe(self, command):
        if command:                        
            command=command.split(";")
            for cmd in command:
                try:  
                    #print cmd     
                    self.simple_eval.eval(cmd.strip())
                except Exception as e:
                    print e
    
    
    def runClickAnim(self, button):
        old_pos=button.getPos()
        new_pos=old_pos+_pos2d(0, 3)
        Sequence(LerpPosInterval(button, 0.05,new_pos),LerpPosInterval(button, 0.05,old_pos)).start()
        
            
    def onButtonClick(self, button, func, event=None): 
        time=globalClock.getFrameTime()
        if (time-self.last_click_time) >0.11:            
            self.last_button=button
            self.runClickAnim(button)                 
            Sequence(Wait(0.1),Func(self.exe, func)).start()            
        self.last_click_time=time
        
    def doNothing(self, arg=None):
        print "nop"    
    
    def saveConfig(self):        
        self.toggleButtonGroup(0)        
        config_file=path+self.setup_data['basic']['config_file']
        self.cfg.saveConfig(config_file)
    
    def exitGame(self):
        #self.app.exit()
        self.shouldExit=True
    
    def showButton(self, group, button_name):
        self.buttons[group][button_name].show()
    
    def selectItem(self, button_name):
        #set the new value in the cfg
        self.cfg.setCfgValueFromString(self.last_select, self.setup_data['select'][self.last_select][button_name])        
        #print self.cfg[self.last_select] 
        #update the button
        self.last_select_button['text']=self.last_select_button.getPythonTag("name")+" "+button_name        
        #hide the select screen
        self.hideSelectScreen()
        #show the last group
        self.toggleButtonGroup(self.last_button_group)
    
    def setSliderValue(self):
        if self.last_slider_config_name:
            round_to=self.setup_data['slide'][self.last_slider_config_name]["round"]
            mini=self.setup_data['slide'][self.last_slider_config_name]["min"]
            maxi=self.setup_data['slide'][self.last_slider_config_name]["max"]
            self.slider_value=mini+self.slider['value']*(maxi-mini)
            if round_to==0:
                self.slider_value=int(self.slider_value)
            else:
                self.slider_value=round(self.slider_value,round_to) 
            self.slider_label['text']=self.last_slider_name+'\n'+str(self.slider_value)
        
    def sliderDone(self):
        self.toggleButtonGroup(self.last_button_group)
        self.slider_label.hide()
        self.slider.hide()        
        self.slider_done_button.hide()
        self.buttons[self.last_button_group][self.last_slider_name]['text']=self.last_slider_name+str(self.slider_value)
        self.cfg[self.last_slider_config_name]=self.slider_value
        cmd="slide('"+self.last_slider_config_name+"', '"+self.last_slider_name+"', "+str(self.slider_value)+")"
        self.buttons[self.last_button_group][self.last_slider_name].bind(DGG.B1PRESS, self.onButtonClick, [self.buttons[self.last_button_group][self.last_slider_name], cmd])    
        
    def showSlideScreen(self, config_name, name, value):
        self.last_slider_config_name=config_name
        self.last_slider_name=name
        for button_group in self.buttons:            
            for button_name in button_group:
                button_group[button_name].hide()        
        self.slider_label.show()
        self.slider_label['text']=name
        self.slider.show()        
        self.slider_done_button.show()
        
        mini=self.setup_data['slide'][self.last_slider_config_name]["min"]
        maxi=self.setup_data['slide'][self.last_slider_config_name]["max"]
        
        self.slider['value']=float(value)/float(maxi-mini)
        
        self.setSliderValue()
        
    def showSelectScreen(self, screen): 
        self.last_select=screen  
        self.last_select_button=self.last_button
        for button_group in self.buttons:            
            for button_name in button_group:
                button_group[button_name].hide()                
        for button in self.select_screens[screen]:            
            button.show()        
        for label in self.select_labels:
            if label == screen:
                self.select_labels[label].show()
            else:    
                self.select_labels[label].hide()
    
    def keyInputDone(self):
        self.toggleButtonGroup(self.last_button_group)
        self.key_input_label.hide()
        self.key_input_current_label.hide()
        self.key_input_done.hide()
        self.buttons[self.last_button_group][self.last_key_name]['text']=self.last_key_name+self.last_key
        self.cfg[self.last_key_config_name]=self.last_key
        cmd="key('"+self.last_key_config_name+"', '"+self.last_key_name+"', '"+self.last_key+"')"
        self.buttons[self.last_button_group][self.last_key_name].bind(DGG.B1PRESS, self.onButtonClick, [self.buttons[self.last_button_group][self.last_key_name], cmd])    
                
    def showKeyInputScreen(self, config_name, name, value):    
        self.last_key_config_name=config_name
        self.last_key_name=name
        for button_group in self.buttons:            
            for button_name in button_group:
                button_group[button_name].hide()
        self.key_input_label.show()
        self.key_input_current_label.show()
        self.key_input_done.show()        
        self.key_input_label['text']=self.setup_data['basic']['msg']['new_key'].format(name)
        self.key_input_current_label['text']=value
                
    def hideSelectScreen(self):
        for screen in self.select_screens:
            for button in self.select_screens[screen]:            
                button.hide()    
        for label in self.select_labels:            
            self.select_labels[label].hide()
                    
    def toggleButtonGroup(self, group):
        self.last_button_group=group
        i=0
        for button_group in self.buttons:            
            for button_name in button_group:
                if i==group:
                    button_group[button_name].show()
                else:    
                    button_group[button_name].hide()
            i+=1          
    
    def getFont(self, font_name, font_size):
        if font_name in self.fonts:
            if font_size in self.fonts[font_name]:            
                font=self.fonts[font_name][font_size]
            else:
                font=self.addFontSize(font_name, font_size)
        else:
            font=self.addFont(font_name, font_size)
        return font    
    
    def addFont(self, font_name, font_size):        
        font=loader.loadFont(path+font_name)     
        font.setPixelsPerUnit(font_size)
        font.setMinfilter(Texture.FTNearest )
        font.setMagfilter(Texture.FTNearest )        
        self.fonts[font_name]={font_size:font}
        return font
        
    def addFontSize(self, font_name, font_size):
        #a bit of a hack to get a font of any size
        font=self.fonts[font_name].itervalues().next()
        new_font=font.makeCopy()        
        new_font.setPixelsPerUnit(font_size)
        self.fonts[font_name][font_size]=new_font        
        return new_font
    
    def getTextAlign(self, align):
        a=align.strip().lower()
        if a == 'center':
            return TextNode.ACenter
        elif a == 'left':
            return TextNode.ALeft    
        elif a == 'right':
            return TextNode.ARight  
        elif a == 'boxed_left':
            return TextNode.ABoxedLeft  
        elif a == 'boxed_right':
            return TextNode.ABoxedRight  
        elif a == 'boxed_center':
            return TextNode.ABoxedCenter  
        else:
            return TextNode.ALeft

    def packSelectButtons(self, button_list):        
        label_y=self.setup_data['style']["label"]["size"][1]
        x_offset=0
        y_offset=0
        button_x=self.setup_data['style']["select"]["size"][0]
        button_y=self.setup_data['style']["select"]["size"][1]
        window_x=self.setup_data['basic']["window_size"][0]
        window_y=self.setup_data['basic']["window_size"][1]+label_y
        button_count=len(button_list)   
        last_row_x_offset=0        
        #how many buttons can I fit side by side?
        buttons_per_row=window_x/button_x
        #how much space is left unused?
        x_offset=(window_x%button_x)/2
        #can all the buttons fit in one row?
        if button_count <= buttons_per_row:
            y_offset=window_y/2-button_y/2
            row_count=1            
            x_offset+=(window_x-(button_count*button_x))/2
        else:
            row_count=button_count/buttons_per_row
            if button_count%buttons_per_row != 0:
                row_count+=1
            y_offset=(window_y-((row_count)*button_y))/2
        if y_offset<0 or x_offset<0:
            print "(warning) Select buttons can't fit the window" 
        #is the last row full?
        if row_count > 1 and buttons_per_row*row_count >  button_count:            
            last_row_x_offset=(buttons_per_row*row_count-button_count)*button_x/2
        #start packing the buttons
        i=0
        row=-1
        for button in button_list:   
            column=i%buttons_per_row  
            if column==0:
                row+=1          
            x=x_offset+button_x*column
            y=y_offset+button_y*row
            if row==row_count-1: #this is the last row
                x+=last_row_x_offset
            button.setPos(_pos2d(x,y))            
            i+=1
                
    def makeLabel(self, name, style_name="label"):
        style=self.setup_data['style'][style_name]
        button=self.makeStyleButton(style)        
        button['state'] = DGG.DISABLED
        button['text']=name        
        x=self.setup_data['basic']["window_size"][0]/2
        x-=style["size"][0]/2
        button.setPos(_pos2d(x,0))
        button.hide()
        return button
            
    def makeSelectButton(self, name):
        style=self.setup_data['style']["select"]
        button=self.makeStyleButton(style)        
        button['text']=name
        button.bind(DGG.B1PRESS, self.onButtonClick, [button, "selectItem('"+name+"')"])
        button.hide()
        return button
        
    def makeButton(self, name, config):
        style=self.setup_data['style'][config["style"]]
        button=self.makeStyleButton(style)        
        button['text']=name
        button.setPos(_pos2d(config["pos"][0], config["pos"][1]))
        if "select" in config:            
            self.select_labels[config["select"]]=self.makeLabel(name)
            current_value=self.cfg.getCfgValueAsString(config["select"])
            if current_value in self.select_names[config["select"]]:
                label_txt=self.select_names[config["select"]][current_value]            
            else:
                label_txt=current_value +"*"    
            button['text']=name+" "+label_txt
            button.bind(DGG.B1PRESS, self.onButtonClick, [button, "select('"+config["select"]+"')"])
            button.setPythonTag("name", name)
        elif "slide" in config:
            current_value=self.cfg.getCfgValueAsString(config["slide"])
            if current_value == "None":
                current_value=str(self.setup_data['slide'][config["slide"]]['default'])
                self.cfg[config["slide"]]=self.setup_data['slide'][config["slide"]]['default']
            button['text']+=current_value
            button.bind(DGG.B1PRESS, self.onButtonClick, [button, "slide('"+config["slide"]+"', '"+name+"', "+current_value+")"])    
        elif "key" in config:
            current_value=self.cfg.getCfgValueAsString(config["key"])
            if current_value == "None":
                current_value=str(self.setup_data['key'][config["key"]])
                self.cfg[config["key"]]=current_value
            button['text']+=current_value
            button.bind(DGG.B1PRESS, self.onButtonClick, [button, "key('"+config["key"]+"', '"+name+"', '"+current_value+"')"])            
        elif "func" in config:
            button.bind(DGG.B1PRESS, self.onButtonClick, [button,config["func"] ])
        return button    
            
    def makeStyleButton(self, config):
        align=self.getTextAlign(config["text_align"])
        if align in (TextNode.ACenter, TextNode.ABoxedCenter):
            text_offset=[
                    -config["size"][0]/2+config["text_offset"][0], 
                    config["size"][1]/2+config["text_offset"][1]
                    ]
        elif align in (TextNode.ALeft, TextNode.ABoxedLeft):
            text_offset=[
                    -config["size"][0]+config["text_offset"][0], 
                    config["size"][1]/2+config["text_offset"][1]
                    ]  
        else:
            text_offset=[
                    +config["text_offset"][0], 
                    config["size"][1]/2+config["text_offset"][1]
                    ]                      
        button=DirectFrame(frameSize=_rec2d(config["size"][0],config["size"][1]),
                           frameColor=(1,1,1, 1), 
                           frameTexture=path+config["img"],
                           text_font=self.getFont(config["font"],config["text_size"]),
                           text=" ",
                           text_scale=config["text_size"],                           
                           text_align=align,
                           text_pos=text_offset,
                           text_fg=config["text_color"],                           
                           state=DGG.NORMAL, 
                           parent=self.root)
        _resetPivot(button)
        button.setTransparency(TransparencyAttrib.MDual)
        return button                 
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

__author__ = 'ipetrash'

# SOURCE: https://github.com/danthedeckie/simpleeval#operators

# pip install simpleeval
from simpleeval import SimpleEval

import ast
import operator as op

expr = "((2 + 2 * 2) / 3) ** 10 - 24"

s = SimpleEval()
print(s.eval(expr))  # 1000.0

# Mad
s.operators[ast.Add] = op.mul
s.operators[ast.Sub] = op.add
s.operators[ast.Mult] = op.pow
s.operators[ast.Pow] = op.sub

print(s.eval(expr))  # 16.666666666666664
コード例 #22
0
 def test_no_operators(self):
     self.s.eval('1+2')
     with self.assertRaises(OperatorNotDefined):
         s = SimpleEval(operators={})
         s.eval('1+2')
コード例 #23
0
# If you want to allow creation of these, the EvalWithCompoundTypes class works. Just replace any use of
# SimpleEval with that.
# """

# pip install simpleeval
from simpleeval import simple_eval, SimpleEval, EvalWithCompoundTypes

# SimpleEval and simple_eval NOT WORK with compound types
try:
    print(simple_eval('[1, 2, 3, 4]'))
except Exception as e:
    print(e)  # Sorry, List is not available in this evaluator

try:
    my_eval = SimpleEval()
    print(my_eval.eval('[1, 2, 3, 4]'))
except Exception as e:
    print(e)  # Sorry, List is not available in this evaluator

print()

# Compound Types
my_compound_types_eval = EvalWithCompoundTypes()
my_compound_types_eval.functions['len'] = len

# list
print(my_compound_types_eval.eval('[1, 2, 3, 4]'))  # [1, 2, 3, 4]
print(my_compound_types_eval.eval('[1, 2] + [3, 4]'))  # [1, 2, 3, 4]
print(my_compound_types_eval.eval('len([1, 2, 3, 4])'))  # 4
print(my_compound_types_eval.eval('[1, 2, 1, 3, 4].count(1)'))  # 2
print(my_compound_types_eval.eval('list("1234")'))  # ['1', '2', '3', '4']
コード例 #24
0
class Launcher(DirectObject):
    def __init__(self, app, setup_data, custom_functions={}):
        #we keep the 'main' application class to call some functions there
        self.app = app
        #load the config
        self.setup_data = setup_data
        self.cfg = Configer(path + self.setup_data['basic']['config_file'])

        #setup the window for the launcher
        wp = WindowProperties.getDefault()
        wp.setFixedSize(True)
        wp.setFullscreen(False)
        wp.setUndecorated(self.setup_data['basic']['undecorated'])
        wp.setOrigin(-2, -2)
        wp.setTitle(self.setup_data['basic']['title'])
        wp.setSize(self.setup_data['basic']['window_size'][0],
                   self.setup_data['basic']['window_size'][1])
        base.openMainWindow(props=wp)
        base.win.setCloseRequestEvent('exit_program')

        #a root node for ell the widgets
        self.root = pixel2d.attachNewNode('launcher_root')

        #set the bacground image
        self.background = DirectFrame(
            frameSize=_rec2d(self.setup_data['basic']['window_size'][0],
                             self.setup_data['basic']['window_size'][1]),
            frameColor=(1, 1, 1, 1),
            frameTexture=path + self.setup_data['basic']['background'],
            parent=self.root)
        _resetPivot(self.background)
        self.background.setPos(_pos2d(0, 0))

        #some vars used later
        self.last_click_time = 0.0
        self.shouldExit = False
        self.last_button = None
        self.last_select_button = None
        self.last_select = None
        self.last_button_group = 0
        self.fonts = {}
        self.buttons = []
        self.last_slider_config_name = None
        self.last_slider_name = None
        #make the needed buttons
        #needed for the updater part...
        self.update_label = self.makeLabel("", 'wait')
        x = self.setup_data['basic']["window_size"][0] / 2
        x -= self.setup_data['style']['default']["size"][0] / 2
        y = self.setup_data['basic']["window_size"][
            1] - self.setup_data['style']['default']["size"][1] * 1.5
        pos = [x, y]
        self.update_done_button = self.makeButton(
            self.setup_data['basic']['msg']['ok'], {
                "style": "default",
                "pos": pos,
                "func": "updateDone()"
            })
        self.update_done_button.hide()
        #needed for the loadscreen
        self.loading_label = self.makeLabel(
            self.setup_data['basic']['msg']['loading'], 'loading')
        #needed for the slider screen
        self.slider = DirectSlider(
            frameSize=_rec2d(
                self.setup_data['style']['slider']["size"][0] * 0.8,
                self.setup_data['style']['slider']["size"][1]),
            range=(0.0, 1.0),
            value=0.5,
            thumb_relief=DGG.FLAT,
            thumb_frameTexture=path +
            self.setup_data['style']['slider']['thumb_img'],
            thumb_frameSize=(
                self.setup_data['style']['slider']['thumb_size'][0] / 2,
                -self.setup_data['style']['slider']['thumb_size'][0] / 2,
                -self.setup_data['style']['slider']['thumb_size'][1] / 2,
                self.setup_data['style']['slider']['thumb_size'][1] / 2),
            frameTexture=path + self.setup_data['style']['slider']['img'],
            frameVisibleScale=(1.25, 1),
            command=self.setSliderValue,
            parent=self.root)
        x = self.setup_data['basic']["window_size"][0] / 2
        x += (self.setup_data['style']['slider']["size"][0] * 0.8) / 2
        y = self.setup_data['basic']["window_size"][1] / 2
        y += self.setup_data['style']['slider']["size"][1] / 2
        self.slider.setPos(_pos2d(x, y))
        self.slider.setTransparency(TransparencyAttrib.MDual)
        self.slider.hide()
        self.slider_done_button = self.makeButton(
            self.setup_data['basic']['msg']['ok'], {
                "style": "default",
                "pos": pos,
                "func": "sliderDone()"
            })
        self.slider_done_button.hide()
        self.slider_label = self.makeLabel("")
        #needed for key input
        self.key_input_label = self.makeLabel("")
        self.key_input_current_label = self.makeLabel("", "key_input")
        self.key_input_done = self.makeButton(
            self.setup_data['basic']['msg']['ok'], {
                "style": "default",
                "pos": pos,
                "func": "keyInputDone()"
            })
        self.key_input_done.hide()
        #the rest
        self.select_screens = {}
        self.select_names = {}
        self.select_labels = {}
        for select_group in self.setup_data["select"]:
            self.select_screens[select_group] = []
            self.select_names[select_group] = {}
            for label in self.setup_data["select"][select_group]:
                self.select_names[select_group][self.setup_data["select"]
                                                [select_group][label]] = label
                self.select_screens[select_group].append(
                    self.makeSelectButton(label))
            self.packSelectButtons(self.select_screens[select_group])
        i = 0
        for button_group in self.setup_data["buttons"]:
            self.buttons.append({})
            for button_name in button_group:
                self.buttons[i][button_name] = self.makeButton(
                    button_name, button_group[button_name])
                if i != 0:
                    self.buttons[i][button_name].hide()
            i += 1
        #SimpleEval stuff
        names = {'None': None}
        functions = {
            'Vec3': Vec3,
            'startGame': self.startGame,
            'exitGame': self.exitGame,
            'updateGame': self.updateGame,
            'updateDone': self.updateDone,
            'toggleButtonGroup': self.toggleButtonGroup,
            'showButton': self.showButton,
            'select': self.showSelectScreen,
            'slide': self.showSlideScreen,
            'key': self.showKeyInputScreen,
            'keyInputDone': self.keyInputDone,
            'sliderDone': self.sliderDone,
            'selectItem': self.selectItem,
            'saveConfig': self.saveConfig
        }
        for key in custom_functions:
            functions[key] = custom_functions[key]
        self.simple_eval = SimpleEval(names=names, functions=functions)

        #events
        self.accept('exit_program', self.exitGame)
        base.buttonThrowers[0].node().setButtonDownEvent('buttonDown')
        self.accept('buttonDown', self.getKey)

        #tasks
        taskMgr.add(self.update, 'launcher_update')

    def disable(self):
        #destroy all buttons
        for button_group in self.buttons:
            for button_name in button_group:
                button_group[button_name].destroy()
        for button_group in self.select_screens:
            for button in self.select_screens[button_group]:
                button.destroy()
        for label in self.select_labels:
            self.select_labels[label].destroy()
        self.key_input_label.destroy()
        self.key_input_current_label.destroy()
        self.key_input_done.destroy()
        self.update_done_button.destroy()
        self.loading_label.destroy()
        self.update_label.destroy()
        self.background.destroy()

        #ignore all events
        self.ignoreAll()
        #remove task
        taskMgr.remove('launcher_update')
        #remove root node
        self.root.removeNode()
        #clear data
        del self.select_names
        del self.setup_data
        del self.last_click_time
        del self.shouldExit
        del self.last_button
        del self.last_select_button
        del self.last_select
        del self.last_button_group
        del self.fonts
        del self.buttons
        del self.last_slider_config_name
        del self.last_slider_name

    def getKey(self, keyname):
        self.last_key = keyname
        self.key_input_current_label['text'] = keyname

    def renderSomeFrames(self, frames=1):
        for i in range(frames):
            base.graphicsEngine.renderFrame()

    def startGame(self):
        self.toggleButtonGroup(-1)
        self.loading_label.show()
        #print "starting game"
        self.app.startGame()

    def hide(self):
        self.root.hide()

    def updateDone(self):
        self.toggleButtonGroup(0)
        self.update_done_button.hide()
        self.update_label['text'] = ""
        self.update_label.hide()

    def updateGame(self, wait_txt):
        url = self.setup_data['basic']['update_url']
        self.downloadUpdates(url)
        self.toggleButtonGroup(-1)
        self.update_label.show()
        self.update_label['text']

    def downloadUpdates(self, url):
        self.files_to_download = []

        self.http = HTTPClient()
        self.channel = self.http.makeChannel(True)

        self.files_to_download.append({
            'url': url,
            'target': path + 'update.json'
        })
        self.channel.beginGetDocument(DocumentSpec(url))
        self.channel.downloadToFile(Filename(path + 'update.json'))
        self.update_label['text'] += self.setup_data['basic']['msg']['collect']

        #add a task that will do the lifting
        taskMgr.add(self.downloadTask, 'downloadTask')

    def downloadTask(self, task):
        if self.files_to_download:
            if self.channel.run():
                #print 'running...'
                return task.cont
            else:
                if not self.channel.isDownloadComplete():
                    #print "Error downloading file."
                    self.update_label['text'] += self.setup_data['basic'][
                        'msg']['download_error']
                    self.update_label['text'] += "\n" + str(
                        self.channel.getStatusString())
                else:
                    #if the downloaded file is named 'update.json'
                    #we get the files and urls there and add them to
                    #the download quene
                    last_file = self.files_to_download[0]['target']
                    #print "downloaded", last_file
                    self.update_label['text'] += self.setup_data['basic'][
                        'msg']['download_ok'] + last_file
                    self.renderSomeFrames(8)
                    if last_file == path + 'update.json':
                        with open(path + 'update.json') as f:
                            try:
                                file_list = json.load(f)
                                #print "loaded json file"
                            except:
                                #print "Error reading file"
                                self.update_label['text'] += self.setup_data[
                                    'basic']['msg']['read_error']
                        #we only download files on the list that we don't have (by name)
                        for f in file_list:
                            #print f
                            if not os.path.exists(path + f['target']):
                                self.files_to_download.append({
                                    'url':
                                    f['url'],
                                    'target':
                                    path + f['target']
                                })
                    #if it's a zipfile we extract
                    elif is_zipfile(last_file):
                        #print "extracting"
                        self.update_label['text'] += self.setup_data['basic'][
                            'msg']['unzip']
                        self.renderSomeFrames(8)
                        with ZipFile(last_file) as zf:
                            zf.extractall(Filename(path).toOsSpecific())
                        #remove zero sized files
                        self.update_label['text'] += self.setup_data['basic'][
                            'msg']['clean_up']
                        self.renderSomeFrames(8)
                        for dirpath, dirs, files in os.walk(path):
                            for file in files:
                                full_path = Filename(
                                    os.path.join(dirpath,
                                                 file)).toOsSpecific()
                                #print full_path
                                if os.stat(full_path).st_size == 0:
                                    os.remove(full_path)
                    else:
                        self.update_label['text'] += path + last_file
                        self.update_label['text'] += "\n - not a zip file!"
                    #remove the last file from the list and get a next one
                    self.files_to_download.pop(0)
                    if self.files_to_download:
                        next_file = self.files_to_download[0]
                        #print "next_file", next_file
                        self.channel.beginGetDocument(
                            DocumentSpec(next_file['url']))
                        self.channel.downloadToFile(
                            Filename(next_file['target']))
                        return task.cont
        #print "done"
        self.update_label['text'] += self.setup_data['basic']['msg']['done']
        self.update_done_button.show()
        return task.done

    def update(self, task):
        #calling exit from a sequence will crash the game
        if self.shouldExit:
            self.app.exit()
        return task.cont

    def exe(self, command):
        if command:
            command = command.split(";")
            for cmd in command:
                try:
                    #print cmd
                    self.simple_eval.eval(cmd.strip())
                except Exception as e:
                    print e

    def runClickAnim(self, button):
        old_pos = button.getPos()
        new_pos = old_pos + _pos2d(0, 3)
        Sequence(LerpPosInterval(button, 0.05, new_pos),
                 LerpPosInterval(button, 0.05, old_pos)).start()

    def onButtonClick(self, button, func, event=None):
        time = globalClock.getFrameTime()
        if (time - self.last_click_time) > 0.11:
            self.last_button = button
            self.runClickAnim(button)
            Sequence(Wait(0.1), Func(self.exe, func)).start()
        self.last_click_time = time

    def doNothing(self, arg=None):
        print "nop"

    def saveConfig(self):
        self.toggleButtonGroup(0)
        config_file = path + self.setup_data['basic']['config_file']
        self.cfg.saveConfig(config_file)

    def exitGame(self):
        #self.app.exit()
        self.shouldExit = True

    def showButton(self, group, button_name):
        self.buttons[group][button_name].show()

    def selectItem(self, button_name):
        #set the new value in the cfg
        self.cfg.setCfgValueFromString(
            self.last_select,
            self.setup_data['select'][self.last_select][button_name])
        #print self.cfg[self.last_select]
        #update the button
        self.last_select_button['text'] = self.last_select_button.getPythonTag(
            "name") + " " + button_name
        #hide the select screen
        self.hideSelectScreen()
        #show the last group
        self.toggleButtonGroup(self.last_button_group)

    def setSliderValue(self):
        if self.last_slider_config_name:
            round_to = self.setup_data['slide'][
                self.last_slider_config_name]["round"]
            mini = self.setup_data['slide'][
                self.last_slider_config_name]["min"]
            maxi = self.setup_data['slide'][
                self.last_slider_config_name]["max"]
            self.slider_value = mini + self.slider['value'] * (maxi - mini)
            if round_to == 0:
                self.slider_value = int(self.slider_value)
            else:
                self.slider_value = round(self.slider_value, round_to)
            self.slider_label['text'] = self.last_slider_name + '\n' + str(
                self.slider_value)

    def sliderDone(self):
        self.toggleButtonGroup(self.last_button_group)
        self.slider_label.hide()
        self.slider.hide()
        self.slider_done_button.hide()
        self.buttons[self.last_button_group][
            self.last_slider_name]['text'] = self.last_slider_name + str(
                self.slider_value)
        self.cfg[self.last_slider_config_name] = self.slider_value
        cmd = "slide('" + self.last_slider_config_name + "', '" + self.last_slider_name + "', " + str(
            self.slider_value) + ")"
        self.buttons[self.last_button_group][self.last_slider_name].bind(
            DGG.B1PRESS, self.onButtonClick,
            [self.buttons[self.last_button_group][self.last_slider_name], cmd])

    def showSlideScreen(self, config_name, name, value):
        self.last_slider_config_name = config_name
        self.last_slider_name = name
        for button_group in self.buttons:
            for button_name in button_group:
                button_group[button_name].hide()
        self.slider_label.show()
        self.slider_label['text'] = name
        self.slider.show()
        self.slider_done_button.show()

        mini = self.setup_data['slide'][self.last_slider_config_name]["min"]
        maxi = self.setup_data['slide'][self.last_slider_config_name]["max"]

        self.slider['value'] = float(value) / float(maxi - mini)

        self.setSliderValue()

    def showSelectScreen(self, screen):
        self.last_select = screen
        self.last_select_button = self.last_button
        for button_group in self.buttons:
            for button_name in button_group:
                button_group[button_name].hide()
        for button in self.select_screens[screen]:
            button.show()
        for label in self.select_labels:
            if label == screen:
                self.select_labels[label].show()
            else:
                self.select_labels[label].hide()

    def keyInputDone(self):
        self.toggleButtonGroup(self.last_button_group)
        self.key_input_label.hide()
        self.key_input_current_label.hide()
        self.key_input_done.hide()
        self.buttons[self.last_button_group][
            self.last_key_name]['text'] = self.last_key_name + self.last_key
        self.cfg[self.last_key_config_name] = self.last_key
        cmd = "key('" + self.last_key_config_name + "', '" + self.last_key_name + "', '" + self.last_key + "')"
        self.buttons[self.last_button_group][self.last_key_name].bind(
            DGG.B1PRESS, self.onButtonClick,
            [self.buttons[self.last_button_group][self.last_key_name], cmd])

    def showKeyInputScreen(self, config_name, name, value):
        self.last_key_config_name = config_name
        self.last_key_name = name
        for button_group in self.buttons:
            for button_name in button_group:
                button_group[button_name].hide()
        self.key_input_label.show()
        self.key_input_current_label.show()
        self.key_input_done.show()
        self.key_input_label['text'] = self.setup_data['basic']['msg'][
            'new_key'].format(name)
        self.key_input_current_label['text'] = value

    def hideSelectScreen(self):
        for screen in self.select_screens:
            for button in self.select_screens[screen]:
                button.hide()
        for label in self.select_labels:
            self.select_labels[label].hide()

    def toggleButtonGroup(self, group):
        self.last_button_group = group
        i = 0
        for button_group in self.buttons:
            for button_name in button_group:
                if i == group:
                    button_group[button_name].show()
                else:
                    button_group[button_name].hide()
            i += 1

    def getFont(self, font_name, font_size):
        if font_name in self.fonts:
            if font_size in self.fonts[font_name]:
                font = self.fonts[font_name][font_size]
            else:
                font = self.addFontSize(font_name, font_size)
        else:
            font = self.addFont(font_name, font_size)
        return font

    def addFont(self, font_name, font_size):
        font = loader.loadFont(path + font_name)
        font.setPixelsPerUnit(font_size)
        font.setMinfilter(Texture.FTNearest)
        font.setMagfilter(Texture.FTNearest)
        self.fonts[font_name] = {font_size: font}
        return font

    def addFontSize(self, font_name, font_size):
        #a bit of a hack to get a font of any size
        font = self.fonts[font_name].itervalues().next()
        new_font = font.makeCopy()
        new_font.setPixelsPerUnit(font_size)
        self.fonts[font_name][font_size] = new_font
        return new_font

    def getTextAlign(self, align):
        a = align.strip().lower()
        if a == 'center':
            return TextNode.ACenter
        elif a == 'left':
            return TextNode.ALeft
        elif a == 'right':
            return TextNode.ARight
        elif a == 'boxed_left':
            return TextNode.ABoxedLeft
        elif a == 'boxed_right':
            return TextNode.ABoxedRight
        elif a == 'boxed_center':
            return TextNode.ABoxedCenter
        else:
            return TextNode.ALeft

    def packSelectButtons(self, button_list):
        label_y = self.setup_data['style']["label"]["size"][1]
        x_offset = 0
        y_offset = 0
        button_x = self.setup_data['style']["select"]["size"][0]
        button_y = self.setup_data['style']["select"]["size"][1]
        window_x = self.setup_data['basic']["window_size"][0]
        window_y = self.setup_data['basic']["window_size"][1] + label_y
        button_count = len(button_list)
        last_row_x_offset = 0
        #how many buttons can I fit side by side?
        buttons_per_row = window_x / button_x
        #how much space is left unused?
        x_offset = (window_x % button_x) / 2
        #can all the buttons fit in one row?
        if button_count <= buttons_per_row:
            y_offset = window_y / 2 - button_y / 2
            row_count = 1
            x_offset += (window_x - (button_count * button_x)) / 2
        else:
            row_count = button_count / buttons_per_row
            if button_count % buttons_per_row != 0:
                row_count += 1
            y_offset = (window_y - ((row_count) * button_y)) / 2
        if y_offset < 0 or x_offset < 0:
            print "(warning) Select buttons can't fit the window"
        #is the last row full?
        if row_count > 1 and buttons_per_row * row_count > button_count:
            last_row_x_offset = (buttons_per_row * row_count -
                                 button_count) * button_x / 2
        #start packing the buttons
        i = 0
        row = -1
        for button in button_list:
            column = i % buttons_per_row
            if column == 0:
                row += 1
            x = x_offset + button_x * column
            y = y_offset + button_y * row
            if row == row_count - 1:  #this is the last row
                x += last_row_x_offset
            button.setPos(_pos2d(x, y))
            i += 1

    def makeLabel(self, name, style_name="label"):
        style = self.setup_data['style'][style_name]
        button = self.makeStyleButton(style)
        button['state'] = DGG.DISABLED
        button['text'] = name
        x = self.setup_data['basic']["window_size"][0] / 2
        x -= style["size"][0] / 2
        button.setPos(_pos2d(x, 0))
        button.hide()
        return button

    def makeSelectButton(self, name):
        style = self.setup_data['style']["select"]
        button = self.makeStyleButton(style)
        button['text'] = name
        button.bind(DGG.B1PRESS, self.onButtonClick,
                    [button, "selectItem('" + name + "')"])
        button.hide()
        return button

    def makeButton(self, name, config):
        style = self.setup_data['style'][config["style"]]
        button = self.makeStyleButton(style)
        button['text'] = name
        button.setPos(_pos2d(config["pos"][0], config["pos"][1]))
        if "select" in config:
            self.select_labels[config["select"]] = self.makeLabel(name)
            current_value = self.cfg.getCfgValueAsString(config["select"])
            if current_value in self.select_names[config["select"]]:
                label_txt = self.select_names[config["select"]][current_value]
            else:
                label_txt = current_value + "*"
            button['text'] = name + " " + label_txt
            button.bind(DGG.B1PRESS, self.onButtonClick,
                        [button, "select('" + config["select"] + "')"])
            button.setPythonTag("name", name)
        elif "slide" in config:
            current_value = self.cfg.getCfgValueAsString(config["slide"])
            if current_value == "None":
                current_value = str(
                    self.setup_data['slide'][config["slide"]]['default'])
                self.cfg[config["slide"]] = self.setup_data['slide'][
                    config["slide"]]['default']
            button['text'] += current_value
            button.bind(DGG.B1PRESS, self.onButtonClick, [
                button, "slide('" + config["slide"] + "', '" + name + "', " +
                current_value + ")"
            ])
        elif "key" in config:
            current_value = self.cfg.getCfgValueAsString(config["key"])
            if current_value == "None":
                current_value = str(self.setup_data['key'][config["key"]])
                self.cfg[config["key"]] = current_value
            button['text'] += current_value
            button.bind(DGG.B1PRESS, self.onButtonClick, [
                button, "key('" + config["key"] + "', '" + name + "', '" +
                current_value + "')"
            ])
        elif "func" in config:
            button.bind(DGG.B1PRESS, self.onButtonClick,
                        [button, config["func"]])
        return button

    def makeStyleButton(self, config):
        align = self.getTextAlign(config["text_align"])
        if align in (TextNode.ACenter, TextNode.ABoxedCenter):
            text_offset = [
                -config["size"][0] / 2 + config["text_offset"][0],
                config["size"][1] / 2 + config["text_offset"][1]
            ]
        elif align in (TextNode.ALeft, TextNode.ABoxedLeft):
            text_offset = [
                -config["size"][0] + config["text_offset"][0],
                config["size"][1] / 2 + config["text_offset"][1]
            ]
        else:
            text_offset = [
                +config["text_offset"][0],
                config["size"][1] / 2 + config["text_offset"][1]
            ]
        button = DirectFrame(frameSize=_rec2d(config["size"][0],
                                              config["size"][1]),
                             frameColor=(1, 1, 1, 1),
                             frameTexture=path + config["img"],
                             text_font=self.getFont(config["font"],
                                                    config["text_size"]),
                             text=" ",
                             text_scale=config["text_size"],
                             text_align=align,
                             text_pos=text_offset,
                             text_fg=config["text_color"],
                             state=DGG.NORMAL,
                             parent=self.root)
        _resetPivot(button)
        button.setTransparency(TransparencyAttrib.MDual)
        return button
コード例 #25
0
print(
    simple_eval("abs(sin(3) * cos(3))",
                functions={
                    'sin': math.sin,
                    'cos': math.cos,
                    'abs': abs
                }))  # 0.13970774909946293


def my_md5(value):
    import hashlib
    return hashlib.md5(bytes(value, 'utf-8')).hexdigest()


print(simple_eval("md5('Hello World!')",
                  functions={'md5':
                             my_md5}))  # ed076287532e86365e841e92bfc50d8c
print(simple_eval("list('1234')", functions={'list':
                                             list}))  # ['1', '2', '3', '4']
print()

# Using SimpleEval class
from simpleeval import SimpleEval

my_eval = SimpleEval()
my_eval.names['a'] = 2
my_eval.functions['square'] = lambda x: x * x

print(my_eval.eval('1 + 1 * a'))  # 3
print(my_eval.eval('square(1 + 1 * a)'))  # 9
import ast
import operator as op

SUPPORTED_OPERATORS = {
    ast.Add: op.add,
    ast.Sub: op.sub,
}

print(simple_eval("2 + 2 - 1", operators=SUPPORTED_OPERATORS))  # 3

try:
    print(simple_eval(
        "2 + 2 * 2",
        operators=SUPPORTED_OPERATORS))  # KeyError: <class '_ast.Mult'>
except Exception as e:
    print(repr(e))

print()

s = SimpleEval(operators=SUPPORTED_OPERATORS)
# # OR:
# s = SimpleEval()
# s.operators = SUPPORTED_OPERATORS

print(s.eval("2 + 2 - 1"))  # 3

try:
    print(s.eval("2 + 2 * 2"))  # KeyError: <class '_ast.Mult'>
except Exception as e:
    print(repr(e))
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

__author__ = 'ipetrash'

# pip install simpleeval
from simpleeval import SimpleEval

my_functions = {
    'dict': dict,
    'list': list,
    'set': set,
    'tuple': tuple,
    'str': str,
    'sorted': sorted,
}

my_eval = SimpleEval(functions=my_functions)

print(my_eval.eval('dict(a="1", b=2)["a"]'))  # "1"
print(my_eval.eval('list("123")[0]'))  # "1"
print(my_eval.eval('sorted(set("12213"))[0]'))  # "1"
print(my_eval.eval('tuple("123")[0]'))  # "1"
print(my_eval.eval('str(123)[0]'))  # "1"
print(my_eval.eval('sorted("43198")[0]'))  # "1"
print()

print(my_eval.eval('"1234567890"[:3]'))  # 123
print(my_eval.eval('list("1234567890")[:3]'))  # ['1', '2', '3']
print(my_eval.eval('"+".join(list("1234567890")[:3])'))  # 1+2+3
コード例 #28
0
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

__author__ = 'ipetrash'


# pip install simpleeval
from simpleeval import simple_eval


my_functions = {
    'my_pos': lambda: {
        'x': 12,
        'y': 10
    },
    'map': map,
    'str': str,
}

print(simple_eval('my_pos()["x"] * my_pos()["y"]', functions=my_functions))          # 120
print(simple_eval('"x".join(map(str, my_pos().values()))', functions=my_functions))  # 12x10
print()

# OR:
from simpleeval import SimpleEval
my_eval = SimpleEval(functions=my_functions)

print(my_eval.eval('my_pos()["x"] * my_pos()["y"]'))          # 120
print(my_eval.eval('"x".join(map(str, my_pos().values()))'))  # 12x10
コード例 #29
0
 def test_no_functions(self):
     self.s.eval('int(42)')
     with self.assertRaises(FunctionNotDefined):
         s = SimpleEval(functions={})
         s.eval('int(42)')
コード例 #30
0
class Reminder(object):
    """
    Base Reminder object to handle watch and notification for a single reminder.
    """
    watcher_type_map = {'http': HTTPWatcher, 'mqtt': MQTTWatcher}
    alerter_type_map = {'log': LogAlerter}

    def __init__(self, condition, daemon=None, watcher=None, alerter=None):
        """
        Create Reminder object.

        :param str condition:
            An expression to indicate that an alert should be sent.
            Should evaluate to True or False only.
        :param ReminderDaemon daemon:
            A ReminderDaemon instance where jobs will be scheduled.
        :param Watcher watcher:
            A Watcher instance to handle resource monitoring.
        :param Alerter alerter:
            An Alerter instance to handle sending notifications for Reminder.
        """
        self._logger = logging.getLogger(__name__)
        self._daemon = daemon
        try:
            self._logger.setLevel(self._daemon.logger.level)
        except AttributeError:
            pass
        self.jobs = []
        self.job_ids = []
        self.condition = condition
        if watcher:
            self._logger.debug('creating watcher from: %s', watcher)
            watcher['reminder'] = self
            WatcherClass = getattr(
                importlib.import_module('reminders.watchers'),
                watcher.get('type'))
            self.watcher = WatcherClass(**watcher)
            jobs = self.watcher.schedules
            for job in jobs:
                job['func'] = self.check
                self._logger.debug('added job to jobs: %s', job)
                self.jobs.append(job)
        if alerter:
            self._logger.debug('creating alerter from: %s', alerter)
            alerter['reminder'] = self
            AlerterClass = getattr(
                importlib.import_module('reminders.alerters'),
                alerter.get('type'))
            self.alerter = AlerterClass(**alerter)
        self.simple_eval = SimpleEval()
        self.simple_eval.names.update({
            'status': self.status,
            'now': self.now,
        })
        self.simple_eval.functions = {
            'pendulum': pendulum,
            'date': pendulum.instance
        }

    @property
    def now(self):
        """Shortcut for expression evaluation against current time"""
        return pendulum.now()

    @property
    def status(self):
        if self.watcher:
            try:
                d = dateparse(self.watcher.update(),
                              settings={'STRICT_PARSING': True})
                if d:
                    return d
                else:
                    return self.watcher.update()
            except TypeError:
                return None
        else:
            self._logger.error('No watcher associated', exc_info=True)
            return None

    def test_condition(self):
        """
        .. deprecated:: 0.1
           Use :func:`eval` instead.
        """
        results = {}
        condition = self.condition.replace('$status', self.watcher.update())
        prefix, comparator, postfix = re.split(r'\s([<>(<=)(>=)(==)(!=)])\s',
                                               condition)
        prefix = "pendulum.instance(dateparse('{}'))".format(
            prefix) if dateparse(prefix, settings={
                'STRICT_PARSING': True
            }) else "'{}'".format(prefix) if (
                isinstance(prefix, str) and not prefix.isnumeric()) else prefix
        postfix = "pendulum.instance(dateparse('{}'))".format(
            postfix) if dateparse(postfix, settings={
                'STRICT_PARSING': True
            }) else "'{}'".format(postfix) if (isinstance(
                postfix, str) and not postfix.isnumeric()) else postfix
        expression = "results['content'] = {} {} {}".format(
            prefix, comparator, postfix)
        exec(expression)
        return results['content']

    def eval(self):
        """
        Evaluate self.expression

        :returns:   True if alert should be started
        :rtype:     bool
        """
        try:
            return self.simple_eval.eval(self.condition)
        except TypeError:
            self._logger.error('Error evaluating expression.', exc_info=True)
            return None

    def check(self):
        """Runs self.test_condition() and sends Alert if True."""
        if self.eval() and self.alerter:
            self._logger.debug('activating alert')
            self.alerter.activate()
        else:
            self._logger.debug('checked successfully - no alert necessary')

    def activate(self):
        """TBD - May be unnecessary at this level."""
        raise NotImplementedError("activate() hasn't been implemented yet")

    def deactivate(self):
        """TBD - May be unnecessary at this level."""
        raise NotImplementedError("deactivate() hasn't been implemented yet")
コード例 #31
0
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

__author__ = 'ipetrash'

# SOURCE: https://github.com/danthedeckie/simpleeval/blob/master/README.rst#creating-an-evaluator-class

# pip install simpleeval
from simpleeval import SimpleEval

# Evaluator class
my_eval = SimpleEval()
print(my_eval.eval("1 + 1"))  # 2
print(my_eval.eval('100 * 10'))  # 1000


# Append functions
def boo():
    return 'Boo!'


my_eval.functions["boo"] = boo

# Set names
my_eval.names['fortytwo'] = 42
print(my_eval.eval('fortytwo * 4'))  # 168
print()


# this actually means you can modify names (or functions) with functions, if you really feel so inclined:
def set_val(name, value):