Source code for sardana.macroserver.msmetamacro

#!/usr/bin/env python

##############################################################################
##
# This file is part of Sardana
##
# http://www.sardana-controls.org/
##
# Copyright 2011 CELLS / ALBA Synchrotron, Bellaterra, Spain
##
# Sardana is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
##
# Sardana is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Lesser General Public License for more details.
##
# You should have received a copy of the GNU Lesser General Public License
# along with Sardana.  If not, see <http://www.gnu.org/licenses/>.
##
##############################################################################

"""This module contains the class definition for the MacroServer meta macro
information"""

__all__ = ["MACRO_TEMPLATE", "MacroLibrary", "MacroClass", "MacroFunction"]

__docformat__ = 'restructuredtext'

import inspect
import operator

from sardana import InvalidId, ElementType
from sardana.sardanameta import SardanaLibrary, SardanaClass, SardanaFunction
from sardana.macroserver.msparameter import Type
import collections

MACRO_TEMPLATE = """class @macro_name@(Macro):
    \"\"\"@macro_name@ description.\"\"\"

    # uncomment the following lines as necessary. Otherwise you may delete them
    #param_def = []
    #result_def = []
    #hints = {}
    #env = (,)

    # uncomment the following lines if need prepare. Otherwise you may delete them
    #def prepare(self):
    #    pass

    def run(self):
        pass

"""

MACRO_TEMPLATE = """\
@macro()
def @macro_name@(self):
    self.output("Running @macro_name@...")

"""


[docs]class MacroLibrary(SardanaLibrary): """Object representing a python module containing macro classes and/or macro functions. Public members: - module - reference to python module - file_path - complete (absolute) path (with file name at the end) - file_name - file name (including file extension) - path - complete (absolute) path - name - (=module name) module name (without file extension) - macros - dict<str, MacroClass> - exc_info - exception information if an error occurred when loading the module""" def __init__(self, **kwargs): kwargs['manager'] = kwargs.pop('macro_server') kwargs['elem_type'] = ElementType.MacroLibrary SardanaLibrary.__init__(self, **kwargs)
[docs] def serialize(self, *args, **kwargs): kwargs = SardanaLibrary.serialize(self, *args, **kwargs) kwargs['macro_server'] = self.get_manager().name kwargs['id'] = InvalidId return kwargs
get_macro = SardanaLibrary.get_meta get_macros = SardanaLibrary.get_metas has_macro = SardanaLibrary.has_meta has_macros = SardanaLibrary.has_metas add_macro_class = SardanaLibrary.add_meta_class get_macro_class = SardanaLibrary.get_meta_class get_macro_classes = SardanaLibrary.get_meta_classes has_macro_class = SardanaLibrary.has_meta_class add_macro_function = SardanaLibrary.add_meta_function get_macro_function = SardanaLibrary.get_meta_function get_macro_functions = SardanaLibrary.get_meta_functions has_macro_function = SardanaLibrary.has_meta_function @property def macros(self): ret = {} ret.update(self.meta_classes) ret.update(self.meta_functions) return ret
[docs]class Parameterizable(object): """Helper class to handle parameter and result definition for a :class:`~sardana.macroserver.msmetamacro.MacroClass` or a :class:`~sardana.macroserver.msmetamacro.MacroFunction`""" def __init__(self): self._parameter = self.build_parameter() self._result = self.build_result() def get_parameter_definition(self): raise NotImplementedError def get_result_definition(self): raise NotImplementedError def get_hints_definition(self): raise NotImplementedError def get_parameter(self): return self._parameter def get_result(self): return self._result def build_parameter(self): try: built_param = self._build_parameter( self.get_parameter_definition()) except: raise Exception("Error in the parameters definition") return built_param def build_result(self): return self._build_parameter(self.get_result_definition()) def _build_parameter(self, param_def): '''Builds a list of parameters, each of them represented by a dictionary containing information: name, type, default_value, description, min and max values. In case of simple parameters, type is the parameter type. In case of repeat parameter, type is a list containing its definition. ''' ret = [] param_def = param_def or () for p in param_def: t = p[1] ret_p = {'min': None, 'max': None} if isinstance(t, collections.abc.Sequence) and not isinstance(t, str): ret_p = {'min': 1, 'max': None} if isinstance(t[-1], collections.abc.Mapping): ret_p.update(t[-1]) t = self._build_parameter(t[:-1]) else: t = self._build_parameter(t) ret_p['name'] = p[0] ret_p['type'] = t ret_p['default_value'] = p[2] ret_p['description'] = p[3] ret.append(ret_p) return ret def build_parameter_info(self, param_def=None): param_def = param_def or self.get_parameter_definition() info = [str(len(param_def))] for name, type_class, def_val, desc in param_def: repeat = isinstance(type_class, list) info.append(name) type_name = (repeat and 'ParamRepeat') or type_class info.append(type_name) info.append(desc) if repeat: rep = type_class opts = sep = '' for opt, val in list(rep.items()): opts += '%s%s=%s' % (sep, opt, val) sep = ', ' info.append(opts) info += self.get_parameter_info(rep.param_def) else: info.append(str(def_val)) return info def build_result_info(self, result_def=None): result_def = result_def or self.get_result_definition() info = [str(len(result_def))] for name, type_class, def_val, desc in result_def: repeat = isinstance(type_class, list) info.append(name) type_name = (repeat and 'ParamRepeat') or type_class info.append(type_name) info.append(desc) if repeat: rep = type_class opts = sep = '' for opt, val in list(rep.items()): opts += '%s%s=%s' % (sep, opt, val) sep = ', ' info.append(opts) info += self.get_parameter_info(rep.param_def) else: info.append(str(def_val)) return info def get_info(self): info = [self.full_name, self.description, str(self.code_object.hints)] info += self.get_parameter_info() info += self.get_result_info() return info def serialize(self, *args, **kwargs): kwargs['macro_server'] = self.get_manager().name kwargs['id'] = InvalidId kwargs['hints'] = self.code_object.hints param, result = self.get_parameter(), self.get_result() kwargs['parameters'] = param kwargs['result'] = result return kwargs
[docs]class MacroClass(SardanaClass, Parameterizable): def __init__(self, **kwargs): kwargs['manager'] = kwargs.pop('macro_server') kwargs['elem_type'] = ElementType.MacroClass SardanaClass.__init__(self, **kwargs) Parameterizable.__init__(self) def __lt__(self, o): return self.name < o.name
[docs] def serialize(self, *args, **kwargs): kwargs = SardanaClass.serialize(self, *args, **kwargs) kwargs = Parameterizable.serialize(self, *args, **kwargs) return kwargs
@property def macro_class(self): return self.klass def get_parameter_definition(self): return self.klass.param_def def get_result_definition(self): return self.klass.result_def def get_hints_definition(self): return self.klass.hints
[docs]class MacroFunction(SardanaFunction, Parameterizable): def __init__(self, **kwargs): kwargs['manager'] = kwargs.pop('macro_server') kwargs['elem_type'] = ElementType.MacroFunction SardanaFunction.__init__(self, **kwargs) Parameterizable.__init__(self) def __lt__(self, o): return self.name < o.name
[docs] def serialize(self, *args, **kwargs): kwargs = SardanaFunction.serialize(self, *args, **kwargs) kwargs = Parameterizable.serialize(self, *args, **kwargs) return kwargs
@property def macro_function(self): return self.function def to_parameter_definition(self): param_def = [] args, varargs, varkw, defaults, *_ = inspect.getfullargspec(self.function) assert varkw is None assert len(args) > 0 if varargs is None: for arg in args[1:]: param_def.append((arg, Type.Any, None, arg + " parameter")) i = len(param_def) - 1 if defaults is not None: for default in reversed(defaults): param_def[i][2] = default i -= 1 else: param_def.append( (varargs, [[varargs, Type.Any, None, varargs + " parameter"]], None, "list of " + varargs)) return param_def def get_parameter_definition(self): param_def = self.function.param_def if param_def is None: param_def = self.to_parameter_definition() return param_def def get_result_definition(self): result_def = self.function.result_def return result_def def get_hints_definition(self): return self.function.hints or ()