We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Error Attaching Wav Files
using test.AttachFromFile(path_to_wav) results in UnicodeDecodeError: 'utf8' codec can't decode byte 0xa4 in position 5: 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/exe/phase_data.py`
Content:
```
1 # Copyright 2014 Google Inc. All Rights Reserved.
2 
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 
7 #     http://www.apache.org/licenses/LICENSE-2.0
8 
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 
15 
16 """Module encapsulating test phase data.
17 
18 HTF tests are comprised of a series of test phases.  These test phases are
19 wrapped in openhtf.PhaseInfo objects to keep track of some necessary
20 state. This wrapping happens by decorating a method with any of various
21 supported decorators.
22 """
23 
24 import contextlib2
25 import copy
26 import logging
27 import mimetypes
28 
29 import mutablerecords
30 
31 from openhtf import util
32 from openhtf.io import test_record
33 from openhtf.util import measurements
34 
35 _LOG = logging.getLogger(__name__)
36 
37 
38 class DuplicateAttachmentError(Exception):
39   """Raised when two attachments are attached with the same name."""
40 
41 
42 class OutcomeWrapper(mutablerecords.Record(
43     'OutcomeWrapper', [], {'outcome': None})):
44   """Wrapper so yielded object can receive an outcome."""
45   def SetOutcome(self, outcome):
46     self.outcome = outcome
47 
48 
49 class PhaseData(object):  # pylint: disable=too-many-instance-attributes
50   """The phase data object passed to test phases as the first argument.
51 
52   Fields:
53     logger: A python logger that goes to the testrun proto, with functions like
54         debug, info, warn, error, and exception.
55     state: A dictionary for passing state data along to future phases.
56     plug_map: Dict mapping plug types to instances to use in phases.
57     measurements: A measurements.Collection for setting measurement values.
58     context: A contextlib.ExitStack, which simplifies context managers in a
59         phase.  This stack is pop'd after each phase.
60     test_record: The test_record.TestRecord for the currently running test.
61   """
62   def __init__(self, logger, plug_map, record):
63     self.logger = logger
64     self.plug_map = plug_map
65     self.test_record = record
66     self.state = {}
67     self.measurements = None  # Will be populated per-phase.
68     self.attachments = {}
69     self.context = contextlib2.ExitStack()
70 
71   def _asdict(self):
72     """Return a dict of this PhaseData's public data."""
73     return {'measurements': self.measurements,
74             'attachments': self.attachments.keys(),
75             'plugs': {
76                 k.__module__ + '.' + k.__name__: str(v)
77                 for k, v in self.plug_map.iteritems()}}
78 
79   def Attach(self, name, data, mimetype=None):
80     """Store the given data as an attachment with the given name.
81 
82     Args:
83       name: Attachment name under which to store this data.
84       data: Data to attach.
85       mimetype: If provided, will be saved in the attachment.
86 
87     Raises:
88       DuplicateAttachmentError: Raised if there is already an attachment with
89         the given name.
90     """
91     if name in self.attachments:
92       raise DuplicateAttachmentError('Duplicate attachment for %s' % name)
93     if mimetype and not mimetypes.guess_extension(mimetype):
94       _LOG.warning('Unrecognized MIME type: "%s" for attachment "%s"',
95                    mimetype, name)
96     self.attachments[name] = test_record.Attachment(data, mimetype)
97 
98   def AttachFromFile(self, filename, name=None, mimetype=None):
99     """Store the contents of the given filename as an attachment.
100 
101     Args:
102       filename: The file to read data from to attach.
103       name: If provided, override the attachment name, otherwise it will
104         default to the filename.
105       mimetype: If provided, override the attachment mime type, otherwise the
106         mime type will be guessed based on the file extension.
107 
108     Raises:
109       DuplicateAttachmentError: Raised if there is already an attachment with
110         the given name.
111       IOError: Raised if the given filename couldn't be opened.
112     """
113     with open(filename, 'r') as f:  # pylint: disable=invalid-name
114       self.Attach(
115           name if name is not None else filename, f.read(),
116           mimetype=mimetype if mimetype is not None else mimetypes.guess_type(
117               filename)[0])
118 
119   @contextlib2.contextmanager
120   def RecordPhaseTiming(self, phase, test_state):
121     """Context manager for the execution of a single phase."""
122 
123     # Check for measurement descriptors and track them in the PhaseRecord.
124     measurement_map = {
125         measurement.name: copy.deepcopy(measurement)
126         for measurement in phase.measurements
127     }
128 
129     # Populate dummy declaration list for frontend API.
130     test_state.running_phase_record.measurements = {
131         measurement.name: measurement._asdict()
132         for measurement in measurement_map.itervalues()
133     }
134     test_state.phase_data.measurements = (
135         measurements.Collection(measurement_map))
136     test_state.phase_data.attachments = {}
137     test_state.running_phase_record.start_time_millis = util.TimeMillis()
138 
139     outcome_wrapper = OutcomeWrapper()
140 
141     try:
142       yield outcome_wrapper
143     finally:
144       # Serialize measurements and measured values, validate as we go.
145       values = dict(test_state.phase_data.measurements)
146 
147       # Initialize with already-validated and UNSET measurements.
148       validated_measurements = {
149           name: measurement for name, measurement in measurement_map.iteritems()
150           if measurement.outcome is not measurements.Outcome.PARTIALLY_SET
151       }
152 
153       # Validate multi-dimensional measurements now that we have all values.
154       validated_measurements.update({
155           name: measurement.Validate(values[name])
156           for name, measurement in measurement_map.iteritems()
157           if measurement.outcome is measurements.Outcome.PARTIALLY_SET
158       })
159 
160       # Fill out and append the PhaseRecord to our test_record.
161       test_state.running_phase_record.measured_values = values
162       test_state.running_phase_record.measurements = validated_measurements
163       test_state.running_phase_record.end_time_millis = util.TimeMillis()
164       test_state.running_phase_record.result = outcome_wrapper.outcome
165       test_state.running_phase_record.attachments.update(self.attachments)
166       self.test_record.phases.append(test_state.running_phase_record)
167 
168       # Clear these between uses for the frontend API.
169       test_state.phase_data.measurements = None
170       test_state.phase_data.attachments = {}
171       test_state.running_phase_record = None
172
```
--- 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()

```

diff --git a/openhtf/exe/phase_data.py b/openhtf/exe/phase_data.py
--- a/openhtf/exe/phase_data.py
+++ b/openhtf/exe/phase_data.py
@@ -110,7 +110,7 @@
         the given name.
       IOError: Raised if the given filename couldn't be opened.
     """
-    with open(filename, 'r') as f:  # pylint: disable=invalid-name
+    with open(filename, 'rb') as f:  # pylint: disable=invalid-name
       self.Attach(
           name if name is not None else filename, f.read(),
           mimetype=mimetype if mimetype is not None else mimetypes.guess_type(

{"golden_diff": "diff --git a/openhtf/exe/phase_data.py b/openhtf/exe/phase_data.py\n--- a/openhtf/exe/phase_data.py\n+++ b/openhtf/exe/phase_data.py\n@@ -110,7 +110,7 @@\n         the given name.\n       IOError: Raised if the given filename couldn't be opened.\n     \"\"\"\n-    with open(filename, 'r') as f:  # pylint: disable=invalid-name\n+    with open(filename, 'rb') as f:  # pylint: disable=invalid-name\n       self.Attach(\n           name if name is not None else filename, f.read(),\n           mimetype=mimetype if mimetype is not None else mimetypes.guess_type(\n", "issue": "Error Attaching Wav Files\nusing test.AttachFromFile(path_to_wav) results in UnicodeDecodeError: 'utf8' codec can't decode byte 0xa4 in position 5: invalid start byte\n\n", "before_files": [{"content": "# Copyright 2014 Google Inc. All Rights Reserved.\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n\n#     http://www.apache.org/licenses/LICENSE-2.0\n\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n\n\"\"\"Module encapsulating test phase data.\n\nHTF tests are comprised of a series of test phases.  These test phases are\nwrapped in openhtf.PhaseInfo objects to keep track of some necessary\nstate. This wrapping happens by decorating a method with any of various\nsupported decorators.\n\"\"\"\n\nimport contextlib2\nimport copy\nimport logging\nimport mimetypes\n\nimport mutablerecords\n\nfrom openhtf import util\nfrom openhtf.io import test_record\nfrom openhtf.util import measurements\n\n_LOG = logging.getLogger(__name__)\n\n\nclass DuplicateAttachmentError(Exception):\n  \"\"\"Raised when two attachments are attached with the same name.\"\"\"\n\n\nclass OutcomeWrapper(mutablerecords.Record(\n    'OutcomeWrapper', [], {'outcome': None})):\n  \"\"\"Wrapper so yielded object can receive an outcome.\"\"\"\n  def SetOutcome(self, outcome):\n    self.outcome = outcome\n\n\nclass PhaseData(object):  # pylint: disable=too-many-instance-attributes\n  \"\"\"The phase data object passed to test phases as the first argument.\n\n  Fields:\n    logger: A python logger that goes to the testrun proto, with functions like\n        debug, info, warn, error, and exception.\n    state: A dictionary for passing state data along to future phases.\n    plug_map: Dict mapping plug types to instances to use in phases.\n    measurements: A measurements.Collection for setting measurement values.\n    context: A contextlib.ExitStack, which simplifies context managers in a\n        phase.  This stack is pop'd after each phase.\n    test_record: The test_record.TestRecord for the currently running test.\n  \"\"\"\n  def __init__(self, logger, plug_map, record):\n    self.logger = logger\n    self.plug_map = plug_map\n    self.test_record = record\n    self.state = {}\n    self.measurements = None  # Will be populated per-phase.\n    self.attachments = {}\n    self.context = contextlib2.ExitStack()\n\n  def _asdict(self):\n    \"\"\"Return a dict of this PhaseData's public data.\"\"\"\n    return {'measurements': self.measurements,\n            'attachments': self.attachments.keys(),\n            'plugs': {\n                k.__module__ + '.' + k.__name__: str(v)\n                for k, v in self.plug_map.iteritems()}}\n\n  def Attach(self, name, data, mimetype=None):\n    \"\"\"Store the given data as an attachment with the given name.\n\n    Args:\n      name: Attachment name under which to store this data.\n      data: Data to attach.\n      mimetype: If provided, will be saved in the attachment.\n\n    Raises:\n      DuplicateAttachmentError: Raised if there is already an attachment with\n        the given name.\n    \"\"\"\n    if name in self.attachments:\n      raise DuplicateAttachmentError('Duplicate attachment for %s' % name)\n    if mimetype and not mimetypes.guess_extension(mimetype):\n      _LOG.warning('Unrecognized MIME type: \"%s\" for attachment \"%s\"',\n                   mimetype, name)\n    self.attachments[name] = test_record.Attachment(data, mimetype)\n\n  def AttachFromFile(self, filename, name=None, mimetype=None):\n    \"\"\"Store the contents of the given filename as an attachment.\n\n    Args:\n      filename: The file to read data from to attach.\n      name: If provided, override the attachment name, otherwise it will\n        default to the filename.\n      mimetype: If provided, override the attachment mime type, otherwise the\n        mime type will be guessed based on the file extension.\n\n    Raises:\n      DuplicateAttachmentError: Raised if there is already an attachment with\n        the given name.\n      IOError: Raised if the given filename couldn't be opened.\n    \"\"\"\n    with open(filename, 'r') as f:  # pylint: disable=invalid-name\n      self.Attach(\n          name if name is not None else filename, f.read(),\n          mimetype=mimetype if mimetype is not None else mimetypes.guess_type(\n              filename)[0])\n\n  @contextlib2.contextmanager\n  def RecordPhaseTiming(self, phase, test_state):\n    \"\"\"Context manager for the execution of a single phase.\"\"\"\n\n    # Check for measurement descriptors and track them in the PhaseRecord.\n    measurement_map = {\n        measurement.name: copy.deepcopy(measurement)\n        for measurement in phase.measurements\n    }\n\n    # Populate dummy declaration list for frontend API.\n    test_state.running_phase_record.measurements = {\n        measurement.name: measurement._asdict()\n        for measurement in measurement_map.itervalues()\n    }\n    test_state.phase_data.measurements = (\n        measurements.Collection(measurement_map))\n    test_state.phase_data.attachments = {}\n    test_state.running_phase_record.start_time_millis = util.TimeMillis()\n\n    outcome_wrapper = OutcomeWrapper()\n\n    try:\n      yield outcome_wrapper\n    finally:\n      # Serialize measurements and measured values, validate as we go.\n      values = dict(test_state.phase_data.measurements)\n\n      # Initialize with already-validated and UNSET measurements.\n      validated_measurements = {\n          name: measurement for name, measurement in measurement_map.iteritems()\n          if measurement.outcome is not measurements.Outcome.PARTIALLY_SET\n      }\n\n      # Validate multi-dimensional measurements now that we have all values.\n      validated_measurements.update({\n          name: measurement.Validate(values[name])\n          for name, measurement in measurement_map.iteritems()\n          if measurement.outcome is measurements.Outcome.PARTIALLY_SET\n      })\n\n      # Fill out and append the PhaseRecord to our test_record.\n      test_state.running_phase_record.measured_values = values\n      test_state.running_phase_record.measurements = validated_measurements\n      test_state.running_phase_record.end_time_millis = util.TimeMillis()\n      test_state.running_phase_record.result = outcome_wrapper.outcome\n      test_state.running_phase_record.attachments.update(self.attachments)\n      self.test_record.phases.append(test_state.running_phase_record)\n\n      # Clear these between uses for the frontend API.\n      test_state.phase_data.measurements = None\n      test_state.phase_data.attachments = {}\n      test_state.running_phase_record = None\n", "path": "openhtf/exe/phase_data.py"}], "after_files": [{"content": "# Copyright 2014 Google Inc. All Rights Reserved.\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n\n#     http://www.apache.org/licenses/LICENSE-2.0\n\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n\n\"\"\"Module encapsulating test phase data.\n\nHTF tests are comprised of a series of test phases.  These test phases are\nwrapped in openhtf.PhaseInfo objects to keep track of some necessary\nstate. This wrapping happens by decorating a method with any of various\nsupported decorators.\n\"\"\"\n\nimport contextlib2\nimport copy\nimport logging\nimport mimetypes\n\nimport mutablerecords\n\nfrom openhtf import util\nfrom openhtf.io import test_record\nfrom openhtf.util import measurements\n\n_LOG = logging.getLogger(__name__)\n\n\nclass DuplicateAttachmentError(Exception):\n  \"\"\"Raised when two attachments are attached with the same name.\"\"\"\n\n\nclass OutcomeWrapper(mutablerecords.Record(\n    'OutcomeWrapper', [], {'outcome': None})):\n  \"\"\"Wrapper so yielded object can receive an outcome.\"\"\"\n  def SetOutcome(self, outcome):\n    self.outcome = outcome\n\n\nclass PhaseData(object):  # pylint: disable=too-many-instance-attributes\n  \"\"\"The phase data object passed to test phases as the first argument.\n\n  Fields:\n    logger: A python logger that goes to the testrun proto, with functions like\n        debug, info, warn, error, and exception.\n    state: A dictionary for passing state data along to future phases.\n    plug_map: Dict mapping plug types to instances to use in phases.\n    measurements: A measurements.Collection for setting measurement values.\n    context: A contextlib.ExitStack, which simplifies context managers in a\n        phase.  This stack is pop'd after each phase.\n    test_record: The test_record.TestRecord for the currently running test.\n  \"\"\"\n  def __init__(self, logger, plug_map, record):\n    self.logger = logger\n    self.plug_map = plug_map\n    self.test_record = record\n    self.state = {}\n    self.measurements = None  # Will be populated per-phase.\n    self.attachments = {}\n    self.context = contextlib2.ExitStack()\n\n  def _asdict(self):\n    \"\"\"Return a dict of this PhaseData's public data.\"\"\"\n    return {'measurements': self.measurements,\n            'attachments': self.attachments.keys(),\n            'plugs': {\n                k.__module__ + '.' + k.__name__: str(v)\n                for k, v in self.plug_map.iteritems()}}\n\n  def Attach(self, name, data, mimetype=None):\n    \"\"\"Store the given data as an attachment with the given name.\n\n    Args:\n      name: Attachment name under which to store this data.\n      data: Data to attach.\n      mimetype: If provided, will be saved in the attachment.\n\n    Raises:\n      DuplicateAttachmentError: Raised if there is already an attachment with\n        the given name.\n    \"\"\"\n    if name in self.attachments:\n      raise DuplicateAttachmentError('Duplicate attachment for %s' % name)\n    if mimetype and not mimetypes.guess_extension(mimetype):\n      _LOG.warning('Unrecognized MIME type: \"%s\" for attachment \"%s\"',\n                   mimetype, name)\n    self.attachments[name] = test_record.Attachment(data, mimetype)\n\n  def AttachFromFile(self, filename, name=None, mimetype=None):\n    \"\"\"Store the contents of the given filename as an attachment.\n\n    Args:\n      filename: The file to read data from to attach.\n      name: If provided, override the attachment name, otherwise it will\n        default to the filename.\n      mimetype: If provided, override the attachment mime type, otherwise the\n        mime type will be guessed based on the file extension.\n\n    Raises:\n      DuplicateAttachmentError: Raised if there is already an attachment with\n        the given name.\n      IOError: Raised if the given filename couldn't be opened.\n    \"\"\"\n    with open(filename, 'rb') as f:  # pylint: disable=invalid-name\n      self.Attach(\n          name if name is not None else filename, f.read(),\n          mimetype=mimetype if mimetype is not None else mimetypes.guess_type(\n              filename)[0])\n\n  @contextlib2.contextmanager\n  def RecordPhaseTiming(self, phase, test_state):\n    \"\"\"Context manager for the execution of a single phase.\"\"\"\n\n    # Check for measurement descriptors and track them in the PhaseRecord.\n    measurement_map = {\n        measurement.name: copy.deepcopy(measurement)\n        for measurement in phase.measurements\n    }\n\n    # Populate dummy declaration list for frontend API.\n    test_state.running_phase_record.measurements = {\n        measurement.name: measurement._asdict()\n        for measurement in measurement_map.itervalues()\n    }\n    test_state.phase_data.measurements = (\n        measurements.Collection(measurement_map))\n    test_state.phase_data.attachments = {}\n    test_state.running_phase_record.start_time_millis = util.TimeMillis()\n\n    outcome_wrapper = OutcomeWrapper()\n\n    try:\n      yield outcome_wrapper\n    finally:\n      # Serialize measurements and measured values, validate as we go.\n      values = dict(test_state.phase_data.measurements)\n\n      # Initialize with already-validated and UNSET measurements.\n      validated_measurements = {\n          name: measurement for name, measurement in measurement_map.iteritems()\n          if measurement.outcome is not measurements.Outcome.PARTIALLY_SET\n      }\n\n      # Validate multi-dimensional measurements now that we have all values.\n      validated_measurements.update({\n          name: measurement.Validate(values[name])\n          for name, measurement in measurement_map.iteritems()\n          if measurement.outcome is measurements.Outcome.PARTIALLY_SET\n      })\n\n      # Fill out and append the PhaseRecord to our test_record.\n      test_state.running_phase_record.measured_values = values\n      test_state.running_phase_record.measurements = validated_measurements\n      test_state.running_phase_record.end_time_millis = util.TimeMillis()\n      test_state.running_phase_record.result = outcome_wrapper.outcome\n      test_state.running_phase_record.attachments.update(self.attachments)\n      self.test_record.phases.append(test_state.running_phase_record)\n\n      # Clear these between uses for the frontend API.\n      test_state.phase_data.measurements = None\n      test_state.phase_data.attachments = {}\n      test_state.running_phase_record = None\n", "path": "openhtf/exe/phase_data.py"}]}