Beispiel #1
0
 def method_symbols(self):
     if self._methods is None:
         pstrings = self.process_strings
         items = pstrings.items() if pstrings is not None else ()
         # variable-method hybrids are handled by the self.variable property
         stored_fields = set(self.fields.names)
         methodnames = [k for k, v in items
                        if self.ismethod(v) and k not in stored_fields]
         # factorial(n) -> factorial
         methodnames = [split_signature(name)[0] if '(' in name else name
                        for name in methodnames]
         self._methods = [(name, MethodSymbol(name, self))
                          for name in methodnames]
     return self._methods
Beispiel #2
0
 def method_symbols(self):
     if self._methods is None:
         pstrings = self.process_strings
         items = pstrings.items() if pstrings is not None else ()
         # variable-method hybrids are handled by the self.variable property
         stored_fields = set(self.fields.names)
         methodnames = [
             k for k, v in items
             if self.ismethod(v) and k not in stored_fields
         ]
         # factorial(n) -> factorial
         methodnames = [
             split_signature(name)[0] if '(' in name else name
             for name in methodnames
         ]
         self._methods = [(name, MethodSymbol(name, self))
                          for name in methodnames]
     return self._methods
Beispiel #3
0
def make_np_class(baseclass, signature, dtypefunc):
    name, args = split_signature(signature)
    if isinstance(dtypefunc, type):
        dtypefunc = always(dtypefunc)
    evalfunc = getattr(np.random, name)

    # we need to explicitly set funcname, because the usual mechanism of
    # getting it from the class name during class creation (in the metaclass)
    # does not work because the class name is not set yet.
    class FuncClass(baseclass):
        np_func = evalfunc
        funcname = name
        argspec = argspec(args, **baseclass.kwonlyargs)
        if dtypefunc is not None:
            dtype = dtypefunc
    FuncClass.__name__ = name.capitalize()
    FuncClass.__doc__ = clean_docstring(evalfunc.__doc__)
    return FuncClass
Beispiel #4
0
    def parse_function(self, k, v, context):
        if isinstance(v, list):
            # v should be a list of dicts (assignments) or strings (actions)
            if "(" in k:
                k, args = split_signature(k)
                argnames = argspec(args).args
                code_def = v
            else:
                argnames, code_def = [], v
                template = """\
Function definitions should have parentheses after their name even if they have no argument.
Please change "{name}:" to "{name}():".
You probably want to use the "upgrade" command to automatically convert your model file to the new syntax."""
                warnings.warn(template.format(name=k), UserDeprecationWarning)
            method_context = self.get_group_context(context, argnames)
            code = self.parse_process_group(k + "_code",
                                            code_def,
                                            method_context,
                                            purge=False)
            # TODO: use code.predictors instead (but it currently
            # fails for some reason) or at least factor this out
            # with the code in parse_process_group
            group_expressions = [
                list(elem.items())[0] if isinstance(elem, dict) else
                (None, elem) for elem in code_def
            ]
            group_predictors = self.collect_predictors(group_expressions,
                                                       in_process_group=True)
            method_context = self.get_group_context(method_context,
                                                    group_predictors)
            return Function(k, self, argnames, code)
        elif isinstance(v, dict) and ('args' in v or 'code' in v
                                      or 'return' in v):
            args = v.get('args', '')
            code = v.get('code', '')
            result = v.get('return', '')
            oldargs = "\n      args: {}".format(args) \
                if args else ''
            oldcode = "\n      code:\n          - ..." \
                if code else ''
            newcode = "\n      - ..." if code else ''
            oldresult = "\n      return: " + result \
                if result else ''
            newresult = "\n      - return " + result \
                if result else ''
            template = """
This syntax for defining functions with arguments or a return value is not
supported anymore:
{funcname}:{oldargs}{oldcode}{oldresult}

Please use this instead:
{funcname}({newargs}):{newcode}{newresult}"""
            msg = template.format(funcname=k,
                                  oldargs=oldargs,
                                  oldcode=oldcode,
                                  oldresult=oldresult,
                                  newargs=args,
                                  newcode=newcode,
                                  newresult=newresult)
            raise SyntaxError(msg)
        elif isinstance(v, dict) and 'predictor' in v:
            raise ValueError("Using the 'predictor' keyword is "
                             "not supported anymore. "
                             "If you need several processes to "
                             "write to the same variable, you "
                             "should rather use functions.")
        elif isinstance(v, (basestring, bool, int, float)):
            if k in self.fields.names:
                msg = """defining a process outside of a function is deprecated because it is ambiguous. You should:
 * wrap the '{name}: {expr}' assignment inside a function like this:
        compute_{name}:  # you can name it any way you like but simply '{name}' is not recommended !
            - {name}: {expr}
 * update the simulation.processes list to use 'compute_{name}' (the function name) instead of '{name}'.
"""
            else:
                msg = """defining a process outside of a function is deprecated because it is ambiguous.
1) If '{name}: {expr}' is an assignment ('{name}' stores the result of '{expr}'), you should:
 * wrap the assignment inside a function, for example, like this:
        compute_{name}:  # you can name it any way you like but simply '{name}' is not recommended !
            - {name}: {expr}
 * update the simulation.processes list to use 'compute_{name}' (the function name) instead of '{name}'.
 * add '{name}' in the entities fields with 'output: False'
2) otherwise if '{expr}' is an expression which does not return any value, you can simply transform it into a function,
   like this:
        {name}:
            - {expr}
            """
            warnings.warn(msg.format(name=k, expr=v), UserDeprecationWarning)
            # TODO: it would be cleaner if the process was wrapped in a function
            return self.parse_expr(k, v, context)
        else:
            raise Exception("unknown expression type for %s: %s (%s)" %
                            (k, v, type(v)))
Beispiel #5
0
    def parse_function(self, k, v, context):
        if isinstance(v, list):
            # v should be a list of dicts (assignments) or strings (actions)
            if "(" in k:
                k, args = split_signature(k)
                argnames = argspec(args).args
                code_def = v
            else:
                argnames, code_def = [], v
                template = """\
Function definitions should have parentheses after their name even if they have no argument.
Please change "{name}:" to "{name}():". 
You probably want to use the "upgrade" command to automatically convert your model file to the new syntax."""
                warnings.warn(template.format(name=k), UserDeprecationWarning)
            method_context = self.get_group_context(context, argnames)
            code = self.parse_process_group(k + "_code", code_def,
                                            method_context,
                                            purge=False)
            # TODO: use code.predictors instead (but it currently
            # fails for some reason) or at least factor this out
            # with the code in parse_process_group
            group_expressions = [list(elem.items())[0] if isinstance(elem, dict) else (None, elem)
                                 for elem in code_def]
            group_predictors = self.collect_predictors(group_expressions, in_process_group=True)
            method_context = self.get_group_context(method_context, group_predictors)
            return Function(k, self, argnames, code)
        elif isinstance(v, dict) and ('args' in v or 'code' in v or 'return' in v):
            args = v.get('args', '')
            code = v.get('code', '')
            result = v.get('return', '')
            oldargs = "\n      args: {}".format(args) \
                if args else ''
            oldcode = "\n      code:\n          - ..." \
                if code else ''
            newcode = "\n      - ..." if code else ''
            oldresult = "\n      return: " + result \
                if result else ''
            newresult = "\n      - return " + result \
                if result else ''
            template = """
This syntax for defining functions with arguments or a return value is not
supported anymore:
{funcname}:{oldargs}{oldcode}{oldresult}

Please use this instead:
{funcname}({newargs}):{newcode}{newresult}"""
            msg = template.format(funcname=k, oldargs=oldargs,
                                  oldcode=oldcode,
                                  oldresult=oldresult,
                                  newargs=args, newcode=newcode,
                                  newresult=newresult)
            raise SyntaxError(msg)
        elif isinstance(v, dict) and 'predictor' in v:
            raise ValueError("Using the 'predictor' keyword is "
                             "not supported anymore. "
                             "If you need several processes to "
                             "write to the same variable, you "
                             "should rather use functions.")
        elif isinstance(v, (basestring, bool, int, float)):
            if k in self.fields.names:
                msg = """defining a process outside of a function is deprecated because it is ambiguous. You should:
 * wrap the '{name}: {expr}' assignment inside a function like this:
        compute_{name}:  # you can name it any way you like but simply '{name}' is not recommended !
            - {name}: {expr}
 * update the simulation.processes list to use 'compute_{name}' (the function name) instead of '{name}'.
"""
            else:
                msg = """defining a process outside of a function is deprecated because it is ambiguous.
1) If '{name}: {expr}' is an assignment ('{name}' stores the result of '{expr}'), you should:
 * wrap the assignment inside a function, for example, like this:
        compute_{name}:  # you can name it any way you like but simply '{name}' is not recommended !
            - {name}: {expr}
 * update the simulation.processes list to use 'compute_{name}' (the function name) instead of '{name}'.
 * add '{name}' in the entities fields with 'output: False'
2) otherwise if '{expr}' is an expression which does not return any value, you can simply transform it into a function,
   like this:
        {name}:
            - {expr}
            """
            warnings.warn(msg.format(name=k, expr=v),
                          UserDeprecationWarning)
            # TODO: it would be cleaner if the process was wrapped in a function
            return self.parse_expr(k, v, context)
        else:
            raise Exception("unknown expression type for %s: %s (%s)" % (k, v, type(v)))