diff --git a/ContextSaver.py b/ContextSaver.py new file mode 100644 index 0000000000000000000000000000000000000000..24b3e497f5569675c66433a75abc628b31e0c4ed --- /dev/null +++ b/ContextSaver.py @@ -0,0 +1,197 @@ +#!/usr/Local/pyroot/PyTangoRoot/bin/python +""" +Python module for scanning and saving configuration of devices. + +Includes a Command Line Interface. +Can be imported as is to use function in user script. +""" +import PyTango as tango +import logging +import argparse +import json + +__version__ = "1.0.0" + +##---------------------------------------------------------------------------## +def get_wattr(proxy): + """ + Get all writable attributes from a device and save their values in a python dict. + + Parameters + ---------- + proxy : PyTango.DeviceProxy + Proxy to the device. + + Returns + ------- + config : dict + Dictionnary, keys are attribute names and value their present values. + """ + logger.debug("Scanning write attribute of device %s"%proxy.name()) + config = dict() + + # Scan all attributes + for attr in proxy.get_attribute_list(): + if proxy.get_attribute_config(attr).writable in [ + tango.AttrWriteType.WRITE, + tango.AttrWriteType.READ_WRITE, + tango.AttrWriteType.READ_WITH_WRITE]: + config[attr]=proxy[attr].value + + logger.debug("Detect writtable attribute %s = %s"%( + attr, + proxy[attr].value)) + + return config + + +##---------------------------------------------------------------------------## +def get_properties(proxy): + """ + Get all properties from a device and save them in a python dict. + + Parameters + ---------- + proxy : PyTango.DeviceProxy + Proxy to the device. + + Returns + ------- + config : dict + Dictionnary, keys are attribute names and value their present values. + """ + logger.debug("Scanning properties of device %s"%proxy.name()) + + pl = proxy.get_property_list('*') + + _props = proxy.get_property(pl) + + props=dict() + + # Here we simply convert tango arrays to python arrays. + # For properties, each prop is an array, one element in + # the array is a line for the property. + # Maybe we need to convert in one single string. + for k in _props.keys(): + if k[:2] !="__": + # Change type + props[k] = list(_props[k]) + logger.debug("Detect property %s = %s"%( + k, props[k])) + + + return props + + +########################################################################## +""" Command Line Interface """ +if __name__ == "__main__": + + # Name the logger after the filename + logger = logging.getLogger("ContextSaver") + + ####################################################### + # Install argument parser + import argparse + + parser = argparse.ArgumentParser(description="Copy attributes and properties to a JSON structure.\n"+ + "Version %s"%__version__) + + parser.add_argument("--fileout", type=str, + help="Save the JSON structure to the specified file. Implicit set no output to stdout."), + + parser.add_argument('--log', type=str, default="INFO", + help="Log level. Default: %(default)s.") + + parser.add_argument('-v', action="store_true", + help="Print in stdout the context. Default is on if no fileout option specified.") + + parser.add_argument('--filemode', action="store_true", + help="Set devices to filemode."+ + " Instead of specifying devices, put a path to a file containing a list of devices."+ + " The file contains one device path per line.") + + parser.add_argument('devices', type=str, nargs='+', + help="List of devices to inspect. Full tango path.") + + args = parser.parse_args() + + + ####################################################### + # Configure logger + + # Add a stream handler + s_handler = logging.StreamHandler() + s_handler.setFormatter(logging.Formatter("%(levelname)s\t[%(funcName)s] \t%(message)s")) + + # Set level according to command line attribute + s_handler.setLevel(level=getattr(logging, args.log.upper())) + logger.setLevel(level=getattr(logging, args.log.upper())) + logger.addHandler(s_handler) + + logger.debug("Parsed arguments: %s"%args) + + logger.info("Context Saver %s"%__version__) + + ####################################################### + # Filemode or not + if args.filemode: + logger.info("Filemode, openning file %s"%args.devices[0]) + # Read the file. Each line is an device + with open(args.devices[0], "r") as fp: + devices = fp.readlines() + + logger.debug("Read lines : %s"%devices) + + # Clean end of line + for i_a in range(len(devices)): + devices[i_a] = devices[i_a].rstrip() + + else: + devices = args.devices + + ####################################################### + # Prepare array for result + results = [] + + ####################################################### + # Scan all devices + + for dev in devices: + logger.info("Scanning device %s..."%dev) + + # Declare proxy + prx = tango.DeviceProxy(dev) + + # Retrieve write attributes + wattr = get_wattr(prx) + + # Retrieve properties + props = get_properties(prx) + + # Build json dict + jdict = { + "tangopath":dev, + "wattributes":wattr, + "properties":props, + } + + # Add to results + results.append(jdict) + + logger.info("Done") + + if args.fileout is None: + print(json.dumps(results, indent=4)) + else: + with open(args.fileout, "w") as fp: + json.dump(results, fp, indent=4) + + # Additionnal dump to stdout + if args.v: + print(json.dumps(results, indent=4)) + + +else: + # Name the logger after the module name + logger = logging.getLogger(__name__)