tcs_proxy
– Proxy to the TCS modules¶
Testing code that uses TCS logging and the TCS subsystem interface outside of HET is not possible. Therefore one need to create classes that mocks the original and a way to easily switch between the development and the production environment.
The tcs_lib.tcs_proxy
provides a proxy between an application and the
TCS systems. It is a thin layer that initialize the necessary objects and allow
easy access to them in a transparent and flexible way.
After importing the module:
from tcs_lib import tcs_proxy
we must initialize the proxy before being able to use it:
tcs_proxy.init(conf, section='urls')
conf
is a configuration object containing in the
section section
all the entries needed to create the logging object and the
necessary TCS subsystems. The configuration entries necessary to initialize the
proxy are described in init()
. An example
configuration to use to initialize the logger and two TCS subsystems is:
[urls]
# url to use for the TCS logger, if the module implementing it is found
tcs_log = tcp://127.0.0.1:5555
# if the TCS logger is not found, use a mock object and use the file of the
# next option to configuration the python loggers to used for the mocks
tcs_log_mock_path = /path/to/conf_file.cfg
# We also want two TCS subsystems called tcs and virus
subsystem_names = tcs, virus
# the tcs subsystem url. But we don't need the tcs_mock_path since the
# configuration is already in ``tcs_log_mock_path``
tcs = tcp://127.0.0.1:5556
# and now the virus subsystem
virus = tcp://127.0.0.1:5557
# for virus we might have a difference logger configuration file for the
# mock object
virus_mock_path = /path/to/virus_logger.cfg
After the initialisation, the following attributes become available:
tcs_proxy.tcs_log
: this attribute refers either to an instance ofTCSLog.TCSLog
or a wrapper around a standard python logger that exposes thelog_*
methods listend in_MockTCSLog
tcs_proxy.tcs
,tcs_proxy.virus
: these attributes refer either to instances oftcssubsystem.TCSSubSystem
or of a mock class that echoes the method called and their arguments via a standard python logger.
Besides those, the TCS proxy exposes also an other attribute:
tcs_proxy.errors
. If the tcssubsystem
is importable, this
attribute is an alias of the module itself: i.e. tcs_proxy.errors.error
is
equivalent to tcssubsystem.error
. If the module is not found, any variable
name is associated with Exception
: i.e. both tcs_proxy.errors.error
and tcs_proxy.errors.MyPersonalError
are equivalent to Exception
.
This attribute allows to catch and/or raise TCS exceptions, when available, or
generic ones otherwise.
As said the mock objects use python loggers to log messages and method
calls, whose names are {mod_name}.{name}
where mod_name
is the value of
tcs_proxy.mod_name
, defaulting to tcs_lib.tcs_proxy
, and name
is either tcs_log
or the name of the TCS subsystem. For other software
using the proxy it might be preferable to set the mod_name
before
initializing it, in order to own the loggers. So for a package my_package
I advice to do the following:
from tcs_lib import tcs_proxy
tcs_proxy.mod_name = 'my_package.tcs_proxy'
tcs_proxy.init(conf, section='urls')
The initialised proxies can be cleared using the
clear()
function. The TCS proxy will be also
marked as not initialized.
Note
Assigning tcs_proxy.mod_name = 'my_package.tcs_proxy'
after
initializing the proxy results in AttributeError
. If necessary it is
possible to clear()
the proxy, set the
mod_name
and then re-initialize.
Implementation¶
Proxy for the python interface to the HET Telescope Control System (TCS).
This module tries to import tcssubsystem
and TCSLog
:
- if it succeeds, initialize all the requested TCS instances.
- otherwise use some mock classes that log every command are used
-
class
tcs_lib._tcs_proxy.
TCSProxy
(mod_name='tcs_lib._tcs_proxy')[source]¶ Bases:
object
Proxy implementation. One instance is exposed as
tcs_lib.tcs_proxy
.The only method public method is
init()
and must be called before the proxy attributes can be used.Parameters: - mod_name : string, optional
name of the module to use by the mock
TCSLog
andtcssubsystem
Attributes: mod_name
Name of the module used to initialize the proxy.
- tcs_log :
TCSLog.TCSLog
or_MockTCSLog
instance of the TCSLog class or of the corresponding mock version
- {name} :
tcssubsystem.TCSSubSystem
or_MockTCSSubsystem
for each name in the
subsystem_names
configuration option, instance of the TCSSubSystem class or of the corresponding mock version- errors
proxy objects for TCS exceptions. If the
tcssubsystem
module is found, this attribute it’s an alias of the module, otherwise it is an instances of_MockErrors
-
mod_name
¶ Name of the module used to initialize the proxy. Can be modified only before calling
init()
-
init
(conf, section='urls')[source]¶ Initialize the TCSLog and tcssubsystems, or their mock counterpart.
The following configuration entries from the
section
are used:tcs_log
, optional: url to use to initialise theTCSLog.TCSLog
class. If not given, empty or theTCSLog
module is not found, initialize a mock log classtcs_log_mock_path
, optional: if theTCSLog.TCSLog
cannot be initialized, a mock class is used instead. This class is a proxy for a standard python logger with name{mod_name}.tcs_log
. By default theNullHandler
is attached. However it is possible to customize the loggers, using a configuration file according to the logger configuration file format. The name of this configuration file can be passed using thetcs_log_mock_path
option.subsystem_names
, optional: list of comma separated names of TCS subsystems to initialize. For eachname
the following options are used{name}
, optional: url to use to initialise thetcssubsystem.TCSSubSystem
class. If not given, empty or thetcssubsystem
module is not found, initialize a mock subsystem class{name}_mock_path
, optional: the option has the same meaning of thetcs_log_mock_path
one, with the difference that the python logger name use is{mod_name}.{name}
Note
If the logger configuration file contains the configurations for the mock logger and subsystems, there is no need to assign it to every
*_mock_path
, but only to the first one used, e.g.tcs_log_mock_path
.Parameters: - conf :
configparser.ConfigParser
instance configuration files necessary to initialize the TCS log and subsystems.
- section : string, optional
name of the section containing the configuration
-
_init_tcs_log
(conf, section)[source]¶ Initialize the tcs logging
Parameters: - conf :
configparser.ConfigParser
instance configuration files necessary to initialize the TCS log and subsystems.
- section : string, optional
name of the section containing the configuration
Returns: - :class:`TCSLog.TCSLog` or :class:`_MockTCSLog`
- conf :
-
_init_tcs_subystem
(name, conf, section)[source]¶ Initialize the TCS subsystem or mock subsystem and return it.
Parameters: - name : string
name of the subsystem
- conf :
configparser.ConfigParser
instance configuration files necessary to initialize the TCS log and subsystems.
- section : string, optional
name of the section containing the configuration
Returns: - :class:`tcssubsystem.TCSSubSystem` or :class:`_MockTCSSubsystem`
-
class
tcs_lib._tcs_proxy.
_MockErrors
[source]¶ Bases:
object
Instances of this class return an
Exception
as attribute.
-
class
tcs_lib._tcs_proxy.
_MockTCSSubsystem
(name, mod_name, log_conf_file)[source]¶ Bases:
object
Class that log the methods called and their positional and keyword arguments.
The name of the logger used is
{mod_name}.{name}
where name is the name to the constructor.In order to customize this logger, use the ocd configuration file as described here. If
log_conf_file
is an empty string or if the configuration parsing fails, thelogging.NullHandler
is added to the logger used here. In case of a parsing failure a warning will be printed.Parameters: - name: string
name of the instance created
- mod_name : string
name of module to associate to the mock proxy objects; used to create the logger name
- log_conf_file : string
name of the configuration files necessary to initialize the mock tcs log
-
class
tcs_lib._tcs_proxy.
_MockTCSLog
(name, mod_name, log_conf_file)[source]¶ Bases:
tcs_lib._tcs_proxy._MockTCSSubsystem
Replacement for the
TCSLog.TCSLog
when theTCSLog
module is not available.This class translates the
TCSLog.TCSLog
log_*
calls to the appropriate python logging levels:method log level log_debug 10 (DEBUG) log_info 20 (INFO) log_warn 30 (WARNING) log_error 40 (ERROR) log_fatal 50 (CRITICAL) log_alarm 60 The
TCSLog.TCSLog.log_*()
methods have the following signature:log_info(msg, *args)
The log message is formatted with
msg.format(*args)
before emitting it.Warning
Because of the formatting, log messages are emitted by a function in this module and not in the place where the
log_*
method is called.The name of the logger used is
{mod_name}.{name}
. When initialised byTCSProxy
{name}
istcs_log
.Parameters: - name: string
name of the logger to use
- mod_name : string
name of module to associate to the mock proxy objects; used to create the logger name
- log_conf_file : string
name of the configuration files necessary to initialize the mock tcs log
-
class
tcs_lib._tcs_proxy.
_LogCall
(log, obj, function)[source]¶ Bases:
object
Callable class log the call to function with all its positional and keyword arguments.
The function is logged as info.
Parameters: - log :
logging.Logger
logger
- obj, function : string
name of the object and the function called
- log :