prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Attaching binary file using test.attach raises UnicodeDecodeError
  If I attach a png or avi I see the following in OutputTestRecord
  
  Python2.7/site-packages/openhtf/**init**.py", line 185, in OutputTestRecord
      output_cb(test_record)
    File "virtualenv/local/lib/python2.7/site-packages/openhtf/**init**.py", line 83, in **call**
      f.write(self.encode(as_dict))
    File "/usr/lib/python2.7/json/encoder.py", line 209, in encode
      chunks = list(chunks)
    File "/usr/lib/python2.7/json/encoder.py", line 434, in _iterencode
      for chunk in _iterencode_dict(o, _current_indent_level):
    File "/usr/lib/python2.7/json/encoder.py", line 408, in _iterencode_dict
      for chunk in chunks:
    File "/usr/lib/python2.7/json/encoder.py", line 332, in _iterencode_list
      for chunk in chunks:
    File "/usr/lib/python2.7/json/encoder.py", line 408, in _iterencode_dict
      for chunk in chunks:
    File "/usr/lib/python2.7/json/encoder.py", line 408, in _iterencode_dict
      for chunk in chunks:
    File "/usr/lib/python2.7/json/encoder.py", line 390, in _iterencode_dict
      yield _encoder(value)
  UnicodeDecodeError: 'utf8' codec can't decode byte 0x89 in position 0: invalid start byte
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `openhtf/io/output/json_factory.py`
  Content:
  ```
  1 """Module for outputting test record to JSON-formatted files."""
  2 
  3 from json import JSONEncoder
  4 
  5 from openhtf import util
  6 from openhtf.exe import test_state
  7 
  8 
  9 class OutputToJSON(JSONEncoder):
  10   """Return an output callback that writes JSON Test Records.
  11 
  12   An example filename_pattern might be:
  13     '/data/test_records/%(dut_id)s.%(start_time_millis)s'
  14 
  15   To use this output mechanism:
  16     test = openhtf.Test(PhaseOne, PhaseTwo)
  17     test.AddOutputCallback(openhtf.OutputToJson(
  18         '/data/test_records/%(dut_id)s.%(start_time_millis)s'))
  19 
  20   Args:
  21     filename_pattern: A format string specifying the filename to write to,
  22       will be formatted with the Test Record as a dictionary.
  23     inline_attachments: Whether attachments should be included inline in the
  24       output.  Set to False if you expect to have large binary attachments.
  25   """
  26 
  27   def __init__(self, filename_pattern=None, inline_attachments=True, **kwargs):
  28     super(OutputToJSON, self).__init__(**kwargs)
  29     self.filename_pattern = filename_pattern
  30     self.inline_attachments = inline_attachments
  31 
  32   def default(self, obj):
  33     if isinstance(obj, BaseException):
  34       # Just repr exceptions.
  35       return repr(obj)
  36     return super(OutputToJSON, self).default(obj)
  37 
  38   # pylint: disable=invalid-name
  39   def __call__(self, test_record):
  40     assert self.filename_pattern, 'filename_pattern required'
  41     if self.inline_attachments:
  42       as_dict = util.ConvertToBaseTypes(test_record)
  43     else:
  44       as_dict = util.ConvertToBaseTypes(test_record, ignore_keys='attachments')
  45     with open(self.filename_pattern % as_dict, 'w') as f:
  46       f.write(self.encode(as_dict))
  47   # pylint: enable=invalid-name
  48
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/openhtf/io/output/json_factory.py b/openhtf/io/output/json_factory.py
  --- a/openhtf/io/output/json_factory.py
  +++ b/openhtf/io/output/json_factory.py
  @@ -1,5 +1,6 @@
   """Module for outputting test record to JSON-formatted files."""
   
  +import base64
   from json import JSONEncoder
   
   from openhtf import util
  @@ -21,7 +22,9 @@
       filename_pattern: A format string specifying the filename to write to,
         will be formatted with the Test Record as a dictionary.
       inline_attachments: Whether attachments should be included inline in the
  -      output.  Set to False if you expect to have large binary attachments.
  +      output. Set to False if you expect to have large binary attachments. If
  +      True (the default), then attachments are base64 encoded to allow for
  +      binary data that's not supported by JSON directly.
     """
   
     def __init__(self, filename_pattern=None, inline_attachments=True, **kwargs):
  @@ -40,6 +43,9 @@
       assert self.filename_pattern, 'filename_pattern required'
       if self.inline_attachments:
         as_dict = util.ConvertToBaseTypes(test_record)
  +      for phase in as_dict['phases']:
  +        for value in phase['attachments'].itervalues():
  +          value['data'] = base64.standard_b64encode(value['data'])
       else:
         as_dict = util.ConvertToBaseTypes(test_record, ignore_keys='attachments')
       with open(self.filename_pattern % as_dict, 'w') as f:
  
verification_info: {"golden_diff": "diff --git a/openhtf/io/output/json_factory.py b/openhtf/io/output/json_factory.py\n--- a/openhtf/io/output/json_factory.py\n+++ b/openhtf/io/output/json_factory.py\n@@ -1,5 +1,6 @@\n \"\"\"Module for outputting test record to JSON-formatted files.\"\"\"\n \n+import base64\n from json import JSONEncoder\n \n from openhtf import util\n@@ -21,7 +22,9 @@\n     filename_pattern: A format string specifying the filename to write to,\n       will be formatted with the Test Record as a dictionary.\n     inline_attachments: Whether attachments should be included inline in the\n-      output.  Set to False if you expect to have large binary attachments.\n+      output. Set to False if you expect to have large binary attachments. If\n+      True (the default), then attachments are base64 encoded to allow for\n+      binary data that's not supported by JSON directly.\n   \"\"\"\n \n   def __init__(self, filename_pattern=None, inline_attachments=True, **kwargs):\n@@ -40,6 +43,9 @@\n     assert self.filename_pattern, 'filename_pattern required'\n     if self.inline_attachments:\n       as_dict = util.ConvertToBaseTypes(test_record)\n+      for phase in as_dict['phases']:\n+        for value in phase['attachments'].itervalues():\n+          value['data'] = base64.standard_b64encode(value['data'])\n     else:\n       as_dict = util.ConvertToBaseTypes(test_record, ignore_keys='attachments')\n     with open(self.filename_pattern % as_dict, 'w') as f:\n", "issue": "Attaching binary file using test.attach raises UnicodeDecodeError\nIf I attach a png or avi I see the following in OutputTestRecord\n\nPython2.7/site-packages/openhtf/**init**.py\", line 185, in OutputTestRecord\n    output_cb(test_record)\n  File \"virtualenv/local/lib/python2.7/site-packages/openhtf/**init**.py\", line 83, in **call**\n    f.write(self.encode(as_dict))\n  File \"/usr/lib/python2.7/json/encoder.py\", line 209, in encode\n    chunks = list(chunks)\n  File \"/usr/lib/python2.7/json/encoder.py\", line 434, in _iterencode\n    for chunk in _iterencode_dict(o, _current_indent_level):\n  File \"/usr/lib/python2.7/json/encoder.py\", line 408, in _iterencode_dict\n    for chunk in chunks:\n  File \"/usr/lib/python2.7/json/encoder.py\", line 332, in _iterencode_list\n    for chunk in chunks:\n  File \"/usr/lib/python2.7/json/encoder.py\", line 408, in _iterencode_dict\n    for chunk in chunks:\n  File \"/usr/lib/python2.7/json/encoder.py\", line 408, in _iterencode_dict\n    for chunk in chunks:\n  File \"/usr/lib/python2.7/json/encoder.py\", line 390, in _iterencode_dict\n    yield _encoder(value)\nUnicodeDecodeError: 'utf8' codec can't decode byte 0x89 in position 0: invalid start byte\n\n", "before_files": [{"content": "\"\"\"Module for outputting test record to JSON-formatted files.\"\"\"\n\nfrom json import JSONEncoder\n\nfrom openhtf import util\nfrom openhtf.exe import test_state\n\n\nclass OutputToJSON(JSONEncoder):\n  \"\"\"Return an output callback that writes JSON Test Records.\n\n  An example filename_pattern might be:\n    '/data/test_records/%(dut_id)s.%(start_time_millis)s'\n\n  To use this output mechanism:\n    test = openhtf.Test(PhaseOne, PhaseTwo)\n    test.AddOutputCallback(openhtf.OutputToJson(\n        '/data/test_records/%(dut_id)s.%(start_time_millis)s'))\n\n  Args:\n    filename_pattern: A format string specifying the filename to write to,\n      will be formatted with the Test Record as a dictionary.\n    inline_attachments: Whether attachments should be included inline in the\n      output.  Set to False if you expect to have large binary attachments.\n  \"\"\"\n\n  def __init__(self, filename_pattern=None, inline_attachments=True, **kwargs):\n    super(OutputToJSON, self).__init__(**kwargs)\n    self.filename_pattern = filename_pattern\n    self.inline_attachments = inline_attachments\n\n  def default(self, obj):\n    if isinstance(obj, BaseException):\n      # Just repr exceptions.\n      return repr(obj)\n    return super(OutputToJSON, self).default(obj)\n\n  # pylint: disable=invalid-name\n  def __call__(self, test_record):\n    assert self.filename_pattern, 'filename_pattern required'\n    if self.inline_attachments:\n      as_dict = util.ConvertToBaseTypes(test_record)\n    else:\n      as_dict = util.ConvertToBaseTypes(test_record, ignore_keys='attachments')\n    with open(self.filename_pattern % as_dict, 'w') as f:\n      f.write(self.encode(as_dict))\n  # pylint: enable=invalid-name\n", "path": "openhtf/io/output/json_factory.py"}], "after_files": [{"content": "\"\"\"Module for outputting test record to JSON-formatted files.\"\"\"\n\nimport base64\nfrom json import JSONEncoder\n\nfrom openhtf import util\nfrom openhtf.exe import test_state\n\n\nclass OutputToJSON(JSONEncoder):\n  \"\"\"Return an output callback that writes JSON Test Records.\n\n  An example filename_pattern might be:\n    '/data/test_records/%(dut_id)s.%(start_time_millis)s'\n\n  To use this output mechanism:\n    test = openhtf.Test(PhaseOne, PhaseTwo)\n    test.AddOutputCallback(openhtf.OutputToJson(\n        '/data/test_records/%(dut_id)s.%(start_time_millis)s'))\n\n  Args:\n    filename_pattern: A format string specifying the filename to write to,\n      will be formatted with the Test Record as a dictionary.\n    inline_attachments: Whether attachments should be included inline in the\n      output. Set to False if you expect to have large binary attachments. If\n      True (the default), then attachments are base64 encoded to allow for\n      binary data that's not supported by JSON directly.\n  \"\"\"\n\n  def __init__(self, filename_pattern=None, inline_attachments=True, **kwargs):\n    super(OutputToJSON, self).__init__(**kwargs)\n    self.filename_pattern = filename_pattern\n    self.inline_attachments = inline_attachments\n\n  def default(self, obj):\n    if isinstance(obj, BaseException):\n      # Just repr exceptions.\n      return repr(obj)\n    return super(OutputToJSON, self).default(obj)\n\n  # pylint: disable=invalid-name\n  def __call__(self, test_record):\n    assert self.filename_pattern, 'filename_pattern required'\n    if self.inline_attachments:\n      as_dict = util.ConvertToBaseTypes(test_record)\n      for phase in as_dict['phases']:\n        for value in phase['attachments'].itervalues():\n          value['data'] = base64.standard_b64encode(value['data'])\n    else:\n      as_dict = util.ConvertToBaseTypes(test_record, ignore_keys='attachments')\n    with open(self.filename_pattern % as_dict, 'w') as f:\n      f.write(self.encode(as_dict))\n  # pylint: enable=invalid-name\n", "path": "openhtf/io/output/json_factory.py"}]}