diff --git a/.make/lint.mk b/.make/lint.mk index 318a1cd587934aa71ed9e6a2a7ba5a3b105a666a..c343c0645e07e9ca87c91acadafa2dc50add13b7 100644 --- a/.make/lint.mk +++ b/.make/lint.mk @@ -7,6 +7,7 @@ _format-lint-install: # install requirements for code formatting and checking format: _format-lint-install # apply code formatting black src/ tests/ + docformatter -r -i --wrap-summaries 88 --pre-summary-newline src/ tests/ lint: _format-lint-install mkdir -p build/reports diff --git a/.release b/.release index ad32ca72c7bc14aa7e85a5d709a4885b615ac56c..3cdbac45f73bd3b082113855510e10a205f3a222 100644 --- a/.release +++ b/.release @@ -1,2 +1,2 @@ -release=0.11.1 -tag=ska_tango_base-0.11.1 +release=0.11.2 +tag=ska_tango_base-0.11.2 diff --git a/README.md b/README.md index e1a557c1d67e735224d5cdd6e98f7c5336f933e5..11528518e02e7817ab860944cb46f0bdf3afe6bd 100644 --- a/README.md +++ b/README.md @@ -247,6 +247,9 @@ Tango devices can be launched with a `-v` parameter to set the logging level. Fo ## Version History +#### 0.11.2 +- Update docstrings for 100% coverage and PEP257 compliance + #### 0.11.1 - Minor breaking change: rename of "Master" devices to "Controller" diff --git a/requirements-lint.txt b/requirements-lint.txt index 08b13b0f611d03e74efd5cfc29167c20f300444d..8c503d57a8744aaa17a0215285e471e3597b7e8a 100644 --- a/requirements-lint.txt +++ b/requirements-lint.txt @@ -1,4 +1,7 @@ black +docformatter flake8 flake8_formatter_junit_xml -flake8-black \ No newline at end of file +flake8-black +flake8-docstrings +flake8-rst-docstrings diff --git a/setup.cfg b/setup.cfg index 00c43d7e4aaaf7fd5723498bceaff04d6a7d4025..6922aa224f5116f607274066b04b6963862e134e 100644 --- a/setup.cfg +++ b/setup.cfg @@ -25,3 +25,6 @@ max-line-length = 120 # E203 and W503 conflict with black ignore = E203,W503 + +rst-directives = inheritance-diagram, uml +rst-roles = py:attr, py:class, py:exc, py:meth, py:mod diff --git a/src/ska_tango_base/__init__.py b/src/ska_tango_base/__init__.py index cbc93f80c682d0fa7d04cf8fc0706abfad041ff0..c7f7ecd4a6f0aa3dcafa483ee3c3f75d3763c332 100644 --- a/src/ska_tango_base/__init__.py +++ b/src/ska_tango_base/__init__.py @@ -1,3 +1,5 @@ +"""This package provides shared functionality and patterns for SKA TANGO devices.""" + __all__ = ( # subpackages "base", diff --git a/src/ska_tango_base/alarm_handler_device.py b/src/ska_tango_base/alarm_handler_device.py index 120198827bf9c752c702d72fc599030d79a0bbfd..ab70e6bfdf25609aec59ff1aa2b87bb1817470f9 100644 --- a/src/ska_tango_base/alarm_handler_device.py +++ b/src/ska_tango_base/alarm_handler_device.py @@ -5,11 +5,12 @@ # # """ -This module implements SKAAlarmHandler, a generic base device for Alarms -for SKA. It exposes SKA alarms and SKA alerts as Tango attributes. SKA -Alarms and SKA/Element Alerts are rules-based configurable conditions -that can be defined over multiple attribute values and quality factors, -and are separate from the "built-in" Tango attribute alarms. +This module implements SKAAlarmHandler, a generic base device for Alarms for SKA. + +It exposes SKA alarms and SKA alerts as Tango attributes. SKA Alarms and +SKA/Element Alerts are rules-based configurable conditions that can be +defined over multiple attribute values and quality factors, and are +separate from the "built-in" Tango attribute alarms. """ # PROTECTED REGION ID(SKAAlarmHandler.additionnal_import) ENABLED START # # Tango imports @@ -26,9 +27,7 @@ __all__ = ["SKAAlarmHandler", "main"] class SKAAlarmHandler(SKABaseDevice): - """ - A generic base device for Alarms for SKA. - """ + """A generic base device for Alarms for SKA.""" # PROTECTED REGION ID(SKAAlarmHandler.class_variable) ENABLED START # # PROTECTED REGION END # // SKAAlarmHandler.class_variable @@ -98,9 +97,7 @@ class SKAAlarmHandler(SKABaseDevice): # --------------- def init_command_objects(self): - """ - Sets up the command objects - """ + """Set up the command objects.""" super().init_command_objects() self.register_command_object( "GetAlarmRule", @@ -125,11 +122,24 @@ class SKAAlarmHandler(SKABaseDevice): def always_executed_hook(self): # PROTECTED REGION ID(SKAAlarmHandler.always_executed_hook) ENABLED START # + """ + Perform actions that are executed before every device command. + + This is a Tango hook. + """ pass # PROTECTED REGION END # // SKAAlarmHandler.always_executed_hook def delete_device(self): # PROTECTED REGION ID(SKAAlarmHandler.delete_device) ENABLED START # + """ + Clean up any resources prior to device deletion. + + This method is a Tango hook that is called by the device + destructor and by the device Init command. It allows for any + memory or other resources allocated in the init_device method to + be released prior to device deletion. + """ pass # PROTECTED REGION END # // SKAAlarmHandler.delete_device @@ -140,7 +150,8 @@ class SKAAlarmHandler(SKABaseDevice): def read_statsNrAlerts(self): # PROTECTED REGION ID(SKAAlarmHandler.statsNrAlerts_read) ENABLED START # """ - Reads number of active alerts. + Read number of active alerts. + :return: Number of active alerts """ return 0 @@ -149,7 +160,8 @@ class SKAAlarmHandler(SKABaseDevice): def read_statsNrAlarms(self): # PROTECTED REGION ID(SKAAlarmHandler.statsNrAlarms_read) ENABLED START # """ - Reads number of active alarms. + Read number of active alarms. + :return: Number of active alarms """ return 0 @@ -158,7 +170,8 @@ class SKAAlarmHandler(SKABaseDevice): def read_statsNrNewAlarms(self): # PROTECTED REGION ID(SKAAlarmHandler.statsNrNewAlarms_read) ENABLED START # """ - Reads number of new active alarms. + Read number of new active alarms. + :return: Number of new active alarms """ return 0 @@ -167,7 +180,8 @@ class SKAAlarmHandler(SKABaseDevice): def read_statsNrUnackAlarms(self): # PROTECTED REGION ID(SKAAlarmHandler.statsNrUnackAlarms_read) ENABLED START # """ - Reads number of unacknowledged alarms. + Read number of unacknowledged alarms. + :return: Number of unacknowledged alarms. """ return 0.0 @@ -176,7 +190,8 @@ class SKAAlarmHandler(SKABaseDevice): def read_statsNrRtnAlarms(self): # PROTECTED REGION ID(SKAAlarmHandler.statsNrRtnAlarms_read) ENABLED START # """ - Reads number of returned alarms. + Read number of returned alarms. + :return: Number of returned alarms """ return 0.0 @@ -185,7 +200,8 @@ class SKAAlarmHandler(SKABaseDevice): def read_activeAlerts(self): # PROTECTED REGION ID(SKAAlarmHandler.activeAlerts_read) ENABLED START # """ - Reads list of active alerts. + Read list of active alerts. + :return: List of active alerts """ return [""] @@ -194,7 +210,8 @@ class SKAAlarmHandler(SKABaseDevice): def read_activeAlarms(self): # PROTECTED REGION ID(SKAAlarmHandler.activeAlarms_read) ENABLED START # """ - Reads list of active alarms. + Read list of active alarms. + :return: List of active alarms """ return [""] @@ -205,9 +222,7 @@ class SKAAlarmHandler(SKABaseDevice): # -------- class GetAlarmRuleCommand(BaseCommand): - """ - A class for the SKAAlarmHandler's GetAlarmRule() command. - """ + """A class for the SKAAlarmHandler's GetAlarmRule() command.""" def do(self, argin): """ @@ -219,9 +234,7 @@ class SKAAlarmHandler(SKABaseDevice): return "" class GetAlarmDataCommand(BaseCommand): - """ - A class for the SKAAlarmHandler's GetAlarmData() command. - """ + """A class for the SKAAlarmHandler's GetAlarmData() command.""" def do(self, argin): """ @@ -233,15 +246,11 @@ class SKAAlarmHandler(SKABaseDevice): return "" class GetAlarmAdditionalInfoCommand(BaseCommand): - """ - A class for the SKAAlarmHandler's GetAlarmAdditionalInfo() - command. - """ + """A class for the SKAAlarmHandler's GetAlarmAdditionalInfo() command.""" def do(self, argin): """ - Stateless hook for SKAAlarmHandler GetAlarmAdditionalInfo() - command. + Stateless hook for SKAAlarmHandler GetAlarmAdditionalInfo() command. :return: Alarm additional info :rtype: JSON string @@ -249,9 +258,7 @@ class SKAAlarmHandler(SKABaseDevice): return "" class GetAlarmStatsCommand(BaseCommand): - """ - A class for the SKAAlarmHandler's GetAlarmStats() command. - """ + """A class for the SKAAlarmHandler's GetAlarmStats() command.""" def do(self): """ @@ -263,9 +270,7 @@ class SKAAlarmHandler(SKABaseDevice): return "" class GetAlertStatsCommand(BaseCommand): - """ - A class for the SKAAlarmHandler's GetAlertStats() command. - """ + """A class for the SKAAlarmHandler's GetAlertStats() command.""" def do(self): """ @@ -308,8 +313,9 @@ class SKAAlarmHandler(SKABaseDevice): def GetAlarmData(self, argin): # PROTECTED REGION ID(SKAAlarmHandler.GetAlarmData) ENABLED START # """ - Get list of current value, quality factor and status of - all attributes participating in the alarm rule. + Get data on all attributes participating in the alarm rule. + + The data includes current value, quality factor and status. To modify behaviour for this command, modify the do() method of the command class. @@ -389,12 +395,7 @@ class SKAAlarmHandler(SKABaseDevice): def main(args=None, **kwargs): # PROTECTED REGION ID(SKAAlarmHandler.main) ENABLED START # - """ - Main function of the SKAAlarmHandler module. - :param args: - :param kwargs: - :return: - """ + """Launch an SKAAlarmHandler device.""" return run((SKAAlarmHandler,), args=args, **kwargs) # PROTECTED REGION END # // SKAAlarmHandler.main diff --git a/src/ska_tango_base/base/__init__.py b/src/ska_tango_base/base/__init__.py index 965a6367fa6fc2eef5d54c5bfa130dfd0f352b47..7f05be17fa38b03f12dafc4c70b2806fa4f41ea1 100644 --- a/src/ska_tango_base/base/__init__.py +++ b/src/ska_tango_base/base/__init__.py @@ -1,7 +1,4 @@ -""" -This subpackage implements Tango device functionality common to all SKA -Tango devices. -""" +"""This subpackage implements functionality common to all SKA Tango devices.""" __all__ = ( "AdminModeModel", diff --git a/src/ska_tango_base/base/admin_mode_model.py b/src/ska_tango_base/base/admin_mode_model.py index 95236b4123cc2d93b9ea37be8da5bef3f9ef44eb..ba70d88f3f8193dca6d25b80e0c01084cbca1103 100644 --- a/src/ska_tango_base/base/admin_mode_model.py +++ b/src/ska_tango_base/base/admin_mode_model.py @@ -1,6 +1,7 @@ """ -This module specifies the admin mode model for SKA LMC Tango devices. It -consists of a single public class: :py:class:`.AdminModeModel`. This +This module specifies the admin mode model for SKA LMC Tango devices. + +It consists of a single public class: :py:class:`.AdminModeModel`. This uses a state machine to device device adminMode, represented as a :py:class:`ska_tango_base.control_model.AdminMode` enum value, and reported by Tango devices through the ``AdminMode`` attribute. @@ -25,7 +26,7 @@ class _AdminModeMachine(Machine): def __init__(self, callback=None, **extra_kwargs): """ - Initialises the admin mode state machine model. + Initialise the admin mode state machine model. :param callback: A callback to be called whenever there is a transition to a new admin mode value @@ -81,8 +82,9 @@ class _AdminModeMachine(Machine): def _state_changed(self): """ - State machine callback that is called every time the admin mode - changes. Responsible for ensuring that callbacks are called. + State machine callback that is called every time the admin mode changes. + + Responsible for ensuring that callbacks are called. """ if self._callback is not None: self._callback(self.state) @@ -140,12 +142,11 @@ class AdminModeModel: .. figure:: _AdminModeMachine_autogenerated.png :alt: Diagram of the admin mode state machine, as implemented - """ def __init__(self, logger, callback=None): """ - Initialises the state model. + Initialise the state model. :param logger: the logger to be used by this state model. :type logger: a logger that implements the standard library @@ -164,7 +165,7 @@ class AdminModeModel: @property def admin_mode(self): """ - Returns the admin_mode + Return the admin_mode. :returns: admin_mode of this state model :rtype: AdminMode @@ -173,12 +174,12 @@ class AdminModeModel: def _admin_mode_changed(self, machine_state): """ - Helper method that updates admin_mode whenever the admin_mode - state machine reports a change of state, ensuring that the - callback is called if one exists. + Handle notification that the admin mode state machine has changed state. - :param machine_state: the new state of the adminMode state - machine + This is a helper method that updates admin mode, ensuring that + the callback is called if one exists. + + :param machine_state: the new state of the admin mode machine :type machine_state: str """ admin_mode = AdminMode[machine_state] @@ -189,7 +190,7 @@ class AdminModeModel: def is_action_allowed(self, action, raise_if_disallowed=False): """ - Whether a given action is allowed in the current state. + Return whether a given action is allowed in the current state. :param action: an action, as given in the transitions table :type action: str @@ -217,7 +218,7 @@ class AdminModeModel: def perform_action(self, action): """ - Performs an action on the state model + Perform an action on the state model. :param action: an action, as given in the transitions table :type action: str @@ -228,8 +229,7 @@ class AdminModeModel: @for_testing_only def _straight_to_state(self, *, admin_mode): """ - Takes this AdminMode state model straight to the specified - AdminMode. + Take this AdminMode state model straight to the specified AdminMode. This method exists to simplify testing; for example, if testing that a command may be run in a given AdminMode, you can push diff --git a/src/ska_tango_base/base/base_device.py b/src/ska_tango_base/base/base_device.py index 005d1d9cd2625ff5e913500be2d048afa7ae5cd6..83ce85a3d327a51793d95451f3ed82965f63943b 100644 --- a/src/ska_tango_base/base/base_device.py +++ b/src/ska_tango_base/base/base_device.py @@ -6,8 +6,9 @@ # """ -This module implements a generic base model and device for SKA. It -exposes the generic attributes, properties and commands of an SKA +This module implements a generic base model and device for SKA. + +It exposes the generic attributes, properties and commands of an SKA device. """ # PROTECTED REGION ID(SKABaseDevice.additionnal_import) ENABLED START # @@ -63,7 +64,8 @@ _DEBUGGER_PORT = 5678 class _Log4TangoLoggingLevel(enum.IntEnum): - """Python enumerated type for Tango log4tango logging levels. + """ + Python enumerated type for Tango log4tango logging levels. This is different to tango.LogLevel, and is required if using a device's set_log_level() method. It is not currently exported @@ -142,7 +144,8 @@ class TangoLoggingServiceHandler(logging.Handler): class LoggingUtils: - """Utility functions to aid logger configuration. + """ + Utility functions to aid logger configuration. These functions are encapsulated in class to aid testing - it allows dependent functions to be mocked. @@ -150,7 +153,8 @@ class LoggingUtils: @staticmethod def sanitise_logging_targets(targets, device_name): - """Validate and return logging targets '<type>::<name>' strings. + """ + Validate and return logging targets '<type>::<name>' strings. :param targets: List of candidate logging target strings, like '<type>[::<name>]' @@ -201,28 +205,46 @@ class LoggingUtils: @staticmethod def get_syslog_address_and_socktype(url): - """Parse syslog URL and extract address and socktype parameters for SysLogHandler. - - :param url: - Universal resource locator string for syslog target. Three types are supported: - file path, remote UDP server, remote TCP server. - - Output to a file: 'file://<path to file>' - Example: 'file:///dev/log' will write to '/dev/log' - - Output to remote server over UDP: 'udp://<hostname>:<port>' - Example: 'udp://syslog.com:514' will send to host 'syslog.com' on UDP port 514 - - Output to remote server over TCP: 'tcp://<hostname>:<port>' - Example: 'tcp://rsyslog.com:601' will send to host 'rsyslog.com' on TCP port 601 - For backwards compatibility, if the protocol prefix is missing, the type is - interpreted as file. This is deprecated. - - Example: '/dev/log' is equivalent to 'file:///dev/log' - - :return: (address, socktype) + """ + Parse syslog URL and extract address and socktype parameters for SysLogHandler. + + :param url: Universal resource locator string for syslog target. + Three types are supported: file path, remote UDP server, + remote TCP server. + + - Output to a file: 'file://<path to file>'. For example, + 'file:///dev/log' will write to '/dev/log'. + + - Output to remote server over UDP: + 'udp://<hostname>:<port>'. For example, + 'udp://syslog.com:514' will send to host 'syslog.com' on + UDP port 514 + + - Output to remote server over TCP: + 'tcp://<hostname>:<port>'. For example, + 'tcp://rsyslog.com:601' will send to host 'rsyslog.com' on + TCP port 601 + + For backwards compatibility, if the protocol prefix is + missing, the type is interpreted as file. This is + deprecated. For example, '/dev/log' is equivalent to + 'file:///dev/log'. + + :return: An (address, socktype) tuple. + For file types: - - address is the file path as as string + + - the address is the file path as as string + - socktype is None + For UDP and TCP: - - address is tuple of (hostname, port), with hostname a string, and port an integer. - - socktype is socket.SOCK_DGRAM for UDP, or socket.SOCK_STREAM for TCP. + + - the address is tuple of (hostname, port), with hostname a + string, and port an integer. + + - socktype is socket.SOCK_DGRAM for UDP, or + socket.SOCK_STREAM for TCP. :raises LoggingTargetError: for invalid url string """ @@ -271,7 +293,10 @@ class LoggingUtils: @staticmethod def create_logging_handler(target, tango_logger=None): - """Create a Python log handler based on the target type (console, file, syslog, tango) + """ + Create a Python log handler based on the target type. + + Supported target types are "console", "file", "syslog", "tango". :param target: Logging target for logger, <type>::<name> @@ -350,21 +375,17 @@ __all__ = ["SKABaseDevice", "main"] class SKABaseDevice(Device): - """ - A generic base device for SKA. - """ + """A generic base device for SKA.""" _global_debugger_listening = False _global_debugger_allocated_port = 0 class InitCommand(ResponseCommand, CompletionCommand): - """ - A class for the SKABaseDevice's init_device() "command". - """ + """A class for the SKABaseDevice's init_device() "command".""" def __init__(self, target, op_state_model, logger=None): """ - Create a new InitCommand + Create a new InitCommand. :param target: the object that this command acts upon; for example, the SKABaseDevice device for which this class @@ -432,10 +453,7 @@ class SKABaseDevice(Device): _logging_configured = False def _init_logging(self): - """ - This method initializes the logging mechanism, based on default - properties. - """ + """Initialize the logging mechanism, using default properties.""" class EnsureTagsFilter(logging.Filter): """Ensure all records have a "tags" field - empty string, if not provided.""" @@ -665,8 +683,11 @@ class SKABaseDevice(Device): def _update_admin_mode(self, admin_mode): """ - Helper method for changing admin_mode; passed to the state model as a - callback + Perform Tango operations in response to a change in admin mode. + + This helper method is passed to the admin mode model as a + callback, so that the model can trigger actions in the Tango + device. :param admin_mode: the new admin_mode value :type admin_mode: :py:class:`~ska_tango_base.control_model.AdminMode` @@ -676,8 +697,11 @@ class SKABaseDevice(Device): def _update_state(self, state): """ - Helper method for changing state; passed to the state model as a - callback + Perform Tango operations in response to a change in op state. + + This helper method is passed to the op state model as a + callback, so that the model can trigger actions in the Tango + device. :param state: the new state value :type state: :py:class:`tango.DevState` @@ -689,8 +713,7 @@ class SKABaseDevice(Device): def set_state(self, state): """ - Helper method for setting device state, ensuring that change - events are pushed. + Set the device state, ensuring that change events are pushed. :param state: the new state :type state: :py:class:`tango.DevState` @@ -701,8 +724,7 @@ class SKABaseDevice(Device): def set_status(self, status): """ - Helper method for setting device status, ensuring that change - events are pushed. + Set the device status, ensuring that change events are pushed. :param status: the new status :type status: str @@ -713,12 +735,12 @@ class SKABaseDevice(Device): def init_device(self): """ - Initializes the tango device after startup. + Initialise the tango device after startup. Subclasses that have no need to override the default - default implementation of state management may leave - ``init_device()`` alone. Override the ``do()`` method - on the nested class ``InitCommand`` instead. + implementation of state management may leave ``init_device()`` + alone. Override the ``do()`` method on the nested class + ``InitCommand`` instead. """ try: super().init_device() @@ -737,9 +759,7 @@ class SKABaseDevice(Device): print(f"ERROR: init_device failed, and no logger: {exc}.") def _init_state_model(self): - """ - Creates the state model for the device - """ + """Initialise the state model for the device.""" self.op_state_model = OpStateModel( logger=self.logger, callback=self._update_state, @@ -750,12 +770,12 @@ class SKABaseDevice(Device): ) def create_component_manager(self): + """Create and return a component manager for this device.""" return BaseComponentManager(self.op_state_model) def register_command_object(self, command_name, command_object): """ - Registers a command object as the object to handle invocations - of a given command + Register an object as a handler for a command. :param command_name: name of the command for which the object is being registered @@ -768,7 +788,7 @@ class SKABaseDevice(Device): def get_command_object(self, command_name): """ - Returns the command object (handler) for a given command. + Return the command object (handler) for a given command. :param command_name: name of the command for which a command object (handler) is sought @@ -780,10 +800,7 @@ class SKABaseDevice(Device): return self._command_objects[command_name] def init_command_objects(self): - """ - Creates and registers command objects (handlers) for the - commands supported by this device. - """ + """Register command objects (handlers) for this device's commands.""" self._command_objects = {} component_args = (self.component_manager, self.op_state_model, self.logger) @@ -803,14 +820,21 @@ class SKABaseDevice(Device): def always_executed_hook(self): # PROTECTED REGION ID(SKABaseDevice.always_executed_hook) ENABLED START # """ - Method that is always executed before any device command gets executed. + Perform actions that are executed before every device command. + + This is a Tango hook. """ # PROTECTED REGION END # // SKABaseDevice.always_executed_hook def delete_device(self): # PROTECTED REGION ID(SKABaseDevice.delete_device) ENABLED START # """ - Method to cleanup when device is stopped. + Clean up any resources prior to device deletion. + + This method is a Tango hook that is called by the device + destructor and by the device Init command. It allows for any + memory or other resources allocated in the init_device method to + be released prior to device deletion. """ # PROTECTED REGION END # // SKABaseDevice.delete_device @@ -821,7 +845,7 @@ class SKABaseDevice(Device): def read_buildState(self): # PROTECTED REGION ID(SKABaseDevice.buildState_read) ENABLED START # """ - Reads the Build State of the device. + Read the Build State of the device. :return: the build state of the device """ @@ -831,7 +855,7 @@ class SKABaseDevice(Device): def read_versionId(self): # PROTECTED REGION ID(SKABaseDevice.versionId_read) ENABLED START # """ - Reads the Version Id of the device. + Read the Version Id of the device. :return: the version id of the device """ @@ -841,7 +865,7 @@ class SKABaseDevice(Device): def read_loggingLevel(self): # PROTECTED REGION ID(SKABaseDevice.loggingLevel_read) ENABLED START # """ - Reads logging level of the device. + Read the logging level of the device. :return: Logging level of the device. """ @@ -851,8 +875,9 @@ class SKABaseDevice(Device): def write_loggingLevel(self, value): # PROTECTED REGION ID(SKABaseDevice.loggingLevel_write) ENABLED START # """ - Sets logging level for the device. Both the Python logger and the - Tango logger are updated. + Set the logging level for the device. + + Both the Python logger and the Tango logger are updated. :param value: Logging level for logger @@ -880,7 +905,7 @@ class SKABaseDevice(Device): def read_loggingTargets(self): # PROTECTED REGION ID(SKABaseDevice.loggingTargets_read) ENABLED START # """ - Reads the additional logging targets of the device. + Read the additional logging targets of the device. Note that this excludes the handlers provided by the ska_ser_logging library defaults. @@ -893,7 +918,7 @@ class SKABaseDevice(Device): def write_loggingTargets(self, value): # PROTECTED REGION ID(SKABaseDevice.loggingTargets_write) ENABLED START # """ - Sets the additional logging targets for the device. + Set the additional logging targets for the device. Note that this excludes the handlers provided by the ska_ser_logging library defaults. @@ -908,7 +933,7 @@ class SKABaseDevice(Device): def read_healthState(self): # PROTECTED REGION ID(SKABaseDevice.healthState_read) ENABLED START # """ - Reads Health State of the device. + Read the Health State of the device. :return: Health State of the device """ @@ -918,7 +943,7 @@ class SKABaseDevice(Device): def read_adminMode(self): # PROTECTED REGION ID(SKABaseDevice.adminMode_read) ENABLED START # """ - Reads Admin Mode of the device. + Read the Admin Mode of the device. :return: Admin Mode of the device :rtype: AdminMode @@ -929,7 +954,7 @@ class SKABaseDevice(Device): def write_adminMode(self, value): # PROTECTED REGION ID(SKABaseDevice.adminMode_write) ENABLED START # """ - Sets Admin Mode of the device. + Set the Admin Mode of the device. :param value: Admin Mode of the device. :type value: :py:class:`~ska_tango_base.control_model.AdminMode` @@ -959,7 +984,7 @@ class SKABaseDevice(Device): def read_controlMode(self): # PROTECTED REGION ID(SKABaseDevice.controlMode_read) ENABLED START # """ - Reads Control Mode of the device. + Read the Control Mode of the device. :return: Control Mode of the device """ @@ -969,7 +994,7 @@ class SKABaseDevice(Device): def write_controlMode(self, value): # PROTECTED REGION ID(SKABaseDevice.controlMode_write) ENABLED START # """ - Sets Control Mode of the device. + Set the Control Mode of the device. :param value: Control mode value """ @@ -979,7 +1004,7 @@ class SKABaseDevice(Device): def read_simulationMode(self): # PROTECTED REGION ID(SKABaseDevice.simulationMode_read) ENABLED START # """ - Reads Simulation Mode of the device. + Read the Simulation Mode of the device. :return: Simulation Mode of the device. """ @@ -989,7 +1014,7 @@ class SKABaseDevice(Device): def write_simulationMode(self, value): # PROTECTED REGION ID(SKABaseDevice.simulationMode_write) ENABLED START # """ - Sets Simulation Mode of the device + Set the Simulation Mode of the device. :param value: SimulationMode """ @@ -999,7 +1024,7 @@ class SKABaseDevice(Device): def read_testMode(self): # PROTECTED REGION ID(SKABaseDevice.testMode_read) ENABLED START # """ - Reads Test Mode of the device. + Read the Test Mode of the device. :return: Test Mode of the device """ @@ -1009,7 +1034,7 @@ class SKABaseDevice(Device): def write_testMode(self, value): # PROTECTED REGION ID(SKABaseDevice.testMode_write) ENABLED START # """ - Sets Test Mode of the device. + Set the Test Mode of the device. :param value: Test Mode """ @@ -1021,9 +1046,7 @@ class SKABaseDevice(Device): # -------- class GetVersionInfoCommand(BaseCommand): - """ - A class for the SKABaseDevice's GetVersionInfo() command. - """ + """A class for the SKABaseDevice's GetVersionInfo() command.""" def do(self): """ @@ -1045,7 +1068,7 @@ class SKABaseDevice(Device): def GetVersionInfo(self): # PROTECTED REGION ID(SKABaseDevice.GetVersionInfo) ENABLED START # """ - Returns the version information of the device. + Return the version information of the device. To modify behaviour for this command, modify the do() method of the command class. @@ -1057,13 +1080,11 @@ class SKABaseDevice(Device): # PROTECTED REGION END # // SKABaseDevice.GetVersionInfo class ResetCommand(StateModelCommand, ResponseCommand): - """ - A class for the SKABaseDevice's Reset() command. - """ + """A class for the SKABaseDevice's Reset() command.""" def __init__(self, target, op_state_model, logger=None): """ - Create a new ResetCommand + Create a new ResetCommand. :param target: the object that this command acts upon; for example, the device's component manager @@ -1095,8 +1116,7 @@ class SKABaseDevice(Device): def is_Reset_allowed(self): """ - Whether the ``Reset()`` command is allowed to be run in the - current state + Whether the ``Reset()`` command is allowed to be run in the current state. :returns: whether the ``Reset()`` command is allowed to be run in the current state @@ -1127,13 +1147,11 @@ class SKABaseDevice(Device): return [[return_code], [message]] class StandbyCommand(StateModelCommand, ResponseCommand): - """ - A class for the SKABaseDevice's Standby() command. - """ + """A class for the SKABaseDevice's Standby() command.""" def __init__(self, target, op_state_model, logger=None): """ - Constructor for StandbyCommand + Initialise a new StandbyCommand instance. :param target: the object that this command acts upon; for example, the device's component manager @@ -1182,7 +1200,7 @@ class SKABaseDevice(Device): @DebugIt() def Standby(self): """ - Put the device into standby mode + Put the device into standby mode. To modify behaviour for this command, modify the do() method of the command class. @@ -1197,13 +1215,11 @@ class SKABaseDevice(Device): return [[return_code], [message]] class OffCommand(StateModelCommand, ResponseCommand): - """ - A class for the SKABaseDevice's Off() command. - """ + """A class for the SKABaseDevice's Off() command.""" def __init__(self, target, op_state_model, logger=None): """ - Constructor for OffCommand + Initialise a new OffCommand instance. :param target: the object that this command acts upon; for example, the device's component manager @@ -1252,7 +1268,7 @@ class SKABaseDevice(Device): @DebugIt() def Off(self): """ - Turn the device off + Turn the device off. To modify behaviour for this command, modify the do() method of the command class. @@ -1267,13 +1283,11 @@ class SKABaseDevice(Device): return [[return_code], [message]] class OnCommand(StateModelCommand, ResponseCommand): - """ - A class for the SKABaseDevice's On() command. - """ + """A class for the SKABaseDevice's On() command.""" def __init__(self, target, op_state_model, logger=None): """ - Constructor for OnCommand + Initialise a new OnCommand instance. :param target: the object that this command acts upon; for example, the device's component manager @@ -1323,7 +1337,7 @@ class SKABaseDevice(Device): @DebugIt() def On(self): """ - Turn device on + Turn device on. To modify behaviour for this command, modify the do() method of the command class. @@ -1338,9 +1352,7 @@ class SKABaseDevice(Device): return [[return_code], [message]] class DebugDeviceCommand(BaseCommand): - """ - A class for the SKABaseDevice's DebugDevice() command. - """ + """A class for the SKABaseDevice's DebugDevice() command.""" def do(self): """ @@ -1370,6 +1382,7 @@ class SKABaseDevice(Device): return SKABaseDevice._global_debugger_allocated_port def start_debugger_and_get_port(self, port): + """Start the debugger and return the allocated port.""" self.logger.warning("Starting debugger...") interface, allocated_port = debugpy.listen(("0.0.0.0", port)) self.logger.warning( @@ -1378,6 +1391,7 @@ class SKABaseDevice(Device): return allocated_port def monkey_patch_all_methods_for_debugger(self): + """Monkeypatch methods that need to be patched for the debugger.""" all_methods = self.get_all_methods() patched = [] for owner, name, method in all_methods: @@ -1390,6 +1404,7 @@ class SKABaseDevice(Device): self.logger.debug("Patched methods: %s", sorted(patched)) def get_all_methods(self): + """Return a list of the device's methods.""" methods = [] device = self.target for name, method in inspect.getmembers(device, inspect.ismethod): @@ -1403,11 +1418,13 @@ class SKABaseDevice(Device): @staticmethod def method_must_be_patched_for_debugger(owner, method): - """Determine if methods are worth debugging. + """ + Determine if methods are worth debugging. - The goal is to find all the user's Python methods, but not the - lower level PyTango device and Boost extension methods. The - `typing.types.FunctionType` check excludes the Boost methods. + The goal is to find all the user's Python methods, but not + the lower level PyTango device and Boost extension methods. + The `typing.types.FunctionType` check excludes the Boost + methods. """ skip_module_names = ["tango.device_server", "tango.server", "logging"] skip_owner_types = [SKABaseDevice.DebugDeviceCommand] @@ -1418,11 +1435,13 @@ class SKABaseDevice(Device): ) def patch_method_for_debugger(self, owner, name, method): - """Ensure method calls trigger the debugger. + """ + Ensure method calls trigger the debugger. - Most methods in a device are executed by calls from threads spawned - by the cppTango layer. These threads are not known to Python, so - we have to explicitly inform the debugger about them. + Most methods in a device are executed by calls from threads + spawned by the cppTango layer. These threads are not known + to Python, so we have to explicitly inform the debugger + about them. """ def debug_thread_wrapper(orig_method, *args, **kwargs): @@ -1438,10 +1457,10 @@ class SKABaseDevice(Device): @DebugIt() def DebugDevice(self): """ - Enables remote debugging of this device. + Enable remote debugging of this device. To modify behaviour for this command, modify the do() method of - the command class: :class:`.DebugDeviceCommand`. + the command class: :py:class:`.DebugDeviceCommand`. """ command = self.get_command_object("DebugDevice") return command() @@ -1455,7 +1474,7 @@ class SKABaseDevice(Device): def main(args=None, **kwargs): # PROTECTED REGION ID(SKABaseDevice.main) ENABLED START # """ - Main function of the SKABaseDevice module. + Launch an SKABaseDevice device. :param args: positional args to tango.server.run :param kwargs: named args to tango.server.run diff --git a/src/ska_tango_base/base/component_manager.py b/src/ska_tango_base/base/component_manager.py index 049fcc1f310a600c75ecc8e154150641e83c27a1..6707bdec3088257064d6d76fd98c8dcee3296dfc 100644 --- a/src/ska_tango_base/base/component_manager.py +++ b/src/ska_tango_base/base/component_manager.py @@ -28,8 +28,9 @@ from ska_tango_base.control_model import PowerMode class BaseComponentManager: """ - An abstract base class for a component manager for SKA Tango - devices, supporting: + An abstract base class for a component manager for SKA Tango devices. + + It supports: * Maintaining a connection to its component @@ -42,7 +43,7 @@ class BaseComponentManager: def __init__(self, op_state_model, *args, **kwargs): """ - Initialise a new ComponentManager instance + Initialise a new ComponentManager instance. :param op_state_model: the op state model used by this component manager @@ -51,8 +52,9 @@ class BaseComponentManager: def start_communicating(self): """ - Establish communication with the component, then start - monitoring. This is the place to do things like: + Establish communication with the component, then start monitoring. + + This is the place to do things like: * Initiate a connection to the component (if your communication is connection-oriented) @@ -64,8 +66,9 @@ class BaseComponentManager: def stop_communicating(self): """ - Cease monitoring the component, and break off all communication - with it. For example, + Cease monitoring the component, and break off all communication with it. + + For example, * If you are communicating over a connection, disconnect. * If you have subscribed to events, unsubscribe. @@ -76,9 +79,9 @@ class BaseComponentManager: @property def is_communicating(self): """ - Whether communication with the component is established and - active, allowing monitoring and control of the component. For - example: + Return whether communication with the component is established. + + For example: * If communication is over a connection, are you connected? * If communication is via event subscription, are you @@ -95,7 +98,7 @@ class BaseComponentManager: @property def power_mode(self): """ - Power mode of the component + Power mode of the component. :return: the power mode of the component """ @@ -104,34 +107,26 @@ class BaseComponentManager: @property def faulty(self): """ - Whether the component is currently faulting + Whether the component is currently faulting. :return: whether the component is faulting """ raise NotImplementedError("BaseComponentManager is abstract.") def off(self): - """ - Turn the component off - """ + """Turn the component off.""" raise NotImplementedError("BaseComponentManager is abstract.") def standby(self): - """ - Put the component into low-power standby mode - """ + """Put the component into low-power standby mode.""" raise NotImplementedError("BaseComponentManager is abstract.") def on(self): - """ - Turn the component on - """ + """Turn the component on.""" raise NotImplementedError("BaseComponentManager is abstract.") def reset(self): - """ - Reset the component (from fault state) - """ + """Reset the component (from fault state).""" raise NotImplementedError("BaseComponentManager is abstract.") action_map = { @@ -142,8 +137,9 @@ class BaseComponentManager: def component_power_mode_changed(self, power_mode): """ - Callback hook, called when whether the component power mode - changes + Handle notification that the component's power mode has changed. + + This is a callback hook. :param power_mode: the new power mode of the component :type power_mode: @@ -154,6 +150,8 @@ class BaseComponentManager: def component_fault(self): """ - Callback hook, called when the component faults + Handle notification that the component has faulted. + + This is a callback hook. """ self.op_state_model.perform_action("component_fault") diff --git a/src/ska_tango_base/base/op_state_model.py b/src/ska_tango_base/base/op_state_model.py index 46a32f9a47c9fa74dbe7c9ba2a482037d00985d1..c9e86888ed090c647e0302dc53fb7c563aa25333 100644 --- a/src/ska_tango_base/base/op_state_model.py +++ b/src/ska_tango_base/base/op_state_model.py @@ -1,6 +1,7 @@ """ -This module specifies the operational state ("opState") model for SKA LMC -Tango devices. It consists of: +This module specifies the operational state ("opState") model for SKA LMC Tango devices. + +It consists of: * an underlying state machine: :py:class:`._OpStateMachine` * an :py:class:`.OpStateModel` that maps state machine state to device @@ -20,8 +21,11 @@ __all__ = ["OpStateModel"] class _OpStateMachine(Machine): """ - State machine representing the overall state of the device with - respect to system component that it monitors. + State machine representing the operational state of the device. + + The operational state of a device is either the state of the system + component that the device monitors, or a state that indicates why + the device is not monitoring the system component. The post-init states supported are: @@ -82,12 +86,11 @@ class _OpStateMachine(Machine): .. figure:: _OpStateMachine_autogenerated.png :alt: Diagram of the op state machine, as implemented - """ def __init__(self, callback=None, **extra_kwargs): """ - Initialises the state model. + Initialise the state model. :param callback: A callback to be called when a transition implies a change to op state @@ -290,8 +293,9 @@ class _OpStateMachine(Machine): def _state_changed(self): """ - State machine callback that is called every time the op_state - changes. Responsible for ensuring that callbacks are called. + State machine callback that is called every time the op_state changes. + + Responsible for ensuring that callbacks are called. """ if self._callback is not None: self._callback(self.state) @@ -299,8 +303,7 @@ class _OpStateMachine(Machine): class OpStateModel: """ - This class implements the state model for device operational state - ("opState"). + This class implements the state model for device operational state ("opState"). The model supports the following states, represented as values of the :py:class:`tango.DevState` enum. @@ -356,7 +359,7 @@ class OpStateModel: def __init__(self, logger, callback=None): """ - Initialises the operational state model. + Initialise the operational state model. :param logger: the logger to be used by this state model. :type logger: a logger that implements the standard library @@ -375,7 +378,7 @@ class OpStateModel: @property def op_state(self): """ - Returns the op state + Return the op state. :returns: the op state of this state model :rtype: :py:class:`tango.DevState` @@ -400,11 +403,12 @@ class OpStateModel: def _op_state_changed(self, machine_state): """ - Helper method that updates op_state whenever the operational - state machine reports a change of state, ensuring that the + Handle notification that the operational state machine has changed state. + + This is a helper method that updates op_state, ensuring that the callback is called if one exists. - :param machine_state: the new state of the operational state + :param machine_state: the new state of the operation state machine :type machine_state: str """ @@ -416,7 +420,7 @@ class OpStateModel: def is_action_allowed(self, action, raise_if_disallowed=False): """ - Whether a given action is allowed in the current state. + Return whether a given action is allowed in the current state. :param action: an action, as given in the transitions table :type action: str @@ -442,7 +446,7 @@ class OpStateModel: def perform_action(self, action): """ - Performs an action on the state model + Perform an action on the state model. :param action: an action, as given in the transitions table :type action: str @@ -453,8 +457,7 @@ class OpStateModel: @for_testing_only def _straight_to_state(self, op_state_name): """ - Takes this op state model straight to the specified underlying - op state. + Take this op state model straight to the specified underlying op state. This method exists to simplify testing; for example, if testing that a command may be run in a given op state, you can push diff --git a/src/ska_tango_base/base/reference_component_manager.py b/src/ska_tango_base/base/reference_component_manager.py index cf2ae9e991e30f8494baeaffa69a579187fac678..065a348bd38821aa72c3006ecfe63b5322a4221a 100644 --- a/src/ska_tango_base/base/reference_component_manager.py +++ b/src/ska_tango_base/base/reference_component_manager.py @@ -1,7 +1,8 @@ """ -This module provided a reference implementation of a -:py:class:`ska_tango_base.base.BaseComponentManager`, for -explanatory purposes, and to support testing of this package. +This module provided a reference implementation of a BaseComponentManager. + +It is provided for explanatory purposes, and to support testing of this +package. """ import functools @@ -12,8 +13,18 @@ from ska_tango_base.faults import ComponentFault def check_communicating(func): """ - Decorator that makes a method first check that there is a connection - to the component, before allowing the wrapped function to proceed + Return a function that checks component communication before calling a function. + + The component manager needs to have established communications with + the component, in order for the function to be called. + + This function is intended to be used as a decorator: + + .. code-block:: python + + @check_communicating + def scan(self): + ... :param func: the wrapped function @@ -23,10 +34,12 @@ def check_communicating(func): @functools.wraps(func) def _wrapper(component_manager, *args, **kwargs): """ - Wrapper function that checks that there is a connection to the - component before invoking the wrapped function + Check for component communication before calling the function. - :param component_manager: the component_manager to check + This is a wrapper function that implements the functionality of + the decorator. + + :param component_manager: the component manager to check :param args: positional arguments to the wrapped function :param kwargs: keyword arguments to the wrapped function @@ -41,7 +54,9 @@ def check_communicating(func): class ReferenceBaseComponentManager(BaseComponentManager): """ - A component manager for Tango devices, supporting: + A component manager for Tango devices. + + It supports: * Maintaining a connection to its component @@ -83,7 +98,7 @@ class ReferenceBaseComponentManager(BaseComponentManager): def __init__(self, _power_mode=PowerMode.OFF, _faulty=False): """ - Initialise a new instance + Initialise a new instance. :param _power_mode: initial power mode of this component (for testing only) @@ -98,7 +113,7 @@ class ReferenceBaseComponentManager(BaseComponentManager): def set_op_callbacks(self, power_mode_callback, fault_callback): """ - Set callbacks for the underlying component + Set callbacks for the underlying component. :param power_mode_callback: a callback to call when the power mode of the component changes @@ -111,7 +126,7 @@ class ReferenceBaseComponentManager(BaseComponentManager): @property def faulty(self): """ - Whether this component is currently experiencing a fault + Return whether this component is currently experiencing a fault. :return: whether this component is faulting :rtype: bool @@ -121,7 +136,7 @@ class ReferenceBaseComponentManager(BaseComponentManager): @property def power_mode(self): """ - Current power mode of the component + Return the current power mode of the component. :return: power mode of the component :rtype: :py:class:`ska_tango_base.control_model.PowerMode` @@ -131,33 +146,27 @@ class ReferenceBaseComponentManager(BaseComponentManager): return self._power_mode def off(self): - """ - Turn the component off - """ + """Turn the component off.""" self.simulate_off() def standby(self): - """ - Put the component into low-power standby mode - """ + """Put the component into low-power standby mode.""" self.simulate_standby() def on(self): - """ - Turn the component on - """ + """Turn the component on.""" self.simulate_on() def reset(self): - """ - Reset the component (from fault state) - """ + """Reset the component (from fault state).""" self._update_faulty(False) def simulate_off(self): """ - Simulate the component being turned off, either - spontaneously or as a result of the Off command. + Simulate the component being turned off. + + This could occur as a result of the Off command, or because + of some external event/action. """ if self.faulty: raise ComponentFault() @@ -165,8 +174,10 @@ class ReferenceBaseComponentManager(BaseComponentManager): def simulate_standby(self): """ - Simulate the component going into low-power standby mode, - either spontaneously or as a result of the Standby command. + Simulate the component going into low-power standby mode. + + This could occur as a result of the Standby command, or + because of some external event/action. """ if self.faulty: raise ComponentFault() @@ -174,30 +185,29 @@ class ReferenceBaseComponentManager(BaseComponentManager): def simulate_on(self): """ - Simulate the component being turned on, either spontaneously - or as a result of the On command. + Simulate the component being turned on. + + This could occur as a result of the On command, or because + of some external event/action. """ if self.faulty: raise ComponentFault() self._update_power_mode(PowerMode.ON) def _invoke_power_callback(self): - """ - Helper method that invokes the callback when the power mode - of the component changes. - """ + """Invoke the callback when the power mode of the component changes.""" if not self.faulty: if self._power_callback is not None: self._power_callback(self._power_mode) def _update_power_mode(self, power_mode): """ - Helper method that updates the power mode of the component, - ensuring that callbacks are called as - required. + Update the power mode of the component. - :param power_mode: new value for the power mode of the - component + This helper method will also ensure that callbacks are + called as required. + + :param power_mode: new value for the power mode :type power_mode: :py:class:`ska_tango_base.control_model.PowerMode` """ @@ -206,24 +216,20 @@ class ReferenceBaseComponentManager(BaseComponentManager): self._invoke_power_callback() def simulate_fault(self): - """ - Tell the component to simulate a fault - """ + """Tell the component to simulate a fault.""" self._update_faulty(True) def _invoke_fault_callback(self): - """ - Helper method that invokes the callback when the component - experiences a fault. - """ + """Invoke the callback when the component experiences a fault.""" if self.faulty and self._fault_callback is not None: self._fault_callback() def _update_faulty(self, faulty): """ - Helper method that updates whether the component is - faulting or not, ensuring that callbacks are called as - required. + Update whether the component is faulty or not. + + This helper method will also ensure that callbacks are + called as required. :param fault: new value for whether the component is faulting or not @@ -235,7 +241,7 @@ class ReferenceBaseComponentManager(BaseComponentManager): def __init__(self, op_state_model, *args, logger=None, _component=None, **kwargs): """ - Initialise a new ComponentManager instance + Initialise a new ComponentManager instance. :param op_state_model: the op state model used by this component manager @@ -253,10 +259,7 @@ class ReferenceBaseComponentManager(BaseComponentManager): super().__init__(op_state_model, *args, **kwargs) def start_communicating(self): - """ - Establish communication with the component, then start - monitoring. - """ + """Establish communication with the component, then start monitoring.""" if self._connected: return @@ -284,10 +287,7 @@ class ReferenceBaseComponentManager(BaseComponentManager): self.component_power_mode_changed(self._component.power_mode) def stop_communicating(self): - """ - Cease monitoring the component, and break off all communication - with it. - """ + """Cease monitoring the component, and break off all communication with it.""" if not self._connected: return @@ -298,7 +298,7 @@ class ReferenceBaseComponentManager(BaseComponentManager): @property def is_communicating(self): """ - Whether there is currently a connection to the component + Whether there is currently a connection to the component. :return: whether there is currently a connection to the component @@ -308,8 +308,7 @@ class ReferenceBaseComponentManager(BaseComponentManager): def simulate_communication_failure(self, fail_communicate): """ - Simulate (or stop simulating) a failure to communicate with the - component + Simulate (or stop simulating) a failure to communicate with the component. :param fail_communicate: whether the connection to the component is failing @@ -324,7 +323,7 @@ class ReferenceBaseComponentManager(BaseComponentManager): @check_communicating def power_mode(self): """ - Power mode of the component + Power mode of the component. :return: the power mode of the component """ @@ -334,7 +333,7 @@ class ReferenceBaseComponentManager(BaseComponentManager): @check_communicating def faulty(self): """ - Whether the component is currently faulting + Whether the component is currently faulting. :return: whether the component is faulting """ @@ -342,33 +341,25 @@ class ReferenceBaseComponentManager(BaseComponentManager): @check_communicating def off(self): - """ - Turn the component off - """ + """Turn the component off.""" self.logger.info("Turning component off") self._component.off() @check_communicating def standby(self): - """ - Put the component into low-power standby mode - """ + """Put the component into low-power standby mode.""" self.logger.info("Putting component into standby mode") self._component.standby() @check_communicating def on(self): - """ - Turn the component on - """ + """Turn the component on.""" self.logger.info("Turning component on") self._component.on() @check_communicating def reset(self): - """ - Reset the component (from fault state) - """ + """Reset the component (from fault state).""" self.logger.info("Resetting component") self._component.reset() @@ -380,8 +371,9 @@ class ReferenceBaseComponentManager(BaseComponentManager): def component_power_mode_changed(self, power_mode): """ - Callback hook, called when whether the component power mode - changes + Handle notification that the component's power mode has changed. + + This is a callback hook. :param power_mode: the new power mode of the component :type power_mode: @@ -392,6 +384,8 @@ class ReferenceBaseComponentManager(BaseComponentManager): def component_fault(self): """ - Callback hook, called when the component faults + Handle notification that the component has faulted. + + This is a callback hook. """ self.op_state_model.perform_action("component_fault") diff --git a/src/ska_tango_base/capability_device.py b/src/ska_tango_base/capability_device.py index 0654b20ad9987c6dd364f0a23a0d2a1895470d3d..44c169c8cac10885c205248c001eb1e99abadea1 100644 --- a/src/ska_tango_base/capability_device.py +++ b/src/ska_tango_base/capability_device.py @@ -4,7 +4,8 @@ # # # -""" SKACapability +""" +SKACapability. Capability handling device """ @@ -24,13 +25,13 @@ __all__ = ["SKACapability", "main"] class SKACapability(SKAObsDevice): """ - A Subarray handling device. It exposes the instances of configured capabilities. + A Subarray handling device. + + It exposes the instances of configured capabilities. """ def init_command_objects(self): - """ - Sets up the command objects - """ + """Set up the command objects.""" super().init_command_objects() self.register_command_object( "ConfigureInstances", @@ -38,6 +39,8 @@ class SKACapability(SKAObsDevice): ) class InitCommand(SKAObsDevice.InitCommand): + """A class for the CapabilityDevice's init_device() "command".""" + def do(self): """ Stateless hook for device initialisation. @@ -109,11 +112,24 @@ class SKACapability(SKAObsDevice): def always_executed_hook(self): # PROTECTED REGION ID(SKACapability.always_executed_hook) ENABLED START # + """ + Perform actions that are executed before every device command. + + This is a Tango hook. + """ pass # PROTECTED REGION END # // SKACapability.always_executed_hook def delete_device(self): # PROTECTED REGION ID(SKACapability.delete_device) ENABLED START # + """ + Clean up any resources prior to device deletion. + + This method is a Tango hook that is called by the device + destructor and by the device Init command. It allows for any + memory or other resources allocated in the init_device method to + be released prior to device deletion. + """ pass # PROTECTED REGION END # // SKACapability.delete_device @@ -124,7 +140,8 @@ class SKACapability(SKAObsDevice): def read_activationTime(self): # PROTECTED REGION ID(SKACapability.activationTime_read) ENABLED START # """ - Reads time of activation since Unix epoch. + Read time of activation since Unix epoch. + :return: Activation time in seconds """ return self._activation_time @@ -133,7 +150,8 @@ class SKACapability(SKAObsDevice): def read_configuredInstances(self): # PROTECTED REGION ID(SKACapability.configuredInstances_read) ENABLED START # """ - Reads the number of instances of a capability in the subarray + Read the number of instances of a capability in the subarray. + :return: The number of configured instances of a capability in a subarray """ return self._configured_instances @@ -142,7 +160,9 @@ class SKACapability(SKAObsDevice): def read_usedComponents(self): # PROTECTED REGION ID(SKACapability.usedComponents_read) ENABLED START # """ - Reads the list of components with no. of instances in use on this Capability + Read the list of components with no. + + of instances in use on this Capability :return: The number of components currently in use. """ return self._used_components @@ -153,14 +173,11 @@ class SKACapability(SKAObsDevice): # -------- class ConfigureInstancesCommand(ResponseCommand): - """ - A class for the SKALoggerDevice's SetLoggingLevel() command. - """ + """A class for the SKALoggerDevice's SetLoggingLevel() command.""" def do(self, argin): """ - Stateless hook for ConfigureInstances()) command - functionality. + Stateless hook for ConfigureInstances()) command functionality. :return: A tuple containing a return code and a string message indicating status. The message is for @@ -184,8 +201,7 @@ class SKACapability(SKAObsDevice): def ConfigureInstances(self, argin): # PROTECTED REGION ID(SKACapability.ConfigureInstances) ENABLED START # """ - This function indicates how many number of instances of the current capacity - should to be configured. + Specify the number of instances of the current capacity to be configured. To modify behaviour for this command, modify the do() method of the command class. @@ -206,7 +222,7 @@ class SKACapability(SKAObsDevice): def main(args=None, **kwargs): # PROTECTED REGION ID(SKACapability.main) ENABLED START # - """Main function of the SKACapability module.""" + """Launch an SKACapability device.""" return run((SKACapability,), args=args, **kwargs) # PROTECTED REGION END # // SKACapability.main diff --git a/src/ska_tango_base/commands.py b/src/ska_tango_base/commands.py index ac28b9ec3a99b5dd07560fd2e8646bf7d3314a72..c14b4f1878682df12308a8d9ee25942e50445a3a 100644 --- a/src/ska_tango_base/commands.py +++ b/src/ska_tango_base/commands.py @@ -1,6 +1,5 @@ """ -This module provides abstract base classes for device commands, and a -ResultCode enum. +This module provides abstract base classes for device commands, and a ResultCode enum. The following command classes are provided: @@ -58,7 +57,6 @@ implement the ``__init__`` and ``do`` methods. For example: def do(self, argin): # do stuff return (ResultCode.OK, "AssignResources command completed OK") - """ import enum import logging @@ -71,9 +69,7 @@ module_logger = logging.getLogger(__name__) class ResultCode(enum.IntEnum): - """ - Python enumerated type for command return codes. - """ + """Python enumerated type for command return codes.""" OK = 0 """ @@ -103,14 +99,15 @@ class ResultCode(enum.IntEnum): class BaseCommand: """ - Abstract base class for Tango device server commands. Checks that - the command is allowed to run in the current state, and runs the - command. + Abstract base class for Tango device server commands. + + Checks that the command is allowed to run in the current state, and + runs the command. """ def __init__(self, target, *args, logger=None, **kwargs): """ - Creates a new BaseCommand object for a device. + Initialise a new BaseCommand instance. :param target: the object that this command acts upon; for example, a component manager @@ -126,9 +123,10 @@ class BaseCommand: def __call__(self, argin=None): """ - What to do when the command is called. This base class simply - calls ``do()`` or ``do(argin)``, depending on whether the - ``argin`` argument is provided. + Invoke the command. + + This is implemented to simply call the do() hook, thus running + the user-specified functionality therein. :param argin: the argument passed to the Tango command, if present @@ -144,8 +142,7 @@ class BaseCommand: def _call_do(self, argin=None): """ - Helper method that ensures the ``do`` method is called with the - right arguments, and that the call is logged. + Call the ``do`` method with the right arguments, and log the call. :param argin: the argument passed to the Tango command, if present @@ -161,9 +158,10 @@ class BaseCommand: def do(self, argin=None): """ - Hook for the functionality that the command implements. This - class provides stub functionality; subclasses should subclass - this method with their command functionality. + Perform the user-specified functionality of the command. + + This class provides stub functionality; subclasses should + subclass this method with their command functionality. :param argin: the argument passed to the Tango command, if present @@ -175,9 +173,11 @@ class BaseCommand: class StateModelCommand(BaseCommand): + """A base class for commands that drive a state model.""" + def __init__(self, target, state_model, action_slug, *args, logger=None, **kwargs): """ - A base command for commands that drive a state model. + Initialise a new command object. :param target: the object that this command acts upon; for example, a component manager @@ -210,8 +210,7 @@ class StateModelCommand(BaseCommand): def __call__(self, argin=None): """ - What to do when the command is called. Ensures that we perform - the "invoked" action on the state machine. + Let the state model know that the command is starting, then invoke the command. :param argin: the argument passed to the Tango command, if present @@ -231,8 +230,7 @@ class StateModelCommand(BaseCommand): def is_allowed(self, raise_if_disallowed=False): """ - Whether this command is allowed to run in the current state of - the state model. + Whether this command is allowed to run in the current state of the state model. :param raise_if_disallowed: whether to raise an error or simply return False if the command is disallowed @@ -257,6 +255,14 @@ class StateModelCommand(BaseCommand): class ObservationCommand(StateModelCommand): + """ + A base class for commands that drive the device's observing state. + + This is a special case of a ``StateModelCommand`` because although + it only drives the observation state model, it has to check also the + operational state model to determine whether it is allowed to run. + """ + def __init__( self, target, @@ -268,11 +274,7 @@ class ObservationCommand(StateModelCommand): **kwargs, ): """ - A base class for commands that drive the device's observing - state. This is a special case of a ``StateModelCommand`` because - although it only drives the observation state model, it has to - check also the operational state model to determine whether it - is allowed to run. + Initialise a new ``ObservationCommand`` object. :param target: the object that this command acts upon; for example, a component manager @@ -303,8 +305,7 @@ class ObservationCommand(StateModelCommand): def is_allowed(self, raise_if_disallowed=False): """ - Whether this command is allowed to run in the current state of - the state model. + Whether this command is allowed to run in the current state of the state model. :param raise_if_disallowed: whether to raise an error or simply return False if the command is disallowed @@ -328,9 +329,10 @@ class ObservationCommand(StateModelCommand): class ResponseCommand(BaseCommand): """ - Abstract base class for a tango command handler, for commands that - execute a procedure/operation and return a (ResultCode, message) - tuple. + A command returns a (ResultCode, message) tuple. + + This is an Abstract base class for commands that execute a procedure + or operation, then return a (ResultCode, message) tuple. """ RESULT_LOG_LEVEL = { @@ -343,8 +345,7 @@ class ResponseCommand(BaseCommand): def _call_do(self, argin=None): """ - Helper method that ensures the ``do`` method is called with the - right arguments, and that the call is logged. + Call the ``do`` method with the right arguments, and log the call. :param argin: the argument passed to the Tango command, if present @@ -370,8 +371,10 @@ class ResponseCommand(BaseCommand): class CompletionCommand(StateModelCommand): """ - Abstract base class for a command that sends a "completed" action to - the state model at command completion. + A command that triggers an action on the state model at completion. + + This is an abstract base class for commands that need to signal + completion by triggering a "completed" action on the state model. """ def __init__(self, target, state_model, action_slug, *args, logger=None, **kwargs): @@ -406,10 +409,11 @@ class CompletionCommand(StateModelCommand): def __call__(self, argin=None): """ - What to do when the command is called. This is implemented to - check that the command is allowed to run, then run the command, - then send an action to the state model advising whether the - command succeeded or failed. + Invoke the command. + + This is implemented to check that the command is allowed to run, + then run the command, then send an action to the state model + advising that the command has completed. :param argin: the argument passed to the Tango command, if present @@ -422,7 +426,5 @@ class CompletionCommand(StateModelCommand): return result def completed(self): - """ - Callback for the completion of the command. - """ + """Let the state model know that the command has completed.""" self.state_model.perform_action(self._completed_hook) diff --git a/src/ska_tango_base/control_model.py b/src/ska_tango_base/control_model.py index 16b6c60eac7dfaed6ac400b7e994e4217b33d5ba..9c038ad9974a932e831d0389a5e196290fde782a 100644 --- a/src/ska_tango_base/control_model.py +++ b/src/ska_tango_base/control_model.py @@ -10,7 +10,6 @@ https://confluence.skatelescope.org/pages/viewpage.action?pageId=105416556 The enumerated types mapping to the states and modes are included here, as well as other useful enumerations. - """ import enum @@ -283,11 +282,12 @@ class SimulationMode(enum.IntEnum): class TestMode(enum.IntEnum): - """Python enumerated type for ``testMode`` attribute. + """ + Python enumerated type for ``testMode`` attribute. This enumeration may be replaced and extended in derived classes to - add additional custom test modes. That would require overriding the base - class ``testMode`` attribute definition. + add additional custom test modes. That would require overriding the + base class ``testMode`` attribute definition. """ __test__ = False # disable pytest discovery for this class @@ -323,8 +323,9 @@ class LoggingLevel(enum.IntEnum): class PowerMode(enum.IntEnum): """ - Enumerated type for the power mode of components that rely upon a - power supply, such as hardware. + Enumerated type for power mode. + + Used by components that rely upon a power supply, such as hardware. """ UNKNOWN = 0 diff --git a/src/ska_tango_base/controller_device.py b/src/ska_tango_base/controller_device.py index c8ec813f7d8e17fb2aa26668e25f051be6560c22..a440120822f5610d4ed9c699a83ae3122065cd1a 100644 --- a/src/ska_tango_base/controller_device.py +++ b/src/ska_tango_base/controller_device.py @@ -5,7 +5,8 @@ # # -""" SKAController +""" +SKAController. Controller device """ @@ -30,14 +31,10 @@ __all__ = ["SKAController", "main"] class SKAController(SKABaseDevice): - """ - Controller device - """ + """Controller device.""" def init_command_objects(self): - """ - Sets up the command objects - """ + """Set up the command objects.""" super().init_command_objects() self.register_command_object( "IsCapabilityAchievable", @@ -45,9 +42,7 @@ class SKAController(SKABaseDevice): ) class InitCommand(SKABaseDevice.InitCommand): - """ - A class for the SKAController's init_device() "command". - """ + """A class for the SKAController's init_device() "command".""" def do(self): """ @@ -149,11 +144,24 @@ class SKAController(SKABaseDevice): def always_executed_hook(self): # PROTECTED REGION ID(SKAController.always_executed_hook) ENABLED START # + """ + Perform actions that are executed before every device command. + + This is a Tango hook. + """ pass # PROTECTED REGION END # // SKAController.always_executed_hook def delete_device(self): # PROTECTED REGION ID(SKAController.delete_device) ENABLED START # + """ + Clean up any resources prior to device deletion. + + This method is a Tango hook that is called by the device + destructor and by the device Init command. It allows for any + memory or other resources allocated in the init_device method to + be released prior to device deletion. + """ pass # PROTECTED REGION END # // SKAController.delete_device @@ -163,37 +171,37 @@ class SKAController(SKABaseDevice): def read_elementLoggerAddress(self): # PROTECTED REGION ID(SKAController.elementLoggerAddress_read) ENABLED START # - """Reads FQDN of Element Logger device""" + """Read FQDN of Element Logger device.""" return self._element_logger_address # PROTECTED REGION END # // SKAController.elementLoggerAddress_read def read_elementAlarmAddress(self): # PROTECTED REGION ID(SKAController.elementAlarmAddress_read) ENABLED START # - """Reads FQDN of Element Alarm device""" + """Read FQDN of Element Alarm device.""" return self._element_alarm_address # PROTECTED REGION END # // SKAController.elementAlarmAddress_read def read_elementTelStateAddress(self): # PROTECTED REGION ID(SKAController.elementTelStateAddress_read) ENABLED START # - """Reads FQDN of Element TelState device""" + """Read FQDN of Element TelState device.""" return self._element_tel_state_address # PROTECTED REGION END # // SKAController.elementTelStateAddress_read def read_elementDatabaseAddress(self): # PROTECTED REGION ID(SKAController.elementDatabaseAddress_read) ENABLED START # - """Reads FQDN of Element Database device""" + """Read FQDN of Element Database device.""" return self._element_database_address # PROTECTED REGION END # // SKAController.elementDatabaseAddress_read def read_maxCapabilities(self): # PROTECTED REGION ID(SKAController.maxCapabilities_read) ENABLED START # - """Reads maximum number of instances of each capability type""" + """Read maximum number of instances of each capability type.""" return convert_dict_to_list(self._max_capabilities) # PROTECTED REGION END # // SKAController.maxCapabilities_read def read_availableCapabilities(self): # PROTECTED REGION ID(SKAController.availableCapabilities_read) ENABLED START # - """Reads list of available number of instances of each capability type""" + """Read list of available number of instances of each capability type.""" return convert_dict_to_list(self._available_capabilities) # PROTECTED REGION END # // SKAController.availableCapabilities_read @@ -202,9 +210,7 @@ class SKAController(SKABaseDevice): # -------- class IsCapabilityAchievableCommand(BaseCommand): - """ - A class for the SKAController's IsCapabilityAchievable() command. - """ + """A class for the SKAController's IsCapabilityAchievable() command.""" def do(self, argin): """ @@ -240,7 +246,7 @@ class SKAController(SKABaseDevice): def isCapabilityAchievable(self, argin): # PROTECTED REGION ID(SKAController.isCapabilityAchievable) ENABLED START # """ - Checks of provided capabilities can be achieved by the resource(s). + Check if provided capabilities can be achieved by the resource(s). To modify behaviour for this command, modify the do() method of the command class. @@ -264,6 +270,7 @@ class SKAController(SKABaseDevice): # Run server # ---------- def main(args=None, **kwargs): + """Launch an SKAController Tango device.""" # PROTECTED REGION ID(SKAController.main) ENABLED START # return run((SKAController,), args=args, **kwargs) # PROTECTED REGION END # // SKAController.main diff --git a/src/ska_tango_base/csp/__init__.py b/src/ska_tango_base/csp/__init__.py index 2aabb983d234ae4634670365eadb287d0838a0a9..4196125365209b214570443a6fcab93fdd1e3834 100644 --- a/src/ska_tango_base/csp/__init__.py +++ b/src/ska_tango_base/csp/__init__.py @@ -1,6 +1,4 @@ -""" -This subpackage contains base devices specific to CSP. -""" +"""This subpackage contains base devices specific to CSP.""" __all__ = ( "CspSubElementObsStateModel", diff --git a/src/ska_tango_base/csp/controller_device.py b/src/ska_tango_base/csp/controller_device.py index d711d5bc41a44057f4f3a6f14f5ae8cd88afc801..1cdc6aa5a62659fee78738087a2d9297a3344b66 100644 --- a/src/ska_tango_base/csp/controller_device.py +++ b/src/ska_tango_base/csp/controller_device.py @@ -7,7 +7,8 @@ # Distributed under the terms of the GPL license. # See LICENSE.txt for more info. -""" CspSubElementController +""" +CspSubElementController. Controller device for SKA CSP Subelement. """ @@ -198,9 +199,7 @@ class CspSubElementController(SKAController): # --------------- def init_command_objects(self): - """ - Sets up the command objects - """ + """Set up the command objects.""" super().init_command_objects() self.register_command_object( "LoadFirmware", @@ -220,9 +219,7 @@ class CspSubElementController(SKAController): ) class InitCommand(SKAController.InitCommand): - """ - A class for the CspSubElementController's init_device() "command". - """ + """A class for the CspSubElementController's init_device() "command".""" def do(self): """ @@ -266,16 +263,22 @@ class CspSubElementController(SKAController): return (ResultCode.OK, message) def always_executed_hook(self): - """Method always executed before any Tango command is executed.""" + """ + Perform actions always executed before any Tango command is executed. + + This is a Tango hook. + """ # PROTECTED REGION ID(CspSubElementController.always_executed_hook) ENABLED START # # PROTECTED REGION END # // CspSubElementController.always_executed_hook def delete_device(self): - """Hook to delete resources allocated in init_device. + """ + Clean up any resources prior to device deletion. - This method allows for any memory or other resources allocated in the - init_device method to be released. This method is called by the device - destructor and by the device Init command. + This method is a Tango hook that is called by the device + destructor and by the device Init command. It allows for any + memory or other resources allocated in the init_device method to + be released prior to device deletion. """ # PROTECTED REGION ID(CspSubElementController.delete_device) ENABLED START # # PROTECTED REGION END # // CspSubElementController.delete_device @@ -414,15 +417,13 @@ class CspSubElementController(SKAController): # Commands # -------- class LoadFirmwareCommand(StateModelCommand, ResponseCommand): - """ - A class for the LoadFirmware command. - """ + """A class for the LoadFirmware command.""" def __init__( self, target, op_state_model, admin_mode_model, *args, logger=None, **kwargs ): """ - Creates a new BaseCommand object for a device. + Initialise a new LoadFirmwareCommand instance. :param target: the object that this base command acts upon. For example, the device's component manager. @@ -461,10 +462,10 @@ class CspSubElementController(SKAController): def is_allowed(self, raise_if_disallowed=False): """ - Check if the command is in the proper state (State/adminMode) - to be executed. - The controller device has to be in OFF/MAINTENACE to process the - LoadFirmware command. + Check if the command is in the proper state to be executed. + + The controller device has to be in op state OFF and admin + mode MAINTENACE to process the LoadFirmware command. :param raise_if_disallowed: whether to raise an error or simply return False if the command is disallowed @@ -487,11 +488,10 @@ class CspSubElementController(SKAController): return False class PowerOnDevicesCommand(StateModelCommand, ResponseCommand): - """ - A class for the CspSubElementController's PowerOnDevices command. - """ + """A class for the CspSubElementController's PowerOnDevices command.""" def __init__(self, target, op_state_model, *args, logger=None, **kwargs): + """Initialise a new `PowerOnDevicesCommand``` instance.""" super().__init__( target, op_state_model, None, *args, logger=logger, **kwargs ) @@ -513,6 +513,7 @@ class CspSubElementController(SKAController): def is_allowed(self, raise_if_disallowed=False): """ Check if the command is in the proper state to be executed. + The controller device has to be in ON to process the PowerOnDevices command. @@ -532,11 +533,10 @@ class CspSubElementController(SKAController): return False class PowerOffDevicesCommand(StateModelCommand, ResponseCommand): - """ - A class for the CspSubElementController's PowerOffDevices command. - """ + """A class for the CspSubElementController's PowerOffDevices command.""" def __init__(self, target, op_state_model, *args, logger=None, **kwargs): + """Initialise a new ``PowerOffDevicesCommand`` instance.""" super().__init__( target, op_state_model, None, *args, logger=logger, **kwargs ) @@ -558,6 +558,7 @@ class CspSubElementController(SKAController): def is_allowed(self, raise_if_disallowed=False): """ Check if the command is in the proper state to be executed. + The controller device has to be in ON to process the PowerOffDevices command. @@ -577,11 +578,10 @@ class CspSubElementController(SKAController): return False class ReInitDevicesCommand(StateModelCommand, ResponseCommand): - """ - A class for the CspSubElementController's ReInitDevices command. - """ + """A class for the CspSubElementController's ReInitDevices command.""" def __init__(self, target, op_state_model, *args, logger=None, **kwargs): + """Initialise a new ``ReInitDevicesCommand`` instance.""" super().__init__( target, op_state_model, None, *args, logger=logger, **kwargs ) @@ -603,6 +603,7 @@ class CspSubElementController(SKAController): def is_allowed(self, raise_if_disallowed=False): """ Check if the command is in the proper state to be executed. + The controller device has to be in ON to process the ReInitDevices command. @@ -623,8 +624,7 @@ class CspSubElementController(SKAController): def is_LoadFirmware_allowed(self): """ - Check if the LoadFirmware command is allowed in the current - state. + Check if the LoadFirmware command is allowed in the current state. :return: ``True`` if command is allowed :rtype: boolean @@ -643,9 +643,10 @@ class CspSubElementController(SKAController): def LoadFirmware(self, argin): # PROTECTED REGION ID(CspSubElementController.LoadFirmware) ENABLED START # """ - Deploy new versions of software and firmware and trigger - a restart so that a Component initializes using a newly - deployed version. + Deploy new versions of software and firmware. + + After deployment, a restart is triggers so that a Component + initializes using a newly deployed version. :param argin: A list of three strings: - The file name or a pointer to the filename specified as URL. @@ -666,8 +667,7 @@ class CspSubElementController(SKAController): def is_PowerOnDevices_allowed(self): """ - Check if the PowerOnDevice command is allowed in the current - state. + Check if the PowerOnDevice command is allowed in the current state. :return: ``True`` if command is allowed :rtype: boolean @@ -702,8 +702,7 @@ class CspSubElementController(SKAController): def is_PowerOffDevices_allowed(self): """ - Check if the PowerOffDevices command is allowed in the current - state. + Check if the PowerOffDevices command is allowed in the current state. :return: ``True`` if command is allowed :rtype: boolean @@ -739,8 +738,7 @@ class CspSubElementController(SKAController): def is_ReInitDevices_allowed(self): """ - Check if the ReInitDevices command is allowed in the current - state. + Check if the ReInitDevices command is allowed in the current state. :return: ``True`` if command is allowed :rtype: boolean @@ -759,6 +757,7 @@ class CspSubElementController(SKAController): # PROTECTED REGION ID(CspSubElementController.ReInitDevices) ENABLED START # """ Reinitialize the devices passed in the input argument. + The exact functionality may vary for different devices and sub-systems, each Tango Device/Server should define what does ReInitDevices means. diff --git a/src/ska_tango_base/csp/obs/__init__.py b/src/ska_tango_base/csp/obs/__init__.py index 5f4d95d65164a6d5bf44cd56c335d8368f7e97a3..fffad0f8373456f33f10dd1a15a7b7e52dab2ffd 100644 --- a/src/ska_tango_base/csp/obs/__init__.py +++ b/src/ska_tango_base/csp/obs/__init__.py @@ -1,6 +1,4 @@ -""" -This subpackage contains obs device functionality specific to CSP. -""" +"""This subpackage contains obs device functionality specific to CSP.""" __all__ = ( "CspSubElementObsStateModel", diff --git a/src/ska_tango_base/csp/obs/component_manager.py b/src/ska_tango_base/csp/obs/component_manager.py index 448d51f36c326fb5669e1e7417d6a4fa3da615cf..a07e8e1720188790fb8e06d9a46583026aabd118 100644 --- a/src/ska_tango_base/csp/obs/component_manager.py +++ b/src/ska_tango_base/csp/obs/component_manager.py @@ -1,12 +1,10 @@ -""" -This module models component management for CSP subelement observation devices. -""" +"""This module models component management for CSP subelement observation devices.""" from ska_tango_base.base import BaseComponentManager class CspObsComponentManager(BaseComponentManager): """ - A component manager for SKA CSP subelement observation Tango devices: + A component manager for SKA CSP subelement observation Tango devices. The current implementation is intended to * illustrate the model @@ -17,12 +15,13 @@ class CspObsComponentManager(BaseComponentManager): """ def __init__(self, op_state_model, obs_state_model, *args, **kwargs): + """Initialise a new ``CspObsComponentManager`` instance.""" self.obs_state_model = obs_state_model super().__init__(op_state_model, *args, **kwargs) def configure_scan(self, configuration): """ - Configure the component + Configure the component. :param configuration: the configuration to be configured :type configuration: dict @@ -30,52 +29,45 @@ class CspObsComponentManager(BaseComponentManager): raise NotImplementedError("CspObsComponentManager is abstract.") def deconfigure(self): - """ - Deconfigure this component. - """ + """Deconfigure this component.""" raise NotImplementedError("CspObsComponentManager is abstract.") def scan(self, args): - """ - Start scanning - """ + """Start scanning.""" raise NotImplementedError("CspObsComponentManager is abstract.") def end_scan(self): - """ - End scanning - """ + """End scanning.""" raise NotImplementedError("CspObsComponentManager is abstract.") def abort(self): - """ - Tell the component to abort whatever it was doing - """ + """Tell the component to abort whatever it was doing.""" raise NotImplementedError("CspObsComponentManager is abstract.") def obsreset(self): - """ - Tell the component to reset to an unconfigured state (but - without releasing any assigned resources) - """ + """Reset the configuration but do not release resources.""" raise NotImplementedError("CspObsComponentManager is abstract.") @property def config_id(self): + """Return the configuration id.""" raise NotImplementedError("CspObsComponentManager is abstract.") @property def scan_id(self): + """Return the scan id.""" raise NotImplementedError("CspObsComponentManager is abstract.") @config_id.setter def config_id(self, config_id): + """Set the configuration id.""" raise NotImplementedError("CspObsComponentManager is abstract.") def component_configured(self, configured): """ - Callback hook, called when whether the component is configured - changes + Handle notification that the component has started or stopped configuring. + + This is callback hook. :param configured: whether this component is configured :type configured: bool @@ -87,8 +79,9 @@ class CspObsComponentManager(BaseComponentManager): def component_scanning(self, scanning): """ - Callback hook, called when whether the component is scanning - changes + Handle notification that the component has started or stopped scanning. + + This is a callback hook. :param scanning: whether this component is scanning :type scanning: bool @@ -100,6 +93,8 @@ class CspObsComponentManager(BaseComponentManager): def component_obsfault(self): """ - Callback hook, called when the component obsfaults + Handle notification that the component has obsfaulted. + + This is a callback hook. """ self.obs_state_model.perform_action("component_obsfault") diff --git a/src/ska_tango_base/csp/obs/obs_device.py b/src/ska_tango_base/csp/obs/obs_device.py index a4d9bf49cf7f4f0964d3f4b4ba2a629bb943a73f..c2f9dff5c4b06d8614d8c0644bf33871771410b0 100644 --- a/src/ska_tango_base/csp/obs/obs_device.py +++ b/src/ska_tango_base/csp/obs/obs_device.py @@ -3,7 +3,8 @@ # This file is part of the CspSubElementObsDevice project # -""" CspSubElementObsDevice +""" +CspSubElementObsDevice. General observing device for SKA CSP Subelement. """ @@ -121,9 +122,7 @@ class CspSubElementObsDevice(SKAObsDevice): # --------------- def _init_state_model(self): - """ - Sets up the state model for the device - """ + """Set up the state model for the device.""" super()._init_state_model() self.obs_state_model = CspSubElementObsStateModel( logger=self.logger, @@ -131,12 +130,11 @@ class CspSubElementObsDevice(SKAObsDevice): ) def create_component_manager(self): + """Create and return the component manager for this device.""" return CspObsComponentManager(self.op_state_model, self.obs_state_model) def init_command_objects(self): - """ - Sets up the command objects - """ + """Set up the command objects.""" super().init_command_objects() for (command_name, command_class) in [ @@ -158,9 +156,7 @@ class CspSubElementObsDevice(SKAObsDevice): ) class InitCommand(SKAObsDevice.InitCommand): - """ - A class for the CspSubElementObsDevice's init_device() "command". - """ + """A class for the CspSubElementObsDevice's init_device() "command".""" def do(self): """ @@ -197,16 +193,22 @@ class CspSubElementObsDevice(SKAObsDevice): return (ResultCode.OK, message) def always_executed_hook(self): - """Method always executed before any Tango command is executed.""" + """ + Perform actions before any Tango command is executed. + + This is a Tango hook. + """ # PROTECTED REGION ID(CspSubElementObsDevice.always_executed_hook) ENABLED START # # PROTECTED REGION END # // CspSubElementObsDevice.always_executed_hook def delete_device(self): - """Hook to delete resources allocated in init_device. + """ + Clean up any resources prior to device deletion. - This method allows for any memory or other resources allocated in the - init_device method to be released. This method is called by the device - destructor and by the device Init command. + This method is a Tango hook that is called by the device + destructor and by the device Init command. It allows for any + memory or other resources allocated in the init_device method to + be released prior to device deletion. """ # PROTECTED REGION ID(CspSubElementObsDevice.delete_device) ENABLED START # # PROTECTED REGION END # // CspSubElementObsDevice.delete_device @@ -268,13 +270,11 @@ class CspSubElementObsDevice(SKAObsDevice): # -------- class ConfigureScanCommand(ObservationCommand, ResponseCommand, CompletionCommand): - """ - A class for the CspSubElementObsDevices's ConfigureScan command. - """ + """A class for the CspSubElementObsDevices's ConfigureScan command.""" def __init__(self, target, op_state_model, obs_state_model, logger=None): """ - Constructor for ConfigureScanCommand + Initialise a new ConfigureScanCommand instance. :param target: the object that this command acts upon; for example, the device's component manager @@ -338,13 +338,11 @@ class CspSubElementObsDevice(SKAObsDevice): ) class ScanCommand(ObservationCommand, ResponseCommand): - """ - A class for the CspSubElementObsDevices's Scan command. - """ + """A class for the CspSubElementObsDevices's Scan command.""" def __init__(self, target, op_state_model, obs_state_model, logger=None): """ - Constructor for ScanCommand + Initialise a new ScanCommand instance. :param target: the object that this command acts upon; for example, the device's component manager @@ -402,13 +400,11 @@ class CspSubElementObsDevice(SKAObsDevice): return (ResultCode.OK, "Scan arguments validation successfull") class EndScanCommand(ObservationCommand, ResponseCommand): - """ - A class for the CspSubElementObsDevices's EndScan command. - """ + """A class for the CspSubElementObsDevices's EndScan command.""" def __init__(self, target, op_state_model, obs_state_model, logger=None): """ - Constructor for EndScanCommand + Initialise a new EndScanCommand instance. :param target: the object that this command acts upon; for example, the device's component manager @@ -443,13 +439,11 @@ class CspSubElementObsDevice(SKAObsDevice): return (ResultCode.OK, "EndScan command completed OK") class GoToIdleCommand(ObservationCommand, ResponseCommand): - """ - A class for the CspSubElementObsDevices's GoToIdle command. - """ + """A class for the CspSubElementObsDevices's GoToIdle command.""" def __init__(self, target, op_state_model, obs_state_model, logger=None): """ - Constructor for EndCommand + Initialise a new EndCommand instance. :param target: the object that this command acts upon; for example, the device's component manager @@ -484,13 +478,11 @@ class CspSubElementObsDevice(SKAObsDevice): return (ResultCode.OK, "GoToIdle command completed OK") class ObsResetCommand(ObservationCommand, ResponseCommand, CompletionCommand): - """ - A class for the CspSubElementObsDevices's ObsReset command. - """ + """A class for the CspSubElementObsDevices's ObsReset command.""" def __init__(self, target, op_state_model, obs_state_model, logger=None): """ - Constructor for ObsReset Command. + Initialise a new ObsResetCommand instance. :param target: the object that this command acts upon; for example, the device's component manager @@ -525,13 +517,11 @@ class CspSubElementObsDevice(SKAObsDevice): return (ResultCode.OK, message) class AbortCommand(ObservationCommand, ResponseCommand, CompletionCommand): - """ - A class for the CspSubElementObsDevices's Abort command. - """ + """A class for the CspSubElementObsDevices's Abort command.""" def __init__(self, target, op_state_model, obs_state_model, logger=None): """ - Constructor for Abort Command. + Initialise a new AbortCommand instance. :param target: the object that this command acts upon; for example, the device's component manager @@ -690,8 +680,7 @@ class CspSubElementObsDevice(SKAObsDevice): def Abort(self): # PROTECTED REGION ID(CspSubElementObsDevice.Abort) ENABLED START # """ - Abort the current observing process and move the device - to ABORTED obsState. + Abort the current observing process and move the device to ABORTED obsState. :return: A tuple containing a return code and a string message indicating status. The message is for information purpose only. @@ -709,7 +698,7 @@ class CspSubElementObsDevice(SKAObsDevice): def main(args=None, **kwargs): - """Main function of the CspSubElementObsDevice module.""" + """Run the CspSubElementObsDevice module.""" # PROTECTED REGION ID(CspSubElementObsDevice.main) ENABLED START # return run((CspSubElementObsDevice,), args=args, **kwargs) # PROTECTED REGION END # // CspSubElementObsDevice.main diff --git a/src/ska_tango_base/csp/obs/obs_state_model.py b/src/ska_tango_base/csp/obs/obs_state_model.py index b9a8bb478655ff175cfdff0caa45a218c1839274..60a5a804fb98b6f2aa87b611695c03fe6ced0aa8 100644 --- a/src/ska_tango_base/csp/obs/obs_state_model.py +++ b/src/ska_tango_base/csp/obs/obs_state_model.py @@ -1,6 +1,7 @@ """ -This module specifies CSP SubElement Observing state machine. It -comprises: +This module specifies CSP SubElement Observing state machine. + +It comprises: * an underlying state machine: :py:class:`._CspSubElementObsStateMachine` @@ -8,7 +9,6 @@ comprises: * a :py:class:`.CspSubElementObsStateModel` that maps the underlying state machine state to a value of the :py:class:`ska_tango_base.control_model.ObsState` enum. - """ from transitions.extensions import LockedMachine as Machine @@ -20,8 +20,7 @@ __all__ = ["CspSubElementObsStateModel"] class _CspSubElementObsStateMachine(Machine): """ - The observation state machine used by a generic CSP sub-element - ObsDevice (derived from SKAObsDevice). + The observation state machine used by a generic CSP sub-element ObsDevice. Compared to the SKA Observation State Machine, it implements a smaller number of states, number that can be further decreased @@ -95,12 +94,11 @@ class _CspSubElementObsStateMachine(Machine): .. figure:: _CspSubElementObsStateMachine_autogenerated.png :alt: Diagram of the CSP subelement obs state machine, as implemented - """ def __init__(self, callback=None, **extra_kwargs): """ - Initialises the model. + Initialise the model. :param callback: A callback to be called when the state changes :type callback: callable @@ -248,8 +246,9 @@ class _CspSubElementObsStateMachine(Machine): def _state_changed(self): """ - State machine callback that is called every time the obs_state - changes. Responsible for ensuring that callbacks are called. + State machine callback that is called every time the obs_state changes. + + Responsible for ensuring that callbacks are called. """ if self._callback is not None: self._callback(self.state) @@ -257,8 +256,7 @@ class _CspSubElementObsStateMachine(Machine): class CspSubElementObsStateModel(ObsStateModel): """ - Implements the observation state model for a generic CSP sub-element - ObsDevice (derived from SKAObsDevice). + Implements the observation state model for a generic CSP sub-element ObsDevice. Compared to the SKA observation state model, it implements a smaller number of states, number that can be further decreased @@ -330,9 +328,10 @@ class CspSubElementObsStateModel(ObsStateModel): def _obs_state_changed(self, machine_state): """ - Helper method that updates obs_state whenever the observation - state machine reports a change of state, ensuring that the - callback is called if one exists. + Handle notification that the observation state machine has changed state. + + This is a helper method that updates obs_state, ensuring that + the callback is called if one exists. :param machine_state: the new state of the observation state machine diff --git a/src/ska_tango_base/csp/obs/reference_component_manager.py b/src/ska_tango_base/csp/obs/reference_component_manager.py index 220176d1cc354862c6f2e962948fd9f83621b743..bee8c571b8c0e9ab73d27f2288c91056aa9972f3 100644 --- a/src/ska_tango_base/csp/obs/reference_component_manager.py +++ b/src/ska_tango_base/csp/obs/reference_component_manager.py @@ -1,6 +1,4 @@ -""" -This module models component management for CSP subelement observation devices. -""" +"""This module models component management for CSP subelement observation devices.""" import functools from ska_tango_base.csp.obs import CspObsComponentManager @@ -12,8 +10,18 @@ from ska_tango_base.faults import ComponentError, ComponentFault def check_on(func): """ - Decorator that makes a method first checks that the component is - turned on and not faulty before allowing the command to proceed + Return a function that checks the component state then calls another function. + + The component needs to be turned on, and not faulty, in order for + the function to be called. + + This function is intended to be used as a decorator: + + .. code-block:: python + + @check_on + def scan(self): + ... :param func: the wrapped function @@ -23,8 +31,10 @@ def check_on(func): @functools.wraps(func) def _wrapper(component, *args, **kwargs): """ - Wrapper function that checks that the component is turned on and - not faulty before invoking the wrapped function + Check that the component is on and not faulty before calling the function. + + This is a wrapper function that implements the functionality of + the decorator. :param component: the component to check :param args: positional arguments to the wrapped function @@ -45,7 +55,7 @@ class ReferenceCspObsComponentManager( CspObsComponentManager, ReferenceBaseComponentManager ): """ - A component manager for SKA CSP subelement observation Tango devices: + A component manager for SKA CSP subelement observation Tango devices. The current implementation is intended to * illustrate the model @@ -57,8 +67,7 @@ class ReferenceCspObsComponentManager( class _Component(ReferenceBaseComponentManager._Component): """ - An example CSP subelement obs component for the component - manager to work with. + An example CSP subelement obs component for the component manager to work with. It can be directly controlled via configure(), scan(), end_scan(), go_to_idle(), abort() and reset() command methods. @@ -78,14 +87,12 @@ class ReferenceCspObsComponentManager( _faulty=False, ): """ - Initialise a new instance - State Machine<State_Machine> + Initialise a new instance. - - :param _power_mode: initial power mode of this component - (for testing only) - :param _faulty: whether this component should initially - simulate a fault (for testing only) + :param _power_mode: initial power mode of this component + (for testing only) + :param _faulty: whether this component should initially + simulate a fault (for testing only) """ self._configured = False self._configured_callback = None @@ -110,93 +117,148 @@ class ReferenceCspObsComponentManager( @property @check_on def configured(self): + """Return whether the component if currently configured.""" return self._configured @property @check_on def config_id(self): + """Return the configuration id.""" return self._config_id - # @config_id.setter - # @check_on - # def config_id(self, config_id): - # self._config_id = config_id - @property @check_on def scanning(self): + """ + Return whether this component is scanning. + + :return: whether this component is scanning + :rtype: bool + """ return self._scanning @property @check_on def scan_id(self): + """Return the scan id.""" return self._scan_id @property @check_on def obsfault(self): + """ + Return whether this component is obsfaulting. + + :return: whether this component is obsfaulting + :rtype: bool + """ return self._obsfault @check_on def configure_scan(self, configuration): + """ + Configure the component. + + :param configuration: the configuration to be configured + :type configuration: dict + """ self._config_id = configuration["id"] self._update_configured(True) @check_on def deconfigure(self): + """Deconfigure this component.""" self._config_id = "" self._update_configured(False) @check_on def scan(self, scan_id): + """Start scanning.""" self._scan_id = scan_id self._update_scanning(True) @check_on def end_scan(self): + """End scanning.""" self.simulate_scan_stopped() @check_on def simulate_scan_stopped(self): + """Tell the component to simulate spontaneous stopping its scan.""" self._scan_id = 0 self._update_scanning(False) @check_on def simulate_obsfault(self, obsfault): + """Tell the component to simulate an obsfault.""" self._update_obsfault(obsfault) def _invoke_configured_callback(self): + """Invoke the callback when whether the component is configured changes.""" if not self.faulty: if self._configured_callback is not None: self._configured_callback(self._configured) def _update_configured(self, configured): + """ + Update whether the component is configured or not. + + This helper method will also ensure that callbacks are + called as required. + + :param configured: new value for whether the component is + configured or not + :type configured: bool + """ if self._configured != configured: self._configured = configured self._invoke_configured_callback() def _invoke_scanning_callback(self): + """Invoke the callback when whether the component is scanning changes.""" if not self.faulty: if self._scanning_callback is not None: self._scanning_callback(self._scanning) def _update_scanning(self, scanning): + """ + Update whether the component is scanning or not. + + This helper method will also ensure that callbacks are + called as required. + + :param scanning: new value for whether the component is + scanning or not + :type scanning: bool + """ if self._scanning != scanning: self._scanning = scanning self._invoke_scanning_callback() def _invoke_obsfault_callback(self): + """Invoke the callback when the component experiences an obsfault.""" if not self.faulty: if self.obsfault and self._obsfault_callback is not None: self._obsfault_callback() def _update_obsfault(self, obsfault): + """ + Update whether the component is obsfaulting or not. + + This helper method will also ensure that callbacks are + called as required. + + :param obsfault: new value for whether the component is + obsfaulting or not + :type obsfaulting: bool + """ if self._obsfault != obsfault: self._obsfault = obsfault if obsfault: self._invoke_obsfault_callback() def __init__(self, op_state_model, obs_state_model, logger=None, _component=None): + """Initialise a new ``ReferenceCspObsComponentManager`` instance.""" super().__init__( op_state_model, obs_state_model, @@ -205,10 +267,7 @@ class ReferenceCspObsComponentManager( ) def start_communicating(self): - """ - Establish communication with the component, then start - monitoring. - """ + """Establish communication with the component, then start monitoring.""" if self._connected: return @@ -238,10 +297,7 @@ class ReferenceCspObsComponentManager( self.op_state_model.to_SCANNING() def stop_communicating(self): - """ - Cease monitoring the component, and break off all communication - with it. - """ + """Cease monitoring the component, and break off all communication with it.""" if not self._connected: return @@ -250,8 +306,7 @@ class ReferenceCspObsComponentManager( def simulate_communication_failure(self, fail_communicate): """ - Simulate (or stop simulating) a failure to communicate with the - component + Simulate (or stop simulating) a failure to communicate with the component. :param fail_communicate: whether the connection to the component is failing @@ -265,32 +320,38 @@ class ReferenceCspObsComponentManager( @check_communicating def configure_scan(self, configuration): + """Configure the component.""" self.logger.info("Configuring component") self._component.configure_scan(configuration) @check_communicating def deconfigure(self): + """Tell the component to deconfigure.""" self.logger.info("Deconfiguring component") self._component.deconfigure() @check_communicating def scan(self, args): + """Tell the component to start scanning.""" self.logger.info("Starting scan in component") self._component.scan(args) @check_communicating def end_scan(self): + """Tell the component to stop scanning.""" self.logger.info("Stopping scan in component") self._component.end_scan() @check_communicating def abort(self): + """Cause the component to abort what it is doing.""" self.logger.info("Aborting component") if self._component.scanning: self._component.end_scan() @check_communicating def obsreset(self): + """Perform an obsreset on the component.""" self.logger.info("Resetting component") if self._component.configured: self._component.deconfigure() @@ -298,11 +359,13 @@ class ReferenceCspObsComponentManager( @property @check_communicating def config_id(self): + """Return the configuration id.""" return self._component.config_id @property @check_on def scan_id(self): + """Return the scan id.""" return self._component.scan_id @config_id.setter @@ -311,16 +374,37 @@ class ReferenceCspObsComponentManager( self._component.config_id = config_id def component_configured(self, configured): + """ + Handle notification that the component has started or stopped configuring. + + This is callback hook. + + :param configured: whether this component is configured + :type configured: bool + """ if configured: self.obs_state_model.perform_action("component_configured") else: self.obs_state_model.perform_action("component_unconfigured") def component_scanning(self, scanning): + """ + Handle notification that the component has started or stopped scanning. + + This is a callback hook. + + :param scanning: whether this component is scanning + :type scanning: bool + """ if scanning: self.obs_state_model.perform_action("component_scanning") else: self.obs_state_model.perform_action("component_not_scanning") def component_obsfault(self): + """ + Handle notification that the component has obsfaulted. + + This is a callback hook. + """ self.obs_state_model.perform_action("component_obsfault") diff --git a/src/ska_tango_base/csp/subarray/__init__.py b/src/ska_tango_base/csp/subarray/__init__.py index 8d936792f3d386c16d45fec777a8b4a2f9e9167c..5d965c9fe46032b7dcfdacef97ca3e93fd655359 100644 --- a/src/ska_tango_base/csp/subarray/__init__.py +++ b/src/ska_tango_base/csp/subarray/__init__.py @@ -1,6 +1,4 @@ -""" -This subpackage contains subarray device functionality specific to CSP. -""" +"""This subpackage contains subarray device functionality specific to CSP.""" __all__ = ( "CspSubarrayComponentManager", diff --git a/src/ska_tango_base/csp/subarray/component_manager.py b/src/ska_tango_base/csp/subarray/component_manager.py index cab4cf55bf07b7c2a43925393e77ff23b2fcfd64..a08da49c4caa13b58dd5cea97a040dac760f669b 100644 --- a/src/ska_tango_base/csp/subarray/component_manager.py +++ b/src/ska_tango_base/csp/subarray/component_manager.py @@ -1,12 +1,10 @@ -""" -This module models component management for CSP subarrays. -""" +"""This module models component management for CSP subarrays.""" from ska_tango_base.subarray import SubarrayComponentManager class CspSubarrayComponentManager(SubarrayComponentManager): """ - A component manager for SKA CSP subarray Tango devices: + A component manager for SKA CSP subarray Tango devices. The current implementation is intended to * illustrate the model @@ -17,6 +15,7 @@ class CspSubarrayComponentManager(SubarrayComponentManager): """ def __init__(self, op_state_model, obs_state_model, *args, **kwargs): + """Initialise a new ``CspSubarrayComponentManager`` instance.""" super().__init__( op_state_model, obs_state_model, @@ -26,8 +25,10 @@ class CspSubarrayComponentManager(SubarrayComponentManager): @property def config_id(self): + """Return the configuration id.""" return NotImplementedError("CspSubarrayComponentManager is abstract.") @property def scan_id(self): + """Return the scan id.""" return NotImplementedError("CspSubarrayComponentManager is abstract.") diff --git a/src/ska_tango_base/csp/subarray/reference_component_manager.py b/src/ska_tango_base/csp/subarray/reference_component_manager.py index 3f8c7eab0885fff8323e58e607326ca8760ae1e2..8a6cca37d8d02578b451d79622ede61b8de9c99a 100644 --- a/src/ska_tango_base/csp/subarray/reference_component_manager.py +++ b/src/ska_tango_base/csp/subarray/reference_component_manager.py @@ -1,6 +1,4 @@ -""" -This module models component management for CSP subelement observation devices. -""" +"""This module models component management for CSP subelement observation devices.""" import functools from ska_tango_base.base import check_communicating @@ -12,8 +10,18 @@ from ska_tango_base.faults import ComponentError, ComponentFault def check_on(func): """ - Decorator that makes a method first checks that the component is - turned on and not faulty before allowing the command to proceed + Return a function that checks the component state then calls another function. + + The component needs to be turned on, and not faulty, in order for + the function to be called. + + This function is intended to be used as a decorator: + + .. code-block:: python + + @check_on + def scan(self): + ... :param func: the wrapped function @@ -23,8 +31,10 @@ def check_on(func): @functools.wraps(func) def _wrapper(component, *args, **kwargs): """ - Wrapper function that checks that the component is turned on and - not faulty before invoking the wrapped function + Check that the component is on and not faulty before calling the function. + + This is a wrapper function that implements the functionality of + the decorator. :param component: the component to check :param args: positional arguments to the wrapped function @@ -46,7 +56,7 @@ class ReferenceCspSubarrayComponentManager( ReferenceSubarrayComponentManager, ): """ - A component manager for SKA CSP subelement observation Tango devices: + A component manager for SKA CSP subelement observation Tango devices. The current implementation is intended to * illustrate the model @@ -58,8 +68,7 @@ class ReferenceCspSubarrayComponentManager( class _Component(ReferenceSubarrayComponentManager._Component): """ - An example CSP subelement obs component for the component - manager to work with. + An example CSP subelement obs component for the component manager to work with. It can be directly controlled via configure(), scan(), end_scan(), go_to_idle(), abort() and reset() command methods. @@ -80,7 +89,7 @@ class ReferenceCspSubarrayComponentManager( _faulty=False, ): """ - Initialise a new instance + Initialise a new instance. :param capability_types: a list strings representing capability types. @@ -127,6 +136,7 @@ class ReferenceCspSubarrayComponentManager( def __init__( self, op_state_model, obs_state_model, capability_types, logger, _component=None ): + """Initialise a new ``ReferenceCspSubarrayComponentManager`` instance.""" super().__init__( op_state_model, obs_state_model, @@ -138,9 +148,11 @@ class ReferenceCspSubarrayComponentManager( @property @check_communicating def config_id(self): + """Return the configuration id.""" return self._component.config_id @property @check_on def scan_id(self): + """Return the scan id.""" return self._component.scan_id diff --git a/src/ska_tango_base/csp/subarray/subarray_device.py b/src/ska_tango_base/csp/subarray/subarray_device.py index 94cbadc288d85b50b3e122d09ccf2e60b0cccc24..8ebf406ee420a9607f3145305bba56c8e6baf41a 100644 --- a/src/ska_tango_base/csp/subarray/subarray_device.py +++ b/src/ska_tango_base/csp/subarray/subarray_device.py @@ -6,7 +6,8 @@ # Distributed under the terms of the BSD3 license. # See LICENSE.txt for more info. -""" CspSubElementSubarray +""" +CspSubElementSubarray. Subarray device for SKA CSP SubElement """ @@ -39,9 +40,7 @@ __all__ = ["CspSubElementSubarray", "main"] class CspSubElementSubarray(SKASubarray): - """ - Subarray device for SKA CSP SubElement - """ + """Subarray device for SKA CSP SubElement.""" # PROTECTED REGION ID(CspSubElementSubarray.class_variable) ENABLED START # # PROTECTED REGION END # // CspSubElementSubarray.class_variable @@ -196,12 +195,11 @@ class CspSubElementSubarray(SKASubarray): # --------------- def create_component_manager(self): + """Create and return the component manager for this device.""" return CspSubarrayComponentManager(self.op_state_model, self.obs_state_model) def init_command_objects(self): - """ - Sets up the command objects - """ + """Set up the command objects.""" super().init_command_objects() device_args = ( @@ -216,9 +214,7 @@ class CspSubElementSubarray(SKASubarray): self.register_command_object("GoToIdle", self.GoToIdleCommand(*device_args)) class InitCommand(SKASubarray.InitCommand): - """ - A class for the CspSubElementObsDevice's init_device() "command". - """ + """A class for the CspSubElementObsDevice's init_device() "command".""" def do(self): """ @@ -292,16 +288,22 @@ class CspSubElementSubarray(SKASubarray): return (ResultCode.OK, message) def always_executed_hook(self): - """Method always executed before any Tango command is executed.""" + """ + Perform actions that are executed before every device command. + + This is a Tango hook. + """ # PROTECTED REGION ID(CspSubElementSubarray.always_executed_hook) ENABLED START # # PROTECTED REGION END # // CspSubElementSubarray.always_executed_hook def delete_device(self): - """Hook to delete resources allocated in init_device. + """ + Clean up any resources prior to device deletion. - This method allows for any memory or other resources allocated in the - init_device method to be released. This method is called by the device - destructor and by the device Init command. + This method is a Tango hook that is called by the device + destructor and by the device Init command. It allows for any + memory or other resources allocated in the init_device method to + be released prior to device deletion. """ # PROTECTED REGION ID(CspSubElementSubarray.delete_device) ENABLED START # # PROTECTED REGION END # // CspSubElementSubarray.delete_device @@ -436,13 +438,11 @@ class CspSubElementSubarray(SKASubarray): # -------- class ConfigureScanCommand(ObservationCommand, ResponseCommand, CompletionCommand): - """ - A class for the CspSubElementObsDevices's ConfigureScan command. - """ + """A class for the CspSubElementObsDevices's ConfigureScan command.""" def __init__(self, target, op_state_model, obs_state_model, logger=None): """ - Constructor for ConfigureScanCommand + Initialise a new ConfigureScanCommand instance. :param target: the object that this base command acts upon. For example, the device's component manager. @@ -482,6 +482,7 @@ class CspSubElementSubarray(SKASubarray): def validate_input(self, argin): """ Validate the configuration parameters against allowed values, as needed. + :param argin: The JSON formatted string with configuration for the device. :type argin: 'DevString' :return: A tuple containing a return code and a string message. @@ -506,13 +507,11 @@ class CspSubElementSubarray(SKASubarray): ) class GoToIdleCommand(ObservationCommand, ResponseCommand): - """ - A class for the CspSubElementObsDevices's GoToIdle command. - """ + """A class for the CspSubElementObsDevices's GoToIdle command.""" def __init__(self, target, op_state_model, obs_state_model, logger=None): """ - Constructor for EndCommand + Initialise a new GoToIdleCommand instance. :param target: the object that this base command acts upon. For example, the device's component manager. @@ -589,8 +588,7 @@ class CspSubElementSubarray(SKASubarray): def Configure(self, argin): # PROTECTED REGION ID(CspSubElementSubarray.Configure) ENABLED START # """ - Redirect to ConfigureScan method. - Configure a complete scan for the subarray. + Redirect to ConfigureScan method. Configure a complete scan for the subarray. :param argin: JSON configuration string @@ -631,8 +629,7 @@ class CspSubElementSubarray(SKASubarray): def End(self): # PROTECTED REGION ID(CspSubElementSubarray.End) ENABLED START # """ - Transit the subarray from READY to IDLE obsState. - Redirect to GoToIdle command. + Transit the subarray from READY to IDLE obsState. Redirect to GoToIdle command. :return:'DevVarLongStringArray' A tuple containing a return code and a string message indicating status. @@ -648,7 +645,7 @@ class CspSubElementSubarray(SKASubarray): def main(args=None, **kwargs): - """Main function of the CspSubElementSubarray module.""" + """Run the CspSubElementSubarray module.""" # PROTECTED REGION ID(CspSubElementSubarray.main) ENABLED START # return run((CspSubElementSubarray,), args=args, **kwargs) # PROTECTED REGION END # // CspSubElementSubarray.main diff --git a/src/ska_tango_base/logger_device.py b/src/ska_tango_base/logger_device.py index 8930377fc5e07c5e40d5481f061a848dea08184f..913dc5cd5b1ff520fa4023c8c9c35014b0dbc6f2 100644 --- a/src/ska_tango_base/logger_device.py +++ b/src/ska_tango_base/logger_device.py @@ -5,10 +5,11 @@ # # """ -This module implements SKALogger device, a generic base device for -logging for SKA. It enables to view on-line logs through the Tango -Logging Services and to store logs using Python logging. It configures -the log levels of remote logging for selected devices. +This module implements SKALogger device, a generic base device for logging for SKA. + +It enables to view on-line logs through the Tango Logging Services and +to store logs using Python logging. It configures the log levels of +remote logging for selected devices. """ # PROTECTED REGION ID(SKALogger.additionnal_import) ENABLED START # # Tango imports @@ -26,9 +27,7 @@ __all__ = ["SKALogger", "main"] class SKALogger(SKABaseDevice): - """ - A generic base device for Logging for SKA. - """ + """A generic base device for Logging for SKA.""" # PROTECTED REGION ID(SKALogger.class_variable) ENABLED START # # PROTECTED REGION END # // SKALogger.class_variable @@ -45,9 +44,7 @@ class SKALogger(SKABaseDevice): # General methods # --------------- def init_command_objects(self): - """ - Sets up the command objects - """ + """Set up the command objects.""" super().init_command_objects() self.register_command_object( "SetLoggingLevel", @@ -56,11 +53,24 @@ class SKALogger(SKABaseDevice): def always_executed_hook(self): # PROTECTED REGION ID(SKALogger.always_executed_hook) ENABLED START # + """ + Perform actions that are executed before every device command. + + This is a Tango hook. + """ pass # PROTECTED REGION END # // SKALogger.always_executed_hook def delete_device(self): # PROTECTED REGION ID(SKALogger.delete_device) ENABLED START # + """ + Clean up any resources prior to device deletion. + + This method is a Tango hook that is called by the device + destructor and by the device Init command. It allows for any + memory or other resources allocated in the init_device method to + be released prior to device deletion. + """ pass # PROTECTED REGION END # // SKALogger.delete_device @@ -72,13 +82,11 @@ class SKALogger(SKABaseDevice): # Commands # -------- class SetLoggingLevelCommand(ResponseCommand): - """ - A class for the SKALoggerDevice's SetLoggingLevel() command. - """ + """A class for the SKALoggerDevice's SetLoggingLevel() command.""" def __init__(self, target, state_model, logger=None): """ - Constructor for SetLoggingLevelCommand + Initialise a new SetLoggingLevelCommand instance. :param target: the object that this base command acts upon. For example, the device's component manager. @@ -135,7 +143,7 @@ class SKALogger(SKABaseDevice): def SetLoggingLevel(self, argin): # PROTECTED REGION ID(SKALogger.SetLoggingLevel) ENABLED START # """ - Sets logging level of the specified devices. + Set the logging level of the specified devices. To modify behaviour for this command, modify the do() method of the command class. @@ -163,9 +171,7 @@ class SKALogger(SKABaseDevice): def main(args=None, **kwargs): # PROTECTED REGION ID(SKALogger.main) ENABLED START # - """ - Main entry point of the module. - """ + """Launch an SKALogger device.""" return run((SKALogger,), args=args, **kwargs) # PROTECTED REGION END # // SKALogger.main diff --git a/src/ska_tango_base/obs/__init__.py b/src/ska_tango_base/obs/__init__.py index be70fa3d4a0447df6930be8725120395e1e7b3d0..4732c7c06bcc8c2bf9c814adcd686cfce0858655 100644 --- a/src/ska_tango_base/obs/__init__.py +++ b/src/ska_tango_base/obs/__init__.py @@ -1,6 +1,4 @@ -""" -This subpackage models a SKA Tango observing device. -""" +"""This subpackage models a SKA Tango observing device.""" __all__ = ( "ObsStateModel", diff --git a/src/ska_tango_base/obs/obs_device.py b/src/ska_tango_base/obs/obs_device.py index d993a9dcbe175588e4cc3fe5f081bea8b948a498..6a74d6cd494a279e9e34c9a22cc9697e08f2548d 100644 --- a/src/ska_tango_base/obs/obs_device.py +++ b/src/ska_tango_base/obs/obs_device.py @@ -4,11 +4,12 @@ # # # -""" SKAObsDevice +""" +SKAObsDevice. -A generic base device for Observations for SKA. It inherits SKABaseDevice -class. Any device implementing an obsMode will inherit from SKAObsDevice -instead of just SKABaseDevice. +A generic base device for Observations for SKA. It inherits +SKABaseDevice class. Any device implementing an obsMode will inherit +from SKAObsDevice instead of just SKABaseDevice. """ # Additional import @@ -27,14 +28,10 @@ __all__ = ["SKAObsDevice", "main"] class SKAObsDevice(SKABaseDevice): - """ - A generic base device for Observations for SKA. - """ + """A generic base device for Observations for SKA.""" class InitCommand(SKABaseDevice.InitCommand): - """ - A class for the SKAObsDevice's init_device() "command". - """ + """A class for the SKAObsDevice's init_device() "command".""" def do(self): """ @@ -105,8 +102,11 @@ class SKAObsDevice(SKABaseDevice): # --------------- def _update_obs_state(self, obs_state): """ - Helper method for changing obs_state; passed to the state model as a - callback + Perform Tango operations in response to a change in obsState. + + This helper method is passed to the observation state model as a + callback, so that the model can trigger actions in the Tango + device. :param obs_state: the new obs_state value :type obs_state: :py:class:`~ska_tango_base.control_model.ObsState` @@ -118,9 +118,9 @@ class SKAObsDevice(SKABaseDevice): def always_executed_hook(self): # PROTECTED REGION ID(SKAObsDevice.always_executed_hook) ENABLED START # """ - Method that is always executed before any device command gets executed. + Perform actions that are executed before every device command. - :return: None + This is a Tango hook. """ pass # PROTECTED REGION END # // SKAObsDevice.always_executed_hook @@ -128,9 +128,12 @@ class SKAObsDevice(SKABaseDevice): def delete_device(self): # PROTECTED REGION ID(SKAObsDevice.delete_device) ENABLED START # """ - Method to cleanup when device is stopped. + Clean up any resources prior to device deletion. - :return: None + This method is a Tango hook that is called by the device + destructor and by the device Init command. It allows for any + memory or other resources allocated in the init_device method to + be released prior to device deletion. """ pass # PROTECTED REGION END # // SKAObsDevice.delete_device @@ -141,25 +144,25 @@ class SKAObsDevice(SKABaseDevice): def read_obsState(self): # PROTECTED REGION ID(SKAObsDevice.obsState_read) ENABLED START # - """Reads Observation State of the device""" + """Read the Observation State of the device.""" return self._obs_state # PROTECTED REGION END # // SKAObsDevice.obsState_read def read_obsMode(self): # PROTECTED REGION ID(SKAObsDevice.obsMode_read) ENABLED START # - """Reads Observation Mode of the device""" + """Read the Observation Mode of the device.""" return self._obs_mode # PROTECTED REGION END # // SKAObsDevice.obsMode_read def read_configurationProgress(self): # PROTECTED REGION ID(SKAObsDevice.configurationProgress_read) ENABLED START # - """Reads percentage configuration progress of the device""" + """Read the percentage configuration progress of the device.""" return self._config_progress # PROTECTED REGION END # // SKAObsDevice.configurationProgress_read def read_configurationDelayExpected(self): # PROTECTED REGION ID(SKAObsDevice.configurationDelayExpected_read) ENABLED START # - """Reads expected Configuration Delay in seconds""" + """Read the expected Configuration Delay in seconds.""" return self._config_delay_expected # PROTECTED REGION END # // SKAObsDevice.configurationDelayExpected_read @@ -176,7 +179,7 @@ class SKAObsDevice(SKABaseDevice): def main(args=None, **kwargs): # PROTECTED REGION ID(SKAObsDevice.main) ENABLED START # """ - Main function of the SKAObsDevice module. + Launch an SKAObsDevice. :param args: positional arguments :param kwargs: keyword arguments diff --git a/src/ska_tango_base/obs/obs_state_model.py b/src/ska_tango_base/obs/obs_state_model.py index c47dc0e2b3c9bbe268e870f373a3ff6109f8978f..829edfebbb98bcea4f7bec34d0174e0afb82de76 100644 --- a/src/ska_tango_base/obs/obs_state_model.py +++ b/src/ska_tango_base/obs/obs_state_model.py @@ -1,9 +1,10 @@ """ -This module defines a basic state model for SKA LMC devices that manage -observations. It consists of a single :py:class:`.ObsStateModel` class, -which drives a state machine to manage device "obs state", represented -by the :py:class:`ska_tango_base.control_model.ObsState` enum, and -published by Tango devices via the ``obsState`` attribute. +This module defines a basic state model for SKA LMC devices that manage observations. + +It consists of a single :py:class:`.ObsStateModel` class, which drives a +state machine to manage device "obs state", represented by the +:py:class:`ska_tango_base.control_model.ObsState` enum, and published by +Tango devices via the ``obsState`` attribute. """ from ska_tango_base.control_model import ObsState from ska_tango_base.faults import StateModelError @@ -15,8 +16,7 @@ __all__ = ["ObsStateModel"] class ObsStateModel: """ - This class implements the state model for observation state - ("obsState"). + This class implements the state model for observation state ("obsState"). The model supports states that are values of the :py:class:`ska_tango_base.control_model.ObsState` enum. Rather than @@ -32,7 +32,7 @@ class ObsStateModel: callback=None, ): """ - Initialises the model. + Initialise the model. :param state_machine_factory: a callable that returns a state machine for this model to use @@ -56,7 +56,7 @@ class ObsStateModel: @property def obs_state(self): """ - Returns the obs_state + Return the obs_state. :returns: obs_state of this state model :rtype: ObsState @@ -65,9 +65,10 @@ class ObsStateModel: def _obs_state_changed(self, machine_state): """ - Helper method that updates obs_state whenever the observation - state machine reports a change of state, ensuring that the - callback is called if one exists. + Handle notification that the observation state machine has changed state. + + This is a helper method that updates obs_state, ensuring that + the callback is called if one exists. :param machine_state: the new state of the observation state machine @@ -81,7 +82,7 @@ class ObsStateModel: def is_action_allowed(self, action, raise_if_disallowed=False): """ - Whether a given action is allowed in the current state. + Return whether a given action is allowed in the current state. :param action: an action, as given in the transitions table :type action: str @@ -110,7 +111,7 @@ class ObsStateModel: def perform_action(self, action): """ - Performs an action on the state model + Perform an action on the state model. :param action: an action, as given in the transitions table :type action: ANY @@ -121,24 +122,25 @@ class ObsStateModel: @for_testing_only def _straight_to_state(self, obs_state_name): """ - Takes this model straight to the specified state. This method - exists to simplify testing; for example, if testing that a - command may be run in a given ObsState, one can push this state - model straight to that ObsState, rather than having to drive it - to that state through a sequence of actions. It is not intended - that this method would be called outside of test setups. A - warning will be raised if it is. + Take this model straight to the specified state. + + This method exists to simplify testing; for example, if testing + that a command may be run in a given ObsState, one can push this + state model straight to that ObsState, rather than having to + drive it to that state through a sequence of actions. It is not + intended that this method would be called outside of test + setups. A warning will be raised if it is. For example, to test that a device transitions from SCANNING to ABORTING when the Abort() command is called: .. code-block:: py - model = ObservationStateModel(logger) - model._straight_to_state("SCANNING") - assert model.obs_state == ObsState.SCANNING - model.perform_action("abort_invoked") - assert model.obs_state == ObsState.ABORTING + model = ObservationStateModel(logger) + model._straight_to_state("SCANNING") + assert model.obs_state == ObsState.SCANNING + model.perform_action("abort_invoked") + assert model.obs_state == ObsState.ABORTING :param obs_state_name: the target obs_state :type obs_state_name: diff --git a/src/ska_tango_base/release.py b/src/ska_tango_base/release.py index 63494f37884de2dd989092ed17442429e438cb99..5b59b1511b2ee54edfd2e0c876522a9ed42c3eb7 100644 --- a/src/ska_tango_base/release.py +++ b/src/ska_tango_base/release.py @@ -4,10 +4,10 @@ # # # -"""Release information for ska_tango_base Python Package""" +"""Release information for ska_tango_base Python Package.""" name = """ska_tango_base""" -version = "0.11.1" +version = "0.11.2" version_info = version.split(".") description = """A set of generic base devices for SKA Telescope.""" author = "SKA India and SARAO and CSIRO and INAF" diff --git a/src/ska_tango_base/subarray/__init__.py b/src/ska_tango_base/subarray/__init__.py index 8d8ffe64bc3e8c9f57a4e6ec1bde981651ec007c..33228e9dea0128f4fe2adb3bdf19cb52d32539c8 100644 --- a/src/ska_tango_base/subarray/__init__.py +++ b/src/ska_tango_base/subarray/__init__.py @@ -1,6 +1,4 @@ -""" -This subpackage models a SKA subarray Tango device. -""" +"""This subpackage models a SKA subarray Tango device.""" __all__ = ( "SubarrayObsStateModel", diff --git a/src/ska_tango_base/subarray/component_manager.py b/src/ska_tango_base/subarray/component_manager.py index 5a65500d84b3a09591bb177aaa314b5d9b151aa3..44cb9efb7df26b092d2de8b0c54750e9fa99dab1 100644 --- a/src/ska_tango_base/subarray/component_manager.py +++ b/src/ska_tango_base/subarray/component_manager.py @@ -1,14 +1,12 @@ -""" -This module provides an abstract component manager for SKA Tango -subarray devices. -""" +"""This module provides an abstract component manager for SKA Tango subarray devices.""" from ska_tango_base.base import BaseComponentManager class SubarrayComponentManager(BaseComponentManager): """ - An abstract base class for a component manager for an SKA subarray - Tango devices, supporting: + An abstract base class for a component manager for an SKA subarray Tango devices. + + It supports: * Maintaining a connection to its component @@ -20,7 +18,7 @@ class SubarrayComponentManager(BaseComponentManager): def __init__(self, op_state_model, obs_state_model): """ - Initialise a new SubarrayComponentManager instance + Initialise a new SubarrayComponentManager instance. :param op_state_model: the op state model used by this component manager :param obs_state_model: the obs state model used by this component manager @@ -31,7 +29,7 @@ class SubarrayComponentManager(BaseComponentManager): def assign(self, resources): """ - Assign resources to the component + Assign resources to the component. :param resources: resources to be assigned """ @@ -39,21 +37,19 @@ class SubarrayComponentManager(BaseComponentManager): def release(self, resources): """ - Release resources from the component + Release resources from the component. :param resources: resources to be released """ raise NotImplementedError("SubarrayComponentManager is abstract.") def release_all(self): - """ - Release all resources - """ + """Release all resources.""" raise NotImplementedError("SubarrayComponentManager is abstract.") def configure(self, configuration): """ - Configure the component + Configure the component. :param configuration: the configuration to be configured :type configuration: dict @@ -61,47 +57,33 @@ class SubarrayComponentManager(BaseComponentManager): raise NotImplementedError("SubarrayComponentManager is abstract.") def deconfigure(self): - """ - Deconfigure this component. - """ + """Deconfigure this component.""" raise NotImplementedError("SubarrayComponentManager is abstract.") def scan(self, args): - """ - Start scanning - """ + """Start scanning.""" raise NotImplementedError("SubarrayComponentManager is abstract.") def end_scan(self): - """ - End scanning - """ + """End scanning.""" raise NotImplementedError("SubarrayComponentManager is abstract.") def abort(self): - """ - Tell the component to abort whatever it was doing - """ + """Tell the component to abort whatever it was doing.""" raise NotImplementedError("SubarrayComponentManager is abstract.") def obsreset(self): - """ - Tell the component to reset to an unconfigured state (but - without releasing any assigned resources) - """ + """Reset the component to unconfigured but do not release resources.""" raise NotImplementedError("SubarrayComponentManager is abstract.") def restart(self): - """ - Tell the component to return to an empty state (unconfigured and - without any assigned resources) - """ + """Deconfigure and release all resources.""" raise NotImplementedError("SubarrayComponentManager is abstract.") @property def assigned_resources(self): """ - Resources assigned to the component + Return the resources assigned to the component. :return: the resources assigned to the component :rtype: list of str @@ -111,7 +93,7 @@ class SubarrayComponentManager(BaseComponentManager): @property def configured_capabilities(self): """ - Configured capabilities of the component + Return the configured capabilities of the component. :return: list of strings indicating number of configured instances of each capability type @@ -121,8 +103,9 @@ class SubarrayComponentManager(BaseComponentManager): def component_resourced(self, resourced): """ - Callback hook, called when whether the component has any - resources changes + Handle notification that the component's resources have changed. + + This is a callback hook. :param resourced: whether this component has any resources :type resourced: bool @@ -134,8 +117,9 @@ class SubarrayComponentManager(BaseComponentManager): def component_configured(self, configured): """ - Callback hook, called when whether the component is configured - changes + Handle notification that the component has started or stopped configuring. + + This is callback hook. :param configured: whether this component is configured :type configured: bool @@ -147,8 +131,9 @@ class SubarrayComponentManager(BaseComponentManager): def component_scanning(self, scanning): """ - Callback hook, called when whether the component is scanning - changes + Handle notification that the component has started or stopped scanning. + + This is a callback hook. :param scanning: whether this component is scanning :type scanning: bool @@ -160,6 +145,8 @@ class SubarrayComponentManager(BaseComponentManager): def component_obsfault(self): """ - Callback hook, called when the component obsfaults + Handle notification that the component has obsfaulted. + + This is a callback hook. """ self.obs_state_model.perform_action("component_obsfault") diff --git a/src/ska_tango_base/subarray/reference_component_manager.py b/src/ska_tango_base/subarray/reference_component_manager.py index 6ca16084809f7b6a41e520080605db4ffe30860a..a878aadc2f5bb6afe055abfb567519d77cd400d5 100644 --- a/src/ska_tango_base/subarray/reference_component_manager.py +++ b/src/ska_tango_base/subarray/reference_component_manager.py @@ -1,6 +1,4 @@ -""" -This module models component management for SKA subarray devices. -""" +"""This module models component management for SKA subarray devices.""" import functools from ska_tango_base.subarray import SubarrayComponentManager @@ -18,8 +16,18 @@ from ska_tango_base.faults import ( def check_on(func): """ - Decorator that makes a method first checks that the component is - turned on and not faulty before allowing the command to proceed + Return a function that checks the component state then calls another function. + + The component needs to be turned on, and not faulty, in order for + the function to be called. + + This function is intended to be used as a decorator: + + .. code-block:: python + + @check_on + def scan(self): + ... :param func: the wrapped function @@ -29,8 +37,10 @@ def check_on(func): @functools.wraps(func) def _wrapper(component, *args, **kwargs): """ - Wrapper function that checks that the component is turned on and - not faulty before invoking the wrapped function + Check that the component is on and not faulty before calling the function. + + This is a wrapper function that implements the functionality of + the decorator. :param component: the component to check :param args: positional arguments to the wrapped function @@ -51,7 +61,7 @@ class ReferenceSubarrayComponentManager( ReferenceBaseComponentManager, SubarrayComponentManager ): """ - A component manager for SKA subarray Tango devices: + A component manager for SKA subarray Tango devices. The current implementation is intended to * illustrate the model @@ -62,13 +72,11 @@ class ReferenceSubarrayComponentManager( """ class _ResourcePool: - """ - A simple class for managing subarray resources - """ + """A simple class for managing subarray resources.""" def __init__(self, callback=None): """ - Initialise a new instance + Initialise a new instance. :param callback: callback to call when the resource pool goes from empty to non-empty or vice-versa @@ -80,9 +88,10 @@ class ReferenceSubarrayComponentManager( def __len__(self): """ - Returns the number of resources currently assigned. Note that - this also functions as a boolean method for whether there are - any assigned resources: ``if len()``. + Return the number of resources currently assigned. + + Note that this also functions as a boolean method for + whether there are any assigned resources: ``if len()``. :return: number of resources assigned :rtype: int @@ -91,7 +100,7 @@ class ReferenceSubarrayComponentManager( def assign(self, resources): """ - Assign some resources + Assign some resources. :param resources: resources to be assigned :type resources: set(str) @@ -101,7 +110,7 @@ class ReferenceSubarrayComponentManager( def release(self, resources): """ - Release some resources + Release some resources. :param resources: resources to be released :type resources: set(str) @@ -110,15 +119,13 @@ class ReferenceSubarrayComponentManager( self._update() def release_all(self): - """ - Release all resources - """ + """Release all resources.""" self._resources.clear() self._update() def get(self): """ - Get current resources + Get current resources. :return: current resources. :rtype: set(str) @@ -135,7 +142,7 @@ class ReferenceSubarrayComponentManager( :return: whether this resource pool contains the specified resources - :rtype bool + :rtype: bool """ return resources in self._resources @@ -148,8 +155,7 @@ class ReferenceSubarrayComponentManager( class _Component(ReferenceBaseComponentManager._Component): """ - An example subarray component for the component manager to work - with. + An example subarray component for the component manager to work with. It can be directly controlled via configure(), scan(), end_scan(), end(), abort(), reset() and restart() command @@ -171,7 +177,7 @@ class ReferenceSubarrayComponentManager( _faulty=False, ): """ - Initialise a new instance + Initialise a new instance. :param capability_types: a list strings representing capability types. @@ -209,7 +215,7 @@ class ReferenceSubarrayComponentManager( obsfault_callback, ): """ - Set callbacks for the underlying component + Set callbacks for the underlying component. :param configured_callback: a callback to call with a boolean argument when whether the component is @@ -227,7 +233,7 @@ class ReferenceSubarrayComponentManager( @check_on def configured(self): """ - Whether this component is configured + Return whether this component is configured. :return: whether this component is configured :rtype: bool @@ -238,7 +244,7 @@ class ReferenceSubarrayComponentManager( @check_on def configured_capabilities(self): """ - Configured capabilities of this component + Return the configured capabilities of this component. :return: list of strings indicating number of configured instances of each capability type @@ -257,7 +263,7 @@ class ReferenceSubarrayComponentManager( @check_on def scanning(self): """ - Whether this component is scanning + Return whether this component is scanning. :return: whether this component is scanning :rtype: bool @@ -268,7 +274,7 @@ class ReferenceSubarrayComponentManager( @check_on def obsfault(self): """ - Whether this component is obsfaulting + Return whether this component is obsfaulting. :return: whether this component is obsfaulting :rtype: bool @@ -277,8 +283,7 @@ class ReferenceSubarrayComponentManager( def _validate_capability_types(self, capability_types): """ - Check the validity of the input parameter passed to the - Configure command. + Check the validity of the input parameter passed to the Configure command. :param capability_types: a list strings representing capability types. @@ -299,7 +304,7 @@ class ReferenceSubarrayComponentManager( @check_on def configure(self, configuration): """ - Configure the component + Configure the component. :param configuration: the configuration to be configured :type configuration: dict @@ -319,9 +324,7 @@ class ReferenceSubarrayComponentManager( @check_on def deconfigure(self): - """ - Deconfigure this component. - """ + """Deconfigure this component.""" self._configured_capabilities = { k: 0 for k in self._configured_capabilities } @@ -329,47 +332,36 @@ class ReferenceSubarrayComponentManager( @check_on def scan(self, args): - """ - Start scanning - """ + """Start scanning.""" self._update_scanning(True) @check_on def end_scan(self): - """ - End scanning - """ + """End scanning.""" self.simulate_scan_stopped() @check_on def simulate_scan_stopped(self): - """ - Tell the component to simulate spontaneous stopping its - scan. - """ + """Tell the component to simulate spontaneous stopping its scan.""" self._update_scanning(False) @check_on def simulate_obsfault(self, obsfault): - """ - Tell the component to simulate an obsfault - """ + """Tell the component to simulate an obsfault.""" self._update_obsfault(obsfault) def _invoke_configured_callback(self): - """ - Helper method that invokes the callback when whether the - component is configured changes. - """ + """Invoke the callback when whether the component is configured changes.""" if not self.faulty: if self._configured_callback is not None: self._configured_callback(self._configured) def _update_configured(self, configured): """ - Helper method that updates whether the component is - configured or not, ensuring that callbacks are called as - required. + Update whether the component is configured or not. + + This helper method will also ensure that callbacks are + called as required. :param configured: new value for whether the component is configured or not @@ -380,19 +372,17 @@ class ReferenceSubarrayComponentManager( self._invoke_configured_callback() def _invoke_scanning_callback(self): - """ - Helper method that invokes the callback when whether the - component is scanning changes. - """ + """Invoke the callback when whether the component is scanning changes.""" if not self.faulty: if self._scanning_callback is not None: self._scanning_callback(self._scanning) def _update_scanning(self, scanning): """ - Helper method that updates whether the component is - scanning or not, ensuring that callbacks are called as - required. + Update whether the component is scanning or not. + + This helper method will also ensure that callbacks are + called as required. :param scanning: new value for whether the component is scanning or not @@ -403,19 +393,17 @@ class ReferenceSubarrayComponentManager( self._invoke_scanning_callback() def _invoke_obsfault_callback(self): - """ - Helper method that invokes the callback when the component - experiences an obsfault. - """ + """Invoke the callback when the component experiences an obsfault.""" if not self.faulty: if self.obsfault and self._obsfault_callback is not None: self._obsfault_callback() def _update_obsfault(self, obsfault): """ - Helper method that updates whether the component is - obsfaulting or not, ensuring that callbacks are called as - required. + Update whether the component is obsfaulting or not. + + This helper method will also ensure that callbacks are + called as required. :param obsfault: new value for whether the component is obsfaulting or not @@ -435,7 +423,7 @@ class ReferenceSubarrayComponentManager( _component=None, ): """ - Initialise a new ReferenceSubarrayComponentManager instance + Initialise a new ReferenceSubarrayComponentManager instance. :param op_state_model: the op state model used by this component manager @@ -458,10 +446,7 @@ class ReferenceSubarrayComponentManager( ) def start_communicating(self): - """ - Establish communication with the component, then start - monitoring. - """ + """Establish communication with the component, then start monitoring.""" if self._connected: return super().start_communicating() @@ -490,10 +475,7 @@ class ReferenceSubarrayComponentManager( self.obs_state_model.to_SCANNING() def stop_communicating(self): - """ - Cease monitoring the component, and break off all communication - with it. - """ + """Cease monitoring the component, and break off all communication with it.""" if not self._connected: return @@ -502,7 +484,7 @@ class ReferenceSubarrayComponentManager( def simulate_communication_failure(self, fail_communicate): """ - Simulate (or stop simulating) a component connection failure + Simulate (or stop simulating) a component connection failure. :param fail_communicate: whether the connection to the component is failing @@ -514,7 +496,7 @@ class ReferenceSubarrayComponentManager( @check_communicating def assign(self, resources): """ - Assign resources to the component + Assign resources to the component. :param resources: resources to be assigned :type resources: list(str) @@ -525,7 +507,7 @@ class ReferenceSubarrayComponentManager( @check_communicating def release(self, resources): """ - Release resources from the component + Release resources from the component. :param resources: resources to be released :type resources: list(str) @@ -535,16 +517,14 @@ class ReferenceSubarrayComponentManager( @check_communicating def release_all(self): - """ - Release all resources - """ + """Release all resources.""" self.logger.info("Releasing all resources in component") self._resource_pool.release_all() @check_communicating def configure(self, configuration): """ - Configure the component + Configure the component. :param configuration: the configuration to be configured :type configuration: dict @@ -554,43 +534,32 @@ class ReferenceSubarrayComponentManager( @check_communicating def deconfigure(self): - """ - Deconfigure this component. - """ + """Deconfigure this component.""" self.logger.info("Deconfiguring component") self._component.deconfigure() @check_communicating def scan(self, args): - """ - Start scanning - """ + """Start scanning.""" self.logger.info("Starting scan in component") self._component.scan(args) @check_communicating def end_scan(self): - """ - End scanning - """ + """End scanning.""" self.logger.info("Stopping scan in component") self._component.end_scan() @check_communicating def abort(self): - """ - Tell the component to abort whatever it was doing - """ + """Tell the component to abort whatever it was doing.""" self.logger.info("Aborting component") if self._component.scanning: self._component.end_scan() @check_communicating def obsreset(self): - """ - Tell the component to reset to an unconfigured state (but - without releasing any assigned resources) - """ + """Deconfigure the component but do not release resources.""" self.logger.info("Resetting component") if self._component.configured: self._component.deconfigure() @@ -598,8 +567,10 @@ class ReferenceSubarrayComponentManager( @check_communicating def restart(self): """ - Tell the component to return to an empty state (unconfigured and - without any assigned resources) + Tell the component to restart. + + It will return to a state in which it is unconfigured and empty + of assigned resources. """ self.logger.info("Restarting component") if self._component.configured: @@ -610,7 +581,7 @@ class ReferenceSubarrayComponentManager( @check_communicating def assigned_resources(self): """ - Resources assigned to the component + Return the resources assigned to the component. :return: the resources assigned to the component :rtype: list of str @@ -621,7 +592,7 @@ class ReferenceSubarrayComponentManager( @check_communicating def configured_capabilities(self): """ - Configured capabilities of the component + Return the configured capabilities of the component. :return: list of strings indicating number of configured instances of each capability type @@ -631,8 +602,9 @@ class ReferenceSubarrayComponentManager( def component_resourced(self, resourced): """ - Callback hook, called when whether the component has any - resources changes + Handle notification that the component's resources have changed. + + This is a callback hook. :param resourced: whether this component has any resources :type resourced: bool @@ -644,8 +616,9 @@ class ReferenceSubarrayComponentManager( def component_configured(self, configured): """ - Callback hook, called when whether the component is configured - changes + Handle notification that the component has started or stopped configuring. + + This is a callback hook. :param configured: whether this component is configured :type configured: bool @@ -657,8 +630,9 @@ class ReferenceSubarrayComponentManager( def component_scanning(self, scanning): """ - Callback hook, called when whether the component is scanning - changes + Handle notification that the component has started or stopped scanning. + + This is a callback hook. :param scanning: whether this component is scanning :type scanning: bool @@ -670,6 +644,8 @@ class ReferenceSubarrayComponentManager( def component_obsfault(self): """ - Callback hook, called when the component obsfaults + Handle notification that the component has obsfaulted. + + This is a callback hook. """ self.obs_state_model.perform_action("component_obsfault") diff --git a/src/ska_tango_base/subarray/subarray_device.py b/src/ska_tango_base/subarray/subarray_device.py index 61e5a1257fa2b3c064c23a4d33e764cd67bc2fd3..a093e8f3cac0965f1ba0d8253e49784a33580f7d 100644 --- a/src/ska_tango_base/subarray/subarray_device.py +++ b/src/ska_tango_base/subarray/subarray_device.py @@ -4,11 +4,13 @@ # # # -""" SKASubarray +""" +SKASubarray. -A SubArray handling device. It allows the assigning/releasing of resources -into/from Subarray, configuring capabilities, and exposes the related -information like assigned resources, configured capabilities, etc. +A SubArray handling device. It allows the assigning/releasing of +resources into/from Subarray, configuring capabilities, and exposes the +related information like assigned resources, configured capabilities, +etc. """ # PROTECTED REGION ID(SKASubarray.additionnal_import) ENABLED START # import json @@ -33,14 +35,10 @@ __all__ = ["SKASubarray", "main"] class SKASubarray(SKAObsDevice): - """ - Implements the SKA SubArray device - """ + """Implements the SKA SubArray device.""" class InitCommand(SKAObsDevice.InitCommand): - """ - A class for the SKASubarray's init_device() "command". - """ + """A class for the SKASubarray's init_device() "command".""" def do(self): """ @@ -63,13 +61,11 @@ class SKASubarray(SKAObsDevice): class AssignResourcesCommand( ObservationCommand, ResponseCommand, CompletionCommand ): - """ - A class for SKASubarray's AssignResources() command. - """ + """A class for SKASubarray's AssignResources() command.""" def __init__(self, target, op_state_model, obs_state_model, logger=None): """ - Constructor for AssignResourcesCommand + Initialise a new AssignResourcesCommand instance. :param target: the object that this command acts upon; for example, the device's component manager @@ -112,13 +108,11 @@ class SKASubarray(SKAObsDevice): class ReleaseResourcesCommand( ObservationCommand, ResponseCommand, CompletionCommand ): - """ - A class for SKASubarray's ReleaseResources() command. - """ + """A class for SKASubarray's ReleaseResources() command.""" def __init__(self, target, op_state_model, obs_state_model, logger=None): """ - Constructor for ReleaseResourcesCommand + Initialise a new ReleaseResourcesCommand instance. :param target: the object that this command acts upon; for example, the device's component manager @@ -161,13 +155,11 @@ class SKASubarray(SKAObsDevice): class ReleaseAllResourcesCommand( ObservationCommand, ResponseCommand, CompletionCommand ): - """ - A class for SKASubarray's ReleaseAllResources() command. - """ + """A class for SKASubarray's ReleaseAllResources() command.""" def __init__(self, target, op_state_model, obs_state_model, logger=None): """ - Constructor for ReleaseResourcesCommand + Initialise a new ReleaseAllResourcesCommand instance. :param target: the object that this command acts upon; for example, the device's component manager @@ -205,13 +197,11 @@ class SKASubarray(SKAObsDevice): return (ResultCode.OK, message) class ConfigureCommand(ObservationCommand, ResponseCommand, CompletionCommand): - """ - A class for SKASubarray's Configure() command. - """ + """A class for SKASubarray's Configure() command.""" def __init__(self, target, op_state_model, obs_state_model, logger=None): """ - Constructor for ConfigureCommand + Initialise a new ConfigureCommand instance. :param target: the object that this command acts upon; for example, the device's component manager @@ -252,13 +242,11 @@ class SKASubarray(SKAObsDevice): return (ResultCode.OK, message) class ScanCommand(ObservationCommand, ResponseCommand): - """ - A class for SKASubarray's Scan() command. - """ + """A class for SKASubarray's Scan() command.""" def __init__(self, target, op_state_model, obs_state_model, logger=None): """ - Constructor for ScanCommand + Initialise a new ScanCommand instance. :param target: the object that this command acts upon; for example, the device's component manager @@ -299,13 +287,11 @@ class SKASubarray(SKAObsDevice): return (ResultCode.STARTED, message) class EndScanCommand(ObservationCommand, ResponseCommand): - """ - A class for SKASubarray's EndScan() command. - """ + """A class for SKASubarray's EndScan() command.""" def __init__(self, target, op_state_model, obs_state_model, logger=None): """ - Constructor for EndScanCommand + Initialise a new EndScanCommand instance. :param target: the object that this command acts upon; for example, the device's component manager @@ -343,13 +329,11 @@ class SKASubarray(SKAObsDevice): return (ResultCode.OK, message) class EndCommand(ObservationCommand, ResponseCommand): - """ - A class for SKASubarray's End() command. - """ + """A class for SKASubarray's End() command.""" def __init__(self, target, op_state_model, obs_state_model, logger=None): """ - Constructor for EndCommand + Initialise a new EndCommand instance. :param target: the object that this command acts upon; for example, the device's component manager @@ -387,13 +371,11 @@ class SKASubarray(SKAObsDevice): return (ResultCode.OK, message) class AbortCommand(ObservationCommand, ResponseCommand, CompletionCommand): - """ - A class for SKASubarray's Abort() command. - """ + """A class for SKASubarray's Abort() command.""" def __init__(self, target, op_state_model, obs_state_model, logger=None): """ - Constructor for AbortCommand + Initialise a new AbortCommand instance. :param target: the object that this command acts upon; for example, the device's component manager @@ -431,13 +413,11 @@ class SKASubarray(SKAObsDevice): return (ResultCode.OK, message) class ObsResetCommand(ObservationCommand, ResponseCommand, CompletionCommand): - """ - A class for SKASubarray's ObsReset() command. - """ + """A class for SKASubarray's ObsReset() command.""" def __init__(self, target, op_state_model, obs_state_model, logger=None): """ - Constructor for ObsResetCommand + Initialise a new ObsResetCommand instance. :param target: the object that this command acts upon; for example, the device's component manager @@ -475,13 +455,11 @@ class SKASubarray(SKAObsDevice): return (ResultCode.OK, message) class RestartCommand(ObservationCommand, ResponseCommand, CompletionCommand): - """ - A class for SKASubarray's Restart() command. - """ + """A class for SKASubarray's Restart() command.""" def __init__(self, target, op_state_model, obs_state_model, logger=None): """ - Constructor for RestartCommand + Initialise a new RestartCommand instance. :param target: the object that this command acts upon; for example, the device's component manager @@ -504,7 +482,7 @@ class SKASubarray(SKAObsDevice): def do(self): """ - Stateless hook for Restart() command functionality. + Execute the functionality of the Restart() command. :return: A tuple containing a return code and a string message indicating status. The message is for @@ -520,21 +498,18 @@ class SKASubarray(SKAObsDevice): # PROTECTED REGION ID(SKASubarray.class_variable) ENABLED START # def _init_state_model(self): - """ - Sets up the state model for the device - """ + """Set up the state model for the device.""" super()._init_state_model() self.obs_state_model = SubarrayObsStateModel( logger=self.logger, callback=self._update_obs_state ) def create_component_manager(self): + """Create and return a component manager for this device.""" return SubarrayComponentManager(self.op_state_model, self.obs_state_model) def init_command_objects(self): - """ - Sets up the command objects - """ + """Set up the command objects.""" super().init_command_objects() for (command_name, command_class) in [ @@ -605,7 +580,9 @@ class SKASubarray(SKAObsDevice): def always_executed_hook(self): # PROTECTED REGION ID(SKASubarray.always_executed_hook) ENABLED START # """ - Method that is always executed before any device command gets executed. + Perform actions that are executed before every device command. + + This is a Tango hook. """ pass # PROTECTED REGION END # // SKASubarray.always_executed_hook @@ -613,7 +590,12 @@ class SKASubarray(SKAObsDevice): def delete_device(self): # PROTECTED REGION ID(SKASubarray.delete_device) ENABLED START # """ - Method to cleanup when device is stopped. + Clean up any resources prior to device deletion. + + This method is a Tango hook that is called by the device + destructor and by the device Init command. It allows for any + memory or other resources allocated in the init_device method to + be released prior to device deletion. """ pass # PROTECTED REGION END # // SKASubarray.delete_device @@ -624,7 +606,7 @@ class SKASubarray(SKAObsDevice): def read_activationTime(self): # PROTECTED REGION ID(SKASubarray.activationTime_read) ENABLED START # """ - Reads the time since device is activated. + Read the time since device is activated. :return: Time of activation in seconds since Unix epoch. """ @@ -634,7 +616,7 @@ class SKASubarray(SKAObsDevice): def read_assignedResources(self): # PROTECTED REGION ID(SKASubarray.assignedResources_read) ENABLED START # """ - Reads the resources assigned to the device. + Read the resources assigned to the device. :return: Resources assigned to the device. """ @@ -644,7 +626,7 @@ class SKASubarray(SKAObsDevice): def read_configuredCapabilities(self): # PROTECTED REGION ID(SKASubarray.configuredCapabilities_read) ENABLED START # """ - Reads capabilities configured in the Subarray. + Read capabilities configured in the Subarray. :return: A list of capability types with no. of instances used in the Subarray @@ -658,8 +640,7 @@ class SKASubarray(SKAObsDevice): def is_AssignResources_allowed(self): """ - Check if command `AssignResources` is allowed in the current - device state. + Check if command `AssignResources` is allowed in the current device state. :return: ``True`` if the command is allowed :rtype: boolean @@ -676,7 +657,7 @@ class SKASubarray(SKAObsDevice): @DebugIt() def AssignResources(self, argin): """ - Assign resources to this subarray + Assign resources to this subarray. To modify behaviour for this command, modify the do() method of the command class. @@ -696,8 +677,7 @@ class SKASubarray(SKAObsDevice): def is_ReleaseResources_allowed(self): """ - Check if command `ReleaseResources` is allowed in the current - device state + Check if command `ReleaseResources` is allowed in the current device state. :return: ``True`` if the command is allowed :rtype: boolean @@ -734,8 +714,7 @@ class SKASubarray(SKAObsDevice): def is_ReleaseAllResources_allowed(self): """ - Check if command `ReleaseAllResources` is allowed in the current - device state. + Check if command `ReleaseAllResources` is allowed in the current device state. :return: ``True`` if the command is allowed :rtype: boolean @@ -766,8 +745,7 @@ class SKASubarray(SKAObsDevice): def is_Configure_allowed(self): """ - Check if command `Configure` is allowed in the current - device state. + Check if command `Configure` is allowed in the current device state. :return: ``True`` if the command is allowed :rtype: boolean @@ -784,7 +762,7 @@ class SKASubarray(SKAObsDevice): @DebugIt() def Configure(self, argin): """ - Configures the capabilities of this subarray + Configure the capabilities of this subarray. To modify behaviour for this command, modify the do() method of the command class. @@ -821,7 +799,7 @@ class SKASubarray(SKAObsDevice): @DebugIt() def Scan(self, argin): """ - Start scanning + Start scanning. To modify behaviour for this command, modify the do() method of the command class. @@ -856,7 +834,7 @@ class SKASubarray(SKAObsDevice): @DebugIt() def EndScan(self): """ - End the scan + End the scan. To modify behaviour for this command, modify the do() method of the command class. @@ -919,8 +897,7 @@ class SKASubarray(SKAObsDevice): @DebugIt() def Abort(self): """ - Abort any long-running command such as ``Configure()`` or - ``Scan()``. + Abort any long-running command such as ``Configure()`` or ``Scan()``. To modify behaviour for this command, modify the do() method of the command class. @@ -936,8 +913,7 @@ class SKASubarray(SKAObsDevice): def is_ObsReset_allowed(self): """ - Check if command `ObsReset` is allowed in the current device - state. + Check if command `ObsReset` is allowed in the current device state. :return: ``True`` if the command is allowed :rtype: boolean @@ -968,8 +944,7 @@ class SKASubarray(SKAObsDevice): def is_Restart_allowed(self): """ - Check if command `Restart` is allowed in the current device - state. + Check if command `Restart` is allowed in the current device state. :return: ``True`` if the command is allowed :rtype: boolean @@ -984,8 +959,7 @@ class SKASubarray(SKAObsDevice): @DebugIt() def Restart(self): """ - Restart the subarray. That is, deconfigure and release - all resources. + Restart the subarray. That is, deconfigure and release all resources. To modify behaviour for this command, modify the do() method of the command class. @@ -1006,7 +980,7 @@ class SKASubarray(SKAObsDevice): def main(args=None, **kwargs): # PROTECTED REGION ID(SKASubarray.main) ENABLED START # """ - Main entry point of the module. + Launch an SKASubarray device. :param args: positional args to tango.server.run :param kwargs: named args to tango.server.run diff --git a/src/ska_tango_base/subarray/subarray_obs_state_model.py b/src/ska_tango_base/subarray/subarray_obs_state_model.py index 76de3042a4451b0a0c424a1a4e4d4e490b8a276a..c2e29846d6bae9005787663c2df9a919c08fa8c7 100644 --- a/src/ska_tango_base/subarray/subarray_obs_state_model.py +++ b/src/ska_tango_base/subarray/subarray_obs_state_model.py @@ -1,13 +1,13 @@ """ -This module specifies the observation state ("obs state") model for SKA -subarray Tango devices. It consists of: +This module specifies the observation state model for SKA subarray Tango devices. + +It consists of: * an underlying state machine: :py:class:`._SubarrayObsStateMachine` * an :py:class:`.SubarrayObsStateModel` that maps the underlying state machine state to a value of the :py:class:`ska_tango_base.control_model.ObsState` enum. - """ from transitions.extensions import LockedMachine as Machine @@ -19,8 +19,7 @@ __all__ = ["SubarrayObsStateModel"] class _SubarrayObsStateMachine(Machine): """ - State machine representing the observation state machine for - subarrays. + State machine representing the observation state machine for subarrays. The machine implemented is essentially as agreed in ADR-8, but with some states broken down into sub-states to account for the @@ -123,13 +122,11 @@ class _SubarrayObsStateMachine(Machine): .. figure:: _SubarrayObsStateMachine_autogenerated.png :alt: Diagram of the subarray obs state machine, as implemented - - """ def __init__(self, callback=None, **extra_kwargs): """ - Initialises the model. + Initialise the model. :param callback: A callback to be called when the state changes :type callback: callable @@ -352,8 +349,9 @@ class _SubarrayObsStateMachine(Machine): def _state_changed(self): """ - State machine callback that is called every time the obs_state - changes. Responsible for ensuring that callbacks are called. + State machine callback that is called every time the obs_state changes. + + Responsible for ensuring that callbacks are called. """ if self._callback is not None: self._callback(self.state) @@ -361,7 +359,7 @@ class _SubarrayObsStateMachine(Machine): class SubarrayObsStateModel(ObsStateModel): """ - Implements the observation state model for subarray + Implements the observation state model for subarray. The model supports all of the states of the :py:class:`ska_tango_base.control_model.ObsState` enum: @@ -393,7 +391,7 @@ class SubarrayObsStateModel(ObsStateModel): def __init__(self, logger, callback=None): """ - Initialises the model. + Initialise the model. :param logger: the logger to be used by this state model. :type logger: a logger that implements the standard library @@ -422,9 +420,10 @@ class SubarrayObsStateModel(ObsStateModel): def _obs_state_changed(self, machine_state): """ - Helper method that updates obs_state whenever the observation - state machine reports a change of state, ensuring that the - callback is called if one exists. + Handle notification that the observation state machine has changed state. + + This is a helper method that updates obs_state, ensuring that + the callback is called if one exists. :param machine_state: the new state of the observation state machine diff --git a/src/ska_tango_base/tel_state_device.py b/src/ska_tango_base/tel_state_device.py index ca3209e2ec049a9bb0d08e006d7fe58189026c16..5708914ee80f96f7ae9e94d9c5e139fac443b6f9 100644 --- a/src/ska_tango_base/tel_state_device.py +++ b/src/ska_tango_base/tel_state_device.py @@ -4,7 +4,8 @@ # # # -""" SKATelState +""" +SKATelState. A generic base device for Telescope State for SKA. """ @@ -22,9 +23,7 @@ __all__ = ["SKATelState", "main"] class SKATelState(SKABaseDevice): - """ - A generic base device for Telescope State for SKA. - """ + """A generic base device for Telescope State for SKA.""" # PROTECTED REGION ID(SKATelState.class_variable) ENABLED START # # PROTECTED REGION END # // SKATelState.class_variable @@ -46,11 +45,24 @@ class SKATelState(SKABaseDevice): # --------------- def always_executed_hook(self): # PROTECTED REGION ID(SKATelState.always_executed_hook) ENABLED START # + """ + Perform actions that are executed before every device command. + + This is a Tango hook. + """ pass # PROTECTED REGION END # // SKATelState.always_executed_hook def delete_device(self): # PROTECTED REGION ID(SKATelState.delete_device) ENABLED START # + """ + Clean up any resources prior to device deletion. + + This method is a Tango hook that is called by the device + destructor and by the device Init command. It allows for any + memory or other resources allocated in the init_device method to + be released prior to device deletion. + """ pass # PROTECTED REGION END # // SKATelState.delete_device @@ -70,15 +82,7 @@ class SKATelState(SKABaseDevice): def main(args=None, **kwargs): # PROTECTED REGION ID(SKATelState.main) ENABLED START # - """ - Main function of the module - - :param args: None by default. - - :param kwargs: - - :return: - """ + """Launch an SKATelState device.""" return run((SKATelState,), args=args, **kwargs) # PROTECTED REGION END # // SKATelState.main diff --git a/src/ska_tango_base/utils.py b/src/ska_tango_base/utils.py index 712715a6cb0096a868ab6908b3c36f93c6e649ec..1cdfe12da26026d7f6ccd42dba7e0709402439e6 100644 --- a/src/ska_tango_base/utils.py +++ b/src/ska_tango_base/utils.py @@ -81,6 +81,7 @@ tango_type_conversion = { @contextmanager def exception_manager(cls, callback=None): + """Return a context manager that manages exceptions.""" try: yield except tango.DevFailed: @@ -140,6 +141,7 @@ def exception_manager(cls, callback=None): def get_dev_info(domain_name, device_server_name, device_ref): + """Get device info.""" dev_info = DbDevInfo() dev_info._class = device_server_name dev_info.server = "%s/%s" % (device_server_name, domain_name) @@ -149,6 +151,7 @@ def get_dev_info(domain_name, device_server_name, device_ref): def dp_set_property(device_name, property_name, property_value): + """Use a DeviceProxy to set a device property.""" dp = DeviceProxy(device_name) db_datum = DbDatum() db_datum.name = property_name @@ -161,13 +164,15 @@ def dp_set_property(device_name, property_name, property_value): def get_device_group_and_id(device_name): + """Return the group and id part of a device name.""" device_name = device_name return device_name.split("/")[1:] def convert_api_value(param_dict): """ - Used to validate tango command parameters which are passed via json + Validate tango command parameters which are passed via json. + :param param_dict: :return: """ @@ -190,6 +195,7 @@ def convert_api_value(param_dict): def coerce_value(value): + """Coerce tango.DevState values to string, leaving other values alone.""" # Enum is not serialised correctly as json # _DevState is tango._tango.DevState # because DevState is tango._tango.DevState != tango.DevState @@ -199,6 +205,7 @@ def coerce_value(value): def get_dp_attribute(device_proxy, attribute, with_value=False, with_context=False): + """Get an attribute from a DeviceProxy.""" attr_dict = { "name": attribute.name, "polling_frequency": attribute.events.per_event.period, @@ -255,10 +262,7 @@ def get_dp_attribute(device_proxy, attribute, with_value=False, with_context=Fal def get_dp_command(device_name, command, with_context=False): - """ - :param command: - :return: - """ + """Get a command from a DeviceProxy.""" def command_parameters(command_desc): try: @@ -286,11 +290,13 @@ def get_dp_command(device_name, command, with_context=False): def get_tango_device_type_id(tango_address): + """Return the type id of a TANGO device.""" return tango_address.split("/")[1:3] def get_groups_from_json(json_definitions): - """Return a dict of tango.Group objects matching the JSON definitions. + """ + Return a dict of tango.Group objects matching the JSON definitions. Extracts the definitions of groups of devices and builds up matching tango.Group objects. Some minimal validation is done - if the definition @@ -385,7 +391,6 @@ def get_groups_from_json(json_definitions): - If a group has multiple parent groups. - If a device is included multiple time in a hierarchy. E.g. g1:[a,b] g2:[a,c] g3:[g1,g2] - """ try: # Parse and validate user's definitions @@ -406,10 +411,10 @@ def get_groups_from_json(json_definitions): def _validate_group(definition): - """Validate and clean up groups definition, raise AssertError if invalid. + """ + Validate and clean up groups definition, raise AssertError if invalid. Used internally by `get_groups_from_json`. - """ error_message = "Missing 'group_name' key - {}".format(definition) assert "group_name" in definition, error_message @@ -435,10 +440,10 @@ def _validate_group(definition): def _build_group(definition): - """Returns tango.Group object according to defined hierarchy. + """ + Return tango.Group object according to defined hierarchy. Used internally by `get_groups_from_json`. - """ group_name = definition["group_name"] devices = definition.get("devices", []) @@ -456,8 +461,7 @@ def _build_group(definition): def validate_capability_types(command_name, requested_capabilities, valid_capabilities): """ - Check the validity of the input parameter passed on to the command - specified by the command_name parameter. + Check the validity of the capability types passed to the specified command. :param command_name: The name of the command to be executed. :type command_name: str @@ -481,8 +485,7 @@ def validate_capability_types(command_name, requested_capabilities, valid_capabi def validate_input_sizes(command_name, argin): """ - Check the validity of the input parameters passed on to the command - specified by the command_name parameter. + Check the validity of the input parameters passed to the specified command. :param command_name: The name of the command which is to be executed. :type command_name: str @@ -500,6 +503,7 @@ def validate_input_sizes(command_name, argin): def convert_dict_to_list(dictionary): + """Convert a dictionary to a list of "key:value" strings.""" the_list = [] for key, value in list(dictionary.items()): the_list.append("{}:{}".format(key, value)) @@ -509,21 +513,26 @@ def convert_dict_to_list(dictionary): def for_testing_only(func, _testing_check=lambda: "pytest" in sys.modules): """ - A decorator that marks a function as available for testing purposes only. - If the decorated function is called outside of testing, a warning is raised. - - Testing this decorator leads to a Godelian paradox: how to test that a - warning is raised when we are not testing. Monkeypatching sys.modules would - break everything, so instead, the condition that we evaluate to decide - whether we are testing or not is exposed through a `_testing_check` - argument, allowing for it to be replaced in testing. (The `_testing_check` - argument is inaccessible via the @-syntax, which is a nice bonus.) + Return a function that warns if called outside of testing, then calls a function. + + This is intended to be used as a decorator that marks a function as + available for testing purposes only. If the decorated function is + called outside of testing, a warning is raised. + + .. code-block:: python + + @for_testing_only + def _straight_to_state(self, state): + ... """ @functools.wraps(func) def _wrapper(*args, **kwargs): """ - Function wrapper for `testing_only` decorator. + Raise a warning if not testing, then call the function. + + This is a wrapper function that implements the functionality of + the decorator. """ if not _testing_check(): warnings.warn(f"{func.__name__} should only be used for testing purposes.") diff --git a/tests/__init__.py b/tests/__init__.py index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..36c9e93476a3054aecc1a16f3677f650fe5c3790 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -0,0 +1 @@ +"""This subpackage contains tests of ``ska_tango_base``.""" diff --git a/tests/conftest.py b/tests/conftest.py index 5dfbbd92010752d8a1e874c2f80824cd58eb6f11..a034716a205a0fd9d0362ee8fd504d88a85a4ff2 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,6 +1,4 @@ -""" -A module defining a list of fixtures that are shared across all ska_tango_base tests. -""" +"""This module defines elements of the pytest test harness shared by all tests.""" import logging from queue import Empty, Queue @@ -12,19 +10,16 @@ from tango.test_context import DeviceTestContext @pytest.fixture(scope="class") def device_properties(): """ - Fixture that returns device_properties to be provided to the - device under test. This is a default implementiong that provides - no properties. + Fixture that returns device_properties to be provided to the device under test. + + This is a default implementiong that provides no properties. """ return {} @pytest.fixture(scope="class") def tango_context(device_test_config): - """ - Fixture that returns a Tango DeviceTestContext object, in which the - device under test is running. - """ + """Return a Tango test context object, in which the device under test is running.""" component_manager_patch = device_test_config.pop("component_manager_patch", None) if component_manager_patch is not None: device_test_config["device"].create_component_manager = component_manager_patch @@ -36,14 +31,15 @@ def tango_context(device_test_config): def pytest_itemcollected(item): - """Make Tango-related tests run in forked mode""" + """Make Tango-related tests run in forked mode.""" if "tango_context" in item.fixturenames: item.add_marker("forked") @pytest.fixture(scope="function") def initialize_device(tango_context): - """Re-initializes the device. + """ + Re-initializes the device. Parameters ---------- @@ -56,10 +52,12 @@ def initialize_device(tango_context): @pytest.fixture(scope="function") def tango_change_event_helper(tango_context): """ - Helper for testing tango change events. To use it, call the subscribe - method with the name of the attribute for which you want change events. - The returned value will be a callback handler that you can interrogate - with ``assert_not_called``, ``assert_call``, ``assert_calls``, and + Return a helper for testing tango change events. + + To use it, call the subscribe method with the name of the attribute + for which you want change events. The returned value will be a + callback handler that you can interrogate with + ``assert_not_called``, ``assert_call``, ``assert_calls``, and ``value`` methods. .. code-block:: py @@ -80,21 +78,20 @@ def tango_change_event_helper(tango_context): tango_context.device.Off() tango_context.device.On() state_callback.assert_calls([DevState.OFF, DevState.ON]) - """ class _Callback: """ - Private callback handler class, an instance of which is returned - by the tango_change_event_helper each time it is used to - subscribe to a change event. + Private callback handler class. + + An instance is returned by the tango_change_event_helper each + time it is used to subscribe to a change event. """ @staticmethod def subscribe(attribute_name): """ - Returns an event subscriber helper object that is subscribed - to change events on the named attribute. + Return an instance that is subscribed to change events on a named attribute. :param attribute_name: name of the attribute for which change events will be subscribed @@ -106,8 +103,10 @@ def tango_change_event_helper(tango_context): def __init__(self, attribute_name): """ - Creates an event subscriber helper object that is subscribed - to change events on the name attribute + Initialise a new instance. + + The instance will be subscribed to change events on the + named attribute. :param attribute_name: name of the attribute for which change events will be subscribed @@ -125,15 +124,13 @@ def tango_change_event_helper(tango_context): ) def __del__(self): - """ - Unsubscribe from events before object is destroyed - """ + """Unsubscribe from events before object is destroyed.""" if hasattr(self, "_id"): tango_context.device.unsubscribe_event(self._id) def __call__(self, event_data): """ - Event subscription callback + Event subscription callback. :param event_data: data about the change events :type event_data: :py:class:`tango.EventData` @@ -148,8 +145,10 @@ def tango_change_event_helper(tango_context): def _next(self): """ - Gets the attribute value from the next event if there is - one or if it arrives in time. + Get the attribute value from the next event. + + A value is returned if there is already one, or if it + arrives in time. :return: the attribute value reported in next change event, or None if there is no event @@ -163,16 +162,20 @@ def tango_change_event_helper(tango_context): def assert_not_called(self): """ - Assert that there are no new callbacks calls. (That is, - there are no callback calls that have not already been - consumed by an ``assert_call`` or ``assert_calls``.) + Assert that there are no new callbacks calls. + + (That is, there are no callback calls that have not already + been consumed by an ``assert_call`` or ``assert_calls``.) """ assert self._values_queue.empty() def assert_call(self, value): """ - Asserts that this callback has been called with a change - event that updates the attribute value to a given value. + Assert a call that has been made on this callback. + + Specifically, asserts that this callback has been called + with a change event that updates the attribute value to a + given value. Note that this method consumes a single event, but may leave other events unconsumed. @@ -185,9 +188,11 @@ def tango_change_event_helper(tango_context): def assert_calls(self, values): """ - Asserts that this callback has been called with a sequence - of change events that update the attribute values to the - given sequence of values. + Assert a sequence of calls that have been made on this callback. + + Specifically, assert that this callback has been called with + a sequence of change events that update the attribute values + to the given sequence of values. Note that this method consumes the events associated with the given values, but may leave subsequent events @@ -205,7 +210,5 @@ def tango_change_event_helper(tango_context): @pytest.fixture() def logger(): - """ - Fixture that returns a default logger for tests - """ + """Fixture that returns a default logger for tests.""" return logging.Logger("Test logger") diff --git a/tests/state/__init__.py b/tests/state/__init__.py index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..eff60bfcbce9242e664ccd798dc62ac6754c34bf 100644 --- a/tests/state/__init__.py +++ b/tests/state/__init__.py @@ -0,0 +1 @@ +"""This subpackage contains tests of ``ska_tango_base`` state machines.""" diff --git a/tests/state/conftest.py b/tests/state/conftest.py index fb1a27e376735c0f7182a5526922bb5452ef8565..2a10e5960d0ad8fc2546feb50bc69b5433821025 100644 --- a/tests/state/conftest.py +++ b/tests/state/conftest.py @@ -1,6 +1,4 @@ -""" -A module defining a list of fixtures that are shared across all ska_tango_base tests. -""" +"""This module defines the test harness for all ska_tango_base tests.""" from collections import defaultdict import itertools import json @@ -15,7 +13,10 @@ from ska_tango_base.faults import StateModelError def pytest_configure(config): """ - pytest hook, used here to register custom "state_machine_tester" marks + Configure pytest to register custom "state_machine_tester" marks. + + :param config: the pytest config object + :type config: :py:class:`pytest.config.Config` """ config.addinivalue_line( "markers", @@ -27,10 +28,12 @@ def pytest_configure(config): def pytest_generate_tests(metafunc): """ - pytest hook that generates tests; this hook ensures that any test - class that is marked with the `state_machine_tester` custom marker - will have its tests parameterised by the states and actions in the - specification provided by that mark + Modify how pytest generates tests to support state machine testing. + + This implementation of this pytest hook ensures that any test class + that is marked with the `state_machine_tester` custom marker will + have its tests parameterised by the states and actions in the + specification provided by that mark. """ mark = metafunc.definition.get_closest_marker("state_machine_tester") if mark: @@ -59,9 +62,7 @@ def pytest_generate_tests(metafunc): class StateMachineTester: - """ - Abstract base class for a class for testing state machines - """ + """Abstract base class for a class for testing state machines.""" def test_state_machine( self, @@ -71,13 +72,17 @@ class StateMachineTester: expected_state, ): """ - Implements the unit test for a state machine: for a given - initial state and an action, does execution of that action, from - that state, yield the expected results? If the action was - allowed from that state, does the machine transition to the - correct state? If the action was not allowed from that state, - does the machine reject the action (e.g. raise an exception or - return an error code) and remain in the current state? + Implements the unit test for a state machine. + + For a given initial state and an action, does execution of that + action, from that state, yield the expected results? + + * If the action was allowed from that state, does the machine + transition to the correct state? + + * If the action was not allowed from that state, does the + machine reject the action (e.g. raise an exception or return + an error code) and remain in the current state? :param machine_under_test: the state machine under test :type machine_under_test: state machine object instance @@ -93,7 +98,6 @@ class StateMachineTester: the action should be disallowed and result in no change of state. :type expected_state: string - """ # Put the device into the state under test self.to_state(machine_under_test, state_under_test) @@ -115,8 +119,7 @@ class StateMachineTester: def assert_state(self, machine_under_test, state): """ - Abstract method for asserting the current state of the state - machine under test + Assert the current state of the state machine. :param machine_under_test: the state machine under test :type machine_under_test: state machine object instance @@ -128,8 +131,7 @@ class StateMachineTester: def is_action_allowed(self, machine_under_test, action): """ - Abstract method for checking whether the action under test is - allowed from the current state. + Check whether an action on the state machine is allowed in the current state. :param machine_under_test: the state machine under test :type machine_under_test: state machine object instance @@ -140,7 +142,7 @@ class StateMachineTester: def perform_action(self, machine_under_test, action): """ - Abstract method for performing an action on the state machine + Perform an action on the state machine. :param machine_under_test: the state machine under test :type machine_under_test: state machine object instance @@ -151,8 +153,7 @@ class StateMachineTester: def check_action_fails(self, machine_under_test, action): """ - Abstract method for asserting that an action fails if performed - on the state machine under test in its current state. + Check that an action on the state machine fails in its current state. :param machine_under_test: the state machine under test :type machine_under_test: state machine object instance @@ -163,8 +164,7 @@ class StateMachineTester: def to_state(self, machine_under_test, target_state): """ - Abstract method for getting the state machine into a target - state. + Abstract method for getting the state machine into a target state. :param machine_under_test: the state machine under test :type machine_under_test: state machine object instance @@ -177,10 +177,11 @@ class StateMachineTester: class TransitionsStateMachineTester(StateMachineTester): """ - Concrete implementation of a StateMachineTester for a pytransitions - state machine (with autotransitions turned on). The states and - actions in the state machine specification must correspond exactly - with the machine's states and triggers. + Concrete ``StateMachineTester`` class for a pytransitions state machine. + + This class assumes pytransitions has autotransitions turned on. The + states and actions in the state machine specification must + correspond exactly with the machine's states and triggers. """ def assert_state(self, machine_under_test, state): @@ -197,8 +198,7 @@ class TransitionsStateMachineTester(StateMachineTester): def is_action_allowed(self, machine_under_test, action): """ - Check whether the action under test is allowed from the current - state. + Check whether the action under test is allowed from the current state. :param machine_under_test: the state machine under test :type machine_under_test: state machine object instance @@ -220,8 +220,7 @@ class TransitionsStateMachineTester(StateMachineTester): def check_action_fails(self, machine_under_test, action): """ - Check that attempting a given action on the state machine under - test fails in its current state. + Check that the action on the state machine fails in its current state. :param machine_under_test: the state machine under test :type machine_under_test: state machine object instance @@ -233,10 +232,11 @@ class TransitionsStateMachineTester(StateMachineTester): def to_state(self, machine_under_test, target_state): """ - Transition the state machine to a target state. This - implementation uses autotransitions. If the pytransitions state - machine under test has autotransitions turned off, then this - method will need to be overridden by some other method of + Transition the state machine to a target state. + + This implementation uses autotransitions. If the pytransitions + state machine under test has autotransitions turned off, then + this method will need to be overridden by some other method of putting the machine into the state under test. :param machine: the state machine under test @@ -252,8 +252,8 @@ class StateModelTester(StateMachineTester): """ Abstract base class for testing state models using state machines. - The ``assert_state`` method has to be implemented in concrete classes, - and the `machine_under_test` fixture must also be provided. + The ``assert_state`` method has to be implemented in concrete + classes, and the `machine_under_test` fixture must also be provided. """ def assert_state(self, machine_under_test, state): @@ -270,8 +270,7 @@ class StateModelTester(StateMachineTester): def is_action_allowed(self, machine_under_test, action): """ - Returns whether the state machine under test thinks an action - is permitted in its current state + Return whether the state machine allows a given action in its current state. :param machine_under_test: the state model under test :type machine_under_test: object @@ -293,8 +292,7 @@ class StateModelTester(StateMachineTester): def check_action_fails(self, machine_under_test, action): """ - Assert that performing a given action on the state maching under - test fails in its current state. + Check that an action is not permitted in the current state machine state. :param machine_under_test: the state model under test :type machine_under_test: object @@ -319,8 +317,10 @@ class StateModelTester(StateMachineTester): def load_data(name): """ - Loads a dataset by name. This implementation uses the name to find a - JSON file containing the data to be loaded. + Load a dataset by name. + + This implementation uses the name to find a JSON file containing the + data to be loaded. :param name: name of the dataset to be loaded; this implementation uses the name to find a JSON file containing the data to be @@ -333,7 +333,7 @@ def load_data(name): def load_state_machine_spec(name): """ - Loads a state machine specification by name. + Load a state machine specification by name. :param name: name of the dataset to be loaded; this implementation uses the name to find a JSON file containing the data to be diff --git a/tests/state/test_admin_mode_model.py b/tests/state/test_admin_mode_model.py index 4843f5a1ae417e30aba74db76f8cdd3f97e73709..de2e3f1e2b656903e89ceef011fc13385e6aedd2 100644 --- a/tests/state/test_admin_mode_model.py +++ b/tests/state/test_admin_mode_model.py @@ -1,7 +1,4 @@ -""" -This module contains the tests for the -:py:mod:`ska_tango_base.base.admin_mode_model` module. -""" +"""This module contains the tests for the ``admin_mode_model`` module.""" import pytest from ska_tango_base.control_model import AdminMode @@ -12,14 +9,12 @@ from .conftest import load_state_machine_spec, StateModelTester @pytest.mark.state_machine_tester(load_state_machine_spec("admin_mode_model")) class TestAdminModeModel(StateModelTester): - """ - This class contains the test for the AdminModeModel class. - """ + """This class contains the test for the AdminModeModel class.""" @pytest.fixture def machine_under_test(self, logger): """ - Fixture that returns the state model under test in this class + Fixture that returns the state model under test in this class. :param logger: a logger for the model under test :type logger: :py:class:`logging.Logger` @@ -31,7 +26,7 @@ class TestAdminModeModel(StateModelTester): def assert_state(self, machine_under_test, state): """ - Assert the current admin mode of the model under test + Assert the current admin mode of the model under test. :param machine_under_test: the state machine under test :type machine_under_test: state machine object instance @@ -41,5 +36,14 @@ class TestAdminModeModel(StateModelTester): """ assert machine_under_test.admin_mode == AdminMode[state] - def to_state(self, machine_under_test, state): - machine_under_test._straight_to_state(admin_mode=AdminMode[state]) + def to_state(self, machine_under_test, target_state): + """ + Transition the state machine to a target state. + + :param machine_under_test: the state model under test + :type machine_under_test: object + :param target_state: specification of the target state that we + want to get the state machine under test into + :type target_state: keyword dictionary + """ + machine_under_test._straight_to_state(admin_mode=AdminMode[target_state]) diff --git a/tests/state/test_csp_subelement_obs_state_model.py b/tests/state/test_csp_subelement_obs_state_model.py index 24ca7c0c8dadaf2261ce722bf70681bd0ca312ff..ac6d8077bdfd05b6cab6fc24ba66ba54aabb5c2c 100644 --- a/tests/state/test_csp_subelement_obs_state_model.py +++ b/tests/state/test_csp_subelement_obs_state_model.py @@ -1,7 +1,4 @@ -""" -Module to test the transitions of a CSP SubElement ObsDevice -(ska_tango_base.csp_subelement_obsdev_state_machine module). -""" +"""This module tests the ``csp_subelement_obs_state_model`` module.""" import pytest from ska_tango_base.csp.obs.obs_state_model import ( @@ -15,14 +12,12 @@ from .conftest import load_state_machine_spec, TransitionsStateMachineTester load_state_machine_spec("csp_subelement_obs_state_machine") ) class TestCspSubElementObsStateMachine(TransitionsStateMachineTester): - """ - This class contains the test for the CspSubElementObsStateMachine class. - """ + """This class contains the test for the CspSubElementObsStateMachine class.""" @pytest.fixture def machine_under_test(self): """ - Fixture that returns the state model under test in this class + Fixture that returns the state model under test in this class. :returns: the state machine under test """ diff --git a/tests/state/test_op_state_model.py b/tests/state/test_op_state_model.py index 567cadcc4e87dd3ab5f7c52dd6557099adf1499b..a8ec6a9faa3df123902deddd15e05bfbb2cb741d 100644 --- a/tests/state/test_op_state_model.py +++ b/tests/state/test_op_state_model.py @@ -1,7 +1,4 @@ -""" -This module contains the tests for the -:py:mod:`ska_tango_base.base.device_state_model` module. -""" +"""This module contains the tests for the ``op_state_model`` module.""" import pytest from ska_tango_base.base.op_state_model import _OpStateMachine @@ -11,14 +8,12 @@ from .conftest import load_state_machine_spec, TransitionsStateMachineTester @pytest.mark.state_machine_tester(load_state_machine_spec("op_state_machine")) class TestOpStateMachine(TransitionsStateMachineTester): - """ - This class contains the test for the _OpStateMachine class. - """ + """This class contains the test for the _OpStateMachine class.""" @pytest.fixture def machine_under_test(self): """ - Fixture that returns the state machine under test in this class + Fixture that returns the state machine under test in this class. :returns: the state machine under test """ diff --git a/tests/state/test_subarray_obs_state_model.py b/tests/state/test_subarray_obs_state_model.py index 1e08fb58d2704afceb5e33733e65014a21cc2c55..1a43deb15da51954ce2c610548ac4fb0e70e8382 100644 --- a/tests/state/test_subarray_obs_state_model.py +++ b/tests/state/test_subarray_obs_state_model.py @@ -1,7 +1,4 @@ -""" -This module contains the tests for the -:py:mod:`ska_tango_base.subarray.subarray_state_model` module. -""" +"""This module contains the tests for the ``subarray_state_model`` module.""" import pytest from ska_tango_base.subarray.subarray_obs_state_model import _SubarrayObsStateMachine @@ -11,14 +8,12 @@ from .conftest import load_state_machine_spec, TransitionsStateMachineTester @pytest.mark.state_machine_tester(load_state_machine_spec("subarray_state_machine")) class TestSubarrayObsStateMachine(TransitionsStateMachineTester): - """ - This class contains the test for the SubarrayObsStateModel class. - """ + """This class contains the test for the SubarrayObsStateModel class.""" @pytest.fixture def machine_under_test(self): """ - Fixture that returns the state model under test in this class + Fixture that returns the state model under test in this class. :returns: the state machine under test """ diff --git a/tests/test_alarm_handler_device.py b/tests/test_alarm_handler_device.py index 8aaffda8837d08d9c889a64751b238575d0f244d..5e405db3048bc20c60ebae1895c4c961c629f3e2 100644 --- a/tests/test_alarm_handler_device.py +++ b/tests/test_alarm_handler_device.py @@ -27,15 +27,15 @@ from ska_tango_base.control_model import AdminMode @pytest.mark.usefixtures("tango_context", "initialize_device") class TestSKAAlarmHandler(object): - """ - Test class for tests of the SKAAlarmHander device class. - """ + """Test class for tests of the SKAAlarmHander device class.""" @pytest.fixture(scope="class") def device_test_config(self, device_properties): """ - Fixture that specifies the device to be tested, along with its - properties and memorized attributes. + Fixture that specifies the device to be tested. + + The specification includes device properties and memorized + attributes. """ return { "device": SKAAlarmHandler, @@ -48,15 +48,14 @@ class TestSKAAlarmHandler(object): @pytest.mark.skip("Not implemented") def test_properties(self, tango_context): - """Test the device properties""" - # Test the properties + """Test the device properties.""" # PROTECTED REGION ID(SKAAlarmHandler.test_properties) ENABLED START # # PROTECTED REGION END # // SKAAlarmHandler.test_properties # PROTECTED REGION ID(SKAAlarmHandler.test_GetAlarmRule_decorators) ENABLED START # # PROTECTED REGION END # // SKAAlarmHandler.test_GetAlarmRule_decorators def test_GetAlarmRule(self, tango_context): - """Test for GetAlarmRule""" + """Test for GetAlarmRule.""" # PROTECTED REGION ID(SKAAlarmHandler.test_GetAlarmRule) ENABLED START # assert tango_context.device.GetAlarmRule("") == "" # PROTECTED REGION END # // SKAAlarmHandler.test_GetAlarmRule @@ -64,7 +63,7 @@ class TestSKAAlarmHandler(object): # PROTECTED REGION ID(SKAAlarmHandler.test_GetAlarmData_decorators) ENABLED START # # PROTECTED REGION END # // SKAAlarmHandler.test_GetAlarmData_decorators def test_GetAlarmData(self, tango_context): - """Test for GetAlarmData""" + """Test for GetAlarmData.""" # PROTECTED REGION ID(SKAAlarmHandler.test_GetAlarmData) ENABLED START # assert tango_context.device.GetAlarmData("") == "" # PROTECTED REGION END # // SKAAlarmHandler.test_GetAlarmData @@ -72,7 +71,7 @@ class TestSKAAlarmHandler(object): # PROTECTED REGION ID(SKAAlarmHandler.test_GetAlarmAdditionalInfo_decorators) ENABLED START # # PROTECTED REGION END # // SKAAlarmHandler.test_GetAlarmAdditionalInfo_decorators def test_GetAlarmAdditionalInfo(self, tango_context): - """Test for GetAlarmAdditionalInfo""" + """Test for GetAlarmAdditionalInfo.""" # PROTECTED REGION ID(SKAAlarmHandler.test_GetAlarmAdditionalInfo) ENABLED START # assert tango_context.device.GetAlarmAdditionalInfo("") == "" # PROTECTED REGION END # // SKAAlarmHandler.test_GetAlarmAdditionalInfo @@ -80,7 +79,7 @@ class TestSKAAlarmHandler(object): # PROTECTED REGION ID(SKAAlarmHandler.test_GetAlarmStats_decorators) ENABLED START # # PROTECTED REGION END # // SKAAlarmHandler.test_GetAlarmStats_decorators def test_GetAlarmStats(self, tango_context): - """Test for GetAlarmStats""" + """Test for GetAlarmStats.""" # PROTECTED REGION ID(SKAAlarmHandler.test_GetAlarmStats) ENABLED START # assert tango_context.device.GetAlarmStats() == "" # PROTECTED REGION END # // SKAAlarmHandler.test_GetAlarmStats @@ -88,7 +87,7 @@ class TestSKAAlarmHandler(object): # PROTECTED REGION ID(SKAAlarmHandler.test_GetAlertStats_decorators) ENABLED START # # PROTECTED REGION END # // SKAAlarmHandler.test_GetAlertStats_decorators def test_GetAlertStats(self, tango_context): - """Test for GetAlertStats""" + """Test for GetAlertStats.""" # PROTECTED REGION ID(SKAAlarmHandler.test_GetAlertStats) ENABLED START # assert tango_context.device.GetAlertStats() == "" # PROTECTED REGION END # // SKAAlarmHandler.test_GetAlertStats @@ -96,7 +95,7 @@ class TestSKAAlarmHandler(object): # PROTECTED REGION ID(SKAAlarmHandler.test_GetVersionInfo_decorators) ENABLED START # # PROTECTED REGION END # // SKAAlarmHandler.test_GetVersionInfo_decorators def test_GetVersionInfo(self, tango_context): - """Test for GetVersionInfo""" + """Test for GetVersionInfo.""" # PROTECTED REGION ID(SKAAlarmHandler.test_GetVersionInfo) ENABLED START # versionPattern = re.compile( f"{tango_context.device.info().dev_class}, ska_tango_base, [0-9]+.[0-9]+.[0-9]+, " @@ -109,7 +108,7 @@ class TestSKAAlarmHandler(object): # PROTECTED REGION ID(SKAAlarmHandler.test_statsNrAlerts_decorators) ENABLED START # # PROTECTED REGION END # // SKAAlarmHandler.test_statsNrAlerts_decorators def test_statsNrAlerts(self, tango_context): - """Test for statsNrAlerts""" + """Test for statsNrAlerts.""" # PROTECTED REGION ID(SKAAlarmHandler.test_statsNrAlerts) ENABLED START # assert tango_context.device.statsNrAlerts == 0 # PROTECTED REGION END # // SKAAlarmHandler.test_statsNrAlerts @@ -117,7 +116,7 @@ class TestSKAAlarmHandler(object): # PROTECTED REGION ID(SKAAlarmHandler.test_statsNrAlarms_decorators) ENABLED START # # PROTECTED REGION END # // SKAAlarmHandler.test_statsNrAlarms_decorators def test_statsNrAlarms(self, tango_context): - """Test for statsNrAlarms""" + """Test for statsNrAlarms.""" # PROTECTED REGION ID(SKAAlarmHandler.test_statsNrAlarms) ENABLED START # assert tango_context.device.statsNrAlarms == 0 # PROTECTED REGION END # // SKAAlarmHandler.test_statsNrAlarms @@ -125,7 +124,7 @@ class TestSKAAlarmHandler(object): # PROTECTED REGION ID(SKAAlarmHandler.test_statsNrNewAlarms_decorators) ENABLED START # # PROTECTED REGION END # // SKAAlarmHandler.test_statsNrNewAlarms_decorators def test_statsNrNewAlarms(self, tango_context): - """Test for statsNrNewAlarms""" + """Test for statsNrNewAlarms.""" # PROTECTED REGION ID(SKAAlarmHandler.test_statsNrNewAlarms) ENABLED START # assert tango_context.device.statsNrNewAlarms == 0 # PROTECTED REGION END # // SKAAlarmHandler.test_statsNrNewAlarms @@ -133,7 +132,7 @@ class TestSKAAlarmHandler(object): # PROTECTED REGION ID(SKAAlarmHandler.test_statsNrUnackAlarms_decorators) ENABLED START # # PROTECTED REGION END # // SKAAlarmHandler.test_statsNrUnackAlarms_decorators def test_statsNrUnackAlarms(self, tango_context): - """Test for statsNrUnackAlarms""" + """Test for statsNrUnackAlarms.""" # PROTECTED REGION ID(SKAAlarmHandler.test_statsNrUnackAlarms) ENABLED START # assert tango_context.device.statsNrUnackAlarms == 0.0 # PROTECTED REGION END # // SKAAlarmHandler.test_statsNrUnackAlarms @@ -141,7 +140,7 @@ class TestSKAAlarmHandler(object): # PROTECTED REGION ID(SKAAlarmHandler.test_statsNrRtnAlarms_decorators) ENABLED START # # PROTECTED REGION END # // SKAAlarmHandler.test_statsNrRtnAlarms_decorators def test_statsNrRtnAlarms(self, tango_context): - """Test for statsNrRtnAlarms""" + """Test for statsNrRtnAlarms.""" # PROTECTED REGION ID(SKAAlarmHandler.test_statsNrRtnAlarms) ENABLED START # assert tango_context.device.statsNrRtnAlarms == 0.0 # PROTECTED REGION END # // SKAAlarmHandler.test_statsNrRtnAlarms @@ -149,7 +148,7 @@ class TestSKAAlarmHandler(object): # PROTECTED REGION ID(SKAAlarmHandler.test_buildState_decorators) ENABLED START # # PROTECTED REGION END # // SKAAlarmHandler.test_buildState_decorators def test_buildState(self, tango_context): - """Test for buildState""" + """Test for buildState.""" # PROTECTED REGION ID(SKAAlarmHandler.test_buildState) ENABLED START # buildPattern = re.compile( r"ska_tango_base, [0-9]+.[0-9]+.[0-9]+, " @@ -161,7 +160,7 @@ class TestSKAAlarmHandler(object): # PROTECTED REGION ID(SKAAlarmHandler.test_versionId_decorators) ENABLED START # # PROTECTED REGION END # // SKAAlarmHandler.test_versionId_decorators def test_versionId(self, tango_context): - """Test for versionId""" + """Test for versionId.""" # PROTECTED REGION ID(SKAAlarmHandler.test_versionId) ENABLED START # versionIdPattern = re.compile(r"[0-9]+.[0-9]+.[0-9]+") assert (re.match(versionIdPattern, tango_context.device.versionId)) is not None @@ -170,7 +169,7 @@ class TestSKAAlarmHandler(object): # PROTECTED REGION ID(SKAAlarmHandler.test_activeAlerts_decorators) ENABLED START # # PROTECTED REGION END # // SKAAlarmHandler.test_activeAlerts_decorators def test_activeAlerts(self, tango_context): - """Test for activeAlerts""" + """Test for activeAlerts.""" # PROTECTED REGION ID(SKAAlarmHandler.test_activeAlerts) ENABLED START # assert tango_context.device.activeAlerts == ("",) # PROTECTED REGION END # // SKAAlarmHandler.test_activeAlerts @@ -178,7 +177,7 @@ class TestSKAAlarmHandler(object): # PROTECTED REGION ID(SKAAlarmHandler.test_activeAlarms_decorators) ENABLED START # # PROTECTED REGION END # // SKAAlarmHandler.test_activeAlarms_decorators def test_activeAlarms(self, tango_context): - """Test for activeAlarms""" + """Test for activeAlarms.""" # PROTECTED REGION ID(SKAAlarmHandler.test_activeAlarms) ENABLED START # assert tango_context.device.activeAlarms == ("",) # PROTECTED REGION END # // SKAAlarmHandler.test_activeAlarms diff --git a/tests/test_base_component_manager.py b/tests/test_base_component_manager.py index 99087a1058e19affe51ba2386fb887e8f4cce82e..7b77327b0da8331b43892e24be8df7ddbb8b7663 100644 --- a/tests/test_base_component_manager.py +++ b/tests/test_base_component_manager.py @@ -1,6 +1,4 @@ -""" -Tests for the :py:mod:`ska_tango_base.component_manager` module. -""" +"""Tests for the :py:mod:`ska_tango_base.component_manager` module.""" import contextlib import pytest @@ -10,16 +8,12 @@ from ska_tango_base.faults import ComponentFault class TestBaseComponentManager: - """ - Tests of the - :py:class:`ska_tango_base.component_manager.ComponentManager` - class. - """ + """This class contains tests of the base component manager.""" @pytest.fixture() def mock_op_state_model(self, mocker): """ - Fixture that returns a mock state model + Fixture that returns a mock state model. :param mocker: pytest fixture that wraps :py:mod:`unittest.mock`. @@ -30,14 +24,17 @@ class TestBaseComponentManager: @pytest.fixture(params=[PowerMode.OFF, PowerMode.STANDBY, PowerMode.ON]) def initial_power_mode(self, request): + """Return the initial power mode of the component under test.""" return request.param @pytest.fixture(params=[False, True]) def initial_fault(self, request): + """Return whether the component under test should initially be faulty.""" return request.param @pytest.fixture() def component(self, initial_power_mode, initial_fault): + """Return a component for testing.""" return ReferenceBaseComponentManager._Component( _power_mode=initial_power_mode, _faulty=initial_fault ) @@ -45,7 +42,7 @@ class TestBaseComponentManager: @pytest.fixture() def component_manager(self, mock_op_state_model, logger, component): """ - Fixture that returns the component manager under test + Fixture that returns the component manager under test. :param mock_op_state_model: a mock state model for testing :param logger: a logger for the component manager @@ -56,13 +53,11 @@ class TestBaseComponentManager: mock_op_state_model, logger=logger, _component=component ) - def test_state_changes_with_start_and_stop( + def test_state_changes_with_start_and_stop_communicating( self, component_manager, mock_op_state_model, initial_power_mode, initial_fault ): """ - Test that the state model is updated with state changes when the - component manager connects to and disconnects from its - component. + Test that state is updated when the component is connected / disconnected. :param component_manager: the component manager under test :param mock_op_state_model: a mock state model for testing @@ -115,8 +110,7 @@ class TestBaseComponentManager: @pytest.mark.parametrize("command", ["off", "standby", "on"]) def test_command_fails_when_disconnected(self, component_manager, command): """ - Test that component commands fail when the component manager - isn't connected to the component. + Test that commands fail when there is not connection to the component. :param component_manager: the component manager under test :param command: the command under test @@ -151,8 +145,7 @@ class TestBaseComponentManager: action, ): """ - Test that component commands succeed when the component manager - is connected to the component. + Test that commands succeed when there is a connection to the component. :param component_manager: the component manager under test :param mock_op_state_model: a mock state model for testing @@ -202,8 +195,11 @@ class TestBaseComponentManager: action, ): """ - Test that spontaneous changes to the state of the component - result in the correct action being performed on the state model. + Test how changes to the components result in actions on the state model. + + For example, when we tell the component to simulate power off, + does the state model receive an action that informs it that the + component is off? :param component_manager: the component manager under test :param mock_op_state_model: a mock state model for testing @@ -236,6 +232,7 @@ class TestBaseComponentManager: def test_reset_from_fault( self, component_manager, mock_op_state_model, initial_fault ): + """Test that the component manager can reset a faulty component.""" component_manager.start_communicating() assert component_manager.faulty == initial_fault mock_op_state_model.reset_mock() diff --git a/tests/test_base_device.py b/tests/test_base_device.py index cfe622ad23cdc566e3b2e641541e3f3280d6c4c6..2f1847ef3dec516b02558ed004b6e69634af76d2 100644 --- a/tests/test_base_device.py +++ b/tests/test_base_device.py @@ -6,9 +6,7 @@ # # ######################################################################################### -""" -This module contains the tests for the SKABaseDevice. -""" +"""This module contains the tests for the SKABaseDevice.""" # PROTECTED REGION ID(SKABaseDevice.test_additional_imports) ENABLED START # import logging @@ -51,8 +49,11 @@ from .state.conftest import load_state_machine_spec class TestTangoLoggingServiceHandler: + """This class contains tests of the TangoLoggingServiceHandler class.""" + @pytest.fixture() def tls_handler(self): + """Return a logging service handler.""" self.tango_logger = mock.MagicMock(spec=tango.Logger) # setup methods used for handler __repr__ self.tango_logger.get_name.return_value = "unit/test/dev" @@ -69,9 +70,11 @@ class TestTangoLoggingServiceHandler: ] ) def python_log_level(self, request): + """Return a python logging level.""" return request.param def test_emit_message_at_correct_level(self, tls_handler, python_log_level): + """Test that emitted messages are logged at the right level.""" # arrange record = logging.LogRecord("test", python_log_level, "", 1, "message", (), None) # act @@ -82,6 +85,7 @@ class TestTangoLoggingServiceHandler: assert self.tango_logger.log.call_args_list == expected_calls def test_emit_message_is_formatted(self, tls_handler): + """Test that emitted messages are formatted as specified.""" # arrange record = logging.LogRecord( "test", logging.INFO, "", 1, "message %s", ("param",), None @@ -100,6 +104,7 @@ class TestTangoLoggingServiceHandler: assert self.tango_logger.log.call_args_list == expected_calls def test_emit_exception_error_handled(self, tls_handler): + """Test exception handling when a record is emitted.""" # arrange record = logging.LogRecord("test", logging.INFO, "", 1, "message", (), None) @@ -114,18 +119,22 @@ class TestTangoLoggingServiceHandler: assert tls_handler.handleError.call_args_list == [mock.call(record)] def test_repr_normal(self, tls_handler): + """Test the string representation of a handler under normal conditions.""" expected = ( "<TangoLoggingServiceHandler unit/test/dev (Python NOTSET, Tango DEBUG)>" ) assert repr(tls_handler) == expected def test_repr_tango_logger_none(self, tls_handler): + """Test the string representation of a handler with no logger.""" tls_handler.tango_logger = None expected = "<TangoLoggingServiceHandler !No Tango logger! (Python NOTSET, Tango UNKNOWN)>" assert repr(tls_handler) == expected class TestLoggingUtils: + """This class contains tests of the LoggingUtils class.""" + @pytest.fixture( params=[ (None, []), @@ -152,6 +161,7 @@ class TestLoggingUtils: ] ) def good_logging_targets(self, request): + """Return some good logging targets for use in testing.""" targets_in, expected = request.param dev_name = "my/dev/name" return targets_in, dev_name, expected @@ -165,16 +175,19 @@ class TestLoggingUtils: ] ) def bad_logging_targets(self, request): + """Return some bad logging targets for use in testing.""" targets_in = request.param dev_name = "my/dev/name" return targets_in, dev_name def test_sanitise_logging_targets_success(self, good_logging_targets): + """Test that good logging targets can be sanitised.""" targets_in, dev_name, expected = good_logging_targets actual = LoggingUtils.sanitise_logging_targets(targets_in, dev_name) assert actual == expected def test_sanitise_logging_targets_fail(self, bad_logging_targets): + """Test that bad logging targets cannot be sanitised.""" targets_in, dev_name = bad_logging_targets with pytest.raises(LoggingTargetError): LoggingUtils.sanitise_logging_targets(targets_in, dev_name) @@ -195,6 +208,7 @@ class TestLoggingUtils: ] ) def good_syslog_url(self, request): + """Return a good logging target URL.""" url, (expected_address, expected_socktype) = request.param return url, (expected_address, expected_socktype) @@ -217,9 +231,11 @@ class TestLoggingUtils: ] ) def bad_syslog_url(self, request): + """Return a bad logging target URL.""" return request.param def test_get_syslog_address_and_socktype_success(self, good_syslog_url): + """Test that logging successfully accepts a good target.""" url, (expected_address, expected_socktype) = good_syslog_url actual_address, actual_socktype = LoggingUtils.get_syslog_address_and_socktype( url @@ -228,6 +244,7 @@ class TestLoggingUtils: assert actual_socktype == expected_socktype def test_get_syslog_address_and_socktype_fail(self, bad_syslog_url): + """Test that logging raises an error when given a bad target.""" with pytest.raises(LoggingTargetError): LoggingUtils.get_syslog_address_and_socktype(bad_syslog_url) @@ -244,6 +261,7 @@ class TestLoggingUtils: mock_syslog_handler, mock_tango_handler, ): + """Test that logging handlers can be created.""" # Expect formatter be created using `get_default_formatter(tags=True)` # Use some mocks to check this. mock_formatter = mock.MagicMock() @@ -297,6 +315,7 @@ class TestLoggingUtils: LoggingUtils.create_logging_handler("tango::logger", tango_logger=None) def test_update_logging_handlers(self): + """Test that logging handlers can be updated.""" logger = logging.getLogger("testing") logger.tango_logger = mock.MagicMock(spec=tango.Logger) @@ -365,15 +384,12 @@ class TestLoggingUtils: # PROTECTED REGION END # // SKABaseDevice.test_SKABaseDevice_decorators class TestSKABaseDevice(object): - """ - Test cases for SKABaseDevice. - """ + """Test cases for SKABaseDevice.""" @pytest.fixture(scope="class") def device_test_config(self, device_properties): """ - Fixture that specifies the device to be tested, along with its - properties and memorized attributes. + Specify device configuration, including properties and memorized attributes. This implementation provides a concrete subclass of SKABaseDevice, and a memorized value for adminMode. @@ -389,7 +405,7 @@ class TestSKABaseDevice(object): @pytest.mark.skip("Not implemented") def test_properties(self, tango_context): - # Test the properties + """Test device properties.""" # PROTECTED REGION ID(SKABaseDevice.test_properties) ENABLED START # """ Test device properties. @@ -405,7 +421,7 @@ class TestSKABaseDevice(object): # PROTECTED REGION ID(SKABaseDevice.test_State_decorators) ENABLED START # # PROTECTED REGION END # // SKABaseDevice.test_State_decorators def test_State(self, tango_context): - """Test for State""" + """Test for State.""" # PROTECTED REGION ID(SKABaseDevice.test_State) ENABLED START # assert tango_context.device.State() == DevState.OFF # PROTECTED REGION END # // SKABaseDevice.test_State @@ -413,7 +429,7 @@ class TestSKABaseDevice(object): # PROTECTED REGION ID(SKABaseDevice.test_Status_decorators) ENABLED START # # PROTECTED REGION END # // SKABaseDevice.test_Status_decorators def test_Status(self, tango_context): - """Test for Status""" + """Test for Status.""" # PROTECTED REGION ID(SKABaseDevice.test_Status) ENABLED START # assert tango_context.device.Status() == "The device is in OFF state." # PROTECTED REGION END # // SKABaseDevice.test_Status @@ -421,7 +437,7 @@ class TestSKABaseDevice(object): # PROTECTED REGION ID(SKABaseDevice.test_GetVersionInfo_decorators) ENABLED START # # PROTECTED REGION END # // SKABaseDevice.test_GetVersionInfo_decorators def test_GetVersionInfo(self, tango_context): - """Test for GetVersionInfo""" + """Test for GetVersionInfo.""" # PROTECTED REGION ID(SKABaseDevice.test_GetVersionInfo) ENABLED START # versionPattern = re.compile( f"{tango_context.device.info().dev_class}, ska_tango_base, [0-9]+.[0-9]+.[0-9]+, " @@ -434,7 +450,7 @@ class TestSKABaseDevice(object): # PROTECTED REGION ID(SKABaseDevice.test_Reset_decorators) ENABLED START # # PROTECTED REGION END # // SKABaseDevice.test_Reset_decorators def test_Reset(self, tango_context): - """Test for Reset""" + """Test for Reset.""" # PROTECTED REGION ID(SKABaseDevice.test_Reset) ENABLED START # # The main test of this command is # TestSKABaseDevice_commands::test_ResetCommand @@ -443,9 +459,7 @@ class TestSKABaseDevice(object): # PROTECTED REGION END # // SKABaseDevice.test_Reset def test_On(self, tango_context, tango_change_event_helper): - """ - Test for On command - """ + """Test for On command.""" state_callback = tango_change_event_helper.subscribe("state") status_callback = tango_change_event_helper.subscribe("status") state_callback.assert_call(DevState.OFF) @@ -462,9 +476,7 @@ class TestSKABaseDevice(object): status_callback.assert_not_called() def test_Standby(self, tango_context): - """ - Test for Standby command - """ + """Test for Standby command.""" # Check that we can put it on standby tango_context.device.Standby() assert tango_context.device.state() == DevState.STANDBY @@ -473,9 +485,7 @@ class TestSKABaseDevice(object): tango_context.device.Standby() def test_Off(self, tango_context, tango_change_event_helper): - """ - Test for Off command - """ + """Test for Off command.""" state_callback = tango_change_event_helper.subscribe("state") status_callback = tango_change_event_helper.subscribe("status") state_callback.assert_call(DevState.OFF) @@ -489,7 +499,7 @@ class TestSKABaseDevice(object): # PROTECTED REGION ID(SKABaseDevice.test_buildState_decorators) ENABLED START # # PROTECTED REGION END # // SKABaseDevice.test_buildState_decorators def test_buildState(self, tango_context): - """Test for buildState""" + """Test for buildState.""" # PROTECTED REGION ID(SKABaseDevice.test_buildState) ENABLED START # buildPattern = re.compile( r"ska_tango_base, [0-9]+.[0-9]+.[0-9]+, " @@ -501,7 +511,7 @@ class TestSKABaseDevice(object): # PROTECTED REGION ID(SKABaseDevice.test_versionId_decorators) ENABLED START # # PROTECTED REGION END # // SKABaseDevice.test_versionId_decorators def test_versionId(self, tango_context): - """Test for versionId""" + """Test for versionId.""" # PROTECTED REGION ID(SKABaseDevice.test_versionId) ENABLED START # versionIdPattern = re.compile(r"[0-9]+.[0-9]+.[0-9]+") assert (re.match(versionIdPattern, tango_context.device.versionId)) is not None @@ -510,7 +520,7 @@ class TestSKABaseDevice(object): # PROTECTED REGION ID(SKABaseDevice.test_loggingLevel_decorators) ENABLED START # # PROTECTED REGION END # // SKABaseDevice.test_loggingLevel_decorators def test_loggingLevel(self, tango_context): - """Test for loggingLevel""" + """Test for loggingLevel.""" # PROTECTED REGION ID(SKABaseDevice.test_loggingLevel) ENABLED START # assert tango_context.device.loggingLevel == LoggingLevel.INFO @@ -526,7 +536,7 @@ class TestSKABaseDevice(object): # PROTECTED REGION ID(SKABaseDevice.test_loggingTargets_decorators) ENABLED START # # PROTECTED REGION END # // SKABaseDevice.test_loggingTargets_decorators def test_loggingTargets(self, tango_context): - """Test for loggingTargets""" + """Test for loggingTargets.""" # PROTECTED REGION ID(SKABaseDevice.test_loggingTargets) ENABLED START # # tango logging target must be enabled by default assert tango_context.device.loggingTargets == ("tango::logger",) @@ -589,7 +599,7 @@ class TestSKABaseDevice(object): # PROTECTED REGION ID(SKABaseDevice.test_healthState_decorators) ENABLED START # # PROTECTED REGION END # // SKABaseDevice.test_healthState_decorators def test_healthState(self, tango_context): - """Test for healthState""" + """Test for healthState.""" # PROTECTED REGION ID(SKABaseDevice.test_healthState) ENABLED START # assert tango_context.device.healthState == HealthState.OK # PROTECTED REGION END # // SKABaseDevice.test_healthState @@ -597,7 +607,7 @@ class TestSKABaseDevice(object): # PROTECTED REGION ID(SKABaseDevice.test_adminMode_decorators) ENABLED START # # PROTECTED REGION END # // SKABaseDevice.test_adminMode_decorators def test_adminMode(self, tango_context, tango_change_event_helper): - """Test for adminMode""" + """Test for adminMode.""" # PROTECTED REGION ID(SKABaseDevice.test_adminMode) ENABLED START # assert tango_context.device.adminMode == AdminMode.ONLINE assert tango_context.device.state() == DevState.OFF @@ -624,7 +634,7 @@ class TestSKABaseDevice(object): # PROTECTED REGION ID(SKABaseDevice.test_controlMode_decorators) ENABLED START # # PROTECTED REGION END # // SKABaseDevice.test_controlMode_decorators def test_controlMode(self, tango_context): - """Test for controlMode""" + """Test for controlMode.""" # PROTECTED REGION ID(SKABaseDevice.test_controlMode) ENABLED START # assert tango_context.device.controlMode == ControlMode.REMOTE # PROTECTED REGION END # // SKABaseDevice.test_controlMode @@ -632,7 +642,7 @@ class TestSKABaseDevice(object): # PROTECTED REGION ID(SKABaseDevice.test_simulationMode_decorators) ENABLED START # # PROTECTED REGION END # // SKABaseDevice.test_simulationMode_decorators def test_simulationMode(self, tango_context): - """Test for simulationMode""" + """Test for simulationMode.""" # PROTECTED REGION ID(SKABaseDevice.test_simulationMode) ENABLED START # assert tango_context.device.simulationMode == SimulationMode.FALSE # PROTECTED REGION END # // SKABaseDevice.test_simulationMode @@ -640,18 +650,20 @@ class TestSKABaseDevice(object): # PROTECTED REGION ID(SKABaseDevice.test_testMode_decorators) ENABLED START # # PROTECTED REGION END # // SKABaseDevice.test_testMode_decorators def test_testMode(self, tango_context): - """Test for testMode""" + """Test for testMode.""" # PROTECTED REGION ID(SKABaseDevice.test_testMode) ENABLED START # assert tango_context.device.testMode == TestMode.NONE # PROTECTED REGION END # // SKABaseDevice.test_testMode def test_debugger_not_listening_by_default(self, tango_context): + """Test that DebugDevice is not active until enabled.""" assert not SKABaseDevice._global_debugger_listening with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: with pytest.raises(ConnectionRefusedError): s.connect(("localhost", _DEBUGGER_PORT)) def test_DebugDevice_starts_listening_on_default_port(self, tango_context): + """Test that enabling DebugDevice makes it listen on its default port.""" port = tango_context.device.DebugDevice() assert port == _DEBUGGER_PORT assert SKABaseDevice._global_debugger_listening @@ -661,12 +673,14 @@ class TestSKABaseDevice(object): @pytest.mark.usefixtures("patch_debugger_to_start_on_ephemeral_port") def test_DebugDevice_twice_does_not_raise(self, tango_context): + """Test that it is safe to enable the DebugDevice when it is already enabled.""" tango_context.device.DebugDevice() tango_context.device.DebugDevice() assert SKABaseDevice._global_debugger_listening @pytest.mark.usefixtures("patch_debugger_to_start_on_ephemeral_port") def test_DebugDevice_does_not_break_a_command(self, tango_context): + """Test that enabling the DebugDevice feature does not break device commands.""" tango_context.device.DebugDevice() assert tango_context.device.State() == DevState.OFF tango_context.device.On() @@ -675,18 +689,24 @@ class TestSKABaseDevice(object): @pytest.fixture() def patch_debugger_to_start_on_ephemeral_port(): + """ + Patch the debugger so that it starts on an ephemeral port. + + This is necessary because of intermittent debugger test failures: if + the previous test has used the debugger port, then when the test + tries to bind to that port, it may find that the OS has not made it + available for use yet. + """ ska_tango_base.base.base_device._DEBUGGER_PORT = 0 class TestSKABaseDevice_commands: - """ - This class contains tests of SKABaseDevice commands - """ + """This class contains tests of SKABaseDevice commands.""" @pytest.fixture def op_state_model(self, logger): """ - Yields a new OpStateModel for testing + Yield a new OpStateModel for testing. :yields: a OpStateModel instance to be tested """ @@ -695,11 +715,10 @@ class TestSKABaseDevice_commands: @pytest.fixture def command_factory(self, mocker, op_state_model): """ - Returns a factory that constructs a command object for a given - class + Return a factory that constructs a command object for a given class. :returns: a factory that constructs a command object for a given - class + class """ def _command_factory(command): @@ -709,10 +728,12 @@ class TestSKABaseDevice_commands: @pytest.fixture def machine_spec(self): + """Return a state machine specification.""" return load_state_machine_spec("op_state_machine") @pytest.fixture() def op_state_mapping(self): + """Return a mapping from state machine state to model state.""" return { "_UNINITIALISED": None, "INIT_DISABLE": DevState.INIT, @@ -748,9 +769,11 @@ class TestSKABaseDevice_commands: slug, ): """ - Test that certain commands can only be invoked in certain - states, and that the result of invoking the command is as - expected. + Test command invokation. + + Specifically, test that certain commands can only be invoked in + certain states, and that the result of invoking the command is + as expected. """ command = command_factory(command_class) diff --git a/tests/test_capability_device.py b/tests/test_capability_device.py index 480316c66c61c9cebfd821ece0fb188b3e8fab03..ee824fafab6ebd0dd2f1b85ad21b1c0eb0358165 100644 --- a/tests/test_capability_device.py +++ b/tests/test_capability_device.py @@ -27,8 +27,10 @@ class TestSKACapability(object): @pytest.fixture(scope="class") def device_test_config(self, device_properties): """ - Fixture that specifies the device to be tested, along with its - properties and memorized attributes. + Specification of the device under test. + + The specification includes the device's properties and memorized + attributes. """ return { "device": SKACapability, @@ -41,13 +43,12 @@ class TestSKACapability(object): @pytest.mark.skip("Not implemented") def test_properties(self, tango_context): - """Test device properties""" - # Test the properties + """Test device properties.""" # PROTECTED REGION ID(SKACapability.test_properties) ENABLED START # # PROTECTED REGION END # // SKACapability.test_properties def test_ConfigureInstances(self, tango_context): - """Test for ConfigureInstances""" + """Test for ConfigureInstances.""" # PROTECTED REGION ID(SKACapability.test_ConfigureInstances) ENABLED START # tango_context.device.ConfigureInstances(1) assert tango_context.device.configuredInstances == 1 @@ -64,7 +65,7 @@ class TestSKACapability(object): # PROTECTED REGION ID(SKACapability.test_activationTime_decorators) ENABLED START # # PROTECTED REGION END # // SKACapability.test_activationTime_decorators def test_activationTime(self, tango_context): - """Test for activationTime""" + """Test for activationTime.""" # PROTECTED REGION ID(SKACapability.test_activationTime) ENABLED START # assert tango_context.device.activationTime == 0.0 # PROTECTED REGION END # // SKACapability.test_activationTime @@ -88,7 +89,7 @@ class TestSKACapability(object): # PROTECTED REGION ID(SKACapability.test_buildState_decorators) ENABLED START # # PROTECTED REGION END # // SKACapability.test_buildState_decorators def test_buildState(self, tango_context): - """Test for buildState""" + """Test for buildState.""" # PROTECTED REGION ID(SKACapability.test_buildState) ENABLED START # buildPattern = re.compile( r"ska_tango_base, [0-9]+.[0-9]+.[0-9]+, " @@ -100,7 +101,7 @@ class TestSKACapability(object): # PROTECTED REGION ID(SKACapability.test_versionId_decorators) ENABLED START # # PROTECTED REGION END # // SKACapability.test_versionId_decorators def test_versionId(self, tango_context): - """Test for versionId""" + """Test for versionId.""" # PROTECTED REGION ID(SKACapability.test_versionId) ENABLED START # versionIdPattern = re.compile(r"[0-9]+.[0-9]+.[0-9]+") assert (re.match(versionIdPattern, tango_context.device.versionId)) is not None @@ -109,7 +110,7 @@ class TestSKACapability(object): # PROTECTED REGION ID(SKACapability.test_configuredInstances_decorators) ENABLED START # # PROTECTED REGION END # // SKACapability.test_configuredInstances_decorators def test_configuredInstances(self, tango_context): - """Test for configuredInstances""" + """Test for configuredInstances.""" # PROTECTED REGION ID(SKACapability.test_configuredInstances) ENABLED START # assert tango_context.device.configuredInstances == 0 # PROTECTED REGION END # // SKACapability.test_configuredInstances @@ -117,7 +118,7 @@ class TestSKACapability(object): # PROTECTED REGION ID(SKACapability.test_usedComponents_decorators) ENABLED START # # PROTECTED REGION END # // SKACapability.test_usedComponents_decorators def test_usedComponents(self, tango_context): - """Test for usedComponents""" + """Test for usedComponents.""" # PROTECTED REGION ID(SKACapability.test_usedComponents) ENABLED START # assert tango_context.device.usedComponents == ("",) # PROTECTED REGION END # // SKACapability.test_usedComponents diff --git a/tests/test_controller_device.py b/tests/test_controller_device.py index c12e55cd06858298ca901465e4f0517e7498e394..40e366b7a7f99ef55de090c0339b4fc6d6b55313 100644 --- a/tests/test_controller_device.py +++ b/tests/test_controller_device.py @@ -30,18 +30,13 @@ from ska_tango_base.control_model import ( @pytest.mark.usefixtures("tango_context") # PROTECTED REGION END # // SKAController.test_SKAController_decorators class TestSKAController(object): - """ - Test class for tests of the SKAController device class. - """ + """Test class for tests of the SKAController device class.""" # capabilities = ['BAND1:1', 'BAND2:1', 'BAND3:0', 'BAND4:0', 'BAND5:0'] @pytest.fixture(scope="class") def device_properties(self): - """ - Fixture that returns device_properties to be provided to the - device under test. - """ + """Fixture that returns properties of the device under test.""" return { "SkaLevel": "4", "LoggingTargetsDefault": "", @@ -54,8 +49,10 @@ class TestSKAController(object): @pytest.fixture(scope="class") def device_test_config(self, device_properties): """ - Fixture that specifies the device to be tested, along with its - properties and memorized attributes. + Specification of the device under test. + + The specification includes the device's properties and + memorized attributes. This implementation provides a concrete subclass of the device class under test, some properties, and a memorized value for @@ -72,7 +69,7 @@ class TestSKAController(object): @pytest.mark.skip("Not implemented") def test_properties(self, tango_context): - # Test the properties + """Test device properties.""" # PROTECTED REGION ID(SKAController.test_properties) ENABLED START # # PROTECTED REGION END # // SKAController.test_properties pass @@ -80,7 +77,7 @@ class TestSKAController(object): # PROTECTED REGION ID(SKAController.test_State_decorators) ENABLED START # # PROTECTED REGION END # // SKAController.test_State_decorators def test_State(self, tango_context): - """Test for State""" + """Test for State.""" # PROTECTED REGION ID(SKAController.test_State) ENABLED START # assert tango_context.device.State() == DevState.OFF # PROTECTED REGION END # // SKAController.test_State @@ -88,7 +85,7 @@ class TestSKAController(object): # PROTECTED REGION ID(SKAController.test_Status_decorators) ENABLED START # # PROTECTED REGION END # // SKAController.test_Status_decorators def test_Status(self, tango_context): - """Test for Status""" + """Test for Status.""" # PROTECTED REGION ID(SKAController.test_Status) ENABLED START # assert tango_context.device.Status() == "The device is in OFF state." # PROTECTED REGION END # // SKAController.test_Status @@ -96,7 +93,7 @@ class TestSKAController(object): # PROTECTED REGION ID(SKAController.test_GetVersionInfo_decorators) ENABLED START # # PROTECTED REGION END # // SKAController.test_GetVersionInfo_decorators def test_GetVersionInfo(self, tango_context): - """Test for GetVersionInfo""" + """Test for GetVersionInfo.""" # PROTECTED REGION ID(SKAController.test_GetVersionInfo) ENABLED START # versionPattern = re.compile( f"{tango_context.device.info().dev_class}, ska_tango_base, [0-9]+.[0-9]+.[0-9]+, " @@ -109,7 +106,7 @@ class TestSKAController(object): # PROTECTED REGION ID(SKAController.test_isCapabilityAchievable_failure_decorators) ENABLED START # # PROTECTED REGION END # // SKAController.test_isCapabilityAchievable_failure_decorators def test_isCapabilityAchievable_failure(self, tango_context): - """Test for isCapabilityAchievable to test failure condition""" + """Test for isCapabilityAchievable to test failure condition.""" # PROTECTED REGION ID(SKAController.test_isCapabilityAchievable_failure) ENABLED START # assert tango_context.device.isCapabilityAchievable([[2], ["BAND1"]]) is False # PROTECTED REGION END # // SKAController.test_isCapabilityAchievable_failure @@ -118,7 +115,7 @@ class TestSKAController(object): # PROTECTED REGION END # // SKAController.test_isCapabilityAchievable_success_decorators def test_isCapabilityAchievable_success(self, tango_context): - """Test for isCapabilityAchievable to test success condition""" + """Test for isCapabilityAchievable to test success condition.""" # PROTECTED REGION ID(SKAController.test_isCapabilityAchievable_success) ENABLED START # assert tango_context.device.isCapabilityAchievable([[1], ["BAND1"]]) is True # PROTECTED REGION END # // SKAController.test_isCapabilityAchievable_success @@ -126,7 +123,7 @@ class TestSKAController(object): # PROTECTED REGION ID(SKAController.test_elementLoggerAddress_decorators) ENABLED START # # PROTECTED REGION END # // SKAController.test_elementLoggerAddress_decorators def test_elementLoggerAddress(self, tango_context): - """Test for elementLoggerAddress""" + """Test for elementLoggerAddress.""" # PROTECTED REGION ID(SKAController.test_elementLoggerAddress) ENABLED START # assert tango_context.device.elementLoggerAddress == "" # PROTECTED REGION END # // SKAController.test_elementLoggerAddress @@ -134,7 +131,7 @@ class TestSKAController(object): # PROTECTED REGION ID(SKAController.test_elementAlarmAddress_decorators) ENABLED START # # PROTECTED REGION END # // SKAController.test_elementAlarmAddress_decorators def test_elementAlarmAddress(self, tango_context): - """Test for elementAlarmAddress""" + """Test for elementAlarmAddress.""" # PROTECTED REGION ID(SKAController.test_elementAlarmAddress) ENABLED START # assert tango_context.device.elementAlarmAddress == "" # PROTECTED REGION END # // SKAController.test_elementAlarmAddress @@ -142,7 +139,7 @@ class TestSKAController(object): # PROTECTED REGION ID(SKAController.test_elementTelStateAddress_decorators) ENABLED START # # PROTECTED REGION END # // SKAController.test_elementTelStateAddress_decorators def test_elementTelStateAddress(self, tango_context): - """Test for elementTelStateAddress""" + """Test for elementTelStateAddress.""" # PROTECTED REGION ID(SKAController.test_elementTelStateAddress) ENABLED START # assert tango_context.device.elementTelStateAddress == "" # PROTECTED REGION END # // SKAController.test_elementTelStateAddress @@ -150,7 +147,7 @@ class TestSKAController(object): # PROTECTED REGION ID(SKAController.test_elementDatabaseAddress_decorators) ENABLED START # # PROTECTED REGION END # // SKAController.test_elementDatabaseAddress_decorators def test_elementDatabaseAddress(self, tango_context): - """Test for elementDatabaseAddress""" + """Test for elementDatabaseAddress.""" # PROTECTED REGION ID(SKAController.test_elementDatabaseAddress) ENABLED START # assert tango_context.device.elementDatabaseAddress == "" # PROTECTED REGION END # // SKAController.test_elementDatabaseAddress @@ -158,7 +155,7 @@ class TestSKAController(object): # PROTECTED REGION ID(SKAController.test_buildState_decorators) ENABLED START # # PROTECTED REGION END # // SKAController.test_buildState_decorators def test_buildState(self, tango_context): - """Test for buildState""" + """Test for buildState.""" # PROTECTED REGION ID(SKAController.test_buildState) ENABLED START # buildPattern = re.compile( r"ska_tango_base, [0-9]+.[0-9]+.[0-9]+, " @@ -170,7 +167,7 @@ class TestSKAController(object): # PROTECTED REGION ID(SKAController.test_versionId_decorators) ENABLED START # # PROTECTED REGION END # // SKAController.test_versionId_decorators def test_versionId(self, tango_context): - """Test for versionId""" + """Test for versionId.""" # PROTECTED REGION ID(SKAController.test_versionId) ENABLED START # versionIdPattern = re.compile(r"[0-9]+.[0-9]+.[0-9]+") assert (re.match(versionIdPattern, tango_context.device.versionId)) is not None @@ -179,7 +176,7 @@ class TestSKAController(object): # PROTECTED REGION ID(SKAController.test_healthState_decorators) ENABLED START # # PROTECTED REGION END # // SKAController.test_healthState_decorators def test_healthState(self, tango_context): - """Test for healthState""" + """Test for healthState.""" # PROTECTED REGION ID(SKAController.test_healthState) ENABLED START # assert tango_context.device.healthState == HealthState.OK # PROTECTED REGION END # // SKAController.test_healthState @@ -187,7 +184,7 @@ class TestSKAController(object): # PROTECTED REGION ID(SKAController.test_adminMode_decorators) ENABLED START # # PROTECTED REGION END # // SKAController.test_adminMode_decorators def test_adminMode(self, tango_context): - """Test for adminMode""" + """Test for adminMode.""" # PROTECTED REGION ID(SKAController.test_adminMode) ENABLED START # assert tango_context.device.adminMode == AdminMode.ONLINE # PROTECTED REGION END # // SKAController.test_adminMode @@ -195,7 +192,7 @@ class TestSKAController(object): # PROTECTED REGION ID(SKAController.test_controlMode_decorators) ENABLED START # # PROTECTED REGION END # // SKAController.test_controlMode_decorators def test_controlMode(self, tango_context): - """Test for controlMode""" + """Test for controlMode.""" # PROTECTED REGION ID(SKAController.test_controlMode) ENABLED START # assert tango_context.device.controlMode == ControlMode.REMOTE # PROTECTED REGION END # // SKAController.test_controlMode @@ -203,7 +200,7 @@ class TestSKAController(object): # PROTECTED REGION ID(SKAController.test_simulationMode_decorators) ENABLED START # # PROTECTED REGION END # // SKAController.test_simulationMode_decorators def test_simulationMode(self, tango_context): - """Test for simulationMode""" + """Test for simulationMode.""" # PROTECTED REGION ID(SKAController.test_simulationMode) ENABLED START # assert tango_context.device.simulationMode == SimulationMode.FALSE # PROTECTED REGION END # // SKAController.test_simulationMode @@ -211,7 +208,7 @@ class TestSKAController(object): # PROTECTED REGION ID(SKAController.test_testMode_decorators) ENABLED START # # PROTECTED REGION END # // SKAController.test_testMode_decorators def test_testMode(self, tango_context): - """Test for testMode""" + """Test for testMode.""" # PROTECTED REGION ID(SKAController.test_testMode) ENABLED START # assert tango_context.device.testMode == TestMode.NONE # PROTECTED REGION END # // SKAController.test_testMode @@ -219,7 +216,7 @@ class TestSKAController(object): # PROTECTED REGION ID(SKAController.test_maxCapabilities_decorators) ENABLED START # # PROTECTED REGION END # // SKAController.test_maxCapabilities_decorators def test_maxCapabilities(self, tango_context): - """Test for maxCapabilities""" + """Test for maxCapabilities.""" # PROTECTED REGION ID(SKAController.test_maxCapabilities) ENABLED START # assert tango_context.device.maxCapabilities == ("BAND1:1", "BAND2:1") # PROTECTED REGION END # // SKAController.test_maxCapabilities @@ -227,7 +224,7 @@ class TestSKAController(object): # PROTECTED REGION ID(SKAController.test_availableCapabilities_decorators) ENABLED START # # PROTECTED REGION END # // SKAController.test_availableCapabilities_decorators def test_availableCapabilities(self, tango_context): - """Test for availableCapabilities""" + """Test for availableCapabilities.""" # PROTECTED REGION ID(SKAController.test_availableCapabilities) ENABLED START # assert tango_context.device.availableCapabilities == ("BAND1:1", "BAND2:1") # PROTECTED REGION END # // SKAController.test_availableCapabilities diff --git a/tests/test_csp_controller.py b/tests/test_csp_controller.py index 6b4217c4f74b4dc6bf981b7244e7099ab527ce9c..a4e12cfc63d40624069d8d9709fe350e7d7d34b9 100644 --- a/tests/test_csp_controller.py +++ b/tests/test_csp_controller.py @@ -38,17 +38,13 @@ class TestCspSubElementController(object): @pytest.fixture(scope="class") def device_properties(self): - """ - Fixture that returns device_properties to be provided to the - device under test. - """ + """Fixture that returns properties of the device under test.""" return {"PowerDelayStandbyOn": "1.5", "PowerDelayStandbyOff": "1.0"} @pytest.fixture(scope="class") def device_test_config(self, device_properties): """ - Fixture that specifies the device to be tested, along with its - properties and memorized attributes. + Specify device configuration, including properties and memorized attributes. This implementation provides a concrete subclass of the device class under test, some properties, and a memorized value for @@ -65,7 +61,7 @@ class TestCspSubElementController(object): @pytest.mark.skip("Not implemented") def test_properties(self, tango_context): - # Test the properties + """Test device properties.""" # PROTECTED REGION ID(CspSubelementController.test_properties) ENABLED START # # PROTECTED REGION END # // CspSubelementController.test_properties pass @@ -73,7 +69,7 @@ class TestCspSubElementController(object): # PROTECTED REGION ID(CspSubelementController.test_State_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementController.test_State_decorators def test_State(self, tango_context): - """Test for State""" + """Test for State.""" # PROTECTED REGION ID(CspSubelementController.test_State) ENABLED START # assert tango_context.device.State() == DevState.OFF # PROTECTED REGION END # // CspSubelementController.test_State @@ -81,7 +77,7 @@ class TestCspSubElementController(object): # PROTECTED REGION ID(CspSubelementController.test_Status_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementController.test_Status_decorators def test_Status(self, tango_context): - """Test for Status""" + """Test for Status.""" # PROTECTED REGION ID(CspSubelementController.test_Status) ENABLED START # assert tango_context.device.Status() == "The device is in OFF state." # PROTECTED REGION END # // CspSubelementController.test_Status @@ -89,7 +85,7 @@ class TestCspSubElementController(object): # PROTECTED REGION ID(CspSubelementController.test_GetVersionInfo_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementController.test_GetVersionInfo_decorators def test_GetVersionInfo(self, tango_context): - """Test for GetVersionInfo""" + """Test for GetVersionInfo.""" # PROTECTED REGION ID(CspSubelementController.test_GetVersionInfo) ENABLED START # versionPattern = re.compile( f"{tango_context.device.info().dev_class}, ska_tango_base, [0-9]+.[0-9]+.[0-9]+, " @@ -101,7 +97,7 @@ class TestCspSubElementController(object): # PROTECTED REGION ID(CspSubelementController.test_configurationProgress_decorators) ENABLED START # def test_buildState(self, tango_context): - """Test for buildState""" + """Test for buildState.""" # PROTECTED REGION ID(CspSubelementController.test_buildState) ENABLED START # buildPattern = re.compile( r"ska_tango_base, [0-9]+.[0-9]+.[0-9]+, " @@ -113,7 +109,7 @@ class TestCspSubElementController(object): # PROTECTED REGION ID(CspSubelementController.test_versionId_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementController.test_versionId_decorators def test_versionId(self, tango_context): - """Test for versionId""" + """Test for versionId.""" # PROTECTED REGION ID(CspSubelementController.test_versionId) ENABLED START # versionIdPattern = re.compile(r"[0-9]+.[0-9]+.[0-9]+") assert (re.match(versionIdPattern, tango_context.device.versionId)) is not None @@ -122,7 +118,7 @@ class TestCspSubElementController(object): # PROTECTED REGION ID(CspSubelementController.test_healthState_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementController.test_healthState_decorators def test_healthState(self, tango_context): - """Test for healthState""" + """Test for healthState.""" # PROTECTED REGION ID(CspSubelementController.test_healthState) ENABLED START # assert tango_context.device.healthState == HealthState.OK # PROTECTED REGION END # // CspSubelementController.test_healthState @@ -130,7 +126,7 @@ class TestCspSubElementController(object): # PROTECTED REGION ID(CspSubelementController.test_adminMode_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementController.test_adminMode_decorators def test_adminMode(self, tango_context): - """Test for adminMode""" + """Test for adminMode.""" # PROTECTED REGION ID(CspSubelementController.test_adminMode) ENABLED START # assert tango_context.device.adminMode == AdminMode.ONLINE # PROTECTED REGION END # // CspSubelementController.test_adminMode @@ -138,7 +134,7 @@ class TestCspSubElementController(object): # PROTECTED REGION ID(CspSubelementController.test_controlMode_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementController.test_controlMode_decorators def test_controlMode(self, tango_context): - """Test for controlMode""" + """Test for controlMode.""" # PROTECTED REGION ID(CspSubelementController.test_controlMode) ENABLED START # assert tango_context.device.controlMode == ControlMode.REMOTE # PROTECTED REGION END # // CspSubelementController.test_controlMode @@ -146,7 +142,7 @@ class TestCspSubElementController(object): # PROTECTED REGION ID(CspSubelementController.test_simulationMode_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementController.test_simulationMode_decorators def test_simulationMode(self, tango_context): - """Test for simulationMode""" + """Test for simulationMode.""" # PROTECTED REGION ID(CspSubelementController.test_simulationMode) ENABLED START # assert tango_context.device.simulationMode == SimulationMode.FALSE # PROTECTED REGION END # // CspSubelementController.test_simulationMode @@ -154,7 +150,7 @@ class TestCspSubElementController(object): # PROTECTED REGION ID(CspSubelementController.test_testMode_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementController.test_testMode_decorators def test_testMode(self, tango_context): - """Test for testMode""" + """Test for testMode.""" # PROTECTED REGION ID(CspSubelementController.test_testMode) ENABLED START # assert tango_context.device.testMode == TestMode.NONE # PROTECTED REGION END # // CspSubelementController.test_testMode @@ -162,7 +158,7 @@ class TestCspSubElementController(object): # PROTECTED REGION ID(CspSubelementController.test_powerDelayStandbyOn_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementController.test_powerDelayStandbyOn_decorators def test_powerDelayStandbyOn(self, tango_context, device_properties): - """Test for powerDelayStandbyOn""" + """Test for powerDelayStandbyOn.""" # PROTECTED REGION ID(CspSubelementController.test_testMode) ENABLED START # assert tango_context.device.powerDelayStandbyOn == pytest.approx( float(device_properties["PowerDelayStandbyOn"]) @@ -174,7 +170,7 @@ class TestCspSubElementController(object): # PROTECTED REGION ID(CspSubelementController.test_powerDelayStandbyOff_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementController.test_powerDelayStandbyOff_decorators def test_powerDelayStandbyOff(self, tango_context, device_properties): - """Test for powerDelayStandbyOff""" + """Test for powerDelayStandbyOff.""" # PROTECTED REGION ID(CspSubelementController.test_testMode) ENABLED START # assert tango_context.device.powerDelayStandbyOff == pytest.approx( float(device_properties["PowerDelayStandbyOff"]) @@ -186,7 +182,7 @@ class TestCspSubElementController(object): # PROTECTED REGION ID(CspSubelementController.test_onProgress_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementController.test_onProgress_decorators def test_onProgress(self, tango_context): - """Test for onProgress""" + """Test for onProgress.""" # PROTECTED REGION ID(CspSubelementController.test_onProgress) ENABLED START # assert tango_context.device.onProgress == 0 # PROTECTED REGION END # // CspSubelementController.test_onProgress @@ -194,7 +190,7 @@ class TestCspSubElementController(object): # PROTECTED REGION ID(CspSubelementController.test_onMaximumDuration_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementController.test_onMaximumDuration_decorators def test_onMaximumDuration(self, tango_context): - """Test for onMaximumDuration""" + """Test for onMaximumDuration.""" # PROTECTED REGION ID(CspSubelementController.test_onMaximumDuration) ENABLED START # tango_context.device.onMaximumDuration = 5 assert tango_context.device.onMaximumDuration == 5 @@ -203,7 +199,7 @@ class TestCspSubElementController(object): # PROTECTED REGION ID(CspSubelementController.test_onMeasuredDuration_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementController.test_onMeasuredDuration_decorators def test_onMeasuredDuration(self, tango_context): - """Test for onMeasuredDuration""" + """Test for onMeasuredDuration.""" # PROTECTED REGION ID(CspSubelementController.test_onMeasuredDuration) ENABLED START # assert tango_context.device.onMeasuredDuration == 0 # PROTECTED REGION END # // CspSubelementController.test_onMeasuredDuration @@ -211,7 +207,7 @@ class TestCspSubElementController(object): # PROTECTED REGION ID(CspSubelementController.test_standbyProgress_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementController.test_standbyProgress_decorators def test_standbyProgress(self, tango_context): - """Test for standbyProgress""" + """Test for standbyProgress.""" # PROTECTED REGION ID(CspSubelementController.test_standbyProgress) ENABLED START # assert tango_context.device.standbyProgress == 0 # PROTECTED REGION END # // CspSubelementController.test_standbyProgress @@ -219,7 +215,7 @@ class TestCspSubElementController(object): # PROTECTED REGION ID(CspSubelementController.test_standbyMaximumDuration_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementController.test_standbyMaximumDuration_decorators def test_standbyMaximumDuration(self, tango_context): - """Test for standbyMaximumDuration""" + """Test for standbyMaximumDuration.""" # PROTECTED REGION ID(CspSubelementController.test_standbyMaximumDuration) ENABLED START # tango_context.device.standbyMaximumDuration = 5 assert tango_context.device.standbyMaximumDuration == 5 @@ -228,7 +224,7 @@ class TestCspSubElementController(object): # PROTECTED REGION ID(CspSubelementController.test_standbyMeasuredDuration_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementController.test_standbyMeasuredDuration_decorators def test_standbyMeasuredDuration(self, tango_context): - """Test for standbyMeasuredDuration""" + """Test for standbyMeasuredDuration.""" # PROTECTED REGION ID(CspSubelementController.test_standbyMeasuredDuration) ENABLED START # assert tango_context.device.standbyMeasuredDuration == 0 # PROTECTED REGION END # // CspSubelementController.test_standbyMeasuredDuration @@ -236,7 +232,7 @@ class TestCspSubElementController(object): # PROTECTED REGION ID(CspSubelementController.test_offProgress_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementController.test_offProgress_decorators def test_offProgress(self, tango_context): - """Test for offProgress""" + """Test for offProgress.""" # PROTECTED REGION ID(CspSubelementController.test_offProgress) ENABLED START # assert tango_context.device.offProgress == 0 # PROTECTED REGION END # // CspSubelementController.test_offProgress @@ -244,7 +240,7 @@ class TestCspSubElementController(object): # PROTECTED REGION ID(CspSubelementController.test_offMaximumDuration_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementController.test_offMaximumDuration_decorators def test_offMaximumDuration(self, tango_context): - """Test for offMaximumDuration""" + """Test for offMaximumDuration.""" # PROTECTED REGION ID(CspSubelementController.test_offMaximumDuration) ENABLED START # tango_context.device.offMaximumDuration = 5 assert tango_context.device.offMaximumDuration == 5 @@ -253,7 +249,7 @@ class TestCspSubElementController(object): # PROTECTED REGION ID(CspSubelementController.test_offMeasuredDuration_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementController.test_offMeasuredDuration_decorators def test_offMeasuredDuration(self, tango_context): - """Test for offMeasuredDuration""" + """Test for offMeasuredDuration.""" # PROTECTED REGION ID(CspSubelementController.test_offMeasuredDuration) ENABLED START # assert tango_context.device.offMeasuredDuration == 0 # PROTECTED REGION END # // CspSubelementController.test_offMeasuredDuration @@ -261,7 +257,7 @@ class TestCspSubElementController(object): # PROTECTED REGION ID(CspSubelementController.test_loadFirmwareProgress_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementController.test_loadFirmwareProgress_decorators def test_loadFirmwareProgress(self, tango_context): - """Test for loadFirmwareProgress""" + """Test for loadFirmwareProgress.""" # PROTECTED REGION ID(CspSubelementController.test_loadFirmwareProgress) ENABLED START # assert tango_context.device.loadFirmwareProgress == 0 # PROTECTED REGION END # // CspSubelementController.test_loadFirmwareProgress @@ -269,7 +265,7 @@ class TestCspSubElementController(object): # PROTECTED REGION ID(CspSubelementController.test_loadFirmwareMaximumDuration_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementController.test_loadFirmwareMaximumDuration_decorators def test_loadFirmwareMaximumDuration(self, tango_context): - """Test for loadFirmwareMaximumDuration""" + """Test for loadFirmwareMaximumDuration.""" # PROTECTED REGION ID(CspSubelementController.test_loadFirmwareMaximumDuration) ENABLED START # tango_context.device.loadFirmwareMaximumDuration = 5 assert tango_context.device.loadFirmwareMaximumDuration == 5 @@ -278,7 +274,7 @@ class TestCspSubElementController(object): # PROTECTED REGION ID(CspSubelementController.test_loadFirmwareMeasuredDuration_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementController.test_loadFirmwareMeasuredDuration_decorators def test_loadFirmwareMeasuredDuration(self, tango_context): - """Test for loadFirmwareMeasuredDuration""" + """Test for loadFirmwareMeasuredDuration.""" # PROTECTED REGION ID(CspSubelementController.test_loadFirmwareMeasuredDuration) ENABLED START # assert tango_context.device.loadFirmwareMeasuredDuration == 0 # PROTECTED REGION END # // CspSubelementController.test_loadFirmwareMeasuredDuration @@ -286,7 +282,7 @@ class TestCspSubElementController(object): # PROTECTED REGION ID(CspSubelementController.test_LoadFirmware_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementController.test_LoadFirmware_decorators def test_LoadFirmware(self, tango_context): - """Test for LoadFirmware""" + """Test for LoadFirmware.""" # PROTECTED REGION ID(CspSubelementController.test_LoadFirmware) ENABLED START # # After initialization the device is in the right state (OFF/MAINTENANCE) to # execute the command. @@ -299,7 +295,7 @@ class TestCspSubElementController(object): # PROTECTED REGION ID(CspSubelementController.test_LoadFirmware_when_in_wrong_state_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementController.test_LoadFirmware_wrong_state_decorators def test_LoadFirmware_when_in_wrong_state(self, tango_context): - """Test for LoadFirmware when the device is in wrong state""" + """Test for LoadFirmware when the device is in wrong state.""" # PROTECTED REGION ID(CspSubelementController.test_LoadFirmware_when_in_wrong_state) ENABLED START # # Set the device in ON/ONLINE state tango_context.device.On() @@ -310,7 +306,7 @@ class TestCspSubElementController(object): # PROTECTED REGION ID(CspSubelementController.test_PowerOnDevices_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementController.test_PowerOnDevices_decorators def test_PowerOnDevices(self, tango_context): - """Test for PowerOnDevices""" + """Test for PowerOnDevices.""" # PROTECTED REGION ID(CspSubelementController.test_PowerOnDevices) ENABLED START # # put it in ON state tango_context.device.On() @@ -323,7 +319,7 @@ class TestCspSubElementController(object): # PROTECTED REGION ID(CspSubelementController.test_PowerOnDevices_when_in_wrong_state_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementController.test_PowerOnDevices_decorators def test_PowerOnDevices_when_in_wrong_state(self, tango_context): - """Test for PowerOnDevices when the Controller is in wrong state""" + """Test for PowerOnDevices when the Controller is in wrong state.""" # PROTECTED REGION ID(CspSubelementController.test_PowerOnDevices_when_in_wrong_state) ENABLED START # with pytest.raises(DevFailed, match="PowerOnDevicesCommand not allowed"): tango_context.device.PowerOnDevices(["test/dev/1", "test/dev/2"]) @@ -332,7 +328,7 @@ class TestCspSubElementController(object): # PROTECTED REGION ID(CspSubelementController.test_PowerOffDevices_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementController.test_PowerOffDevices_decorators def test_PowerOffDevices(self, tango_context): - """Test for PowerOffDEvices""" + """Test for PowerOffDEvices.""" # PROTECTED REGION ID(CspSubelementController.test_PowerOffDevices) ENABLED START # # put it in ON state tango_context.device.On() @@ -345,7 +341,7 @@ class TestCspSubElementController(object): # PROTECTED REGION ID(CspSubelementController.test_PowerOffDevices_when_in_wrong_state_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementController.test_PowerOffDevices_decorators def test_PowerOffDevices_when_in_wrong_state(self, tango_context): - """Test for PowerOffDevices when the Controller is in wrong state""" + """Test for PowerOffDevices when the Controller is in wrong state.""" # PROTECTED REGION ID(CspSubelementController.test_PowerOffDevices_when_in_wrong_state) ENABLED START # with pytest.raises(DevFailed, match="PowerOffDevicesCommand not allowed"): tango_context.device.PowerOffDevices(["test/dev/1", "test/dev/2"]) @@ -354,7 +350,7 @@ class TestCspSubElementController(object): # PROTECTED REGION ID(CspSubelementController.test_ReInitDevices_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementController.test_ReInitDevices_decorators def test_ReInitDevices(self, tango_context): - """Test for ReInitDevices""" + """Test for ReInitDevices.""" # PROTECTED REGION ID(CspSubelementController.test_ReInitDevices) ENABLED START # # put it in ON state tango_context.device.On() @@ -367,7 +363,7 @@ class TestCspSubElementController(object): # PROTECTED REGION ID(CspSubelementController.test_ReInitDevices_when_in_wrong_state_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementController.test_ReInitDevices_when_in_wrong_state_decorators def test_ReInitDevices_when_in_wrong_state(self, tango_context): - """Test for ReInitDevices whe the device is in a wrong state""" + """Test for ReInitDevices whe the device is in a wrong state.""" # PROTECTED REGION ID(CspSubelementController.test_ReInitDevices_when_in_wrong_state) ENABLED START # # put it in ON state with pytest.raises(DevFailed, match="ReInitDevicesCommand not allowed"): @@ -377,7 +373,7 @@ class TestCspSubElementController(object): @pytest.mark.forked def test_multiple_devices_in_same_process(): - + """Test that we can run this device with other devices in a single process.""" # The order here is important - base class last, so that we can # test that the subclass isn't breaking anything. devices_info = ( diff --git a/tests/test_csp_obs_device.py b/tests/test_csp_obs_device.py index 8007dfa6911d0a6891129ce636d6571d2b8e6182..1c37743139527cb6d64b3de69c13b28627358bf0 100644 --- a/tests/test_csp_obs_device.py +++ b/tests/test_csp_obs_device.py @@ -6,9 +6,7 @@ # # ######################################################################################### -"""Contain the tests for the CspSubelementObsDevice and the State model implemented by - such device. -""" +"""This module contains the tests for the CspSubelementObsDevice.""" # Imports import re import pytest @@ -44,7 +42,7 @@ from ska_tango_base.csp import ( @pytest.fixture def csp_subelement_obsdevice_state_model(logger): """ - Yields a new CspSubElementObsDevice StateModel for testing + Yield a new CspSubElementObsDevice StateModel for testing. :param logger: fixture that returns a logger """ @@ -56,17 +54,13 @@ class TestCspSubElementObsDevice(object): @pytest.fixture(scope="class") def device_properties(self): - """ - Fixture that returns device_properties to be provided to the - device under test. - """ + """Fixture that returns properties of the device under test.""" return {"DeviceID": "11"} @pytest.fixture(scope="class") def device_test_config(self, device_properties): """ - Fixture that specifies the device to be tested, along with its - properties and memorized attributes. + Specify device configuration, including properties and memorized attributes. This implementation provides a concrete subclass of the device class under test, some properties, and a memorized value for @@ -84,7 +78,7 @@ class TestCspSubElementObsDevice(object): # PROTECTED REGION ID(CspSubelementObsDevice.test_State_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementObsDevice.test_State_decorators def test_State(self, tango_context): - """Test for State""" + """Test for State.""" # PROTECTED REGION ID(CspSubelementObsDevice.test_State) ENABLED START # assert tango_context.device.State() == DevState.OFF # PROTECTED REGION END # // CspSubelementObsDevice.test_State @@ -92,7 +86,7 @@ class TestCspSubElementObsDevice(object): # PROTECTED REGION ID(CspSubelementObsDevice.test_Status_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementObsDevice.test_Status_decorators def test_Status(self, tango_context): - """Test for Status""" + """Test for Status.""" # PROTECTED REGION ID(CspSubelementObsDevice.test_Status) ENABLED START # assert tango_context.device.Status() == "The device is in OFF state." # PROTECTED REGION END # // CspSubelementObsDevice.test_Status @@ -100,7 +94,7 @@ class TestCspSubElementObsDevice(object): # PROTECTED REGION ID(CspSubelementObsDevice.test_GetVersionInfo_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementObsDevice.test_GetVersionInfo_decorators def test_GetVersionInfo(self, tango_context): - """Test for GetVersionInfo""" + """Test for GetVersionInfo.""" # PROTECTED REGION ID(CspSubelementObsDevice.test_GetVersionInfo) ENABLED START # versionPattern = re.compile( f"{tango_context.device.info().dev_class}, ska_tango_base, [0-9]+.[0-9]+.[0-9]+, " @@ -113,7 +107,7 @@ class TestCspSubElementObsDevice(object): # PROTECTED REGION ID(CspSubelementObsDevice.test_buildState_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementObsDevice.test_buildState_decorators def test_buildState(self, tango_context): - """Test for buildState""" + """Test for buildState.""" # PROTECTED REGION ID(CspSubelementObsDevice.test_buildState) ENABLED START # buildPattern = re.compile( r"ska_tango_base, [0-9]+.[0-9]+.[0-9]+, " @@ -125,7 +119,7 @@ class TestCspSubElementObsDevice(object): # PROTECTED REGION ID(CspSubelementObsDevice.test_versionId_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementObsDevice.test_versionId_decorators def test_versionId(self, tango_context): - """Test for versionId""" + """Test for versionId.""" # PROTECTED REGION ID(CspSubelementObsDevice.test_versionId) ENABLED START # versionIdPattern = re.compile(r"[0-9]+.[0-9]+.[0-9]+") assert (re.match(versionIdPattern, tango_context.device.versionId)) is not None @@ -134,7 +128,7 @@ class TestCspSubElementObsDevice(object): # PROTECTED REGION ID(CspSubelementObsDevice.test_healthState_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementObsDevice.test_healthState_decorators def test_healthState(self, tango_context): - """Test for healthState""" + """Test for healthState.""" # PROTECTED REGION ID(CspSubelementObsDevice.test_healthState) ENABLED START # assert tango_context.device.healthState == HealthState.OK # PROTECTED REGION END # // CspSubelementObsDevice.test_healthState @@ -142,7 +136,7 @@ class TestCspSubElementObsDevice(object): # PROTECTED REGION ID(CspSubelementObsDevice.test_adminMode_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementObsDevice.test_adminMode_decorators def test_adminMode(self, tango_context): - """Test for adminMode""" + """Test for adminMode.""" # PROTECTED REGION ID(CspSubelementObsDevice.test_adminMode) ENABLED START # assert tango_context.device.adminMode == AdminMode.ONLINE # PROTECTED REGION END # // CspSubelementObsDevice.test_adminMode @@ -150,7 +144,7 @@ class TestCspSubElementObsDevice(object): # PROTECTED REGION ID(CspSubelementObsDevice.test_controlMode_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementObsDevice.test_controlMode_decorators def test_controlMode(self, tango_context): - """Test for controlMode""" + """Test for controlMode.""" # PROTECTED REGION ID(CspSubelementObsDevice.test_controlMode) ENABLED START # assert tango_context.device.controlMode == ControlMode.REMOTE # PROTECTED REGION END # // CspSubelementObsDevice.test_controlMode @@ -158,7 +152,7 @@ class TestCspSubElementObsDevice(object): # PROTECTED REGION ID(CspSubelementObsDevice.test_simulationMode_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementObsDevice.test_simulationMode_decorators def test_simulationMode(self, tango_context): - """Test for simulationMode""" + """Test for simulationMode.""" # PROTECTED REGION ID(CspSubelementObsDevice.test_simulationMode) ENABLED START # assert tango_context.device.simulationMode == SimulationMode.FALSE # PROTECTED REGION END # // CspSubelementObsDevice.test_simulationMode @@ -166,7 +160,7 @@ class TestCspSubElementObsDevice(object): # PROTECTED REGION ID(CspSubelementObsDevice.test_testMode_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementObsDevice.test_testMode_decorators def test_testMode(self, tango_context): - """Test for testMode""" + """Test for testMode.""" # PROTECTED REGION ID(CspSubelementObsDevice.test_testMode) ENABLED START # assert tango_context.device.testMode == TestMode.NONE # PROTECTED REGION END # // CspSubelementObsDevice.test_testMode @@ -174,7 +168,7 @@ class TestCspSubElementObsDevice(object): # PROTECTED REGION ID(CspSubelementObsDevice.test_scanID_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementObsDevice.test_scanID_decorators def test_scanID(self, tango_context): - """Test for scanID""" + """Test for scanID.""" # PROTECTED REGION ID(CspSubelementObsDevice.test_scanID) ENABLED START # device_under_test = tango_context.device device_under_test.On() @@ -185,7 +179,7 @@ class TestCspSubElementObsDevice(object): # PROTECTED REGION ID(CspSubelementObsDevice.test_deviceID_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementObsDevice.test_deviceID_decorators def test_deviceID(self, tango_context, device_properties): - """Test for deviceID""" + """Test for deviceID.""" # PROTECTED REGION ID(CspSubelementObsDevice.test_scanID) ENABLED START # assert tango_context.device.deviceID == int(device_properties["DeviceID"]) # PROTECTED REGION END # // CspSubelementObsDevice.test_scanID @@ -193,7 +187,7 @@ class TestCspSubElementObsDevice(object): # PROTECTED REGION ID(CspSubelementObsDevice.test_sdpDestinationAddresses_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementObsDevice.test_sdpDestinationAddresses_decorators def test_sdpDestinationAddresses(self, tango_context): - """Test for sdpDestinationAddresses""" + """Test for sdpDestinationAddresses.""" # PROTECTED REGION ID(CspSubelementObsDevice.test_sdpDestinationAddresses) ENABLED START # addresses_dict = {"outputHost": [], "outputMac": [], "outputPort": []} assert tango_context.device.sdpDestinationAddresses == json.dumps( @@ -204,7 +198,7 @@ class TestCspSubElementObsDevice(object): # PROTECTED REGION ID(CspSubelementObsDevice.test_sdpLinkActive_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementObsDevice.test_sdpLinkActive_decorators def test_sdpLinkActivity(self, tango_context): - """Test for sdpLinkActive""" + """Test for sdpLinkActive.""" # PROTECTED REGION ID(CspSubelementObsDevice.test_sdpLinkActive) ENABLED START # actual = tango_context.device.sdpLinkActive n_links = len(actual) @@ -215,7 +209,7 @@ class TestCspSubElementObsDevice(object): # PROTECTED REGION ID(CspSubelementObsDevice.test_sdpLinkCapacity_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementObsDevice.test_sdpLinkCapacity_decorators def test_sdpLinkCapacity(self, tango_context): - """Test for sdpLinkCapacity""" + """Test for sdpLinkCapacity.""" # PROTECTED REGION ID(CspSubelementObsDevice.test_sdpLinkCapacity) ENABLED START # assert tango_context.device.sdpLinkCapacity == 0 # PROTECTED REGION END # // CspSubelementObsDevice.test_sdpLinkCapacity @@ -223,7 +217,7 @@ class TestCspSubElementObsDevice(object): # PROTECTED REGION ID(CspSubelementObsDevice.test_healthFailureMessage_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementObsDevice.test_healthFailureMessage_decorators def test_healthFailureMessage(self, tango_context): - """Test for healthFailureMessage""" + """Test for healthFailureMessage.""" # PROTECTED REGION ID(CspSubelementObsDevice.test_healthFailureMessage) ENABLED START # assert tango_context.device.healthFailureMessage == "" # PROTECTED REGION END # // CspSubelementObsDevice.test_healthFailureMessage @@ -231,7 +225,7 @@ class TestCspSubElementObsDevice(object): # PROTECTED REGION ID(CspSubelementObsDevice.test_ConfigureScan_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementObsDevice.test_ConfigureScan_decorators def test_ConfigureScan(self, tango_context, tango_change_event_helper): - """Test for ConfigureScan""" + """Test for ConfigureScan.""" # PROTECTED REGION ID(CspSubelementObsDevice.test_ConfigureScan) ENABLED START # device_under_test = tango_context.device device_under_test.On() @@ -251,7 +245,7 @@ class TestCspSubElementObsDevice(object): # PROTECTED REGION ID(CspSubelementObsDevice.test_ConfigureScan_when_in_wrong_state_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementObsDevice.test_ConfigureScan_when_in_wrong_state_decorators def test_ConfigureScan_when_in_wrong_state(self, tango_context): - """Test for ConfigureScan when the device is in wrong state""" + """Test for ConfigureScan when the device is in wrong state.""" # PROTECTED REGION ID(CspSubelementObsDevice.test_ConfigureScan_when_in_wrong_state) ENABLED START # # The device in in OFF/IDLE state, not valid to invoke ConfigureScan. device_under_test = tango_context.device @@ -263,8 +257,11 @@ class TestCspSubElementObsDevice(object): # PROTECTED REGION ID(CspSubelementObsDevice.test_ConfigureScan_with_wrong_input_args_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementObsDevice.test_ConfigureScan_with_wrong_input_args_decorators def test_ConfigureScan_with_wrong_input_args(self, tango_context): - """Test for ConfigureScan when input argument specifies a wrong json configuration - and the device is in IDLE state. + """ + Test ConfigureScan's handling of wrong input arguments. + + Specifically, test when input argument specifies a wrong json + configuration and the device is in IDLE state. """ # PROTECTED REGION ID(CspSubelementObsDevice.test_ConfigureScan_with_wrong_input_args_when_idle) ENABLED START # tango_context.device.On() @@ -280,7 +277,7 @@ class TestCspSubElementObsDevice(object): # PROTECTED REGION ID(CspSubelementObsDevice.test_ConfigureScan_with_json_syntax_error) ENABLED START # # PROTECTED REGION END # // CspSubelementObsDevice.test_ConfigureScan_with_json_syntax_error_decorators def test_ConfigureScan_with_json_syntax_error(self, tango_context): - """Test for ConfigureScan when syntax error in json configuration""" + """Test for ConfigureScan when syntax error in json configuration.""" # PROTECTED REGION ID(CspSubelementObsDevice.test_ConfigureScan_with_json_syntax_error) ENABLED START # tango_context.device.On() assert tango_context.device.obsState == ObsState.IDLE @@ -293,7 +290,7 @@ class TestCspSubElementObsDevice(object): # PROTECTED REGION ID(CspSubelementObsDevice.test_GoToIdle_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementObsDevice.test_GoToIdle_decorators def test_GoToIdle(self, tango_context, tango_change_event_helper): - """Test for GoToIdle""" + """Test for GoToIdle.""" # PROTECTED REGION ID(CspSubelementObsDevice.test_GoToIdle) ENABLED START # tango_context.device.On() obs_state_callback = tango_change_event_helper.subscribe("obsState") @@ -310,7 +307,7 @@ class TestCspSubElementObsDevice(object): # PROTECTED REGION ID(CspSubelementObsDevice.test_GoToIdle_when_in_wrong_state_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementObsDevice.test_GoToIdle_when_in_wrong_state_decorators def test_GoToIdle_when_in_wrong_state(self, tango_context): - """Test for GoToIdle when the device is in wrong state""" + """Test for GoToIdle when the device is in wrong state.""" # PROTECTED REGION ID(CspSubelementObsDevice.test_GoToIdle_when_in_wrong_state) ENABLED START # # The device in in OFF/IDLE state, not valid to invoke GoToIdle. with pytest.raises(DevFailed, match="Command not permitted by state model."): @@ -321,7 +318,7 @@ class TestCspSubElementObsDevice(object): # PROTECTED REGION ID(CspSubelementObsDevice.test_Scan_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementObsDevice.test_Scan_decorators def test_Scan(self, tango_context, tango_change_event_helper): - """Test for Scan""" + """Test for Scan.""" # PROTECTED REGION ID(CspSubelementObsDevice.test_Scan) ENABLED START # tango_context.device.On() tango_context.device.ConfigureScan('{"id":"sbi-mvp01-20200325-00002"}') @@ -334,7 +331,7 @@ class TestCspSubElementObsDevice(object): # PROTECTED REGION ID(CspSubelementObsDevice.test_Scan_when_in_wrong_state_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementObsDevice.test_Scan_when_in_wrong_state_decorators def test_Scan_when_in_wrong_state(self, tango_context): - """Test for Scan when the device is in wrong state""" + """Test for Scan when the device is in wrong state.""" # PROTECTED REGION ID(CspSubelementObsDevice.test_Scan_when_in_wrong_state) ENABLED START # # Set the device in ON/IDLE state tango_context.device.On() @@ -358,7 +355,7 @@ class TestCspSubElementObsDevice(object): # PROTECTED REGION ID(CspSubelementObsDevice.test_EndScan_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementObsDevice.test_EndScan_decorators def test_EndScan(self, tango_context, tango_change_event_helper): - """Test for EndScan""" + """Test for EndScan.""" # PROTECTED REGION ID(CspSubelementObsDevice.test_EndScan) ENABLED START # tango_context.device.On() tango_context.device.ConfigureScan('{"id":"sbi-mvp01-20200325-00002"}') @@ -373,7 +370,7 @@ class TestCspSubElementObsDevice(object): # PROTECTED REGION ID(CspSubelementObsDevice.test_EndScan_when_in_wrong_state_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementObsDevice.test_EndScan_when_in_wrong_state_decorators def test_EndScan_when_in_wrong_state(self, tango_context): - """Test for EndScan when the device is in wrong state""" + """Test for EndScan when the device is in wrong state.""" # PROTECTED REGION ID(CspSubelementObsDevice.test_EndScan_when_in_wrong_state) ENABLED START # # Set the device in ON/READY state tango_context.device.On() @@ -386,7 +383,7 @@ class TestCspSubElementObsDevice(object): # PROTECTED REGION ID(CspSubelementObsDevice.test_ObsReset_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementObsDevice.test_ObsReset_decorators def test_ObsReset(self, tango_context, tango_change_event_helper): - """Test for ObsReset""" + """Test for ObsReset.""" # PROTECTED REGION ID(CspSubelementObsDevice.test_ObsReset) ENABLED START # tango_context.device.On() tango_context.device.ConfigureScan('{"id":"sbi-mvp01-20200325-00002"}') @@ -401,7 +398,7 @@ class TestCspSubElementObsDevice(object): # PROTECTED REGION ID(CspSubelementObsDevice.test_ObsReset_when_in_wrong_state_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementObsDevice.test_ObsReset_when_in_wrong_state_decorators def test_ObsReset_when_in_wrong_state(self, tango_context): - """Test for ObsReset when the device is in wrong state""" + """Test for ObsReset when the device is in wrong state.""" # PROTECTED REGION ID(CspSubelementObsDevice.test_ObsReset_when_in_wrong_state) ENABLED START # # Set the device in ON/IDLE state tango_context.device.On() @@ -412,7 +409,7 @@ class TestCspSubElementObsDevice(object): # PROTECTED REGION ID(CspSubelementObsDevice.test_Abort_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementObsDevice.test_Abort_decorators def test_Abort(self, tango_context, tango_change_event_helper): - """Test for Abort""" + """Test for Abort.""" # PROTECTED REGION ID(CspSubelementObsDevice.test_Abort) ENABLED START # tango_context.device.On() tango_context.device.ConfigureScan('{"id":"sbi-mvp01-20200325-00002"}') @@ -426,6 +423,7 @@ class TestCspSubElementObsDevice(object): @pytest.mark.forked def test_multiple_devices_in_same_process(): + """Test that we can run this device with other devices in a single process.""" devices_info = ( {"class": CspSubElementObsDevice, "devices": [{"name": "test/se/1"}]}, {"class": SKAObsDevice, "devices": [{"name": "test/obsdevice/1"}]}, diff --git a/tests/test_csp_subarray.py b/tests/test_csp_subarray.py index 22cffd03e0fe3d5516d496f8612ddba8dd1270f2..d844a2b8ac8a98b25671026a00f8064a446392f2 100644 --- a/tests/test_csp_subarray.py +++ b/tests/test_csp_subarray.py @@ -6,9 +6,7 @@ # # ######################################################################################### -"""Contain the tests for the CspSubelementSubarray and the State model implemented by - such device. -""" +"""This module tests the :py:mod:``ska_tango_base.csp.subarray_device`` module.""" # Imports import re import pytest @@ -44,17 +42,16 @@ class TestCspSubElementSubarray(object): @pytest.fixture(scope="class") def device_properties(self): - """ - Fixture that returns device_properties to be provided to the - device under test. - """ + """Fixture that returns device properties of the device under test.""" return {"CapabilityTypes": ["id"]} @pytest.fixture(scope="class") def device_test_config(self, device_properties): """ - Fixture that specifies the device to be tested, along with its - properties and memorized attributes. + Return a specification of the device to be tested. + + The specification includes the device's properties and memorized + attributes. This implementation provides a concrete subclass of the device class under test, some properties, and a memorized value for @@ -74,7 +71,7 @@ class TestCspSubElementSubarray(object): @pytest.mark.skip(reason="Not implemented") def test_properties(self, tango_context): - # Test the properties + """Test the device properties.""" # PROTECTED REGION ID(CspSubelementSubarray.test_properties) ENABLED START # # PROTECTED REGION END # // CspSubelementSubarray.test_properties pass @@ -82,7 +79,7 @@ class TestCspSubElementSubarray(object): # PROTECTED REGION ID(CspSubelementSubarray.test_State_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementSubarray.test_State_decorators def test_State(self, tango_context): - """Test for State""" + """Test for State.""" # PROTECTED REGION ID(CspSubelementSubarray.test_State) ENABLED START # assert tango_context.device.State() == DevState.OFF # PROTECTED REGION END # // CspSubelementSubarray.test_State @@ -90,7 +87,7 @@ class TestCspSubElementSubarray(object): # PROTECTED REGION ID(CspSubelementSubarray.test_Status_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementSubarray.test_Status_decorators def test_Status(self, tango_context): - """Test for Status""" + """Test for Status.""" # PROTECTED REGION ID(CspSubelementSubarray.test_Status) ENABLED START # assert tango_context.device.Status() == "The device is in OFF state." # PROTECTED REGION END # // CspSubelementSubarray.test_Status @@ -98,7 +95,7 @@ class TestCspSubElementSubarray(object): # PROTECTED REGION ID(CspSubelementSubarray.test_GetVersionInfo_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementSubarray.test_GetVersionInfo_decorators def test_GetVersionInfo(self, tango_context): - """Test for GetVersionInfo""" + """Test for GetVersionInfo.""" # PROTECTED REGION ID(CspSubelementSubarray.test_GetVersionInfo) ENABLED START # versionPattern = re.compile( f"{tango_context.device.info().dev_class}, ska_tango_base, [0-9]+.[0-9]+.[0-9]+, " @@ -110,7 +107,7 @@ class TestCspSubElementSubarray(object): # PROTECTED REGION ID(CspSubelementSubarray.test_configurationProgress_decorators) ENABLED START # def test_buildState(self, tango_context): - """Test for buildState""" + """Test for buildState.""" # PROTECTED REGION ID(CspSubelementSubarray.test_buildState) ENABLED START # buildPattern = re.compile( r"ska_tango_base, [0-9]+.[0-9]+.[0-9]+, " @@ -122,7 +119,7 @@ class TestCspSubElementSubarray(object): # PROTECTED REGION ID(CspSubelementSubarray.test_versionId_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementSubarray.test_versionId_decorators def test_versionId(self, tango_context): - """Test for versionId""" + """Test for versionId.""" # PROTECTED REGION ID(CspSubelementSubarray.test_versionId) ENABLED START # versionIdPattern = re.compile(r"[0-9]+.[0-9]+.[0-9]+") assert (re.match(versionIdPattern, tango_context.device.versionId)) is not None @@ -131,7 +128,7 @@ class TestCspSubElementSubarray(object): # PROTECTED REGION ID(CspSubelementSubarray.test_healthState_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementSubarray.test_healthState_decorators def test_healthState(self, tango_context): - """Test for healthState""" + """Test for healthState.""" # PROTECTED REGION ID(CspSubelementSubarray.test_healthState) ENABLED START # assert tango_context.device.healthState == HealthState.OK # PROTECTED REGION END # // CspSubelementSubarray.test_healthState @@ -139,7 +136,7 @@ class TestCspSubElementSubarray(object): # PROTECTED REGION ID(CspSubelementSubarray.test_adminMode_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementSubarray.test_adminMode_decorators def test_adminMode(self, tango_context): - """Test for adminMode""" + """Test for adminMode.""" # PROTECTED REGION ID(CspSubelementSubarray.test_adminMode) ENABLED START # assert tango_context.device.adminMode == AdminMode.ONLINE # PROTECTED REGION END # // CspSubelementSubarray.test_adminMode @@ -147,7 +144,7 @@ class TestCspSubElementSubarray(object): # PROTECTED REGION ID(CspSubelementSubarray.test_controlMode_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementSubarray.test_controlMode_decorators def test_controlMode(self, tango_context): - """Test for controlMode""" + """Test for controlMode.""" # PROTECTED REGION ID(CspSubelementSubarray.test_controlMode) ENABLED START # assert tango_context.device.controlMode == ControlMode.REMOTE # PROTECTED REGION END # // CspSubelementSubarray.test_controlMode @@ -155,7 +152,7 @@ class TestCspSubElementSubarray(object): # PROTECTED REGION ID(CspSubelementSubarray.test_simulationMode_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementSubarray.test_simulationMode_decorators def test_simulationMode(self, tango_context): - """Test for simulationMode""" + """Test for simulationMode.""" # PROTECTED REGION ID(CspSubelementSubarray.test_simulationMode) ENABLED START # assert tango_context.device.simulationMode == SimulationMode.FALSE # PROTECTED REGION END # // CspSubelementSubarray.test_simulationMode @@ -163,7 +160,7 @@ class TestCspSubElementSubarray(object): # PROTECTED REGION ID(CspSubelementSubarray.test_testMode_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementSubarray.test_testMode_decorators def test_testMode(self, tango_context): - """Test for testMode""" + """Test for testMode.""" # PROTECTED REGION ID(CspSubelementSubarray.test_testMode) ENABLED START # assert tango_context.device.testMode == TestMode.NONE # PROTECTED REGION END # // CspSubelementSubarray.test_testMode @@ -171,7 +168,7 @@ class TestCspSubElementSubarray(object): # PROTECTED REGION ID(CspSubelementSubarray.test_scanID_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementSubarray.test_scanID_decorators def test_scanID(self, tango_context): - """Test for scanID""" + """Test for scanID.""" # PROTECTED REGION ID(CspSubelementSubarray.test_scanID) ENABLED START # device_under_test = tango_context.device device_under_test.On() @@ -181,7 +178,7 @@ class TestCspSubElementSubarray(object): # PROTECTED REGION ID(CspSubelementSubarray.test_sdpDestinationAddresses_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementSubarray.test_sdpDestinationAddresses_decorators def test_sdpDestinationAddresses(self, tango_context): - """Test for sdpDestinationAddresses""" + """Test for sdpDestinationAddresses.""" # PROTECTED REGION ID(CspSubelementSubarray.test_sdpDestinationAddresses) ENABLED START # addresses_dict = {"outputHost": [], "outputMac": [], "outputPort": []} tango_context.device.sdpDestinationAddresses = json.dumps(addresses_dict) @@ -193,7 +190,7 @@ class TestCspSubElementSubarray(object): # PROTECTED REGION ID(CspSubelementSubarray.test_sdpLinkActive_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementSubarray.test_sdpLinkActive_decorators def test_sdpLinkActivity(self, tango_context): - """Test for sdpLinkActive""" + """Test for sdpLinkActive.""" # PROTECTED REGION ID(CspSubelementSubarray.test_sdpLinkActive) ENABLED START # actual = tango_context.device.sdpLinkActive n_links = len(actual) @@ -204,7 +201,7 @@ class TestCspSubElementSubarray(object): # PROTECTED REGION ID(CspSubelementSubarray.test_outputDataRateToSdp_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementSubarray.test_outputDataRateToSdp_decorators def test_outputDataRateToSdp(self, tango_context): - """Test for outputDataRateToSdp""" + """Test for outputDataRateToSdp.""" # PROTECTED REGION ID(CspSubelementSubarray.test_outputDataRateToSdp) ENABLED START # assert tango_context.device.outputDataRateToSdp == 0 # PROTECTED REGION END # // CspSubelementSubarray.test_outputDataRateToSdp @@ -212,7 +209,7 @@ class TestCspSubElementSubarray(object): # PROTECTED REGION ID(CspSubelementSubarray.test_listOfDevicesCompletedTasks_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementSubarray.test_listOfDevicesCompletedTasks_decorators def test_listOfDevicesCompletedTasks(self, tango_context): - """Test for listOfDevicesCompletedTasks""" + """Test for listOfDevicesCompletedTasks.""" # PROTECTED REGION ID(CspSubelementSubarray.test_listOfDevicesCompletedTasks) ENABLED START # attr_value_as_dict = json.loads( tango_context.device.listOfDevicesCompletedTasks @@ -226,7 +223,7 @@ class TestCspSubElementSubarray(object): # PROTECTED REGION ID(CspSubelementSubarray.test_assignResourcesMaximumDuration_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementSubarray.test_assignResourcesMaximumDuration_decorators def test_assignResourcesMaximumDuration(self, tango_context): - """Test for assignResourcesMaximumDuration""" + """Test for assignResourcesMaximumDuration.""" # PROTECTED REGION ID(CspSubelementSubarray.test_assignResourcesMaximumDuration) ENABLED START # tango_context.device.assignResourcesMaximumDuration = 5 assert tango_context.device.assignResourcesMaximumDuration == 5 @@ -235,7 +232,7 @@ class TestCspSubElementSubarray(object): # PROTECTED REGION ID(CspSubelementSubarray.test_configureScanMeasuredDuration_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementSubarray.test_configureScanMeasuredDuration_decorators def test_configureScanMeasuredDuration(self, tango_context): - """Test for configureScanMeasuredDuration""" + """Test for configureScanMeasuredDuration.""" # PROTECTED REGION ID(CspSubelementSubarray.test_configureScanMeasuredDuration) ENABLED START # assert tango_context.device.configureScanMeasuredDuration == 0 # PROTECTED REGION END # // CspSubelementSubarray.test_configureScanMeasuredDuration @@ -243,7 +240,7 @@ class TestCspSubElementSubarray(object): # PROTECTED REGION ID(CspSubelementSubarray.test_configurationProgress_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementSubarray.test_configurationProgress_decorators def test_configurationProgress(self, tango_context): - """Test for configurationProgress""" + """Test for configurationProgress.""" # PROTECTED REGION ID(CspSubelementSubarray.test_configurationProgress) ENABLED START # assert tango_context.device.configurationProgress == 0 # PROTECTED REGION END # // CspSubelementSubarray.test_configurationProgress @@ -251,7 +248,7 @@ class TestCspSubElementSubarray(object): # PROTECTED REGION ID(CspSubelementSubarray.test_assignResourcesMeasuredDuration_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementSubarray.test_assignResourcesMeasuredDuration_decorators def test_assignResourcesMeasuredDuration(self, tango_context): - """Test for assignResourcesMeasuredDuration""" + """Test for assignResourcesMeasuredDuration.""" # PROTECTED REGION ID(CspSubelementSubarray.test_assignResourcesMeasuredDuration) ENABLED START # assert tango_context.device.assignResourcesMeasuredDuration == 0 # PROTECTED REGION END # // CspSubelementSubarray.test_assignResourcesMeasuredDuration @@ -259,7 +256,7 @@ class TestCspSubElementSubarray(object): # PROTECTED REGION ID(CspSubelementSubarray.test_assignResourcesProgress_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementSubarray.test_assignResourcesProgress_decorators def test_assignResourcesProgress(self, tango_context): - """Test for assignResourcesProgress""" + """Test for assignResourcesProgress.""" # PROTECTED REGION ID(CspSubelementSubarray.test_assignResourcesProgress) ENABLED START # assert tango_context.device.assignResourcesProgress == 0 # PROTECTED REGION END # // CspSubelementSubarray.test_assignResourcesProgress @@ -267,7 +264,7 @@ class TestCspSubElementSubarray(object): # PROTECTED REGION ID(CspSubelementSubarray.test_releaseResourcesMaximumDuration_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementSubarray.test_releaseResourcesMaximumDuration_decorators def test_releaseResourcesMaximumDuration(self, tango_context): - """Test for releaseResourcesMaximumDuration""" + """Test for releaseResourcesMaximumDuration.""" # PROTECTED REGION ID(CspSubelementSubarray.test_releaseResourcesMaximumDuration) ENABLED START # tango_context.device.releaseResourcesMaximumDuration = 5 assert tango_context.device.releaseResourcesMaximumDuration == 5 @@ -276,7 +273,7 @@ class TestCspSubElementSubarray(object): # PROTECTED REGION ID(CspSubelementSubarray.test_releaseResourcesMeasuredDuration_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementSubarray.test_releaseResourcesMeasuredDuration_decorators def test_releaseResourcesMeasuredDuration(self, tango_context): - """Test for releaseResourcesMeasuredDuration""" + """Test for releaseResourcesMeasuredDuration.""" # PROTECTED REGION ID(CspSubelementSubarray.test_releaseResourcesMeasuredDuration) ENABLED START # assert tango_context.device.releaseResourcesMeasuredDuration == 0 # PROTECTED REGION END # // CspSubelementSubarray.test_releaseResourcesMeasuredDuration @@ -284,7 +281,7 @@ class TestCspSubElementSubarray(object): # PROTECTED REGION ID(CspSubelementSubarray.test_releaseResourcesProgress_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementSubarray.test_releaseResourcesProgress_decorators def test_releaseResourcesProgress(self, tango_context): - """Test for releaseResourcesProgress""" + """Test for releaseResourcesProgress.""" # PROTECTED REGION ID(CspSubelementSubarray.test_releaseResourcesProgress) ENABLED START # assert tango_context.device.releaseResourcesProgress == 0 # PROTECTED REGION END # // CspSubelementSubarray.test_releaseResourcesProgress @@ -292,7 +289,7 @@ class TestCspSubElementSubarray(object): # PROTECTED REGION ID(CspSubelementSubarray.test_timeoutExpiredFlag_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementSubarray.test_timeoutExpiredFlag_decorators def test_configureScanTimeoutExpiredFlag(self, tango_context): - """Test for timeoutExpiredFlag""" + """Test for timeoutExpiredFlag.""" # PROTECTED REGION ID(CspSubelementSubarray.test_timeoutExpiredFlag) ENABLED START # assert not tango_context.device.configureScanTimeoutExpiredFlag # PROTECTED REGION END # // CspSubelementSubarray.test_timeoutExpiredFlag @@ -300,7 +297,7 @@ class TestCspSubElementSubarray(object): # PROTECTED REGION ID(CspSubelementSubarray.test_timeoutExpiredFlag_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementSubarray.test_timeoutExpiredFlag_decorators def test_assignResourcesTimeoutExpiredFlag(self, tango_context): - """Test for timeoutExpiredFlag""" + """Test for timeoutExpiredFlag.""" # PROTECTED REGION ID(CspSubelementSubarray.test_timeoutExpiredFlag) ENABLED START # assert not tango_context.device.assignResourcesTimeoutExpiredFlag # PROTECTED REGION END # // CspSubelementSubarray.test_timeoutExpiredFlag @@ -308,7 +305,7 @@ class TestCspSubElementSubarray(object): # PROTECTED REGION ID(CspSubelementSubarray.test_timeoutExpiredFlag_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementSubarray.test_timeoutExpiredFlag_decorators def test_releaseResourcesTimeoutExpiredFlag(self, tango_context): - """Test for timeoutExpiredFlag""" + """Test for timeoutExpiredFlag.""" # PROTECTED REGION ID(CspSubelementSubarray.test_timeoutExpiredFlag) ENABLED START # assert not tango_context.device.releaseResourcesTimeoutExpiredFlag # PROTECTED REGION END # // CspSubelementSubarray.test_timeoutExpiredFlag @@ -319,7 +316,7 @@ class TestCspSubElementSubarray(object): def test_ConfigureScan( self, tango_context, tango_change_event_helper, command_alias ): - """Test for ConfigureScan""" + """Test for ConfigureScan.""" # PROTECTED REGION ID(CspSubelementSubarray.test_ConfigureScan) ENABLED START # device_under_test = tango_context.device device_under_test.On() @@ -340,7 +337,7 @@ class TestCspSubElementSubarray(object): # PROTECTED REGION ID(CspSubelementSubarray.test_ConfigureScan_when_in_wrong_state_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementSubarray.test_ConfigureScan_when_in_wrong_state_decorators def test_ConfigureScan_when_in_wrong_state(self, tango_context): - """Test for ConfigureScan when the device is in wrong state""" + """Test for ConfigureScan when the device is in wrong state.""" # PROTECTED REGION ID(CspSubelementSubarray.test_ConfigureScan_when_in_wrong_state) ENABLED START # # The device in in OFF/EMPTY state, not valid to invoke ConfigureScan. with pytest.raises(DevFailed, match="Command not permitted by state model."): @@ -350,9 +347,7 @@ class TestCspSubElementSubarray(object): # PROTECTED REGION ID(CspSubelementSubarray.test_ConfigureScan_with_wrong_configId_key_decorators) ENABLED START # # PROTECTED REGION END # // CspSubelementSubarray.test_ConfigureScan_with_wrong_configId_key_decorators def test_ConfigureScan_with_wrong_configId_key(self, tango_context): - """Test for ConfigureScan when json configuration specifies a wrong key for - configuration ID - """ + """Test that ConfigureScan handles a wrong configuration id key.""" # PROTECTED REGION ID(CspSubelementSubarray.test_ConfigureScan_with_wrong_configId_key) ENABLED START # tango_context.device.On() tango_context.device.AssignResources(json.dumps([1, 2, 3])) @@ -368,7 +363,7 @@ class TestCspSubElementSubarray(object): # PROTECTED REGION ID(CspSubelementSubarray.test_ConfigureScan_with_json_syntax_error) ENABLED START # # PROTECTED REGION END # // CspSubelementSubarray.test_ConfigureScan_with_json_syntax_error_decorators def test_ConfigureScan_with_json_syntax_error(self, tango_context): - """Test for ConfigureScan when syntax error in json configuration""" + """Test for ConfigureScan when syntax error in json configuration.""" # PROTECTED REGION ID(CspSubelementSubarray.test_ConfigureScan_with_json_syntax_error) ENABLED START # tango_context.device.On() tango_context.device.AssignResources(json.dumps([1, 2, 3])) @@ -383,7 +378,7 @@ class TestCspSubElementSubarray(object): # PROTECTED REGION END # // CspSubelementSubarray.test_GoToIdle_decorators @pytest.mark.parametrize("command_alias", ["GoToIdle", "End"]) def test_GoToIdle(self, tango_context, tango_change_event_helper, command_alias): - """Test for GoToIdle""" + """Test for GoToIdle.""" # PROTECTED REGION ID(CspSubelementSubarray.test_GoToIdle) ENABLED START # tango_context.device.On() tango_context.device.AssignResources(json.dumps([1, 2, 3])) diff --git a/tests/test_csp_subarray_component_manager.py b/tests/test_csp_subarray_component_manager.py index 3caa84f5664395e787021d8a7791c799b4f7db46..c9e2f03160507ddce4f9a8d40f61b5f8c3f558b0 100644 --- a/tests/test_csp_subarray_component_manager.py +++ b/tests/test_csp_subarray_component_manager.py @@ -1,8 +1,4 @@ -""" -Tests for the -:py:mod:`ska_tango_base.csp_subelement_component_manager` -module. -""" +"""Tests for the ``csp_subelement_component_manager`` module.""" import contextlib import itertools @@ -14,16 +10,12 @@ from ska_tango_base.control_model import PowerMode class TestCspSubelementSubarrayComponentManager: - """ - Tests of the - :py:class:`ska_tango_base.csp_subelement_component_manager.SubarrayComponentManager` - class. - """ + """Tests of the ``SubarrayComponentManager`` class.""" @pytest.fixture() def mock_op_state_model(self, mocker): """ - Fixture that returns a mock op state model + Fixture that returns a mock op state model. :param mocker: pytest fixture that wraps :py:mod:`unittest.mock`. @@ -35,7 +27,7 @@ class TestCspSubelementSubarrayComponentManager: @pytest.fixture() def mock_obs_state_model(self, mocker): """ - Fixture that returns a mock observation state model + Fixture that returns a mock observation state model. :param mocker: pytest fixture that wraps :py:mod:`unittest.mock`. @@ -46,31 +38,38 @@ class TestCspSubelementSubarrayComponentManager: @pytest.fixture() def mock_resource_factory(self, mocker): + """Return a factory that provides mock resources.""" return mocker.Mock @pytest.fixture() def mock_capability_types(self, mocker): + """Return some mock capability types.""" return ["foo", "bah"] @pytest.fixture() def mock_config_factory(self): + """Return a factory that provides mock arguments to the configure() method.""" mock_config_generator = ({"id": f"mock_id_{i}"} for i in itertools.count(1)) return lambda: next(mock_config_generator) @pytest.fixture() def mock_scan_args(self, mocker): + """Return some mock arguments to the scan() method.""" return mocker.Mock() @pytest.fixture(params=[PowerMode.OFF, PowerMode.STANDBY, PowerMode.ON]) def initial_power_mode(self, request): + """Return the initial power mode of the component under test.""" return request.param @pytest.fixture(params=[False, True]) def initial_fault(self, request): + """Return whether the component under test should initially be faulty.""" return request.param @pytest.fixture() def component(self, mock_capability_types, initial_power_mode, initial_fault): + """Return a component for testing.""" return ReferenceCspSubarrayComponentManager._Component( mock_capability_types, _power_mode=initial_power_mode, _faulty=initial_fault ) @@ -85,7 +84,7 @@ class TestCspSubelementSubarrayComponentManager: component, ): """ - Fixture that returns the component manager under test + Fixture that returns the component manager under test. :param mock_op_state_model: a mock state model for testing :param logger: a logger for the component manager @@ -104,9 +103,7 @@ class TestCspSubelementSubarrayComponentManager: self, component_manager, mock_op_state_model, initial_power_mode, initial_fault ): """ - Test that the state model is updated with state changes when the - component manager connects to and disconnects from its - component. + Test that the state model updates with component connection/disconnection. :param component_manager: the component manager under test :param mock_op_state_model: a mock state model for testing @@ -159,8 +156,7 @@ class TestCspSubelementSubarrayComponentManager: @pytest.mark.parametrize("command", ["off", "standby", "on"]) def test_base_command_fails_when_disconnected(self, component_manager, command): """ - Test that component commands fail when the component manager - isn't connected to the component. + Test that component commands fail when there's no connection to the component. :param component_manager: the component manager under test :param command: the command under test @@ -195,8 +191,7 @@ class TestCspSubelementSubarrayComponentManager: action, ): """ - Test that component commands succeed when the component manager - is connected to the component. + Test that component commands succeed when there's a connection to the component. :param component_manager: the component manager under test :param mock_op_state_model: a mock state model for testing @@ -246,8 +241,11 @@ class TestCspSubelementSubarrayComponentManager: action, ): """ - Test that spontaneous changes to the state of the component - result in the correct action being performed on the state model. + Test that changes to the component propagate up to the state model. + + Specifically, test that spontaneous changes to the state of the + component result in the correct action being performed on the + state model. :param component_manager: the component manager under test :param mock_op_state_model: a mock state model for testing @@ -280,6 +278,7 @@ class TestCspSubelementSubarrayComponentManager: def test_reset_from_fault( self, component_manager, mock_op_state_model, initial_fault ): + """Test that a component manager can reset a faulty component.""" component_manager.start_communicating() assert component_manager.faulty == initial_fault mock_op_state_model.reset_mock() @@ -297,6 +296,7 @@ class TestCspSubelementSubarrayComponentManager: mock_obs_state_model, mock_resource_factory, ): + """Test management of a component through resource assignment.""" component_manager.start_communicating() mock_resource_1 = mock_resource_factory() @@ -341,6 +341,7 @@ class TestCspSubelementSubarrayComponentManager: mock_resource_factory, mock_config_factory, ): + """Test management of a component through configuration.""" component_manager.start_communicating() mock_resource = mock_resource_factory() @@ -388,6 +389,7 @@ class TestCspSubelementSubarrayComponentManager: mock_config_factory, mock_scan_args, ): + """Test management of a scanning component.""" component_manager.start_communicating() mock_resource = mock_resource_factory() @@ -441,6 +443,7 @@ class TestCspSubelementSubarrayComponentManager: mock_config_factory, mock_scan_args, ): + """Test management of a faulting component.""" component_manager.start_communicating() mock_resource = mock_resource_factory() diff --git a/tests/test_logger_device.py b/tests/test_logger_device.py index 9d818b86a7daa5558c49d73a26208235e0d52b89..b474c825a45783fab433386ba3a0994fd60dfd70 100644 --- a/tests/test_logger_device.py +++ b/tests/test_logger_device.py @@ -34,15 +34,15 @@ from ska_tango_base.control_model import ( @pytest.mark.usefixtures("tango_context", "initialize_device") # PROTECTED REGION END # // SKALogger.test_SKALogger_decorators class TestSKALogger(object): - """ - Test class for tests of the SKALogger device class. - """ + """Test class for tests of the SKALogger device class.""" @pytest.fixture(scope="class") def device_test_config(self, device_properties): """ - Fixture that specifies the device to be tested, along with its - properties and memorized attributes. + Specification of the device under test. + + The specification includes the device's properties and memorized + attributes. """ return { "device": SKALogger, @@ -55,7 +55,7 @@ class TestSKALogger(object): @pytest.mark.skip("Not implemented") def test_properties(self, tango_context): - # test the properties + """Test device properties.""" # PROTECTED REGION ID(SKALogger.test_properties) ENABLED START # # PROTECTED REGION END # // SKALogger.test_properties pass @@ -63,7 +63,7 @@ class TestSKALogger(object): # PROTECTED REGION ID(SKALogger.test_State_decorators) ENABLED START # # PROTECTED REGION END # // SKALogger.test_State_decorators def test_State(self, tango_context): - """Test for State""" + """Test for State.""" # PROTECTED REGION ID(SKALogger.test_State) ENABLED START # assert tango_context.device.State() == DevState.OFF # PROTECTED REGION END # // SKALogger.test_State @@ -71,7 +71,7 @@ class TestSKALogger(object): # PROTECTED REGION ID(SKALogger.test_Status_decorators) ENABLED START # # PROTECTED REGION END # // SKALogger.test_Status_decorators def test_Status(self, tango_context): - """Test for Status""" + """Test for Status.""" # PROTECTED REGION ID(SKALogger.test_Status) ENABLED START # assert tango_context.device.Status() == "The device is in OFF state." # PROTECTED REGION END # // SKALogger.test_Status @@ -79,7 +79,7 @@ class TestSKALogger(object): # PROTECTED REGION ID(SKALogger.test_GetVersionInfo_decorators) ENABLED START # # PROTECTED REGION END # // SKALogger.test_GetVersionInfo_decorators def test_GetVersionInfo(self, tango_context): - """Test for GetVersionInfo""" + """Test for GetVersionInfo.""" # PROTECTED REGION ID(SKALogger.test_GetVersionInfo) ENABLED START # versionPattern = re.compile( f"{tango_context.device.info().dev_class}, ska_tango_base, [0-9]+.[0-9]+.[0-9]+, " @@ -92,7 +92,7 @@ class TestSKALogger(object): # PROTECTED REGION ID(SKALogger.test_buildState_decorators) ENABLED START # # PROTECTED REGION END # // SKALogger.test_buildState_decorators def test_buildState(self, tango_context): - """Test for buildState""" + """Test for buildState.""" # PROTECTED REGION ID(SKALogger.test_buildState) ENABLED START # buildPattern = re.compile( r"ska_tango_base, [0-9]+.[0-9]+.[0-9]+, " @@ -104,7 +104,7 @@ class TestSKALogger(object): # PROTECTED REGION ID(SKALogger.test_versionId_decorators) ENABLED START # # PROTECTED REGION END # // SKALogger.test_versionId_decorators def test_versionId(self, tango_context): - """Test for versionId""" + """Test for versionId.""" # PROTECTED REGION ID(SKALogger.test_versionId) ENABLED START # versionIdPattern = re.compile(r"[0-9]+.[0-9]+.[0-9]+") assert (re.match(versionIdPattern, tango_context.device.versionId)) is not None @@ -113,7 +113,7 @@ class TestSKALogger(object): # PROTECTED REGION ID(SKALogger.test_loggingLevel_decorators) ENABLED START # # PROTECTED REGION END # // SKALogger.test_loggingLevel_decorators def test_loggingLevel(self, tango_context): - """Test for loggingLevel""" + """Test for loggingLevel.""" # PROTECTED REGION ID(SKALogger.test_loggingLevel) ENABLED START # assert tango_context.device.loggingLevel == LoggingLevel.INFO # PROTECTED REGION END # // SKALogger.test_loggingLevel @@ -121,7 +121,7 @@ class TestSKALogger(object): # PROTECTED REGION ID(SKALogger.test_healthState_decorators) ENABLED START # # PROTECTED REGION END # // SKALogger.test_healthState_decorators def test_healthState(self, tango_context): - """Test for healthState""" + """Test for healthState.""" # PROTECTED REGION ID(SKALogger.test_healthState) ENABLED START # assert tango_context.device.healthState == HealthState.OK # PROTECTED REGION END # // SKALogger.test_healthState @@ -129,7 +129,7 @@ class TestSKALogger(object): # PROTECTED REGION ID(SKALogger.test_adminMode_decorators) ENABLED START # # PROTECTED REGION END # // SKALogger.test_adminMode_decorators def test_adminMode(self, tango_context): - """Test for adminMode""" + """Test for adminMode.""" # PROTECTED REGION ID(SKALogger.test_adminMode) ENABLED START # assert tango_context.device.adminMode == AdminMode.ONLINE # PROTECTED REGION END # // SKALogger.test_adminMode @@ -137,7 +137,7 @@ class TestSKALogger(object): # PROTECTED REGION ID(SKALogger.test_controlMode_decorators) ENABLED START # # PROTECTED REGION END # // SKALogger.test_controlMode_decorators def test_controlMode(self, tango_context): - """Test for controlMode""" + """Test for controlMode.""" # PROTECTED REGION ID(SKALogger.test_controlMode) ENABLED START # assert tango_context.device.controlMode == ControlMode.REMOTE # PROTECTED REGION END # // SKALogger.test_controlMode @@ -145,7 +145,7 @@ class TestSKALogger(object): # PROTECTED REGION ID(SKALogger.test_simulationMode_decorators) ENABLED START # # PROTECTED REGION END # // SKALogger.test_simulationMode_decorators def test_simulationMode(self, tango_context): - """Test for simulationMode""" + """Test for simulationMode.""" # PROTECTED REGION ID(SKALogger.test_simulationMode) ENABLED START # assert tango_context.device.simulationMode == SimulationMode.FALSE # PROTECTED REGION END # // SKALogger.test_simulationMode @@ -153,7 +153,7 @@ class TestSKALogger(object): # PROTECTED REGION ID(SKALogger.test_testMode_decorators) ENABLED START # # PROTECTED REGION END # // SKALogger.test_testMode_decorators def test_testMode(self, tango_context): - """Test for testMode""" + """Test for testMode.""" # PROTECTED REGION ID(SKALogger.test_testMode) ENABLED START # assert tango_context.device.testMode == TestMode.NONE # PROTECTED REGION END # // SKALogger.test_testMode @@ -161,7 +161,7 @@ class TestSKALogger(object): @pytest.mark.forked def test_SetLoggingLevel(): - """Test for SetLoggingLevel""" + """Test for SetLoggingLevel.""" logging_level = int(tango.LogLevel.LOG_ERROR) logging_target = "logger/target/1" logger_device = "logger/device/1" diff --git a/tests/test_obs_device.py b/tests/test_obs_device.py index 59388f949dd45f0f98ce6e432a72f2b37ff1d71c..f374783fe8df55a2b73854c7745b223912a5a6ed 100644 --- a/tests/test_obs_device.py +++ b/tests/test_obs_device.py @@ -36,15 +36,12 @@ from ska_tango_base.control_model import ( @pytest.mark.usefixtures("tango_context", "initialize_device") # PROTECTED REGION END # // SKAObsDevice.test_SKAObsDevice_decorators class TestSKAObsDevice(object): - """ - Test class for tests of the SKAObsDevice device class. - """ + """Test class for tests of the SKAObsDevice device class.""" @pytest.fixture(scope="class") def device_test_config(self, device_properties): """ - Fixture that specifies the device to be tested, along with its - properties and memorized attributes. + Specify device configuration, including properties and memorized attributes. This implementation provides a concrete subclass of the device class under test, some properties, and a memorized value for @@ -61,7 +58,7 @@ class TestSKAObsDevice(object): @pytest.mark.skip("Not implemented") def test_properties(self, tango_context): - # Test the properties + """Test device properties.""" # PROTECTED REGION ID(SKAObsDevice.test_properties) ENABLED START # # PROTECTED REGION END # // SKAObsDevice.test_properties pass @@ -69,7 +66,7 @@ class TestSKAObsDevice(object): # PROTECTED REGION ID(SKAObsDevice.test_State_decorators) ENABLED START # # PROTECTED REGION END # // SKAObsDevice.test_State_decorators def test_State(self, tango_context): - """Test for State""" + """Test for State.""" # PROTECTED REGION ID(SKAObsDevice.test_State) ENABLED START # assert tango_context.device.State() == DevState.OFF # PROTECTED REGION END # // SKAObsDevice.test_State @@ -77,7 +74,7 @@ class TestSKAObsDevice(object): # PROTECTED REGION ID(SKAObsDevice.test_Status_decorators) ENABLED START # # PROTECTED REGION END # // SKAObsDevice.test_Status_decorators def test_Status(self, tango_context): - """Test for Status""" + """Test for Status.""" # PROTECTED REGION ID(SKAObsDevice.test_Status) ENABLED START # assert tango_context.device.Status() == "The device is in OFF state." # PROTECTED REGION END # // SKAObsDevice.test_Status @@ -85,7 +82,7 @@ class TestSKAObsDevice(object): # PROTECTED REGION ID(SKAObsDevice.test_GetVersionInfo_decorators) ENABLED START # # PROTECTED REGION END # // SKAObsDevice.test_GetVersionInfo_decorators def test_GetVersionInfo(self, tango_context): - """Test for GetVersionInfo""" + """Test for GetVersionInfo.""" # PROTECTED REGION ID(SKAObsDevice.test_GetVersionInfo) ENABLED START # versionPattern = re.compile( f"{tango_context.device.info().dev_class}, ska_tango_base, [0-9]+.[0-9]+.[0-9]+, " @@ -98,7 +95,7 @@ class TestSKAObsDevice(object): # PROTECTED REGION ID(SKAObsDevice.test_obsState_decorators) ENABLED START # # PROTECTED REGION END # // SKAObsDevice.test_obsState_decorators def test_obsState(self, tango_context, tango_change_event_helper): - """Test for obsState""" + """Test for obsState.""" # PROTECTED REGION ID(SKAObsDevice.test_obsState) ENABLED START # assert tango_context.device.obsState == ObsState.EMPTY @@ -111,7 +108,7 @@ class TestSKAObsDevice(object): # PROTECTED REGION ID(SKAObsDevice.test_obsMode_decorators) ENABLED START # # PROTECTED REGION END # // SKAObsDevice.test_obsMode_decorators def test_obsMode(self, tango_context): - """Test for obsMode""" + """Test for obsMode.""" # PROTECTED REGION ID(SKAObsDevice.test_obsMode) ENABLED START # assert tango_context.device.obsMode == ObsMode.IDLE # PROTECTED REGION END # // SKAObsDevice.test_obsMode @@ -119,7 +116,7 @@ class TestSKAObsDevice(object): # PROTECTED REGION ID(SKAObsDevice.test_configurationProgress_decorators) ENABLED START # # PROTECTED REGION END # // SKAObsDevice.test_configurationProgress_decorators def test_configurationProgress(self, tango_context): - """Test for configurationProgress""" + """Test for configurationProgress.""" # PROTECTED REGION ID(SKAObsDevice.test_configurationProgress) ENABLED START # assert tango_context.device.configurationProgress == 0 # PROTECTED REGION END # // SKAObsDevice.test_configurationProgress @@ -127,7 +124,7 @@ class TestSKAObsDevice(object): # PROTECTED REGION ID(SKAObsDevice.test_configurationDelayExpected_decorators) ENABLED START # # PROTECTED REGION END # // SKAObsDevice.test_configurationDelayExpected_decorators def test_configurationDelayExpected(self, tango_context): - """Test for configurationDelayExpected""" + """Test for configurationDelayExpected.""" # PROTECTED REGION ID(SKAObsDevice.test_configurationDelayExpected) ENABLED START # assert tango_context.device.configurationDelayExpected == 0 # PROTECTED REGION END # // SKAObsDevice.test_configurationDelayExpected @@ -135,7 +132,7 @@ class TestSKAObsDevice(object): # PROTECTED REGION ID(SKAObsDevice.test_buildState_decorators) ENABLED START # # PROTECTED REGION END # // SKAObsDevice.test_buildState_decorators def test_buildState(self, tango_context): - """Test for buildState""" + """Test for buildState.""" # PROTECTED REGION ID(SKAObsDevice.test_buildState) ENABLED START # buildPattern = re.compile( r"ska_tango_base, [0-9]+.[0-9]+.[0-9]+, " @@ -147,7 +144,7 @@ class TestSKAObsDevice(object): # PROTECTED REGION ID(SKAObsDevice.test_versionId_decorators) ENABLED START # # PROTECTED REGION END # // SKAObsDevice.test_versionId_decorators def test_versionId(self, tango_context): - """Test for versionId""" + """Test for versionId.""" # PROTECTED REGION ID(SKAObsDevice.test_versionId) ENABLED START # versionIdPattern = re.compile(r"[0-9]+.[0-9]+.[0-9]+") assert (re.match(versionIdPattern, tango_context.device.versionId)) is not None @@ -156,7 +153,7 @@ class TestSKAObsDevice(object): # PROTECTED REGION ID(SKAObsDevice.test_healthState_decorators) ENABLED START # # PROTECTED REGION END # // SKAObsDevice.test_healthState_decorators def test_healthState(self, tango_context): - """Test for healthState""" + """Test for healthState.""" # PROTECTED REGION ID(SKAObsDevice.test_healthState) ENABLED START # assert tango_context.device.healthState == HealthState.OK # PROTECTED REGION END # // SKAObsDevice.test_healthState @@ -164,7 +161,7 @@ class TestSKAObsDevice(object): # PROTECTED REGION ID(SKAObsDevice.test_adminMode_decorators) ENABLED START # # PROTECTED REGION END # // SKAObsDevice.test_adminMode_decorators def test_adminMode(self, tango_context): - """Test for adminMode""" + """Test for adminMode.""" # PROTECTED REGION ID(SKAObsDevice.test_adminMode) ENABLED START # assert tango_context.device.adminMode == AdminMode.ONLINE # PROTECTED REGION END # // SKAObsDevice.test_adminMode @@ -172,7 +169,7 @@ class TestSKAObsDevice(object): # PROTECTED REGION ID(SKAObsDevice.test_controlMode_decorators) ENABLED START # # PROTECTED REGION END # // SKAObsDevice.test_controlMode_decorators def test_controlMode(self, tango_context): - """Test for controlMode""" + """Test for controlMode.""" # PROTECTED REGION ID(SKAObsDevice.test_controlMode) ENABLED START # assert tango_context.device.controlMode == ControlMode.REMOTE # PROTECTED REGION END # // SKAObsDevice.test_controlMode @@ -180,7 +177,7 @@ class TestSKAObsDevice(object): # PROTECTED REGION ID(SKAObsDevice.test_simulationMode_decorators) ENABLED START # # PROTECTED REGION END # // SKAObsDevice.test_simulationMode_decorators def test_simulationMode(self, tango_context): - """Test for simulationMode""" + """Test for simulationMode.""" # PROTECTED REGION ID(SKAObsDevice.test_simulationMode) ENABLED START # assert tango_context.device.simulationMode == SimulationMode.FALSE # PROTECTED REGION END # // SKAObsDevice.test_simulationMode @@ -188,7 +185,7 @@ class TestSKAObsDevice(object): # PROTECTED REGION ID(SKAObsDevice.test_testMode_decorators) ENABLED START # # PROTECTED REGION END # // SKAObsDevice.test_testMode_decorators def test_testMode(self, tango_context): - """Test for testMode""" + """Test for testMode.""" # PROTECTED REGION ID(SKAObsDevice.test_testMode) ENABLED START # assert tango_context.device.testMode == TestMode.NONE # PROTECTED REGION END # // SKAObsDevice.test_testMode @@ -196,7 +193,7 @@ class TestSKAObsDevice(object): @pytest.mark.forked def test_multiple_devices_in_same_process(): - + """Test that we can run this device with other devices in a single process.""" # The order here is important - base class last, so that we can # test that the subclass isn't breaking anything. devices_info = ( diff --git a/tests/test_subarray_component_manager.py b/tests/test_subarray_component_manager.py index f41d47cf3a8104aea700a1e92058e4bb1d0d6661..b384085732c0904bcc2753d2f950b5c5542d1b2a 100644 --- a/tests/test_subarray_component_manager.py +++ b/tests/test_subarray_component_manager.py @@ -1,7 +1,4 @@ -""" -Tests for the :py:mod:`ska_tango_base.component_manager` -module. -""" +"""Tests for the :py:mod:`ska_tango_base.component_manager` module.""" import contextlib import itertools @@ -15,18 +12,17 @@ from ska_tango_base.control_model import PowerMode class TestSubarrayComponentResourceManager: - """ - Test suite for the Subarray._Component._ResourceManager - """ + """Test suite for the Subarray._Component._ResourceManager.""" @pytest.fixture def mock_callback(self, mocker): + """Return a mock that can be used as a callback.""" return mocker.Mock() @pytest.fixture def resource_pool(self, mock_callback): """ - Fixture that yields the component's resource manager + Fixture that yields the component's resource manager. :return: :py:class:`SubarrayComponentManager._ResourcePool` @@ -34,9 +30,7 @@ class TestSubarrayComponentResourceManager: return ReferenceSubarrayComponentManager._ResourcePool(mock_callback) def test_ResourceManager_assign(self, resource_pool, mock_callback): - """ - Test that the ResourceManager assigns resource correctly. - """ + """Test that the ResourceManager assigns resource correctly.""" # create a resource manager and check that it is empty assert not len(resource_pool) assert resource_pool.get() == set() @@ -73,9 +67,7 @@ class TestSubarrayComponentResourceManager: mock_callback.assert_not_called() def test_ResourceManager_release(self, resource_pool, mock_callback): - """ - Test that the ResourceManager releases resource correctly. - """ + """Test that the ResourceManager releases resource correctly.""" resource_pool.assign(["A", "B", "C", "D"]) mock_callback.assert_called_once_with(True) mock_callback.reset_mock() @@ -113,16 +105,12 @@ class TestSubarrayComponentResourceManager: class TestSubarrayComponentManager: - """ - Tests of the - :py:class:`ska_tango_base.component_manager.SubarrayComponentManager` - class. - """ + """Tests of the ``SubarrayComponentManager`` class.""" @pytest.fixture() def mock_op_state_model(self, mocker): """ - Fixture that returns a mock op state model + Fixture that returns a mock op state model. :param mocker: pytest fixture that wraps :py:mod:`unittest.mock`. @@ -134,7 +122,7 @@ class TestSubarrayComponentManager: @pytest.fixture() def mock_obs_state_model(self, mocker): """ - Fixture that returns a mock observation state model + Fixture that returns a mock observation state model. :param mocker: pytest fixture that wraps :py:mod:`unittest.mock`. @@ -145,31 +133,38 @@ class TestSubarrayComponentManager: @pytest.fixture() def mock_resource_factory(self, mocker): + """Return a factory that provides mock resources.""" return mocker.Mock @pytest.fixture() def mock_capability_types(self, mocker): + """Return some mock capability types.""" return ["foo", "bah"] @pytest.fixture() def mock_config_factory(self): + """Return a factory that provides mock arguments to the configure() method.""" mock_config_generator = ({"foo": i, "bah": i} for i in itertools.count(1)) return lambda: next(mock_config_generator) @pytest.fixture() def mock_scan_args(self, mocker): + """Return mock arguments to the scan() method.""" return mocker.Mock() @pytest.fixture(params=[PowerMode.OFF, PowerMode.STANDBY, PowerMode.ON]) def initial_power_mode(self, request): + """Return the initial power mode of the component under test.""" return request.param @pytest.fixture(params=[False, True]) def initial_fault(self, request): + """Return whether the component under test should initially be faulty.""" return request.param @pytest.fixture() def component(self, mock_capability_types, initial_power_mode, initial_fault): + """Return a component for use in testing.""" return ReferenceSubarrayComponentManager._Component( mock_capability_types, _power_mode=initial_power_mode, _faulty=initial_fault ) @@ -184,7 +179,7 @@ class TestSubarrayComponentManager: component, ): """ - Fixture that returns the component manager under test + Fixture that returns the component manager under test. :param mock_op_state_model: a mock state model for testing :param logger: a logger for the component manager @@ -209,9 +204,7 @@ class TestSubarrayComponentManager: initial_fault, ): """ - Test that the state model is updated with state changes when the - component manager connects to and disconnects from its - component. + Test that the state model updates with component connection and disconnection. :param component_manager: the component manager under test :param mock_op_state_model: a mock state model for testing @@ -280,8 +273,7 @@ class TestSubarrayComponentManager: @pytest.mark.parametrize("command", ["off", "standby", "on"]) def test_base_command_fails_when_disconnected(self, component_manager, command): """ - Test that component commands fail when the component manager - isn't connected to the component. + Test that component commands fail when there's no connection to the component. :param component_manager: the component manager under test :param command: the command under test @@ -316,8 +308,7 @@ class TestSubarrayComponentManager: action, ): """ - Test that component commands succeed when the component manager - is connected to the component. + Test that component commands succeed when there's a connection to the component. :param component_manager: the component manager under test :param mock_op_state_model: a mock state model for testing @@ -367,8 +358,11 @@ class TestSubarrayComponentManager: action, ): """ - Test that spontaneous changes to the state of the component - result in the correct action being performed on the state model. + Test that component changes propagate up to the state model. + + Specifically, test that spontaneous changes to the state of the + component result in the correct action being performed on the + state model. :param component_manager: the component manager under test :param mock_op_state_model: a mock state model for testing @@ -401,6 +395,7 @@ class TestSubarrayComponentManager: def test_reset_from_fault( self, component_manager, mock_op_state_model, initial_fault ): + """Test that the component manager can reset a faulty component.""" component_manager.start_communicating() assert component_manager.faulty == initial_fault mock_op_state_model.reset_mock() @@ -417,6 +412,7 @@ class TestSubarrayComponentManager: mock_obs_state_model, mock_resource_factory, ): + """Test management of a component during assignment of resources.""" component_manager.start_communicating() mock_resource_1 = mock_resource_factory() @@ -460,6 +456,7 @@ class TestSubarrayComponentManager: mock_resource_factory, mock_config_factory, ): + """Test management of a component through configuration.""" component_manager.start_communicating() mock_resource = mock_resource_factory() @@ -507,6 +504,7 @@ class TestSubarrayComponentManager: mock_config_factory, mock_scan_args, ): + """Test management of a scanning component.""" component_manager.start_communicating() mock_resource = mock_resource_factory() @@ -560,6 +558,7 @@ class TestSubarrayComponentManager: mock_config_factory, mock_scan_args, ): + """Test management of a faulting component.""" component_manager.start_communicating() mock_resource = mock_resource_factory() diff --git a/tests/test_subarray_device.py b/tests/test_subarray_device.py index 34d5fdedc9c9c40606ab974695bec0378125afd7..18af1c9332d79893cb365f431f5414b7b5ef05c6 100644 --- a/tests/test_subarray_device.py +++ b/tests/test_subarray_device.py @@ -37,16 +37,11 @@ from ska_tango_base.subarray import ( class TestSKASubarray: - """ - Test cases for SKASubarray device. - """ + """Test cases for SKASubarray device.""" @pytest.fixture(scope="class") def device_properties(self): - """ - Fixture that returns device_properties to be provided to the - device under test. - """ + """Fixture that returns properties of the device under test.""" return { "CapabilityTypes": ["BAND1", "BAND2"], "LoggingTargetsDefault": "", @@ -58,8 +53,7 @@ class TestSKASubarray: @pytest.fixture(scope="class") def device_test_config(self, device_properties): """ - Fixture that specifies the device to be tested, along with its - properties and memorized attributes. + Specify device configuration, including properties and memorized attributes. This implementation provides a concrete subclass of the device class under test, some properties, and a memorized value for @@ -79,15 +73,15 @@ class TestSKASubarray: @pytest.mark.skip(reason="Not implemented") def test_properties(self, tango_context): - # Test the properties + """Test device properties.""" # PROTECTED REGION ID(SKASubarray.test_properties) ENABLED START # # PROTECTED REGION END # // SKASubarray.test_properties - """Test the Tango device properties of this subarray device""" + """Test the Tango device properties of this subarray device.""" # PROTECTED REGION ID(SKASubarray.test_Abort_decorators) ENABLED START # # PROTECTED REGION END # // SKASubarray.test_Abort_decorators def test_Abort(self, tango_context, tango_change_event_helper): - """Test for Abort""" + """Test for Abort.""" # PROTECTED REGION ID(SKASubarray.test_Abort) ENABLED START # tango_context.device.On() @@ -107,7 +101,7 @@ class TestSKASubarray: # PROTECTED REGION ID(SKASubarray.test_Configure_decorators) ENABLED START # # PROTECTED REGION END # // SKASubarray.test_Configure_decorators def test_Configure(self, tango_context, tango_change_event_helper): - """Test for Configure""" + """Test for Configure.""" # PROTECTED REGION ID(SKASubarray.test_Configure) ENABLED START # tango_context.device.On() tango_context.device.AssignResources(json.dumps(["BAND1"])) @@ -125,7 +119,7 @@ class TestSKASubarray: # PROTECTED REGION ID(SKASubarray.test_GetVersionInfo_decorators) ENABLED START # # PROTECTED REGION END # // SKASubarray.test_GetVersionInfo_decorators def test_GetVersionInfo(self, tango_context): - """Test for GetVersionInfo""" + """Test for GetVersionInfo.""" # PROTECTED REGION ID(SKASubarray.test_GetVersionInfo) ENABLED START # versionPattern = re.compile( f"{tango_context.device.info().dev_class}, ska_tango_base, [0-9]+.[0-9]+.[0-9]+, " @@ -138,7 +132,7 @@ class TestSKASubarray: # PROTECTED REGION ID(SKASubarray.test_Status_decorators) ENABLED START # # PROTECTED REGION END # // SKASubarray.test_Status_decorators def test_Status(self, tango_context): - """Test for Status""" + """Test for Status.""" # PROTECTED REGION ID(SKASubarray.test_Status) ENABLED START # assert tango_context.device.Status() == "The device is in OFF state." # PROTECTED REGION END # // SKASubarray.test_Status @@ -146,7 +140,7 @@ class TestSKASubarray: # PROTECTED REGION ID(SKASubarray.test_State_decorators) ENABLED START # # PROTECTED REGION END # // SKASubarray.test_State_decorators def test_State(self, tango_context): - """Test for State""" + """Test for State.""" # PROTECTED REGION ID(SKASubarray.test_State) ENABLED START # assert tango_context.device.State() == DevState.OFF # PROTECTED REGION END # // SKASubarray.test_State @@ -154,7 +148,7 @@ class TestSKASubarray: # PROTECTED REGION ID(SKASubarray.test_AssignResources_decorators) ENABLED START # # PROTECTED REGION END # // SKASubarray.test_AssignResources_decorators def test_AssignResources(self, tango_context, tango_change_event_helper): - """Test for AssignResources""" + """Test for AssignResources.""" # PROTECTED REGION ID(SKASubarray.test_AssignResources) ENABLED START # tango_context.device.On() @@ -179,7 +173,7 @@ class TestSKASubarray: # PROTECTED REGION ID(SKASubarray.test_EndSB_decorators) ENABLED START # # PROTECTED REGION END # // SKASubarray.test_EndSB_decorators def test_End(self, tango_context, tango_change_event_helper): - """Test for EndSB""" + """Test for EndSB.""" # PROTECTED REGION ID(SKASubarray.test_EndSB) ENABLED START # tango_context.device.On() tango_context.device.AssignResources(json.dumps(["BAND1"])) @@ -199,7 +193,7 @@ class TestSKASubarray: # PROTECTED REGION ID(SKASubarray.test_EndScan_decorators) ENABLED START # # PROTECTED REGION END # // SKASubarray.test_EndScan_decorators def test_EndScan(self, tango_context, tango_change_event_helper): - """Test for EndScan""" + """Test for EndScan.""" # PROTECTED REGION ID(SKASubarray.test_EndScan) ENABLED START # tango_context.device.On() tango_context.device.AssignResources(json.dumps(["BAND1"])) @@ -221,7 +215,7 @@ class TestSKASubarray: # PROTECTED REGION ID(SKASubarray.test_ReleaseAllResources_decorators) ENABLED START # # PROTECTED REGION END # // SKASubarray.test_ReleaseAllResources_decorators def test_ReleaseAllResources(self, tango_context, tango_change_event_helper): - """Test for ReleaseAllResources""" + """Test for ReleaseAllResources.""" # PROTECTED REGION ID(SKASubarray.test_ReleaseAllResources) ENABLED START # # assert tango_context.device.ReleaseAllResources() == [""] tango_context.device.On() @@ -239,7 +233,7 @@ class TestSKASubarray: # PROTECTED REGION ID(SKASubarray.test_ReleaseResources_decorators) ENABLED START # # PROTECTED REGION END # // SKASubarray.test_ReleaseResources_decorators def test_ReleaseResources(self, tango_context, tango_change_event_helper): - """Test for ReleaseResources""" + """Test for ReleaseResources.""" # PROTECTED REGION ID(SKASubarray.test_ReleaseResources) ENABLED START # tango_context.device.On() tango_context.device.AssignResources(json.dumps(["BAND1", "BAND2"])) @@ -257,7 +251,7 @@ class TestSKASubarray: # PROTECTED REGION ID(SKASubarray.test_Reset_decorators) ENABLED START # # PROTECTED REGION END # // SKASubarray.test_Reset_decorators def test_ObsReset(self, tango_context, tango_change_event_helper): - """Test for Reset""" + """Test for Reset.""" # PROTECTED REGION ID(SKASubarray.test_Reset) ENABLED START # tango_context.device.On() tango_context.device.AssignResources(json.dumps(["BAND1"])) @@ -279,7 +273,7 @@ class TestSKASubarray: # PROTECTED REGION ID(SKASubarray.test_Scan_decorators) ENABLED START # # PROTECTED REGION END # // SKASubarray.test_Scan_decorators def test_Scan(self, tango_context, tango_change_event_helper): - """Test for Scan""" + """Test for Scan.""" # PROTECTED REGION ID(SKASubarray.test_Scan) ENABLED START # tango_context.device.On() tango_context.device.AssignResources(json.dumps(["BAND1"])) @@ -304,7 +298,7 @@ class TestSKASubarray: # PROTECTED REGION ID(SKASubarray.test_activationTime_decorators) ENABLED START # # PROTECTED REGION END # // SKASubarray.test_activationTime_decorators def test_activationTime(self, tango_context): - """Test for activationTime""" + """Test for activationTime.""" # PROTECTED REGION ID(SKASubarray.test_activationTime) ENABLED START # assert tango_context.device.activationTime == 0.0 # PROTECTED REGION END # // SKASubarray.test_activationTime @@ -312,7 +306,7 @@ class TestSKASubarray: # PROTECTED REGION ID(SKASubarray.test_adminMode_decorators) ENABLED START # # PROTECTED REGION END # // SKASubarray.test_adminMode_decorators def test_adminMode(self, tango_context, tango_change_event_helper): - """Test for adminMode""" + """Test for adminMode.""" # PROTECTED REGION ID(SKASubarray.test_adminMode) ENABLED START # device_under_test = tango_context.device assert device_under_test.state() == DevState.OFF @@ -339,7 +333,7 @@ class TestSKASubarray: # PROTECTED REGION ID(SKASubarray.test_buildState_decorators) ENABLED START # # PROTECTED REGION END # // SKASubarray.test_buildState_decorators def test_buildState(self, tango_context): - """Test for buildState""" + """Test for buildState.""" # PROTECTED REGION ID(SKASubarray.test_buildState) ENABLED START # buildPattern = re.compile( r"ska_tango_base, [0-9]+.[0-9]+.[0-9]+, " @@ -351,7 +345,7 @@ class TestSKASubarray: # PROTECTED REGION ID(SKASubarray.test_configurationDelayExpected_decorators) ENABLED START # # PROTECTED REGION END # // SKASubarray.test_configurationDelayExpected_decorators def test_configurationDelayExpected(self, tango_context): - """Test for configurationDelayExpected""" + """Test for configurationDelayExpected.""" # PROTECTED REGION ID(SKASubarray.test_configurationDelayExpected) ENABLED START # assert tango_context.device.configurationDelayExpected == 0 # PROTECTED REGION END # // SKASubarray.test_configurationDelayExpected @@ -359,7 +353,7 @@ class TestSKASubarray: # PROTECTED REGION ID(SKASubarray.test_configurationProgress_decorators) ENABLED START # # PROTECTED REGION END # // SKASubarray.test_configurationProgress_decorators def test_configurationProgress(self, tango_context): - """Test for configurationProgress""" + """Test for configurationProgress.""" # PROTECTED REGION ID(SKASubarray.test_configurationProgress) ENABLED START # assert tango_context.device.configurationProgress == 0 # PROTECTED REGION END # // SKASubarray.test_configurationProgress @@ -367,7 +361,7 @@ class TestSKASubarray: # PROTECTED REGION ID(SKASubarray.test_controlMode_decorators) ENABLED START # # PROTECTED REGION END # // SKASubarray.test_controlMode_decorators def test_controlMode(self, tango_context): - """Test for controlMode""" + """Test for controlMode.""" # PROTECTED REGION ID(SKASubarray.test_controlMode) ENABLED START # assert tango_context.device.controlMode == ControlMode.REMOTE # PROTECTED REGION END # // SKASubarray.test_controlMode @@ -375,7 +369,7 @@ class TestSKASubarray: # PROTECTED REGION ID(SKASubarray.test_healthState_decorators) ENABLED START # # PROTECTED REGION END # // SKASubarray.test_healthState_decorators def test_healthState(self, tango_context): - """Test for healthState""" + """Test for healthState.""" # PROTECTED REGION ID(SKASubarray.test_healthState) ENABLED START # assert tango_context.device.healthState == HealthState.OK # PROTECTED REGION END # // SKASubarray.test_healthState @@ -383,7 +377,7 @@ class TestSKASubarray: # PROTECTED REGION ID(SKASubarray.test_obsMode_decorators) ENABLED START # # PROTECTED REGION END # // SKASubarray.test_obsMode_decorators def test_obsMode(self, tango_context): - """Test for obsMode""" + """Test for obsMode.""" # PROTECTED REGION ID(SKASubarray.test_obsMode) ENABLED START # assert tango_context.device.obsMode == ObsMode.IDLE # PROTECTED REGION END # // SKASubarray.test_obsMode @@ -391,7 +385,7 @@ class TestSKASubarray: # PROTECTED REGION ID(SKASubarray.test_obsState_decorators) ENABLED START # # PROTECTED REGION END # // SKASubarray.test_obsState_decorators def test_obsState(self, tango_context): - """Test for obsState""" + """Test for obsState.""" # PROTECTED REGION ID(SKASubarray.test_obsState) ENABLED START # assert tango_context.device.obsState == ObsState.EMPTY # PROTECTED REGION END # // SKASubarray.test_obsState @@ -399,7 +393,7 @@ class TestSKASubarray: # PROTECTED REGION ID(SKASubarray.test_simulationMode_decorators) ENABLED START # # PROTECTED REGION END # // SKASubarray.test_simulationMode_decorators def test_simulationMode(self, tango_context): - """Test for simulationMode""" + """Test for simulationMode.""" # PROTECTED REGION ID(SKASubarray.test_simulationMode) ENABLED START # assert tango_context.device.simulationMode == SimulationMode.FALSE # PROTECTED REGION END # // SKASubarray.test_simulationMode @@ -407,7 +401,7 @@ class TestSKASubarray: # PROTECTED REGION ID(SKASubarray.test_testMode_decorators) ENABLED START # # PROTECTED REGION END # // SKASubarray.test_testMode_decorators def test_testMode(self, tango_context): - """Test for testMode""" + """Test for testMode.""" # PROTECTED REGION ID(SKASubarray.test_testMode) ENABLED START # assert tango_context.device.testMode == TestMode.NONE # PROTECTED REGION END # // SKASubarray.test_testMode @@ -415,7 +409,7 @@ class TestSKASubarray: # PROTECTED REGION ID(SKASubarray.test_versionId_decorators) ENABLED START # # PROTECTED REGION END # // SKASubarray.test_versionId_decorators def test_versionId(self, tango_context): - """Test for versionId""" + """Test for versionId.""" # PROTECTED REGION ID(SKASubarray.test_versionId) ENABLED START # versionIdPattern = re.compile(r"[0-9]+.[0-9]+.[0-9]+") assert (re.match(versionIdPattern, tango_context.device.versionId)) is not None @@ -424,7 +418,7 @@ class TestSKASubarray: # PROTECTED REGION ID(SKASubarray.test_assignedResources_decorators) ENABLED START # # PROTECTED REGION END # // SKASubarray.test_assignedResources_decorators def test_assignedResources(self, tango_context): - """Test for assignedResources""" + """Test for assignedResources.""" # PROTECTED REGION ID(SKASubarray.test_assignedResources) ENABLED START # tango_context.device.On() assert tango_context.device.assignedResources is None @@ -433,7 +427,7 @@ class TestSKASubarray: # PROTECTED REGION ID(SKASubarray.test_configuredCapabilities_decorators) ENABLED START # # PROTECTED REGION END # // SKASubarray.test_configuredCapabilities_decorators def test_configuredCapabilities(self, tango_context): - """Test for configuredCapabilities""" + """Test for configuredCapabilities.""" # PROTECTED REGION ID(SKASubarray.test_configuredCapabilities) ENABLED START # tango_context.device.On() assert tango_context.device.configuredCapabilities == ("BAND1:0", "BAND2:0") @@ -441,28 +435,22 @@ class TestSKASubarray: class TestSKASubarray_commands: - """ - This class contains tests of SKASubarray commands - """ + """This class contains tests of SKASubarray commands.""" @pytest.fixture def op_state_model(self, logger): - """ - Yields a new OpStateModel for testing - """ + """Yield a new OpStateModel for testing.""" yield OpStateModel(logger) @pytest.fixture def subarray_state_model(self, logger): - """ - Yields a new SubarrayObsStateModel for testing - """ + """Yield a new SubarrayObsStateModel for testing.""" yield SubarrayObsStateModel(logger) @pytest.fixture() def component_manager(self, op_state_model, subarray_state_model, logger, mocker): """ - Fixture that returns the component manager under test + Fixture that returns the component manager under test. :param mock_op_state_model: a mock state model for testing :param logger: a logger for the component manager @@ -477,9 +465,7 @@ class TestSKASubarray_commands: def test_AssignCommand( self, component_manager, op_state_model, subarray_state_model ): - """ - Test for SKASubarray.AssignResourcesCommand - """ + """Test for SKASubarray.AssignResourcesCommand.""" op_state_model._straight_to_state("DISABLE") component_manager.start_communicating() component_manager.on() diff --git a/tests/test_tel_state_device.py b/tests/test_tel_state_device.py index c5c987a571d3badb631a7431fd14bf07bae2494c..4055e81afe851fe1f0dc8d140ca87aa54b28b282 100644 --- a/tests/test_tel_state_device.py +++ b/tests/test_tel_state_device.py @@ -30,15 +30,15 @@ from ska_tango_base.control_model import ( @pytest.mark.usefixtures("tango_context", "initialize_device") # PROTECTED REGION END # // SKATelState.test_SKATelState_decorators class TestSKATelState(object): - """ - Test class for tests of the SKATelState device class. - """ + """Test class for tests of the SKATelState device class.""" @pytest.fixture(scope="class") def device_test_config(self, device_properties): """ - Fixture that specifies the device to be tested, along with its - properties and memorized attributes. + Specification of the device under test. + + The specification includes the device's properties and memorized + attributes. """ return { "device": SKATelState, @@ -51,7 +51,7 @@ class TestSKATelState(object): @pytest.mark.skip("Not implemented") def test_properties(self, tango_context): - # Test the properties + """Test device properties.""" # PROTECTED REGION ID(SKATelState.test_properties) ENABLED START # # PROTECTED REGION END # // SKATelState.test_properties pass @@ -59,7 +59,7 @@ class TestSKATelState(object): # PROTECTED REGION ID(SKATelState.test_State_decorators) ENABLED START # # PROTECTED REGION END # // SKATelState.test_State_decorators def test_State(self, tango_context): - """Test for State""" + """Test for State.""" # PROTECTED REGION ID(SKATelState.test_State) ENABLED START # assert tango_context.device.State() == DevState.OFF # PROTECTED REGION END # // SKATelState.test_State @@ -67,7 +67,7 @@ class TestSKATelState(object): # PROTECTED REGION ID(SKATelState.test_Status_decorators) ENABLED START # # PROTECTED REGION END # // SKATelState.test_Status_decorators def test_Status(self, tango_context): - """Test for Status""" + """Test for Status.""" # PROTECTED REGION ID(SKATelState.test_Status) ENABLED START # assert tango_context.device.Status() == "The device is in OFF state." # PROTECTED REGION END # // SKATelState.test_Status @@ -75,7 +75,7 @@ class TestSKATelState(object): # PROTECTED REGION ID(SKATelState.test_GetVersionInfo_decorators) ENABLED START # # PROTECTED REGION END # // SKATelState.test_GetVersionInfo_decorators def test_GetVersionInfo(self, tango_context): - """Test for GetVersionInfo""" + """Test for GetVersionInfo.""" # PROTECTED REGION ID(SKATelState.test_GetVersionInfo) ENABLED START # versionPattern = re.compile( f"{tango_context.device.info().dev_class}, ska_tango_base, [0-9]+.[0-9]+.[0-9]+, " @@ -88,7 +88,7 @@ class TestSKATelState(object): # PROTECTED REGION ID(SKATelState.test_buildState_decorators) ENABLED START # # PROTECTED REGION END # // SKATelState.test_buildState_decorators def test_buildState(self, tango_context): - """Test for buildState""" + """Test for buildState.""" # PROTECTED REGION ID(SKATelState.test_buildState) ENABLED START # buildPattern = re.compile( r"ska_tango_base, [0-9]+.[0-9]+.[0-9]+, " @@ -100,7 +100,7 @@ class TestSKATelState(object): # PROTECTED REGION ID(SKATelState.test_versionId_decorators) ENABLED START # # PROTECTED REGION END # // SKATelState.test_versionId_decorators def test_versionId(self, tango_context): - """Test for versionId""" + """Test for versionId.""" # PROTECTED REGION ID(SKATelState.test_versionId) ENABLED START # versionIdPattern = re.compile(r"[0-9]+.[0-9]+.[0-9]+") assert (re.match(versionIdPattern, tango_context.device.versionId)) is not None @@ -109,7 +109,7 @@ class TestSKATelState(object): # PROTECTED REGION ID(SKATelState.test_healthState_decorators) ENABLED START # # PROTECTED REGION END # // SKATelState.test_healthState_decorators def test_healthState(self, tango_context): - """Test for healthState""" + """Test for healthState.""" # PROTECTED REGION ID(SKATelState.test_healthState) ENABLED START # assert tango_context.device.healthState == HealthState.OK # PROTECTED REGION END # // SKATelState.test_healthState @@ -117,7 +117,7 @@ class TestSKATelState(object): # PROTECTED REGION ID(SKATelState.test_adminMode_decorators) ENABLED START # # PROTECTED REGION END # // SKATelState.test_adminMode_decorators def test_adminMode(self, tango_context): - """Test for adminMode""" + """Test for adminMode.""" # PROTECTED REGION ID(SKATelState.test_adminMode) ENABLED START # assert tango_context.device.adminMode == AdminMode.ONLINE # PROTECTED REGION END # // SKATelState.test_adminMode @@ -125,7 +125,7 @@ class TestSKATelState(object): # PROTECTED REGION ID(SKATelState.test_controlMode_decorators) ENABLED START # # PROTECTED REGION END # // SKATelState.test_controlMode_decorators def test_controlMode(self, tango_context): - """Test for controlMode""" + """Test for controlMode.""" # PROTECTED REGION ID(SKATelState.test_controlMode) ENABLED START # assert tango_context.device.controlMode == ControlMode.REMOTE # PROTECTED REGION END # // SKATelState.test_controlMode @@ -133,7 +133,7 @@ class TestSKATelState(object): # PROTECTED REGION ID(SKATelState.test_simulationMode_decorators) ENABLED START # # PROTECTED REGION END # // SKATelState.test_simulationMode_decorators def test_simulationMode(self, tango_context): - """Test for simulationMode""" + """Test for simulationMode.""" # PROTECTED REGION ID(SKATelState.test_simulationMode) ENABLED START # assert tango_context.device.simulationMode == SimulationMode.FALSE # PROTECTED REGION END # // SKATelState.test_simulationMode @@ -141,7 +141,7 @@ class TestSKATelState(object): # PROTECTED REGION ID(SKATelState.test_testMode_decorators) ENABLED START # # PROTECTED REGION END # // SKATelState.test_testMode_decorators def test_testMode(self, tango_context): - """Test for testMode""" + """Test for testMode.""" # PROTECTED REGION ID(SKATelState.test_testMode) ENABLED START # assert tango_context.device.testMode == TestMode.NONE # PROTECTED REGION END # // SKATelState.test_testMode diff --git a/tests/test_utils.py b/tests/test_utils.py index 80829884ad1cc0ec10ffed1c34b08ca3f3681ff8..a27e644172833edef179dd820e8cf541fa61ba3d 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -117,7 +117,7 @@ BAD_GROUP_KEYS = [ def _jsonify_group_configs(group_configs): - """Returns list of JSON definitions for groups.""" + """Return a list of JSON definitions for groups.""" definitions = [] for group_config in group_configs: definitions.append(json.dumps(group_config)) @@ -125,7 +125,7 @@ def _jsonify_group_configs(group_configs): def _get_group_configs_from_keys(group_keys): - """Provides list of group configs based on keys for TEST_GROUPS.""" + """Provide list of group configs based on keys for TEST_GROUPS.""" group_configs = [] for group_key in group_keys: group_config = TEST_GROUPS[group_key] @@ -134,23 +134,28 @@ def _get_group_configs_from_keys(group_keys): def _group_id_name(keys): - """Helper function to give tests nicer names.""" + """ + Return a comma-separated string of keys. + + This is a helper function to give tests nicer names. + """ return ",".join(keys) @pytest.fixture(scope="module", params=VALID_GROUP_KEYS, ids=_group_id_name) def valid_group_configs(request): - """Provides valid lists of groups configs, one at a time.""" + """Provide valid lists of groups configs, one at a time.""" return _get_group_configs_from_keys(request.param) @pytest.fixture(scope="module", params=BAD_GROUP_KEYS, ids=_group_id_name) def bad_group_configs(request): - """Provides bad lists of groups configs, one at a time.""" + """Provide bad lists of groups configs, one at a time.""" return _get_group_configs_from_keys(request.param) def test_get_groups_from_json_empty_list(): + """Test the ``get_groups_from_json`` helper functions handling of empty input.""" groups = get_groups_from_json([]) assert groups == {} # empty or whitespace strings should also be ignored @@ -181,6 +186,7 @@ def _validate_group(definition, group): def test_get_groups_from_json_valid(valid_group_configs): + """Test the ``get_groups_from_json`` helper function's handling of valid input.""" json_definitions = _jsonify_group_configs(valid_group_configs) groups = get_groups_from_json(json_definitions) @@ -193,12 +199,14 @@ def test_get_groups_from_json_valid(valid_group_configs): def test_get_groups_from_json_invalid(bad_group_configs): + """Test the ``get_groups_from_json`` helper function's handling of invalid input.""" json_definitions = _jsonify_group_configs(bad_group_configs) with pytest.raises(GroupDefinitionsError): get_groups_from_json(json_definitions) def test_get_tango_device_type_id(): + """Test the ``get_tango_device_type_id`` helper function.""" device_name = "domain/family/member" result = get_tango_device_type_id(device_name) assert result == ["family", "member"] @@ -218,13 +226,19 @@ def test_get_tango_device_type_id(): ) def test_for_testing_only(in_test, context): """ - Test the @for_testing_only decorator, to ensure that a warning is raised if and only - if we are NOT testing. This is achieved by patching the test, which cannot be done - using the @decorator syntax. + Test the @for_testing_only decorator. + + Test that a warning is raised if and only if we are NOT testing. + This is achieved by patching the test, which cannot be done using + the ``@decorator`` syntax. """ def foo(): - """Dummy function for wrapping by decorator under test.""" + """ + Return a known value. + + This is a dummy function for the decorator under test to wrap. + """ return "foo" foo = for_testing_only(foo, _testing_check=lambda: in_test) @@ -234,13 +248,15 @@ def test_for_testing_only(in_test, context): def test_for_testing_only_decorator(): - """ - Test the unpatched for_testing_only decorator using the usual @decorator syntax - """ + """Test the for_testing_only decorator using the usual @decorator syntax.""" @for_testing_only def bah(): - """Dummy function for wrapping by decorator under test.""" + """ + Return a known value. + + This is a dummy function for the decorator under test to wrap. + """ return "bah" with pytest.warns(None) as warning_record: