Commit 86aad6b6 authored by Piergiorgio Pancino's avatar Piergiorgio Pancino
Browse files

logbook_print:

- added `lprint` function on shell/standard to sent messages to stdout
  and to logbook (not yet implemented)
parent 58fc9952
Pipeline #17940 failed with stages
in 43 minutes and 57 seconds
......@@ -39,6 +39,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Typing Helper
- pressing F7 will disable typing helper on Bliss Shell
- avoid interpretation of multiline code and of properties
- lprint: new function intended to replace print for printing to stdout and to logbook
### Changed
......
......@@ -38,6 +38,7 @@ from bliss.common.encoder import Encoder
from bliss.config.channels import Channel
from bliss.physics.trajectory import LinearTrajectory
from bliss.common.logtools import *
from bliss.common.utils import rounder
import bliss
import gevent
......@@ -98,6 +99,14 @@ class GroupMove:
polling_time,
)
for _, ax in motions_dict.items():
for mot in ax:
start_ = rounder(mot.axis.tolerance, mot.axis.position)
end_ = rounder(
mot.axis.tolerance,
mot.axis.dial2user(mot.target_pos / mot.axis.steps_per_unit),
)
lprint(f"Moving {mot.axis.name} from {start_} to {end_}")
try:
# Wait for the move to be started (or finished)
gevent.wait([started, self._move_task], count=1)
......
......@@ -5,6 +5,7 @@
# Copyright (c) 2015-2019 Beamline Control Unit, ESRF
# Distributed under the GNU LGPLv3. See LICENSE for more info.
import sys
import logging
import contextlib
from logging import Logger, NullHandler, Formatter
......@@ -30,6 +31,7 @@ __all__ = [
"hexify",
"asciify",
"get_logger",
"lprint",
]
......@@ -211,6 +213,85 @@ def set_log_format(instance, frmt):
raise
from logging import LoggerAdapter
from logging import StreamHandler
class LogbookAdapter(LoggerAdapter):
def process(self, msg, extra):
end = extra.get("end", "\n")
flush = chr(extra.get("flush", True))
return msg + f",{end},{flush}", extra
class LogbookStdoutHandler(StreamHandler):
def emit(self, record):
"""
Emit a record.
If a formatter is specified, it is used to format the record.
The record is then written to the stream with a trailing newline. If
exception information is present, it is formatted using
traceback.print_exception and appended to the stream. If the stream
has an 'encoding' attribute, it is used to determine how to do the
output to the stream.
"""
try:
msg = self.format(record)
stream = sys.stdout
msg, end, flush = msg.rsplit(",", maxsplit=2)
stream.write(msg)
if flush:
self.flush()
if end:
stream.write(end)
except (KeyboardInterrupt, SystemExit):
raise
except:
self.handleError(record)
class LogbookPrint:
def __init__(self):
self.extra = {"flush": True, "end": "\n"}
self.logger = logging.getLogger("bliss.logbook_print")
self.adapter = LogbookAdapter(self.logger, self.extra)
self.logger.setLevel(logging.INFO)
self.logger.propagate = False
self.stdout_handler = LogbookStdoutHandler()
self.stdout_handler.setLevel(logging.INFO)
def add_stdout_handler(self):
"""adding handler will prints to stdout lprint messages"""
if self.stdout_handler not in self.logger.handlers:
self.logger.addHandler(self.stdout_handler)
def remove_stdout_handler(self):
if self.stdout_handler in self.logger.handlers:
self.logger.removeHandler(self.stdout_handler)
def add_logbook_handler(self):
raise NotImplementedError
def remove_logbook_handler(self):
raise NotImplementedError
def lprint(self, *args, **kwargs):
sep = kwargs.pop("sep", " ")
self.extra["end"] = kwargs.pop("end", "\n")
self.extra["flush"] = kwargs.pop("flush", True)
if len(args) > 1:
self.adapter.info(sep.join((str(arg) for arg in args)))
else:
self.adapter.info(args[0])
logbook_printer = LogbookPrint()
lprint = logbook_printer.lprint
@contextlib.contextmanager
def bliss_logger():
saved_logger_class = logging.getLoggerClass()
......
......@@ -86,6 +86,7 @@ def sync(*axes):
axes: list of axis objects or names. If no axis is given, it syncs all
all axes present in the session
"""
lprint("Forcing axes synchronization with hardware")
if axes:
axes = global_map.get_axis_objects_iter(*axes)
else:
......
......@@ -442,6 +442,11 @@ def cli(
set_bliss_shell_mode(True)
# adding stdout print of lprint messages
from bliss.common.logtools import logbook_printer
logbook_printer.add_stdout_handler()
ERROR_REPORT = install_excepthook()
ERROR_REPORT.expert_mode = expert_error_report
......
......@@ -127,7 +127,6 @@ def sync(*axes):
axes: list of axis objects or names. If no axis is given, it syncs all
all axes present in the session
"""
print("Forcing axes synchronization with hardware")
std_sync(*axes)
......
......@@ -142,6 +142,18 @@ spec_m3 READY (Axis is READY)
## introspection, doc, logging
### logbook print ###
The `lprint` function is a replacement for python standard `print` function
that sends what is given to both stdout and to the logbook.
Everything that should be logged to the logbook for any reason should use this
instead of the normal print.
You can use `lprint` even when using Bliss in library mode: no output will
be send to stdout, but messages will be forwarded to logbook.
### prdef (print definition)
`prdef(<function>)`: Displays information about given function :
definition file, docstring and source code.
......
import logging
import subprocess
import pytest
from bliss.shell.standard import wa, wm, sta, stm
from bliss.shell.standard import wa, wm, sta, stm, umvr, lprint, sync
@pytest.fixture
......@@ -179,3 +182,51 @@ def test_stm_exception(default_session, capsys):
errmsg = "RuntimeError: Error on motor 'bad': BAD POSITION\n"
assert captured.err[-len(errmsg) :] == errmsg
def execute_in_subprocess(command):
script = subprocess.Popen(
["python", "-c", command], stderr=subprocess.PIPE, stdout=subprocess.PIPE
)
output, err = script.communicate()
returncode = script.returncode
return output.decode(), err.decode(), returncode
def test_umvr_lib_mode(capsys, default_session):
"""lprint should not show anything"""
commands = (
"from bliss.shell.standard import umv",
"from bliss.config import static",
"config = static.get_config()",
"roby = config.get('roby')",
"umv(roby,10)",
)
output, err, returncode = execute_in_subprocess(";".join(commands))
assert "Moving," not in output
assert "MockupAxis" not in output
assert returncode == 0
assert len(err) == 0
def test_sync_lib_mode(capsys, default_session):
"""lprint should not show anything"""
commands = (
"from bliss.shell.standard import sync",
"from bliss.config import static",
"config = static.get_config()",
"roby = config.get('roby')",
"sync(roby)",
)
output, err, returncode = execute_in_subprocess(";".join(commands))
assert "Forcing axes synchronization with hardware" not in output
assert returncode == 0
assert len(err) == 0
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment