Commit 9f079ee0 authored by Matias Guijarro's avatar Matias Guijarro

fix issue #767: use map to retrieve axes in .get_axes_iter()

* Mapping, logtools refactoring: attach mapping to Session object
* Register motor controller in `controllers` category
* Register axes to their own category
* Register all Counter objects to 'counters'
* Added 'instance_iter' method to Map, to simplify specific objects lookup
* Added get_counters_iter() in utils
parent fcde1fcc
......@@ -7,11 +7,6 @@
"""Bliss main package
For your convenience, configuration motion and scan APIs have been made available
directly at this level.
Here are the main bliss sub-systems:
.. autosummary::
:toctree:
......@@ -40,5 +35,3 @@ monkey.patch_all(thread=False)
from redis import selector
selector._DEFAULT_SELECTOR = selector.SelectSelector
from bliss.common import logtools
......@@ -32,7 +32,7 @@ from ...common.greenlet_utils import KillMask, protect_from_kill
from bliss.comm.util import HexMsg
from bliss.common.tango import DeviceProxy
from bliss.common import mapping
from bliss.common import session
from bliss.common.logtools import LogMixin
__TMO_TUPLE = (
......@@ -137,7 +137,7 @@ class Prologix(LogMixin):
hostname = match.group(2)
port = match.group(3) and int(match.group(3)) or 1234
self._sock = Socket(hostname, port, timeout=keys.get("timeout"))
mapping.register(self, children_list=["comms", self._sock])
session.get_current().map.register(self, children_list=["comms", self._sock])
self._logger.debug(f"Prologix::__init__() host = {hostname} port = {port}")
self._gpib_kwargs = keys
......@@ -237,7 +237,7 @@ class TangoDeviceServer(LogMixin):
self._pad = keys["pad"]
self._sad = keys.get("sad", 0)
self._pad_sad = self._pad + (self._sad << 8)
mapping.register(self)
session.get_current().map.register(self)
def init(self):
self._logger.debug("TangoDeviceServer::init()")
......@@ -283,7 +283,7 @@ class LocalGpib(LogMixin):
raise LocalGpibError("LocalGpib: url is not valid (%s)" % url)
self._gpib_kwargs = keys
mapping.register(self, tag=str(self))
session.get_current().map.register(self, tag=str(self))
def __str__(self):
return "{0}(board={1})".format(type(self).__name__, self.board_index)
......@@ -373,7 +373,7 @@ class Gpib(LogMixin):
self._raw_handler = None
self._data = b""
mapping.register(self, tag=str(self))
session.get_current().map.register(self, tag=str(self))
def __str__(self):
opts = self._gpib_kwargs
......
......@@ -35,7 +35,7 @@
import socket, sys
from struct import *
from bliss.common import mapping
from bliss.common import session
from bliss.common.logtools import LogMixin
# debug = ["io", "ignore_not_impl"] # "dummy_io", "rw"
......@@ -75,12 +75,12 @@ class EnetSocket(LogMixin):
self.sta = self.err = self.cnt = 0
self.enet1000 = False
self._extra_socket = list()
mapping.register(self, parents_list=["comms"], tag=str(self))
session.get_current().map.register(self, parents_list=["comms"], tag=str(self))
def _open(self):
self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self._sock.connect((self._host, self._port))
mapping.register(
session.get_current().map.register(
self, parents_list=["comms"], children_list=[self._sock], tag=str(self)
)
......
......@@ -18,7 +18,7 @@ from .exceptions import CommunicationError, CommunicationTimeout
from ..common.greenlet_utils import KillMask, protect_from_kill
from . import serial
from bliss.common import mapping
from bliss.common import session
from bliss.common.logtools import LogMixin
......@@ -94,7 +94,7 @@ class Modbus_RTU(LogMixin):
self._serial = serial.Serial(*args, **kwargs)
self.node = node
self._lock = lock.RLock()
mapping.register(self, children_list=[self._serial])
session.get_current().map.register(self, children_list=[self._serial])
def __del__(self):
self._serial.close()
......
......@@ -19,7 +19,7 @@ from gevent import socket, select, lock, event
from ..common.greenlet_utils import KillMask
from bliss.common.cleanup import capture_exceptions
from bliss.common import mapping
from bliss.common import session
from bliss.common.logtools import LogMixin
import serial
......@@ -746,7 +746,7 @@ class Serial(LogMixin):
self._timeout = timeout
self._raw_handler = None
self._lock = lock.RLock()
mapping.register(self, parents_list=["comms"], tag=str(self))
session.get_current().map.register(self, parents_list=["comms"], tag=str(self))
def __del__(self):
self.close()
......@@ -771,7 +771,7 @@ class Serial(LogMixin):
self._raw_handler = TangoSerial(self, **self._serial_kwargs)
else: # LOCAL
self._raw_handler = LocalSerial(self, **self._serial_kwargs)
mapping.register(
session.get_current().map.register(
self,
parents_list=["comms"],
children_list=[self._raw_handler],
......
......@@ -23,7 +23,7 @@ from .exceptions import CommunicationError, CommunicationTimeout
from ..common.greenlet_utils import KillMask
from bliss.common.cleanup import error_cleanup, capture_exceptions
from bliss.common import mapping
from bliss.common import session
from bliss.common.logtools import LogMixin
......@@ -90,7 +90,7 @@ class BaseSocket(LogMixin):
self._event = event.Event()
self._raw_read_task = None
self._lock = lock.RLock()
mapping.register(self, parents_list=["comms"], tag=str(self))
session.get_current().map.register(self, parents_list=["comms"], tag=str(self))
def __del__(self):
self.close()
......@@ -411,7 +411,7 @@ class Command(LogMixin):
self.__transaction = transaction
self.__clear_transaction = clear_transaction
self.data = b""
mapping.register(
session.get_current().map.register(
self, children_list=[self.__socket], parents_list=["comms"]
)
......@@ -461,7 +461,7 @@ class Command(LogMixin):
self._raw_read_task = None
self._transaction_list = []
self._lock = lock.RLock()
mapping.register(self, parents_list=["comms"], tag=str(self))
session.get_current().map.register(self, parents_list=["comms"], tag=str(self))
def __del__(self):
self.close()
......@@ -501,7 +501,7 @@ class Command(LogMixin):
return True
self._fd = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
mapping.register(
session.get_current().map.register(
self._fd,
parents_list=[self, "comms"],
tag=f"Socket[{local_host}:{local_port}",
......
......@@ -18,6 +18,7 @@ from tabulate import tabulate
from bliss.config import static
from bliss import setup_globals
from bliss.common import session
from bliss.common.utils import get_counters_iter
class AliasMixin(object):
......@@ -173,14 +174,13 @@ class Alias(object):
# check if there is a counter around that can be linked to this alias
if not disable_link_search:
from bliss.common.utils import counter_dict
for key, item in counter_dict().items():
for cnt in get_counters_iter():
key = cnt.fullname
if key == original_name:
self._link_to(item)
self._link_to(cnt)
break
elif item.name == original_name:
self._link_to(item)
elif cnt.name == original_name:
self._link_to(cnt)
break
print(f"Alias '{alias_name}' added for '{original_name}'")
......
......@@ -40,8 +40,6 @@ from bliss.common.hook import MotionHook
from bliss.config.channels import Channel
from bliss.common.alias import AliasMixin
from bliss.physics.trajectory import LinearTrajectory
from bliss import setup_globals
from bliss.common import mapping
from bliss.common.logtools import LogMixin
import gevent
import re
......@@ -590,7 +588,6 @@ class Axis(AliasMixin, LogMixin):
disabled_cache.extend(config.get("disabled_cache", [])) # get it for this axis
for settings_name in disabled_cache:
self.settings.disable_cache(settings_name)
mapping.register(self, parents_list=[self.__controller], tag=f"axis.{name}")
self._unit = self.config.get("unit", str, None)
def __close__(self):
......
......@@ -11,10 +11,11 @@ from fnmatch import fnmatch, fnmatchcase
import functools
import networkx as nx
from bliss.common.utils import common_prefix, autocomplete_property
from bliss.common.mapping import _BEAMLINE_MAP, BEAMLINE_GRAPH, format_node
from bliss.common.utils import autocomplete_property
from bliss.common.mapping import format_node
from bliss.common import session
__all__ = ["log", "lslog", "lsdebug"]
__all__ = ["lslog", "lsdebug"]
def logging_startup(
......@@ -31,12 +32,11 @@ def logging_startup(
class LogMixin:
@autocomplete_property
def _logger(self, *args, **kwargs):
m = session.get_current().map
id_ = id(self)
if id_ not in BEAMLINE_GRAPH:
raise UnboundLocalError(
"Instance should be registered with mapping.register before using _logger"
)
return BEAMLINE_GRAPH.node[id_]["_logger"]
if id_ not in m.G:
return None
return m.G.node[id_]["_logger"]
def improve_logger(logger_instance):
......@@ -156,9 +156,9 @@ class Log:
def __init__(self, map_beamline):
self.map_beamline = map_beamline
logging.getLogger("beamline").setLevel(
logging.WARNING
) # setting starting level
map_beamline.add_map_handler(map_update_loggers)
logging.getLogger("session").setLevel(logging.WARNING) # setting starting level
map_beamline.trigger_update()
def _check_log_level(self: (str, int), level):
"""
......@@ -513,20 +513,9 @@ def map_update_loggers(G):
G.node[node]["_logger"].name = logger_name
def set_log(map_beamline):
"""
Instantiates a logger bliss instance and creates global references to it
"""
global log
global lslog
global lsdebug
log = Log(map_beamline=map_beamline)
log.map_beamline.add_map_handler(map_update_loggers)
log.map_beamline.trigger_update()
lslog = log.lslog # shortcut
lsdebug = log.lsdebug # shortcut
def lslog(glob: str = None, level: int = None, inherited: bool = True):
return session.get_current().log.lslog(glob, level, inherited)
set_log(_BEAMLINE_MAP)
def lsdebug(inherited=True):
return session.get_current().log.lsdebug(inherited)
This diff is collapsed.
......@@ -14,8 +14,24 @@ import weakref
from collections import namedtuple
import enum
from bliss.common.utils import add_conversion_function
from bliss.common.alias import AliasMixin
from bliss.common import session
def add_conversion_function(obj, method_name, function):
meth = getattr(obj, method_name)
if inspect.ismethod(meth):
if callable(function):
def new_method(*args, **kwargs):
values = meth(*args, **kwargs)
return function(values)
setattr(obj, method_name, new_method)
else:
raise ValueError("conversion function must be callable")
else:
raise ValueError("'%s` is not a method" % method_name)
# Counter namespaces
......@@ -188,6 +204,10 @@ class Counter(BaseCounter):
self._unit = unit
if grouped_read_handler:
Counter.GROUPED_READ_HANDLERS[self] = grouped_read_handler
parents_list = (
["counters", controller] if controller is not None else ["counters"]
)
session.get_current().map.register(self, parents_list, tag=self.name)
# Standard interface
......
......@@ -10,6 +10,13 @@ from bliss.common.utils import Null
from bliss.config.static import get_config
def _get_config():
from bliss.common import session
cfg = session.get_current().config
return cfg
class StaticConfig(object):
NO_VALUE = Null()
......@@ -55,19 +62,19 @@ class StaticConfig(object):
raise KeyError("no property '%s` in config" % property_name)
def set(self, property_name, value):
cfg = get_config()
cfg = _get_config()
config_node = cfg.get_config(self.config_dict["name"])
config_node[property_name] = value
self.config_dict = config_node.to_dict()
def save(self):
cfg = get_config()
cfg = _get_config()
config_node = cfg.get_config(self.config_dict["name"])
config_node.save()
self._update_channel()
def reload(self):
cfg = get_config()
cfg = _get_config()
# this reloads *all* the configuration, hopefully it is not such
# a big task and it can be left as simple as it is, if needed
# we could selectively reload only parts of the config (e.g one
......@@ -83,7 +90,7 @@ class StaticConfig(object):
self.config_channel.value = self.config_dict
def _config_changed(self, config_dict):
cfg = get_config()
cfg = _get_config()
config_node = cfg.get_config(self.config_dict["name"])
for key, value in config_dict.items():
config_node[key] = value
......
......@@ -14,7 +14,8 @@ import __main__ as interpreter_main
from bliss import setup_globals
from bliss.config import static
from bliss.common.alias import Aliases
from bliss.common.mapping import Map
from bliss.common.logtools import Log
from bliss.config.conductor.client import get_text_file, get_python_modules, get_file
......@@ -192,6 +193,8 @@ class Session(object):
self.__objects_names = None
self.__children_tree = None
self.__include_sessions = []
self.__map = None
self.__log = None
self.init(config_tree)
......@@ -247,6 +250,14 @@ class Session(object):
def synoptic_file(self):
return self.__synoptic_file
@property
def map(self):
return self.__map
@property
def log(self):
return self.__log
@property
def _scripts_module_path(self):
return self.__scripts_module_path
......@@ -361,11 +372,22 @@ class Session(object):
env_dict = self.env_dict
env_dict["config"] = self.config
self._load_config(env_dict, verbose)
global CURRENT_SESSION
CURRENT_SESSION = self
self.__map = Map()
self.__map.register(self)
self.__map.register("devices", parents_list=[self], tag="devices")
self.__map.register("controllers", parents_list=[self], tag="controllers")
self.__map.register("comms", parents_list=[self], tag="comms")
self.__map.register("axes", parents_list=[self], tag="axes")
self.__map.register("counters", parents_list=[self], tag="counters")
self.__log = Log(map_beamline=self.__map)
self._load_config(env_dict, verbose)
if self.__scripts_module_path and self.name not in _SESSION_IMPORTERS:
sys.meta_path.append(_StringImporter(self.__scripts_module_path, self.name))
_SESSION_IMPORTERS.add(self.name)
......@@ -406,6 +428,8 @@ class Session(object):
###### add alias suppport
from bliss.common.alias import Aliases
setattr(setup_globals, "ALIASES", Aliases(self, env_dict))
env_dict["ALIASES"] = setup_globals.ALIASES
......
......@@ -7,7 +7,6 @@
from bliss.controllers.motors.soft import SoftController
from bliss.common import session
from bliss.common import mapping
from bliss import setup_globals
......@@ -43,6 +42,8 @@ def SoftAxis(
controller._init()
axis = controller.get_axis(name)
mapping.register(axis, parents_list=[controller], tag=f"axis.{name}")
session.get_current().map.register(
axis, parents_list=[controller], tag=f"axis.{name}"
)
setattr(setup_globals, name, axis)
return axis
......@@ -17,6 +17,7 @@ from bliss.common.measurement import SoftCounter
from bliss.common.cleanup import cleanup, error_cleanup
from bliss.common import logtools
from bliss.common.logtools import *
from bliss.common.utils import get_counters_iter
import sys
......@@ -487,7 +488,7 @@ def cntdict():
counters_dict = dict()
shape = ["0D", "1D", "2D"]
for fname, cnt in counter_dict().items():
for cnt in get_counters_iter():
tmp = cnt.fullname.split(".")
tmp_controller_name = ".".join(tmp[:-1])
counters_dict[cnt.fullname] = (
......
......@@ -14,7 +14,6 @@ import itertools
import functools
import numpy
from bliss.common.event import saferef
from bliss.common import session
import sys
import copy
import collections.abc
......@@ -52,22 +51,6 @@ def wrap_methods(from_object, target_object):
)
def add_conversion_function(obj, method_name, function):
meth = getattr(obj, method_name)
if inspect.ismethod(meth):
if callable(function):
def new_method(*args, **kwargs):
values = meth(*args, **kwargs)
return function(values)
setattr(obj, method_name, new_method)
else:
raise ValueError("conversion function must be callable")
else:
raise ValueError("'%s` is not a method" % method_name)
def add_property(inst, name, method):
cls = type(inst)
module = cls.__module__
......@@ -452,9 +435,11 @@ def get_objects_type_iter(typ):
def get_axes_iter():
from bliss.common.axis import Axis
from bliss.common import session
return get_objects_type_iter(Axis)
m = session.get_current().map
for mot in m.instance_iter("axes"):
yield mot
def get_axes_names_iter():
......@@ -462,6 +447,17 @@ def get_axes_names_iter():
yield axis.alias_or_name
def get_counters_iter():
from bliss.common import session
for cnt in session.get_current().map.instance_iter("counters"):
try:
for cnt in cnt.counters:
yield cnt
except AttributeError:
yield cnt
def safe_get(obj, member, on_error=None, **kwargs):
try:
if isinstance(getattr(type(obj), member), property):
......
......@@ -688,6 +688,17 @@ class Config:
self._name2instance.update(name2items)
instance_object = name2items.get(name)
from bliss.common.axis import Axis
if isinstance(instance_object, Axis):
from bliss.common import session
session.get_current().map.register(
instance_object,
parents_list=[instance_object.controller, "axes"],
tag=instance_object.name,
)
return instance_object
def _create_index(self, node):
......
......@@ -13,6 +13,7 @@ from .bpm import Bpm
from .roi import Roi, RoiCounters
from .image import ImageCounter
from .bgsub import BgSub
from bliss.common import session
from bliss.common.utils import common_prefix, autocomplete_property
from bliss.common.tango import DeviceProxy, DevFailed
from bliss.common.measurement import namespace, counter_namespace
......@@ -121,11 +122,12 @@ class Lima(object):
self.__tg_timeout = config_tree.get("tango_timeout", 3)
self.__bpm = None
self.__roi_counters = None
self._proxy = self._get_proxy()
self.__bg_sub = None
self._camera = None
self._image = None
self._acquisition = None
self._proxy = self._get_proxy()
session.get_current().map.register(self, parents_list=["counters"])
self._directories_mapping = config_tree.get("directories_mapping", dict())
self._active_dir_mapping = settings.SimpleSetting(
"%s:directories_mapping" % name
......
......@@ -15,7 +15,8 @@ import collections
import gevent
from .roi import RoiConfig
from bliss.controllers.mca.roi import RoiConfig
from bliss.common import session
# Enums
......@@ -48,6 +49,9 @@ class BaseMCA(object):
def __init__(self, name, config):
self._name = name
session.get_current().map.register(
self, parents_list=["counters", "controllers"]
)
self._config = config
self._rois = RoiConfig(self)
self.initialize_attributes()
......
......@@ -87,7 +87,8 @@ class Controller(LogMixin):
if obj_class is None:
raise ValueError("Missing **class** for '%s`" % obj_name)
object_dict[obj_name] = obj_class(obj_name, self, obj_config)
mapping.register(self)
mapping_name = config.get("name") or self.__class__.__name__.lower()
mapping.register(self, parents_list=["controllers"], tag=mapping_name)
def _init(self):
for axis in self.axes.values():
......
......@@ -11,7 +11,7 @@ from bliss.common.axis import AxisState
from bliss.config.channels import Cache
from bliss.controllers.motor import Controller
from bliss.common.utils import object_method
from bliss.common import session
import string
import time
......@@ -602,12 +602,14 @@ class Aerotech(Controller):
def __init__(self, *args, **kwargs):
Controller.__init__(self, *args, **kwargs)
self._comm = None
def initialize(self):
config = self.config.config_dict
opt = {"port": 8000, "eol": "\n"}
self._comm = get_comm(config, ctype=TCP, **opt)
session.get_current().map.register(self, children_list=[self._comm])
def initialize(self):
self._aero_axis = {}
self._aero_speed = {}
self._aero_acc = {}
......
......@@ -15,8 +15,8 @@ from bliss.config.channels import Cache
from bliss.controllers.motor import Controller
from bliss.common.axis import AxisState, Axis
from bliss.common.utils import object_method
from bliss.common import mapping
from bliss.common.logtools import LogMixin
from bliss.common import session
from bliss.comm.tcp import Command
import struct
import numpy
......@@ -75,15 +75,12 @@ class Icepap(Controller, LogMixin):
def __init__(self, *args, **kwargs):
Controller.__init__(self, *args, **kwargs)
self._cnx = None
self._last_axis_power_time = dict()
mapping.register(self, parents_list=["devices"])
def initialize(self):
hostname = self.config.get("host")
self._cnx = Command(hostname, 5000, eol="\n")
mapping.register(self, children_list=[self._cnx], parents_list=["devices"])
session.get_current().map.register(self, children_list=[self._cnx])
self._last_axis_power_time = dict()
def initialize(self):
self._icestate = AxisState()
self._icestate.create_state("POWEROFF", "motor power is off")
self._icestate.create_state("HOMEFOUND", "home signal found")
......
......@@ -53,7 +53,7 @@ from bliss.comm.util import get_comm, TCP
from bliss.comm.tcp import SocketTimeout
from bliss.common.axis import AxisState
from bliss.controllers.motor import Controller
from bliss.common.mapping import register
from bliss.common import session
from bliss.common.logtools import LogMixin
ROLES = "tx", "ty", "tz", "rx", "ry", "rz"
......@@ -218,7 +218,9 @@ class SHexapod(Controller):
for klass in all_klass:
try:
protocol = klass(self.config.config_dict)
register(protocol, parents_list=[self], children_list=[protocol.comm])
session.get_current().map.register(
protocol, parents_list=[self], children_list=[protocol.comm]
)
protocol.comm.open()
self._protocol = protocol
break
......
......@@ -12,10 +12,10 @@ import pprint
from bliss.scanning.chain import AcquisitionDevice, AcquisitionChannel
from bliss.scanning.acquisition.counter import SamplingMode
from bliss.common.measurement import GroupedReadMixin, Counter
from bliss.common import session
# for logging
import logging
from bliss.common import mapping
from bliss.common.logtools import LogMixin
"""
......@@ -111,7 +111,7 @@ dscan(m1,-1,1, 13, 0.01)
class SimulationCounter_AcquisitionDevice(AcquisitionDevice, LogMixin):
def __init__(self, counter, scan_param, distribution, gauss_param, noise_factor):
mapping.register(self)
session.get_current().map.register(self)
self._logger.debug(
"SIMULATION_COUNTER_ACQ_DEV -- SimulationCounter_AcquisitionDevice()"
)
......@@ -320,7 +320,7 @@ class SimulationCounter(Counter, LogMixin):
def __init__(self, name, config):
Counter.__init__(self, name)
mapping.register(self)
session.get_current().map.register(self)
self.config = config
self.acq_device = None
......
......@@ -45,7 +45,8 @@ class Controller(LogMixin):
"""
def __init__(self, config, inputs, outputs, loops):
mapping.register(self)
mapping_name = config.get("name") or self.__class__.__name__.lower()
mapping.register(self, parents_list=["controllers"], tag=mapping_name)
# self._logger.info("on Controller")
self.__config = config