Skip to content

Serial Collection Plug#759

Merged
jettisonjoe merged 3 commits intogoogle:masterfrom
maddychan:serial
Apr 19, 2018
Merged

Serial Collection Plug#759
jettisonjoe merged 3 commits intogoogle:masterfrom
maddychan:serial

Conversation

@maddychan
Copy link
Contributor

@maddychan maddychan commented Apr 13, 2018

  • Upstreaming serial collection plug

This change is Reviewable

Copy link
Contributor

@Kenadia Kenadia left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added some minor comments and a question about error handling. Thanks!

Allows for writing out to a serial port.
"""

from contextlib import contextmanager
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: prefer import contextlib

def save_data(self, dest):
"""Save serial data to the named destination while in context.

Spawns a thread that will open the configured serial port, continously
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

continuously

collection_thread.daemon = True
try:
self.logger.debug(
'Starting serial data collection on %s.' % self._serial.port)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit - ...collection on port %s.

yield
except self.SERIAL_EXCEPTIONS:
self.logger.error('Serial port error. Stopping data collection.',
exc_info=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm suspicious of this except clause. It will catch certain errors, including any ValueErrors, that occur in the code managed by this context. But it won't catch errors that occur in the thread. Is that the intention? If so, could you give an example of how this plug is used, and what kind of ValueErrors you're trying to catch? Catching all ValueErrors in the managed block doesn't seem right

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your input! Upon further inspection we decided to retool save_data to start_collection() and stop_collection(), which doesn't use the context manager anymore.


from contextlib import contextmanager
import threading
import serial
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider adding something like

try:
  import serial
except ImportError:
  logging.error('Failed to import pyserial. Please install the `serial_collection_plug` extra, '
                'e.g. via `pip install openhtf[serial_collection_plug]`.')
  raise

I notice we do this for the usb plugs.

Copy link
Contributor

@Kenadia Kenadia left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall LGTM, just a couple more small questions

stop_collection() is called.
"""
SERIAL_EXCEPTIONS = (serial.SerialException,
serial.SerialTimeoutException,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

serial.SerialTimeoutException is a subclass of serial.SerialException so it's not needed here

"""
SERIAL_EXCEPTIONS = (serial.SerialException,
serial.SerialTimeoutException,
ValueError)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could use a comment here explaining what this is intended to catch

not self._collection_thread.is_alive()):
self.logger.warning(
'Data collection was not running, cannot be stopped.')
return
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just some minor observations here. I wonder what an example usage of this API looks like. It looks like the code using this plug can't tell if the thread is still running, so it can't know whether it's appropriate to call stop_collection() or not. Because of this I imagine usage looks like:

try:
  serial_plug.start_collection()
finally:
  serial_plug.stop_collection()

This makes me think we should log an error only if start_collection() was never called, but not if the thread was started and errored out. (The warning would be sort of redundant with the error.) It also makes me wonder why a context manager is no longer used.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, we made the state of collecting available to the test author (is_collecting property)

  - Upstreaming serial collection plug
  - Addressed a couple more nits on documentation and exposing
  thread status.
@jettisonjoe jettisonjoe merged commit 1edf50a into google:master Apr 19, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants