Extracted handler result normalization and added tests for it

Caught some more bugs while doing that.
This commit is contained in:
Gina Häußge 2016-01-05 17:46:52 +01:00 committed by Gina Häußge
parent 53bfbf5acf
commit 7b5848b9c3

View file

@ -2204,7 +2204,7 @@ class MachineCom(object):
except:
self._logger.exception("Error while processing hook {name} for phase {phase} and command {command}:".format(**locals()))
else:
normalized = self._handle_command_handler_result(command, command_type, gcode, hook_results)
normalized = _normalize_command_handler_result(command, command_type, gcode, hook_results)
# make sure we don't allow multi entry results in sending and sent phase
if phase in ("sending", "sent") and len(normalized) > 1:
@ -2224,7 +2224,7 @@ class MachineCom(object):
gcode_handler = "_gcode_" + gcode + "_" + phase
if hasattr(self, gcode_handler):
handler_results = getattr(self, gcode_handler)(command, cmd_type=command_type)
new_results += self._handle_command_handler_result(command, command_type, gcode, handler_results)
new_results += _normalize_command_handler_result(command, command_type, gcode, handler_results)
else:
new_results.append((command, command_type, gcode))
if not new_results:
@ -2238,98 +2238,12 @@ class MachineCom(object):
new_results = []
for command, command_type, gcode in results:
handler_results = getattr(self, command_phase_handler)(command, cmd_type=command_type, gcode=gcode)
new_results += self._handle_command_handler_result(command, command_type, gcode, handler_results)
new_results += _normalize_command_handler_result(command, command_type, gcode, handler_results)
results = new_results
# finally return whatever we resulted on
return results
def _handle_command_handler_result(self, command, command_type, gcode, handler_results):
"""
Normalizes a command handler results.
Handler results can be either ``None``, a single result entry or a list of result
entries.
``None`` results are ignored, the provided ``command``, ``command_type``
and ``gcode`` are returned in that case (as single-entry list with one
3-tuple as entry).
Single result entries are either:
* a single string defining a replacement ``command``
* a 1-tuple defining a replacement ``command``
* a 2-tuple defining a replacement ``command`` and ``command_type``
A ``command`` that is ``None`` will lead to the entry being ignored for
the normalized result.
The method returns a list of normalized result entries. Normalized result
entries always are a 3-tuple consisting of ``command``, ``command_type``
and ``gcode``, the latter two being allowed to be ``None``. The list may
be empty in which case the command is to be suppressed.
Parameters:
command (str or None): The command for which the handler result was
generated
command_type (str or None): The command type for which the handler
result was generated
gcode (str or None): The GCODE for which the handler result was
generated
handler_results: The handler result(s) to normalized. Can be either
a single result entry or a list of result entries.
Returns:
(list) - A list of normalized handler result entries, which are
3-tuples consisting of ``command``, ``command_type`` and
``gcode``, the latter two of which may be ``None``.
"""
if handler_results is None:
# handler didn't return anything, we'll just continue
return [(command, command_type, gcode)]
if not isinstance(handler_results, list):
handler_results = [handler_results,]
result = []
for handler_result in handler_results:
# we iterate over all handler result entries and process each one
# individually here
if handler_result is None:
# entry is None, we'll ignore that entry and continue
continue
if isinstance(handler_result, basestring):
# entry is just a string, replace command with it
command = handler_result
gcode = gcode_command_for_cmd(command)
result.append((command, command_type, gcode))
elif isinstance(handler_result, tuple):
# entry is a tuple, extract command and command_type
hook_result_length = len(handler_results)
if hook_result_length == 1:
# handler returned just the command
command, = handler_results
elif hook_result_length == 2:
# handler returned command and command_type
command, command_type = handler_results
else:
# handler returned a tuple of an unexpected length, ignore
# and continue
continue
if command is None:
# command is None, ignore it and continue
continue
gcode = gcode_command_for_cmd(command)
result.append((command, command_type, gcode))
return result
##~~ actual sending via serial
def _do_increment_and_send_with_checksum(self, cmd):
@ -3210,6 +3124,120 @@ def gcode_command_for_cmd(cmd):
return None
def _normalize_command_handler_result(command, command_type, gcode, handler_results):
"""
Normalizes a command handler result.
Handler results can be either ``None``, a single result entry or a list of result
entries.
``None`` results are ignored, the provided ``command``, ``command_type``
and ``gcode`` are returned in that case (as single-entry list with one
3-tuple as entry).
Single result entries are either:
* a single string defining a replacement ``command``
* a 1-tuple defining a replacement ``command``
* a 2-tuple defining a replacement ``command`` and ``command_type``
A ``command`` that is ``None`` will lead to the entry being ignored for
the normalized result.
The method returns a list of normalized result entries. Normalized result
entries always are a 3-tuple consisting of ``command``, ``command_type``
and ``gcode``, the latter two being allowed to be ``None``. The list may
be empty in which case the command is to be suppressed.
Examples:
>>> _normalize_command_handler_result("M105", None, "M105", None)
[('M105', None, 'M105')]
>>> _normalize_command_handler_result("M105", None, "M105", "M110")
[('M110', None, 'M110')]
>>> _normalize_command_handler_result("M105", None, "M105", ["M110"])
[('M110', None, 'M110')]
>>> _normalize_command_handler_result("M105", None, "M105", ["M110", "M117 Foobar"])
[('M110', None, 'M110'), ('M117 Foobar', None, 'M117')]
>>> _normalize_command_handler_result("M105", None, "M105", [("M110",), "M117 Foobar"])
[('M110', None, 'M110'), ('M117 Foobar', None, 'M117')]
>>> _normalize_command_handler_result("M105", None, "M105", [("M110", "lineno_reset"), "M117 Foobar"])
[('M110', 'lineno_reset', 'M110'), ('M117 Foobar', None, 'M117')]
>>> _normalize_command_handler_result("M105", None, "M105", [])
[]
>>> _normalize_command_handler_result("M105", None, "M105", ["M110", None])
[('M110', None, 'M110')]
>>> _normalize_command_handler_result("M105", None, "M105", [("M110",), (None, "ignored")])
[('M110', None, 'M110')]
>>> _normalize_command_handler_result("M105", None, "M105", [("M110",), ("M117 Foobar", "display_message"), ("tuple", "of unexpected", "length"), ("M110", "lineno_reset")])
[('M110', None, 'M110'), ('M117 Foobar', 'display_message', 'M117'), ('M110', 'lineno_reset', 'M110')]
Arguments:
command (str or None): The command for which the handler result was
generated
command_type (str or None): The command type for which the handler
result was generated
gcode (str or None): The GCODE for which the handler result was
generated
handler_results: The handler result(s) to normalized. Can be either
a single result entry or a list of result entries.
Returns:
(list) - A list of normalized handler result entries, which are
3-tuples consisting of ``command``, ``command_type`` and
``gcode``, the latter two of which may be ``None``.
"""
original = (command, command_type, gcode)
if handler_results is None:
# handler didn't return anything, we'll just continue
return [original]
if not isinstance(handler_results, list):
handler_results = [handler_results,]
result = []
for handler_result in handler_results:
# we iterate over all handler result entries and process each one
# individually here
if handler_result is None:
# entry is None, we'll ignore that entry and continue
continue
if isinstance(handler_result, basestring):
# entry is just a string, replace command with it
command = handler_result
gcode = gcode_command_for_cmd(command)
result.append((command, command_type, gcode))
elif isinstance(handler_result, tuple):
# entry is a tuple, extract command and command_type
hook_result_length = len(handler_result)
if hook_result_length == 1:
# handler returned just the command
command, = handler_result
elif hook_result_length == 2:
# handler returned command and command_type
command, command_type = handler_result
else:
# handler returned a tuple of an unexpected length, ignore
# and continue
continue
if command is None:
# command is None, ignore it and continue
continue
gcode = gcode_command_for_cmd(command)
result.append((command, command_type, gcode))
# reset to original
command, command_type, gcode = original
return result
# --- Test code for speed testing the comm layer via command line follows