Commit dadaff84 authored by Mauro Rovezzi's avatar Mauro Rovezzi

Merge remote-tracking branch 'upstream/master'

parents b5e59f00 9ba5b0f4
Pipeline #10994 failed with stages
......@@ -36,4 +36,9 @@ version_info = release.version_info
from gevent import monkey
monkey.patch_all(thread=False)
from redis import selector
selector._DEFAULT_SELECTOR = selector.SelectSelector
from bliss.common import logtools
......@@ -167,7 +167,7 @@ def cmd_expr_to_reg_expr_str(cmd_expr):
# Basicaly we replace [] -> ()?, and LOWercase -> LOW(ercase)?
# Also we add :? optional to the start and $ to the end to make sure
# we have an exact match
reg_expr, low_zone = "\:?", False
reg_expr, low_zone = r"\:?", False
for c in cmd_expr:
cl = c.islower()
if not cl:
......@@ -204,7 +204,7 @@ def cmd_expr_to_reg_expr(cmd_expr):
class Commands(object):
"""
r"""
A dict like container for SCPI commands. Construct a Commands object like a
dict. When creating a Commands object, *args* must either:
......
......@@ -122,7 +122,7 @@ def get_comm_type(config):
def get_comm(config, ctype=None, **opts):
"""
r"""
Expects a dict like config object. It recognizes keywords: *tcp*, *gpib* or
*serial*.
......
......@@ -17,7 +17,7 @@ from tabulate import tabulate
from bliss.config import static
from bliss import setup_globals
from bliss.common.utils import counter_dict, closable
from bliss.common import session
class AliasMixin(object):
......@@ -32,8 +32,6 @@ class AliasMixin(object):
)
"""Assign an alias for this object"""
from bliss.common.utils import _get_env_dict
alias_config = {
"original_name": self.name,
"alias_name": alias,
......@@ -43,7 +41,9 @@ class AliasMixin(object):
}
if not hasattr(setup_globals, "ALIASES"):
setattr(setup_globals, "ALIASES", Aliases(self, _get_env_dict()))
setattr(
setup_globals, "ALIASES", Aliases(self, session.get_current().env_dict)
)
setup_globals.ALIASES.create_alias(
**alias_config,
......@@ -173,6 +173,8 @@ 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():
if key == original_name:
self._link_to(item)
......@@ -366,5 +368,7 @@ class Aliases(object):
if hasattr(setup_globals, obj.name):
delattr(setup_globals, obj.name)
if not hasattr(setup_globals, obj_name) and obj.has_object_ref:
if closable(obj.object_ref):
obj.object_ref.close()
try:
obj.object_ref.__close__()
except Exception:
pass
......@@ -620,7 +620,7 @@ class Axis(AliasMixin, LogMixin):
mapping.register(self, parents_list=[self.__controller], tag=f"axis.{name}")
self._unit = self.config.get("unit", str, None)
def close(self):
def __close__(self):
try:
controller_close = self.__controller.close
except AttributeError:
......@@ -987,7 +987,6 @@ class Axis(AliasMixin, LogMixin):
return _user_vel
@property
@lazy_init
def config_velocity(self):
"""
Returns the config velocity.
......@@ -1026,7 +1025,6 @@ class Axis(AliasMixin, LogMixin):
return _acceleration
@property
@lazy_init
def config_acceleration(self):
return self.config.get("acceleration", float)
......@@ -1049,7 +1047,6 @@ class Axis(AliasMixin, LogMixin):
return self.velocity / self.acceleration
@property
@lazy_init
def config_acctime(self):
"""
Returns the config acceleration time.
......@@ -1105,7 +1102,6 @@ class Axis(AliasMixin, LogMixin):
return self.high_limit
@property
@lazy_init
def config_limits(self):
ll = self.config.get("low_limit", float, float("-inf"))
hl = self.config.get("high_limit", float, float("+inf"))
......@@ -1574,22 +1570,11 @@ class Axis(AliasMixin, LogMixin):
"""
if reload:
self.config.reload()
# Applies velocity and acceleration only if possible.
# Try to execute <config_name> function to check if axis supports it.
for config_param in ["velocity", "acceleration"]:
try:
config_value = getattr(self, "config_%s" % config_param)
setattr(self, config_param, config_value)
except (NotImplementedError, KeyError):
self._logger.debug(
"'%s' for '%s' is not implemented" % (config_param, self.name)
)
else:
self._logger.debug(
"set '%s' for '%s' done." % (config_param, self.name)
)
self.limits = self.config_limits
self.controller.axis_settings._clear(self, "velocity")
self.controller.axis_settings._clear(self, "acceleration")
self.controller.axis_settings._clear(self, "low_limit")
self.controller.axis_settings._clear(self, "high_limit")
self.controller._init_settings(self)
@lazy_init
def set_event_positions(self, positions):
......
......@@ -5,13 +5,13 @@
# Copyright (c) 2015-2019 Beamline Control Unit, ESRF
# Distributed under the GNU LGPLv3. See LICENSE for more info.
from bliss.common import log as elog
from bliss.common import event
from bliss.config import settings
import sys
def setting_update_from_channel(value, setting_name=None, axis=None):
# print 'setting update from channel', axis.name, setting_name, str(value)
# print('setting update from channel', axis.name, setting_name, str(value))
if setting_name == "state":
if "MOVING" in str(value):
axis._set_moving_state(from_channel=True)
......@@ -19,7 +19,10 @@ def setting_update_from_channel(value, setting_name=None, axis=None):
if axis.is_moving:
axis._set_move_done()
event.send(axis, setting_name, value)
try:
event.send(axis, setting_name, value)
except Exception:
sys.excepthook(*sys.exc_info())
def floatOrNone(x):
......@@ -51,7 +54,7 @@ class ControllerAxisSettings:
self.add("_set_position", float)
self.add("position", float)
self.add("state", stateSetting, persistent=False)
self.add("steps_per_unit", float, persistent=True, config=True)
self.add("steps_per_unit", float, config=True)
def config_settings(self):
return tuple(
......@@ -79,17 +82,20 @@ class ControllerAxisSettings:
hash_setting = settings.HashSetting("axis.%s" % axis.name)
value = hash_setting.get(setting_name)
else:
value = None
if value is None:
chan = axis._beacon_channels.get(setting_name)
if chan:
value = chan.value
else:
value = None
if value is not None:
convert_func = self.convert_func.get(setting_name)
if convert_func is not None:
value = convert_func(value)
return value
def _clear(self, axis, setting_name):
settings.HashSetting("axis.%s" % axis.name)[setting_name] = None
def set(self, axis, setting_name, value):
"""
* set setting
......@@ -109,7 +115,10 @@ class ControllerAxisSettings:
axis._beacon_channels[setting_name].value = value
event.send(axis, "internal_" + setting_name, value)
event.send(axis, setting_name, value)
try:
event.send(axis, setting_name, value)
except Exception:
sys.excepthook(*sys.exc_info())
class AxisSettings:
......@@ -137,7 +146,7 @@ class AxisSettings:
def disable_cache(self, setting_name, flag=True):
"""
Remove the cache setting for the a setting_name.
Remove cache for specified setting
"""
disabled_settings = self.__axis.controller.axis_settings.disabled_settings.setdefault(
self.__axis, set()
......
......@@ -10,10 +10,10 @@ import sys
from types import ModuleType
import functools
from treelib import Tree
import __main__ as interpreter_main
from bliss import setup_globals
from bliss.config import static
from bliss.common.utils import closable
from bliss.common.alias import Aliases
from bliss.config.conductor.client import get_text_file, get_python_modules, get_file
......@@ -25,6 +25,10 @@ def get_current():
"""
return the current session object
"""
global CURRENT_SESSION
if CURRENT_SESSION is None:
CURRENT_SESSION = DefaultSession()
CURRENT_SESSION.setup()
return CURRENT_SESSION
......@@ -179,8 +183,15 @@ class Session(object):
def __init__(self, name, config_tree):
self.__name = name
self.__config = static.get_config()
self.__env_dict = {}
self.__scripts_module_path = None
self.__setup_file = None
self.__synoptic_file = None
self.__config_objects_names = []
self.__exclude_objects_names = []
self.__objects_names = None
self.__children_tree = None
self.__include_sessions = []
self.init(config_tree)
......@@ -226,7 +237,7 @@ class Session(object):
@property
def config(self):
return self.__config
return static.get_config()
@property
def setup_file(self):
......@@ -331,22 +342,25 @@ class Session(object):
@property
def env_dict(self):
return self.__env_dict
try:
# does Python run in interactive mode ?
interpreter_main.__file__
except AttributeError:
# interactive interpreter: use the main dict
# in order to export objects naturally as globals
return interpreter_main.__dict__
else:
# running as a library
return self.__env_dict
def setup(self, env_dict=None, verbose=False):
if env_dict is None:
# does Python run in interactive mode?
import __main__ as main
if not hasattr(main, "__file__"):
# interactive interpreter
self.__env_dict = main.__dict__
else:
self.__env_dict = {}
else:
if env_dict is not None:
# set a new env dict
self.__env_dict = env_dict
env_dict = self.__env_dict
# use existing env dict
env_dict = self.env_dict
env_dict["config"] = self.config
self._load_config(env_dict, verbose)
global CURRENT_SESSION
......@@ -359,15 +373,17 @@ class Session(object):
if not "load_script" in env_dict:
env_dict["load_script"] = functools.partial(load_script, env_dict)
from bliss.scanning.scan import ScanSaving, ScanDisplay, SCANS
exec("from bliss.common.standard import *", env_dict)
from bliss.scanning.scan import ScanSaving, ScanDisplay, SCANS
env_dict["SCANS"] = SCANS
env_dict["SCAN_SAVING"] = ScanSaving(self.name)
env_dict["SCAN_DISPLAY"] = ScanDisplay()
env_dict["SCANS"] = SCANS
env_dict["SCAN_SAVING"] = ScanSaving(self.name)
env_dict["SCAN_DISPLAY"] = ScanDisplay()
from bliss.common.measurementgroup import ACTIVE_MG
from bliss.common.measurementgroup import ACTIVE_MG
env_dict["ACTIVE_MG"] = ACTIVE_MG
env_dict["ACTIVE_MG"] = ACTIVE_MG
sessions_tree = self.sessions_tree
for child_session in reversed(
......@@ -418,17 +434,24 @@ class Session(object):
return True
def close(self):
if get_current() is self:
try:
for obj_name, obj in self.__env_dict.items():
if obj is self or obj is self.config:
continue
try:
delattr(setup_globals, obj_name)
except Exception:
pass
try:
obj.__close__()
except Exception:
pass
self.__env_dict.clear()
finally:
global CURRENT_SESSION
CURRENT_SESSION = None
for obj_name, obj in self.__env_dict.items():
if obj is self:
continue
if hasattr(setup_globals, obj_name):
delattr(setup_globals, obj_name)
if closable(obj):
obj.close()
self.__env_dict.clear()
if CURRENT_SESSION is self:
self.config.close()
CURRENT_SESSION = None
def _load_config(self, env_dict, verbose=True):
for item_name in self.object_names:
......@@ -454,30 +477,18 @@ class Session(object):
del o
def resetup(self, verbose=False):
env_dict = self.__env_dict
for name in self.object_names:
delattr(setup_globals, name)
try:
obj = env_dict.pop(name)
except KeyError:
pass
else:
if closable(obj):
obj.close()
self.close()
self.config.reload()
self.init(self.config.get_config(self.name))
self.setup(env_dict, verbose)
self.setup(self.env_dict, verbose)
class DefaultSession(Session):
def __init__(self):
Session.__init__(
self, "default", {"exclude-objects": static.get_config().names_list}
)
Session.__init__(self, "default", {"config-objects": []})
def _load_config(self, env_dict, verbose=True):
return
......
......@@ -14,7 +14,7 @@ import itertools
import functools
import numpy
from bliss.common.event import saferef
from bliss.common import session
import sys
import collections.abc
......@@ -499,15 +499,6 @@ def common_prefix(paths, sep=os.path.sep):
return sep.join(x[0] for x in itertools.takewhile(allnamesequal, bydirectorylevels))
def closable(obj):
"""Return True if the given object is closable, False otherwise."""
return (
hasattr(obj, "close")
and inspect.ismethod(obj.close)
and obj.close.__self__ is not None
)
def human_time_fmt(num, suffix="s"):
"""
format time second in human readable format
......@@ -570,18 +561,6 @@ class Statistics(object):
return standard._tabulate(data)
def _get_env_dict():
if "bliss.shell.cli.repl" in sys.modules.keys():
repl = sys.modules["bliss.shell.cli.repl"]
if repl.REPL is not None:
return repl.REPL.get_globals()
else:
return dict()
else:
return dict()
def counter_dict():
"""
Return a list of counters
......@@ -591,7 +570,7 @@ def counter_dict():
counters_dict = dict()
env_dict = _get_env_dict()
env_dict = session.get_current().env_dict
for name, obj in itertools.chain(
inspect.getmembers(setup_globals),
......
......@@ -52,7 +52,8 @@ import weakref
import yaml
from .conductor import client
from bliss.config.conductor import client
from bliss.config import channels
CONFIG = None
......@@ -361,6 +362,11 @@ class Config:
self._connection = connection or client.get_default_connection()
self.reload(timeout=timeout)
def close(self):
self._clear_instances()
channels.Bus.clear_cache()
self._connection.close()
def reload(self, base_path=None, timeout=3):
"""
Reloads the configuration from the bliss server.
......
#=== Define default shell to use ===================================
#set-option -g default-shell /usr/bin/zsh
#=== Enable mouse in a virtual terminal (> version 2.1) ============
#=== Monitor activity ==============================================
#setw -g monitor-activity on
#=== delay for escape key press ====================================
# Reduce delay for escape key press (millisec)
set -g escape-time 50
#=== Use 256-colors ================================================
#set -g default-terminal screen-256color
#=== Enable mouse mode in a virtual terminal (> version 2.1) =======
set-option -g mouse on
#=== Modify the prefix =============================================
set-option -g prefix C-a
# if commented, use the default one : Control-b
# (we prefer to keep Control-a to go to begining of the line.)
# set-option -g prefix C-a
#=== No status bar =================================================
set-option -g status off
#=== Use larger history buffer =====================================
set -g history-limit 100000
#=== Use vi copy-mode ==============================================
set-window-option -g mode-keys vi
#===Define separator for the Word selection=========================
set-option -g word-separators "; @()\'\`\"" #"
#===================================================================
#======================== KEYS BINDINGS ============================
#===================================================================
#=== keep Native xterm scrolling ===================================
# useful to keep S-PageUp Binding to scroll up half a page
#set -g terminal-overrides "xterm*:XT:smcup@:rmcup@:kUP5=\eOA:kDN5=\eOB:kLFT5=\eOD:kRIT5=\eOC"
#set -ga terminal-overrides ',xterm*:smcup@:rmcup@'
set -g terminal-overrides 'xterm*:smcup@:rmcup@'
#=== Bind F5 to switch window and clear copy selection =============
bind -n F5 if -F -t= '#{pane_in_mode}' 'send -X cancel' \; next-window
#=== Bind Ctrl-c to escape scan display function ===================
#=== switch to bliss repl window and stop ongoing scan =============
bind -n C-c if -F '#{==:#W,scan}' 'next-window' \; send -t bliss C-c
#=== Copy paste with mouse =========================================
#=== Bind pageup to enter copy mode and scroll one page=============
bind -n S-PageUp select-pane \; copy-mode -eu
bind -n S-PageDown select-pane \; if -F -t= '#{pane_in_mode}' 'send -X page-down'
bind -n S-Home select-pane \; copy-mode -e \; send -X history-top
bind -n S-End select-pane \; if -F -t= '#{pane_in_mode}' 'send -X cancel'
#====================================================================
#============================= MOUSE ================================
#====================================================================
#---Copy with Left click dragged (using 'primary' buffer instead of 'clipboard')
#=== Copy paste with mouse ==========================================
#===Copy with Left click dragged (using 'primary' buffer instead of 'clipboard')======
unbind -Tcopy-mode-vi MouseDragEnd1Pane
# bind -Tcopy-mode-vi MouseDragEnd1Pane send -X copy-selection \; run "tmux save-buffer - | xclip -i -selection primary > /dev/null && tmux save-buffer - | xclip -i -selection clipboard > /dev/null"
bind -Tcopy-mode-vi MouseDragEnd1Pane send -X copy-pipe "xclip -in -selection primary"
#---Paste with Middle click (using 'primary' buffer instead of 'clipboard')
#===Paste with Middle click (using 'primary' buffer instead of 'clipboard')============
unbind -n MouseDown2Pane
bind -n MouseDown2Pane select-pane\; run "tmux set-buffer \"$(xclip -o -selection primary)\"; tmux paste-buffer" \; if -F -t= '#{pane_in_mode}' 'send -X cancel'
#---Double Left Mouse Button Select & Copy (Word)
#===Double Left Mouse Button Select & Copy (Word)====================
bind -T copy-mode-vi DoubleClick1Pane select-pane \; send-keys -X select-word \; send-keys -X copy-pipe "xclip -in -sel primary"
bind -n DoubleClick1Pane select-pane \; copy-mode -M \; send-keys -X select-word \; send-keys -X copy-pipe "xclip -in -sel primary"
bind -n DoubleClick1Pane select-pane \; copy-mode -eM \; send-keys -X select-word \; send-keys -X copy-pipe "xclip -in -sel primary"
#---Triple Left Mouse Button Select & Copy (Line)
#===Triple Left Mouse Button Select & Copy (Line)====================
bind -T copy-mode-vi TripleClick1Pane select-pane \; send-keys -X select-line \; send-keys -X copy-pipe "xclip -in -sel primary"
bind -n TripleClick1Pane select-pane \; copy-mode -M \; send-keys -X select-line \; send-keys -X copy-pipe "xclip -in -sel primary"
bind -n TripleClick1Pane select-pane \; copy-mode -eM \; send-keys -X select-line \; send-keys -X copy-pipe "xclip -in -sel primary"
#---Exit copy-mode with a Right click
#===Exit copy-mode with a Right click================================
bind -Tcopy-mode-vi MouseDown3Pane if -F -t= '#{pane_in_mode}' 'send -X cancel'
#---Define separator for the Word selection
set-option -g word-separators "; @()\'\`\"" #"
#---Native xterm scrolling
#set -g terminal-overrides "xterm*:XT:smcup@:rmcup@:kUP5=\eOA:kDN5=\eOB:kLFT5=\eOD:kRIT5=\eOC"
#set -ga terminal-overrides ',xterm*:smcup@:rmcup@'
#set -g terminal-overrides 'xterm*:smcup@:rmcup@'
#=== THEME ==========================================================
#set -g status-bg black
#set -g status-fg white
#set -g window-status-current-bg white
#set -g window-status-current-fg black
#set -g window-status-current-attr bold
#set -g status-interval 60
#set -g status-left-length 30
#set -g status-left '#[fg=green](#S) #(whoami)'
#set -g status-right '#[fg=yellow]#(cut -d " " -f 1-3 /proc/loadavg)#[default] #[fg=white]%H:%M#[default]'
#=== DESIGN CHANGES =================================================
#===loud or quiet?===================================================
#set-option -g visual-activity off
#set-option -g visual-bell off
#set-option -g visual-silence off
#set-window-option -g monitor-activity off
#set-option -g bell-action none
#=== Tip and tricks =============================================
#===modes============================================================
#setw -g clock-mode-colour colour5
#setw -g mode-attr bold
#setw -g mode-fg colour1
#setw -g mode-bg colour18
#---Display a message
#bind -n m set-option mouse\; display-message "Mouse is now #{?mouse,on,off}"
#===panes============================================================
#set -g pane-border-bg colour0
#set -g pane-border-fg colour19
#set -g pane-active-border-bg colour0
#set -g pane-active-border-fg colour9
#===statusbar========================================================
#set -g status-position bottom
#set -g status-justify left
#set -g status-bg colour18
#set -g status-fg colour137
#set -g status-attr dim
#set -g status-left ''
#set -g status-right '#[fg=colour233,bg=colour19,bold] %d/%m #[fg=colour233,bg=colour8,bold] %H:%M:%S '
#set -g status-right-length 50
#set -g status-left-length 20
#setw -g window-status-current-fg colour1
#setw -g window-status-current-bg colour19
#setw -g window-status-current-attr bold
#setw -g window-status-current-format ' #I#[fg=colour249]:#[fg=colour255]#W#[fg=colour249]#F '
#setw -g window-status-fg colour9
#setw -g window-status-bg colour18
#setw -g window-status-attr none
#setw -g window-status-format ' #I#[fg=colour237]:#[fg=colour250]#W#[fg=colour244]#F '
#setw -g window-status-bell-attr bold
#setw -g window-status-bell-fg colour255
#setw -g window-status-bell-bg colour1
#===messages=========================================================
#set -g message-attr bold
#set -g message-fg colour232
#set -g message-bg colour16
#=== Tip and tricks =================================================
#===Display a message
#bind -n m set-option mouse\; display-message "Mouse is now #{?mouse,on,off}"
#===Use clipboard options============================================
#set -g set-clipboard on
#---Unbind all keys
#===Unbind all keys==================================================
#unbind -a
#unbind -a -Tcopy-mode
#unbind -a -Tcopy-mode-vi
#---Turn the mouse on, but without copy mode dragging
#===Turn the mouse on, but without copy mode dragging================
#unbind -n MouseDrag1Pane
#unbind -Tcopy-mode MouseDrag1Pane
#unbind -Tcopy-mode MouseDragEnd1Pane
#===Copy-Paste=======================================================
#bind -Tcopy-mode-vi MouseDown1Pane select-pane
#bind -Tcopy-mode-vi MouseDrag1Pane select-pane\; send -X begin-selection
#bind -Tcopy-mode-vi MouseDragEnd1Pane send -X copy-selection-and-cancel
......@@ -73,20 +176,9 @@ set-option -g word-separators "; @()\'\`\"" #"
#bind -Tcopy-mode-vi DoubleClick1Pane select-pane\; send -X select-word
#bind -Tcopy-mode-vi TripleClick1Pane select-pane\; send -X select-line
#---???---------
#===Copy-Paste=======================================================
#bind -n MouseDrag1Pane if -Ft= '#{mouse_any_flag}' 'if -Ft= \"#{pane_in_mode}\" \"copy-mode -M\" \"send-keys -M\"' 'copy-mode -M'
#bind -n MouseDown3Pane if-shell -Ft= '#{mouse_any_flag}' 'select-pane -t=; send-keys -M' 'select-pane -mt='
#bind -n WheelUpPane if-shell -Ft= '#{mouse_any_flag}' 'send-keys -M' 'if -Ft= \"#{pane_in_mode}\" \"send-keys -M\" \"copy-mode -et=\"'
#bind -n WheelUpPane if-shell -F -t = "#{mouse_any_flag}" "send-keys -M" "if -Ft= '#{pane_in_mode}' 'send-keys -M' 'copy-mode -e; send-keys -M'"
#---Native xterm scrolling
#set -g terminal-overrides "xterm*:XT:smcup@:rmcup@:kUP5=\eOA:kDN5=\eOB:kLFT5=\eOD:kRIT5=\eOC"
#set -ga terminal-overrides ',xterm*:smcup@:rmcup@'
#set -g terminal-overrides 'xterm*:smcup@:rmcup@'
......@@ -6,6 +6,7 @@
# Distributed under the GNU LGPLv3. See LICENSE for more info.
import numpy
import inspect
import functools
from bliss.common.motor_config import StaticConfig
from bliss.common.motor_settings import (
......@@ -98,7 +99,28 @@ class Controller(LogMixin):
if not isinstance(axis, AxisRef)
]
self._update_refs()
self._init_settings()
for axis in self.axes.values():
axis._beacon_channels.clear()
hash_setting = settings.HashSetting("axis.%s" % axis.name)
for setting_name in axis.settings:
setting_value = get_setting_or_config_value(axis, setting_name)
if setting_value is not None:
# write setting to cache
hash_setting[setting_name] = setting_value
chan_name = "axis.%s.%s" % (axis.name, setting_name)
cb = functools.partial(
setting_update_from_channel, setting_name=setting_name, axis=axis
)
if setting_value is None:
chan = Channel(chan_name, callback=cb)
else: