Skip to content

callbacks.OutputToFile always silently fails #1242

@Sporarum

Description

@Sporarum

When callbacks.OutputToFile is used as a callback, the test passes with no warning, but the output file is not written to.

We can learn more by looking at the log_records object which does log the error: TypeError: a bytes-like object is required, not 'int'.

Example:

import openhtf
from openhtf.output import callbacks

import logging
logger = logging.getLogger(__name__)

line_break = "\n"

test = openhtf.Test()

test.add_output_callbacks(
  callbacks.OutputToFile("./test.pickle"),
  lambda tr: logger.warning(f"{ line_break.join(list(map(lambda lr: lr.message,tr.log_records)))}")
)

test.execute()

Output:

> python main.py
Tearing down all plugs.
Finishing test execution normally with outcome PASS.
Thread finished: TestExecutorThread
DUT ID is still not set; using default.
Test completed for openhtf_test, outputting now.
Output callback <openhtf.output.callbacks.OutputToFile object at 0x103b39a90> raised:
Traceback (most recent call last):
  File "/Users/<user>/Projects/python-tmp/.venv/lib/python3.13/site-packages/openhtf/core/test_descriptor.py", line 355, in execute
    output_cb(final_state.test_record)
    ~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/<user>/Projects/python-tmp/.venv/lib/python3.13/site-packages/openhtf/output/callbacks/__init__.py", line 138, in __call__
    outfile.write(chunk.encode() if isinstance(chunk, str) else chunk)
    ~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/<user>/Projects/python-tmp/.venv/lib/python3.13/site-packages/openhtf/output/callbacks/__init__.py", line 48, in write
    return self.temp.write(write_data)
           ~~~~~~~~~~~~~~~^^^^^^^^^^^^
  File "/opt/homebrew/Cellar/python@3.13/3.13.4/Frameworks/Python.framework/Versions/3.13/lib/python3.13/tempfile.py", line 499, in func_wrapper
    return func(*args, **kwargs)
TypeError: a bytes-like object is required, not 'int'

Continuing anyway...

======================= test: openhtf_test  outcome: PASS ======================

This is caused by the following code in openhtf/output/callbacks/__init__.py:

  def __call__(self, test_rec: test_record.TestRecord) -> None:
    with self.open_output_file(test_rec) as outfile:
      serialized_record = self.serialize_test_record(test_rec)
      if isinstance(serialized_record, str):
        outfile.write(serialized_record.encode())
      elif isinstance(serialized_record, Iterable):
        for chunk in serialized_record:
          outfile.write(chunk.encode() if isinstance(chunk, str) else chunk)
      else:
        raise TypeError('Expected string or iterable but got {}.'.format(
            type(serialized_record)))

serialize_record is a bytes (so an Iterables), but this implies chunk is an int, whereas write expects a bytes

Here is one possible fix:

  def __call__(self, test_rec: test_record.TestRecord) -> None:
    with self.open_output_file(test_rec) as outfile:
      serialized_record = self.serialize_test_record(test_rec)
      if isinstance(serialized_record, str):
        outfile.write(serialized_record.encode())
+     elif isinstance(serialized_record, bytes):
+       outfile.write(serialized_record)
      elif isinstance(serialized_record, Iterable):
        for chunk in serialized_record:
          outfile.write(chunk.encode() if isinstance(chunk, str) else chunk)
      else:
        raise TypeError('Expected string or iterable but got {}.'.format(
            type(serialized_record)))

Which seems to work

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions