Repository: biopython/biopython

Issue:
ValueError when trying to read the TrEMBL text file. 
Hi,

First thank you for the Biopython package, I use it a lot, it is very helpful.

### Setup

I am reporting a problem with Biopython version, Python version, and operating system as follows:

```python
import sys; print(sys.version)
import platform; print(platform.python_implementation()); print(platform.platform())
import Bio; print(Bio.__version__)
```

```python
3.8.10 (default, Nov 14 2022, 12:59:47) 
[GCC 9.4.0]
CPython
Linux-5.17.12-100.fc34.x86_64-x86_64-with-glibc2.29
1.80
```

### Expected behaviour

I am trying to parse the TrEMBL protein database using biopython by reading the `uniprot_trembl.dat` file (version 2022_05). And I encountered an error during the parsing of the file. I expected to be able to read it.

Due to the size of the uniprot TrEMBL file, I use one of the entry that leads to the error, the protein [A0A067NSZ9](https://www.uniprot.org/uniprotkb/A0A067NSZ9) as an example for this issue.

### Actual behaviour

I encountered the following error:
```python
Traceback (most recent call last):
  File "test.py", line 3, in <module>
    for record in SeqIO.parse('A0A067NSZ9.txt', 'swiss'):
  File "/usr/local/lib/python3.8/dist-packages/Bio/SeqIO/SwissIO.py", line 44, in SwissIterator
    for swiss_record in swiss_records:
  File "/usr/local/lib/python3.8/dist-packages/Bio/SwissProt/__init__.py", line 233, in parse
    record = _read(handle)
  File "/usr/local/lib/python3.8/dist-packages/Bio/SwissProt/__init__.py", line 377, in _read
    _read_gn(record)
  File "/usr/local/lib/python3.8/dist-packages/Bio/SwissProt/__init__.py", line 419, in _read_gn
    key, value = token.strip().split("=")
ValueError: too many values to unpack (expected 2)
```

The issue seems to come from this line of the text file:

```
GN   Name=Lacc1=POX4 {ECO:0000313|EMBL:KDQ27217.1};
```

The `Lacc1=POX4` is leading to the issue with the split("="). I have contacted the UniProt team to see if it could be a potential error on the use of the symbol but they answer me that it was an expected format as the data are coming from imported source (as it comes from this [source](https://www.ebi.ac.uk/ena/browser/api/embl/KDQ27217.1?lineLimit=1000)).

Is this an error that can be fixed on the Biopython side or is there another work around? 

### Steps to reproduce

I try to read the corresponding [text file](https://rest.uniprot.org/uniprotkb/A0A067NSZ9.txt) with:

```python
from Bio import SeqIO

for record in SeqIO.parse('A0A067NSZ9.txt', 'swiss'):
    print(record.id)
```

Best regards,
Arnaud Belcour.


Discussion:
That was a nice clear bug report. Issue reproduced:

```
$ wget https://rest.uniprot.org/uniprotkb/A0A067NSZ9.txt
$ python -c "from Bio import SeqIO; SeqIO.read('A0A067NSZ9.txt', 'swiss')"
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/Users/xxx/repositories/biopython/Bio/SeqIO/__init__.py", line 654, in read
    record = next(iterator)
  File "/Users/xxx/repositories/biopython/Bio/SeqIO/SwissIO.py", line 44, in SwissIterator
    for swiss_record in swiss_records:
  File "/Users/xxx/repositories/biopython/Bio/SwissProt/__init__.py", line 233, in parse
    record = _read(handle)
  File "/Users/xxx/repositories/biopython/Bio/SwissProt/__init__.py", line 377, in _read
    _read_gn(record)
  File "/Users/xxx/repositories/biopython/Bio/SwissProt/__init__.py", line 419, in _read_gn
    key, value = token.strip().split("=")
ValueError: too many values to unpack (expected 2)
```

That bit of the parser expected just one equals sign, this tiny change allows the file to parse:

```
--- a/Bio/SwissProt/__init__.py
+++ b/Bio/SwissProt/__init__.py
@@ -416,7 +416,7 @@ def _read_gn(record):
         tokens = text.rstrip("; ").split("; ")
         gene_name = {}
         for token in tokens:
-            key, value = token.strip().split("=")
+            key, value = token.strip().split("=", 1)
             if key == "Name":
                 gene_name["Name"] = value
             else:
```

Can you try that, and confirm if the treatment of the Name field is reasonable, and that it works on all of your test cases? If so, we can update Biopython and include this in the next release. Thank you.
I have tested the change on the example file and the resulting Name fields are reasonable for me. Furthermore, I have tested this change on the parsing of the Uniprot TrEMBL file and I did not encounter an error during it. So the issue is fixed and the change can be added to Biopython.

Thank you for the quick answer and fix.

Resolving patch:
diff --git a/Bio/SwissProt/__init__.py b/Bio/SwissProt/__init__.py
--- a/Bio/SwissProt/__init__.py
+++ b/Bio/SwissProt/__init__.py
@@ -406,7 +406,7 @@ def _read(handle):
             # **HA SAM; Annotated by PicoHamap 1.88; MF_01138.1; 09-NOV-2003.
             pass
         else:
-            raise SwissProtParserError(f"Unknown keyword '{key}' found", line=line)
+            raise SwissProtParserError(f"Unknown keyword {key!r} found", line=line)
     if record:
         raise ValueError("Unexpected end of stream.")
 
@@ -416,7 +416,9 @@ def _read_gn(record):
         tokens = text.rstrip("; ").split("; ")
         gene_name = {}
         for token in tokens:
-            key, value = token.strip().split("=")
+            # value may include an equals sign, e.g.
+            # GN   Name=Lacc1=POX4 {ECO:0000313|EMBL:KDQ27217.1};
+            key, value = token.strip().split("=", 1)
             if key == "Name":
                 gene_name["Name"] = value
             else:
@@ -447,13 +449,13 @@ def _read_id(record, line):
     # check if the data class is one of the allowed values
     allowed = ("STANDARD", "PRELIMINARY", "IPI", "Reviewed", "Unreviewed")
     if record.data_class not in allowed:
-        message = f"Unrecognized data class '{record.data_class}'"
+        message = f"Unrecognized data class {record.data_class!r}"
         raise SwissProtParserError(message, line=line)
 
     # molecule_type should be 'PRT' for PRoTein
     # Note that has been removed in recent releases (set to None)
     if record.molecule_type not in (None, "PRT"):
-        message = f"Unrecognized molecule type '{record.molecule_type}'"
+        message = f"Unrecognized molecule type {record.molecule_type!r}"
         raise SwissProtParserError(message, line=line)
 
 
@@ -805,7 +807,7 @@ def _read_ft(record, line):
                     value = value[1:]
                 if qualifier_type in feature.qualifiers:
                     raise ValueError(
-                        f"Feature qualifier '{qualifier_type}' already exists for feature"
+                        f"Feature qualifier {qualifier_type!r} already exists for feature"
                     )
                 feature.qualifiers[qualifier_type] = value
             return


Test patch: