Repository: internetarchive/openlibrary

Issue:
TypeError at /api/import: argument should be integer or bytes-like object, not str
<!-- What problem are we solving? What does the experience look like today? What are the symptoms? -->

### Evidence / Screenshot (if possible)

Noticing that BWB Imports are completely halted because of some bug
2020-12-30/224049836043 on ol-web2

```
<div id="summary">
  <h1>&lt;class &#39;TypeError&#39;&gt; at /api/import</h1>
  <h2>argument should be integer or bytes-like object, not &#39;str&#39;</h2>
  <table><tr>
    <th>Python</th>
    <td>/openlibrary/openlibrary/plugins/importapi/code.py in parse_data, line 66</td>
  </tr><tr>
    <th>Web</th>
    <td>POST https://openlibrary.org/api/import</td>
  </tr></table>
</div>
<div id="traceback">
<h2>Traceback <span>(innermost first)</span></h2>
<ul class="traceback">
<li class="frame">
<code>/openlibrary/openlibrary/plugins/importapi/code.py</code> in <code>parse_data</code>
<div class="context" id="c140001045356736">
<ol start="59" class="pre-context" id="pre140001045356736">
<li onclick="toggle('pre140001045356736', 'post140001045356736')">    suitable for adding to OL.</li>
<li onclick="toggle('pre140001045356736', 'post140001045356736')"></li>
<li onclick="toggle('pre140001045356736', 'post140001045356736')">    :param str data: Raw data</li>
<li onclick="toggle('pre140001045356736', 'post140001045356736')">    :rtype: (dict|None, str|None)</li>
<li onclick="toggle('pre140001045356736', 'post140001045356736')">    :return: (Edition record, format (rdf|opds|marcxml|json|marc)) or (None, None)</li>
<li onclick="toggle('pre140001045356736', 'post140001045356736')">    &quot;&quot;&quot;</li>
<li onclick="toggle('pre140001045356736', 'post140001045356736')">    data = data.strip()</li>
</ol>
<ol start="66" class="context-line"><li onclick="toggle('pre140001045356736', 'post140001045356736')">    if -1 != data[:10].find(&#39;&lt;?xml&#39;): <span>...</span></li></ol>
<ol start='67' class="post-context" id="post140001045356736">
<li onclick="toggle('pre140001045356736', 'post140001045356736')">        root = etree.fromstring(data)</li>
<li onclick="toggle('pre140001045356736', 'post140001045356736')">        if &#39;{http://www.w3.org/1999/02/22-rdf-syntax-ns#}RDF&#39; == root.tag:</li>
<li onclick="toggle('pre140001045356736', 'post140001045356736')">            edition_builder = import_rdf.parse(root)</li>
<li onclick="toggle('pre140001045356736', 'post140001045356736')">            format = &#39;rdf&#39;</li>
<li onclick="toggle('pre140001045356736', 'post140001045356736')">        elif &#39;{http://www.w3.org/2005/Atom}entry&#39; == root.tag:</li>
<li onclick="toggle('pre140001045356736', 'post140001045356736')">            edition_builder = import_opds.parse(root)</li>
</ol>
  </div>

<div class="commands">
<a href='#' onclick="return varToggle(this, '140001045356736')"><span>&#x25b6;</span> Local vars</a>

</div>

<table class="vars" id="v140001045356736"><thead><tr><th>Variable</th><th>Value</th></tr></thead>
<tbody>
<tr><td>data</td><td class="code"><div>(b&#39;{&quot;publishers&quot;: [&quot;Bloomsbury Publishing Plc&quot;], &quot;number_of_pages&quot;: &quot;76&quot;, &quot;sour&#39;
 b&#39;ce_records&quot;: [&quot;bwb:9780413483201&quot;], &quot;languages&quot;: [&quot;eng&quot;], &quot;title&quot;: &quot;A-A-Amer&#39;
 b&#39;ica! and Stone&quot;, &quot;isbn_13&quot;: [&quot;9780413483201&quot;], &quot;lc_classifications&quot;: [&quot;&quot;], &quot;&#39;
 b&#39;publish_date&quot;: &quot;2006&quot;, &quot;authors&quot;: [{&quot;name&quot;: &quot;Bond, Edward&quot;}], &quot;subjects&quot;: [&quot;&#39;
 b&#39;British and irish drama (dramatic works by one author)&quot;]}&#39;)</div></td></tr>
</tbody>
</table> 
```
### Relevant url?
<!-- `https://openlibrary.org/...` -->

### Steps to Reproduce
<!-- What steps caused you to find the bug? -->
1. Go to ...
2. Do ...

<!-- What actually happened after these steps? What did you expect to happen? -->
* Actual: 
* Expected: 

### Details

- **Logged in (Y/N)?** 
- **Browser type/version?** 
- **Operating system?** 
- **Environment (prod/dev/local)?** prod
<!-- If not sure, put prod -->

### Proposal & Constraints
<!-- What is the proposed solution / implementation? Is there a precedent of this approach succeeding elsewhere? -->

### Related files
<!-- Files related to this issue; this is super useful for new contributors who might want to help! If you're not sure, leave this blank; a maintainer will add them. -->

### Stakeholders
<!-- @ tag stakeholders of this bug -->

TypeError at /api/import: argument should be integer or bytes-like object, not str
<!-- What problem are we solving? What does the experience look like today? What are the symptoms? -->

### Evidence / Screenshot (if possible)

Noticing that BWB Imports are completely halted because of some bug
2020-12-30/224049836043 on ol-web2

```
<div id="summary">
  <h1>&lt;class &#39;TypeError&#39;&gt; at /api/import</h1>
  <h2>argument should be integer or bytes-like object, not &#39;str&#39;</h2>
  <table><tr>
    <th>Python</th>
    <td>/openlibrary/openlibrary/plugins/importapi/code.py in parse_data, line 66</td>
  </tr><tr>
    <th>Web</th>
    <td>POST https://openlibrary.org/api/import</td>
  </tr></table>
</div>
<div id="traceback">
<h2>Traceback <span>(innermost first)</span></h2>
<ul class="traceback">
<li class="frame">
<code>/openlibrary/openlibrary/plugins/importapi/code.py</code> in <code>parse_data</code>
<div class="context" id="c140001045356736">
<ol start="59" class="pre-context" id="pre140001045356736">
<li onclick="toggle('pre140001045356736', 'post140001045356736')">    suitable for adding to OL.</li>
<li onclick="toggle('pre140001045356736', 'post140001045356736')"></li>
<li onclick="toggle('pre140001045356736', 'post140001045356736')">    :param str data: Raw data</li>
<li onclick="toggle('pre140001045356736', 'post140001045356736')">    :rtype: (dict|None, str|None)</li>
<li onclick="toggle('pre140001045356736', 'post140001045356736')">    :return: (Edition record, format (rdf|opds|marcxml|json|marc)) or (None, None)</li>
<li onclick="toggle('pre140001045356736', 'post140001045356736')">    &quot;&quot;&quot;</li>
<li onclick="toggle('pre140001045356736', 'post140001045356736')">    data = data.strip()</li>
</ol>
<ol start="66" class="context-line"><li onclick="toggle('pre140001045356736', 'post140001045356736')">    if -1 != data[:10].find(&#39;&lt;?xml&#39;): <span>...</span></li></ol>
<ol start='67' class="post-context" id="post140001045356736">
<li onclick="toggle('pre140001045356736', 'post140001045356736')">        root = etree.fromstring(data)</li>
<li onclick="toggle('pre140001045356736', 'post140001045356736')">        if &#39;{http://www.w3.org/1999/02/22-rdf-syntax-ns#}RDF&#39; == root.tag:</li>
<li onclick="toggle('pre140001045356736', 'post140001045356736')">            edition_builder = import_rdf.parse(root)</li>
<li onclick="toggle('pre140001045356736', 'post140001045356736')">            format = &#39;rdf&#39;</li>
<li onclick="toggle('pre140001045356736', 'post140001045356736')">        elif &#39;{http://www.w3.org/2005/Atom}entry&#39; == root.tag:</li>
<li onclick="toggle('pre140001045356736', 'post140001045356736')">            edition_builder = import_opds.parse(root)</li>
</ol>
  </div>

<div class="commands">
<a href='#' onclick="return varToggle(this, '140001045356736')"><span>&#x25b6;</span> Local vars</a>

</div>

<table class="vars" id="v140001045356736"><thead><tr><th>Variable</th><th>Value</th></tr></thead>
<tbody>
<tr><td>data</td><td class="code"><div>(b&#39;{&quot;publishers&quot;: [&quot;Bloomsbury Publishing Plc&quot;], &quot;number_of_pages&quot;: &quot;76&quot;, &quot;sour&#39;
 b&#39;ce_records&quot;: [&quot;bwb:9780413483201&quot;], &quot;languages&quot;: [&quot;eng&quot;], &quot;title&quot;: &quot;A-A-Amer&#39;
 b&#39;ica! and Stone&quot;, &quot;isbn_13&quot;: [&quot;9780413483201&quot;], &quot;lc_classifications&quot;: [&quot;&quot;], &quot;&#39;
 b&#39;publish_date&quot;: &quot;2006&quot;, &quot;authors&quot;: [{&quot;name&quot;: &quot;Bond, Edward&quot;}], &quot;subjects&quot;: [&quot;&#39;
 b&#39;British and irish drama (dramatic works by one author)&quot;]}&#39;)</div></td></tr>
</tbody>
</table> 
```
### Relevant url?
<!-- `https://openlibrary.org/...` -->

### Steps to Reproduce
<!-- What steps caused you to find the bug? -->
1. Go to ...
2. Do ...

<!-- What actually happened after these steps? What did you expect to happen? -->
* Actual: 
* Expected: 

### Details

- **Logged in (Y/N)?** 
- **Browser type/version?** 
- **Operating system?** 
- **Environment (prod/dev/local)?** prod
<!-- If not sure, put prod -->

### Proposal & Constraints
<!-- What is the proposed solution / implementation? Is there a precedent of this approach succeeding elsewhere? -->

### Related files
<!-- Files related to this issue; this is super useful for new contributors who might want to help! If you're not sure, leave this blank; a maintainer will add them. -->

### Stakeholders
<!-- @ tag stakeholders of this bug -->



Discussion:

Resolving patch:
diff --git a/openlibrary/plugins/importapi/code.py b/openlibrary/plugins/importapi/code.py
--- a/openlibrary/plugins/importapi/code.py
+++ b/openlibrary/plugins/importapi/code.py
@@ -30,7 +30,6 @@
 logger = logging.getLogger('openlibrary.importapi')
 
 
-
 class DataError(ValueError):
     pass
 
@@ -54,17 +53,21 @@ def parse_meta_headers(edition_builder):
             meta_key = m.group(1).lower()
             edition_builder.add(meta_key, v, restrict_keys=False)
 
+
 def parse_data(data):
     """
     Takes POSTed data and determines the format, and returns an Edition record
     suitable for adding to OL.
 
-    :param str data: Raw data
+    :param bytes data: Raw data
     :rtype: (dict|None, str|None)
     :return: (Edition record, format (rdf|opds|marcxml|json|marc)) or (None, None)
+
+    from typing import Dict, Optional, Tuple
+    def parse_data(data: bytes) -> Tuple[Optional[Dict], Optional[str]]:
     """
     data = data.strip()
-    if -1 != data[:10].find('<?xml'):
+    if b'<?xml' in data[:10]:
         root = etree.fromstring(data)
         if '{http://www.w3.org/1999/02/22-rdf-syntax-ns#}RDF' == root.tag:
             edition_builder = import_rdf.parse(root)


Test patch: