internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: biopython/biopython

Issue:
Installing on old pythons.
### Setup

I am reporting a problem with Biopython source, and Python 3.5. This stems from the pypi packages not declaring for which versions of python they are compatible (not specifying `python_requires="....",` in the call to `setup()` in `setup.py`.

### Expected behaviour

Trying to install biopython with pip should install a version of biopython that is compatible with python 3.5.

### Actual behaviour

Without a version specified pip will download the latest and then when `setup.py` is invoked the python version is caught and the install exits.

### Steps to reproduce

```pip install biopython

Collecting biopython
  Downloading biopython-1.77.tar.gz (16.8 MB)
     |████████████████████████████████| 16.8 MB 9.5 MB/s
    ERROR: Command errored out with exit status 1:
     command: /home/OXFORDNANOLABS/cwright/git/medaka/venv/bin/python3 -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-fal177xf/biopython/setup.py'"'"'; __file__='"'"'/tmp/pip-install-fal177xf/biopython/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' egg_info --egg-base /tmp/pip-pip-egg-info-c1oi4si4
         cwd: /tmp/pip-install-fal177xf/biopython/
    Complete output (1 lines):
    Biopython requires Python 3.6 or later. Python 3.5 detected.
    ----------------------------------------
ERROR: Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.
```



Discussion:
Biopython 1.76 was our final release to support Python 3.5

It does look like we should add ``python_requires=">=3.6"`` to ``setup.py``, but that won't fix Biopython 1.77 which is already out.

https://packaging.python.org/guides/distributing-packages-using-setuptools/#python-requires 

Do you want to submit that as a pull request?

Resolving patch:
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -47,10 +47,11 @@
 
 
 # Make sure we have the right Python version.
-if sys.version_info[:2] < (3, 6):
+MIN_PY_VER = (3, 6)
+if sys.version_info[:2] < MIN_PY_VER:
     sys.stderr.write(
-        "Biopython requires Python 3.6 or later. "
-        "Python %d.%d detected.\n" % sys.version_info[:2]
+        ("Biopython requires Python %i.%i or later. " % MIN_PY_VER)
+        + ("Python %d.%d detected.\n" % sys.version_info[:2])
     )
     sys.exit(1)
 
@@ -256,4 +257,5 @@ def can_import(module_name):
     ext_modules=EXTENSIONS,
     include_package_data=True,  # done via MANIFEST.in under setuptools
     install_requires=REQUIRES,
+    python_requires=">=%i.%i" % MIN_PY_VER,
 )


Test patch:
Repository: biopython/biopython

Issue:
Information in the SeqFeature repr is hidden
The current behavior of repr hides its `qualifiers` attribute, even if it is non-empty. It would be helpful in some situations to surface the qualifiers attribute in the repr as discussed in https://github.com/biopython/biopython/issues/3576.

A proposal for such a behaviour has been made by @peterjc in https://github.com/biopython/biopython/pull/3578.


Discussion:

Resolving patch:
diff --git a/Bio/SeqFeature.py b/Bio/SeqFeature.py
--- a/Bio/SeqFeature.py
+++ b/Bio/SeqFeature.py
@@ -279,6 +279,8 @@ def __repr__(self):
             answer += ", location_operator=%r" % self.location_operator
         if self.id and self.id != "<unknown id>":
             answer += ", id=%r" % self.id
+        if self.qualifiers:
+            answer += ", qualifiers=..."
         if self.ref:
             answer += ", ref=%r" % self.ref
         if self.ref_db:


Test patch:
diff --git a/Tests/test_Uniprot.py b/Tests/test_Uniprot.py
--- a/Tests/test_Uniprot.py
+++ b/Tests/test_Uniprot.py
@@ -45,7 +45,7 @@ def test_uni001(self):
         self.assertEqual(len(seq_record.features), 1)
         self.assertEqual(
             repr(seq_record.features[0]),
-            "SeqFeature(FeatureLocation(ExactPosition(0), ExactPosition(116)), type='chain', id='PRO_0000377969')",
+            "SeqFeature(FeatureLocation(ExactPosition(0), ExactPosition(116)), type='chain', id='PRO_0000377969', qualifiers=...)",
         )
 
         self.assertEqual(
@@ -434,7 +434,7 @@ def test_uni003(self):
 
         self.assertEqual(
             repr(seq_record.features[1]),
-            "SeqFeature(FeatureLocation(ExactPosition(17), ExactPosition(43)), type='propeptide', id='PRO_0000009556')",
+            "SeqFeature(FeatureLocation(ExactPosition(17), ExactPosition(43)), type='propeptide', id='PRO_0000009556', qualifiers=...)",
         )
 
         self.assertEqual(
Repository: biopython/biopython

Issue:
Unreachable code in Nexus.py
Bio/Nexus/Nexus.py
The last line below (799 in Nexus.py) does not appear to be reachable.

``` python
        if 'transpose' in options:
            raise NexusError('TRANSPOSE is not supported!')
            self.transpose = True
```



Discussion:
Perhaps some user code used to trigger it via the `._format` method, although with a leading underscore is considered private?

Would anyone else like to comment? @etal maybe?

According to `git blame`, this exception, the subsequent unreachable line, and the unused `self.transpose` attribute have been there since @idoerg first committed Nexus.py in early 2005 (6a403e1e). The private _format method isn't used in Biopython, but maybe it was used in the standalone program that the Nexus module was extracted from.

My bet is that the original author meant it as a note-to-self, indicating the place to implement the transpose option at some later date, time permitting, which it didn't.

In any case, there is no way within Biopython to set or use the `transpose` attribute other than by setting it directly on a Nexus object, which could be done similarly with any other unreserved attribute name whether it existed or not. It seems very safe to delete this line.


Resolving patch:
diff --git a/Bio/Nexus/Nexus.py b/Bio/Nexus/Nexus.py
--- a/Bio/Nexus/Nexus.py
+++ b/Bio/Nexus/Nexus.py
@@ -868,9 +868,6 @@ def _format(self, options):
             self.matchchar = options["matchchar"][0]
         if "labels" in options:
             self.labels = options["labels"]
-        if "transpose" in options:
-            # self.transpose = True
-            raise NexusError("TRANSPOSE is not supported!")
         if "interleave" in options:
             if options["interleave"] is None or options["interleave"].lower() == "yes":
                 self.interleave = True


Test patch:
Repository: biopython/biopython

Issue:
Bio.UniProt.GOA does not parse current gaf file format
Gene Ontology Annotations have a new minor change in their GAF format.

http://geneontology.org/docs/go-annotation-file-gaf-format-2.2/

The current parser in biopython (Bio.UniProt.GOA) does not recognise
this format yet.





Discussion:

Resolving patch:
diff --git a/Bio/UniProt/GOA.py b/Bio/UniProt/GOA.py
--- a/Bio/UniProt/GOA.py
+++ b/Bio/UniProt/GOA.py
@@ -12,6 +12,7 @@
 ftp://ftp.ebi.ac.uk/pub/databases/GO/goa/UNIPROT/README
 
 Gene Association File, GAF formats:
+http://geneontology.org/docs/go-annotation-file-gaf-format-2.2/
 http://geneontology.org/docs/go-annotation-file-gaf-format-2.1/
 http://geneontology.org/docs/go-annotation-file-gaf-format-2.0/
 
@@ -385,16 +386,22 @@ def gafbyproteiniterator(handle):
         # Handle GAF 2.1 as GAF 2.0 for now TODO: fix
         # sys.stderr.write("gaf 2.1\n")
         return _gaf20byproteiniterator(handle)
+    elif inline.strip() == "!gaf-version: 2.2":
+        # Handle GAF 2.2 as GAF 2.0 for now. Change from
+        # 2.1 to 2.2 is that Qualifier field is no longer optional.
+        # As this type of checks has not been done before, we can
+        # continue to use the gaf2.0 parser
+        return _gaf20byproteiniterator(handle)
     else:
         raise ValueError(f"Unknown GAF version {inline}\n")
 
 
 def gafiterator(handle):
-    """Iterate over a GAF 1.0 or 2.0 file.
+    """Iterate over a GAF 1.0 or 2.x file.
 
     This function should be called to read a
     gene_association.goa_uniprot file. Reads the first record and
-    returns a gaf 2.0 or a gaf 1.0 iterator as needed
+    returns a gaf 2.x or a gaf 1.0 iterator as needed
 
     Example: open, read, interat and filter results.
 
@@ -434,6 +441,12 @@ def gafiterator(handle):
         # sys.stderr.write("gaf 2.1\n")
         # Handle GAF 2.1 as GAF 2.0 for now. TODO: fix
         return _gaf20iterator(handle)
+    elif inline.strip() == "!gaf-version: 2.2":
+        # Handle GAF 2.2 as GAF 2.0 for now. Change from
+        # 2.1 to 2.2 is that Qualifier field is no longer optional.
+        # As this type of checks has not been done before, we can
+        # continue to use the gaf2.0 parser
+        return _gaf20iterator(handle)
     elif inline.strip() == "!gaf-version: 1.0":
         # sys.stderr.write("gaf 1.0\n")
         return _gaf10iterator(handle)


Test patch:
Repository: biopython/biopython

Issue:
Can't write peptide genbank files with extra long headers
This line
https://github.com/biopython/biopython/blob/cb4f6edf59f9434c177dcd1af21dd588f9dfa161/Bio/SeqIO/InsdcIO.py#L799

should be changed to:

```
splitline[3].strip() == "aa"
```

because in genbank peptide files there isn't a molecule type, so that field gets eaten by the split and it won't ever be `""`


Discussion:
~I think you're right - would you like to submit that as a pull request please?~
You may be right, I've not looked at NCBI GenPept files to check.

But still, would you like to submit that as a pull request please, with a test case ideally.

Resolving patch:
diff --git a/Bio/GenBank/__init__.py b/Bio/GenBank/__init__.py
--- a/Bio/GenBank/__init__.py
+++ b/Bio/GenBank/__init__.py
@@ -1285,7 +1285,8 @@ def feature_qualifier(self, key, value):
             return
 
         # Remove enclosing quotation marks
-        value = re.sub('^"|"$', "", value)
+        if len(value) > 1 and value[0] == '"' and value[-1] == '"':
+            value = value[1:-1]
 
         # Handle NCBI escaping
         # Warn if escaping is not according to standard
diff --git a/Bio/SeqIO/InsdcIO.py b/Bio/SeqIO/InsdcIO.py
--- a/Bio/SeqIO/InsdcIO.py
+++ b/Bio/SeqIO/InsdcIO.py
@@ -798,7 +798,7 @@ def _write_the_first_line(self, record):
                 )
 
             if not (
-                splitline[4].strip() == ""
+                splitline[3].strip() == "aa"
                 or "DNA" in splitline[4].strip().upper()
                 or "RNA" in splitline[4].strip().upper()
             ):


Test patch:
diff --git a/Tests/test_SeqIO.py b/Tests/test_SeqIO.py
--- a/Tests/test_SeqIO.py
+++ b/Tests/test_SeqIO.py
@@ -3203,6 +3203,26 @@ def test_genbank22(self):
 
         self.assertEqual(db_source, read_db_source)
 
+    def test_genbank23(self):
+        """Test that peptide genbank files can be written with long names."""
+        record = SeqRecord(
+            Seq("MAGICCATS"), id="REALLYREALLYREALLYREALLYLONGID", description=""
+        )
+        record.annotations["molecule_type"] = "protein"
+        record.annotations["topology"] = "linear"
+
+        handle = StringIO()
+        with warnings.catch_warnings():
+            # ignore the warning about line length
+            warnings.simplefilter("ignore", BiopythonWarning)
+            SeqIO.write(record, handle, "genbank")
+
+        handle.seek(0)
+        read_record = SeqIO.read(handle, "genbank")
+        self.assertEqual(str(read_record.seq), str(record.seq))
+        self.assertEqual(read_record.id, record.id)
+        self.assertEqual(read_record.description, record.description)
+
     def test_embl1(self):
         sequences = [None]
         ids = ["DS830848.1"]
Repository: biopython/biopython

Issue:
Casting Seq objects to list requires iterative __getitem__ calls
### Setup

I am reporting a problem with Biopython version, Python version, and operating
system as follows:

```
3.7.2 (v3.7.2:9a3ffc0492, Dec 24 2018, 02:44:43) 
[Clang 6.0 (clang-600.0.57)]
CPython
Darwin-20.6.0-x86_64-i386-64bit
1.79
```

### Expected behaviour

Casting a `Seq` object to `list` should behave the same as casting a `str` to `list` AND it should have approximately the same performance qualities. Currently it does produce the same output, but casting `list(Seq(...))` is *significantly* slower due to the absence of an `__iter__` method.`list(Seq("ATG"))` should have approximately the same performance as `list(str(Seq("ATG")))`.

### Actual behaviour

Currently `list(Seq("ATG"))` will internally call `Seq.__getitem__` three times, once for each position. For long sequences, this can take a significant amount of time. 

### Steps to reproduce

Run cProfile and evaluate the difference between `list(Seq("ATG"))` and `list(str(Seq("ATG")))`.

### Solution

Add an `__iter__` method to `_SeqAbstractBaseClass`.



Discussion:

Resolving patch:
diff --git a/Bio/Seq.py b/Bio/Seq.py
--- a/Bio/Seq.py
+++ b/Bio/Seq.py
@@ -428,6 +428,10 @@ def __len__(self):
         """Return the length of the sequence."""
         return len(self._data)
 
+    def __iter__(self):
+        """Return an iterable of the sequence."""
+        return self._data.decode("ASCII").__iter__()
+
     def __getitem__(self, index):
         """Return a subsequence as a single letter or as a sequence object.
 


Test patch:
diff --git a/Tests/test_seq.py b/Tests/test_seq.py
--- a/Tests/test_seq.py
+++ b/Tests/test_seq.py
@@ -130,6 +130,16 @@ def test_concatenation_of_seq(self):
     def test_replace(self):
         self.assertEqual("ATCCCA", Seq.Seq("ATC-CCA").replace("-", ""))
 
+    def test_cast_to_list(self):
+        self.assertEqual(list("ATC"), list(Seq.Seq("ATC")))
+        self.assertEqual(list("ATC"), list(Seq.MutableSeq("ATC")))
+        self.assertEqual(list(""), list(Seq.MutableSeq("")))
+        self.assertEqual(list(""), list(Seq.Seq("")))
+        with self.assertRaises(Seq.UndefinedSequenceError):
+            list(Seq.Seq(None, length=3))
+        with self.assertRaises(Seq.UndefinedSequenceError):
+            list(Seq.Seq({3: "ACGT"}, length=10))
+
 
 class TestSeqStringMethods(unittest.TestCase):
     def setUp(self):
Repository: biopython/biopython

Issue:
Define SeqFeature __sub__ for integer offset
See https://github.com/biopython/biopython/blob/master/Bio/SeqFeature.py and ``__add__``, need to do the same specifically for integer offsets.

Workaround ``feature + (-5)`` instead of ``feature - 5``, see https://twitter.com/tomeraltman/status/1473764959347638273


Discussion:

Resolving patch:
diff --git a/Bio/SeqFeature.py b/Bio/SeqFeature.py
--- a/Bio/SeqFeature.py
+++ b/Bio/SeqFeature.py
@@ -926,6 +926,24 @@ def __radd__(self, other):
         else:
             return NotImplemented
 
+    def __sub__(self, other):
+        """Subtracting an integer will shift the start and end by that amount.
+
+        >>> from Bio.SeqFeature import FeatureLocation
+        >>> f1 = FeatureLocation(105, 150)
+        >>> print(f1)
+        [105:150]
+        >>> print(f1 - 100)
+        [5:50]
+
+        This can be useful when editing annotation. You can also add an integer
+        to a feature location (which shifts in the opposite direction).
+        """
+        if isinstance(other, int):
+            return self._shift(-other)
+        else:
+            return NotImplemented
+
     def __nonzero__(self):
         """Return True regardless of the length of the feature.
 


Test patch:
diff --git a/Tests/test_SeqFeature.py b/Tests/test_SeqFeature.py
--- a/Tests/test_SeqFeature.py
+++ b/Tests/test_SeqFeature.py
@@ -57,6 +57,19 @@ def test_eq_identical(self):
 class TestFeatureLocation(unittest.TestCase):
     """Tests for the SeqFeature.FeatureLocation class."""
 
+    def test_offsets(self):
+        """Test adding and subtracting integer offsets."""
+        loc1 = FeatureLocation(23, 42, -1)
+        loc2 = FeatureLocation(123, 142, -1)
+        self.assertEqual(loc1 + 100, loc2)
+        self.assertEqual(loc1, loc2 + (-100))
+        self.assertEqual(loc1, loc2 - 100)
+        self.assertEqual(loc1 + 50, loc2 - 50)
+        with self.assertRaises(TypeError):
+            loc1 + "Hello"
+        with self.assertRaises(TypeError):
+            loc1 - "Hello"
+
     def test_eq_identical(self):
         """Test two identical locations are equal."""
         loc1 = FeatureLocation(23, 42, 1)
Repository: biopython/biopython

Issue:
pairwise2 alignments are much slower when using Bio.Align.substitution_matrices.Array compared to a regular dictionary

When using `pairwise2.aligndX` (biopython==1.78, python==3.8.6) I noticed that alignments are much slower when doing as shown [in the docs](https://biopython.org/docs/1.75/api/Bio.pairwise2.html):

```
from Bio.Align import substitution_matrices
matrix = substitution_matrices.load("BLOSUM62")
for a in pairwise2.align.globaldx("KEVLA", "EVL", matrix):
    print(format_alignment(*a))
```
If I run `align.globaldx` (or any other alignment function using a similarity matrix) on two long-ish sequences (200 and 900 AAs), execution time is ~10s:

```python
start = time.time()
sequenceA = "..."
sequenceB = "..."
blosum = substitution_matrices.load("BLOSUM62")
alignments = pairwise2.align.globaldx(sequenceA, sequenceB, blosum)
end = time.time()
print(f"Time: {end - start}")
-----------
Time: 9.997540712356567

```
But if I convert the blosum object (which is of type Bio.Align.substitution_matrices.Array) into a regular dictionary, runtime is ~30x faster:

```python
start = time.time()
blosum_dic = as_dictionary(blosum) # convert the blosum object into a normal dictionary
alignments = pairwise2.align.globaldxs(sequenceA, sequenceB, blosum_dic)
end = time.time()
print(f"Time: {end - start}")
-----------
Time: 0.31342601776123047
```

I suggest this conversion is done automatically inside `pairwise2` when using a scoring matrix


Discussion:
@clami66 Thanks for reporting this and showing how this can be made much faster. I guess the problem has come when we changed the implementation of the substitution matrices. It could be that the match function in the C code cannot handle the new substitution matrices and instead the Python replacement code is used.

Note that we are thinking about to declare pairwise2 deprecated, you may want to try the "new" ```Pairwise.Aligner```. 
Having decided to deprecate ``Bio. pairwise2``, I don't think we'll work on this. But thank you for diagnosing the issue and reporting it.

Resolving patch:
diff --git a/Bio/pairwise2.py b/Bio/pairwise2.py
--- a/Bio/pairwise2.py
+++ b/Bio/pairwise2.py
@@ -273,6 +273,7 @@
 
 from Bio import BiopythonWarning
 from Bio import BiopythonDeprecationWarning
+from Bio.Align import substitution_matrices
 
 warnings.warn(
     "Bio.pairwise2 has been deprecated, and we intend to remove it in a "
@@ -1282,6 +1283,8 @@ class dictionary_match:
 
     def __init__(self, score_dict, symmetric=1):
         """Initialize the class."""
+        if isinstance(score_dict, substitution_matrices.Array):
+            score_dict = dict(score_dict)  # Access to dict is much faster
         self.score_dict = score_dict
         self.symmetric = symmetric
 


Test patch:
Repository: biopython/biopython

Issue:
Insecure Temporary File using tempfile.mktemp()
This is a security issue spotted by @srikanthprathi reported by @JamieSlome on #3839, https://huntr.dev/bounties/bf1fb12c-7ed5-417a-912f-934006bcfcef/

Having review the private report, I considered it low risk, and with their agreement am posting it publicly:

> **Insecure Temporary File in biopython/biopython**
> biopython package is using the deprecated function tempfile.mktemp() which is not secure. Because a different process may create a file with this name in the time between the call to mktemp() and the subsequent attempt to create the file by the first process.
>
> Impact
> Availability will get affected because of this vulnerability.
>
> Remediation
> Use mkstemp() instead of tempfile.mktemp()

We appear to have two uses in the test suite, both using the same code style:

https://github.com/biopython/biopython/blob/master/Tests/test_Phylo_CDAO.py
https://github.com/biopython/biopython/blob/master/Tests/test_PhyloXML.py

And one use in the main code base in the PDB module for invoking the MSMS command line tool:

https://github.com/biopython/biopython/blob/master/Bio/PDB/ResidueDepth.py


Discussion:

Resolving patch:
diff --git a/Bio/PDB/ResidueDepth.py b/Bio/PDB/ResidueDepth.py
--- a/Bio/PDB/ResidueDepth.py
+++ b/Bio/PDB/ResidueDepth.py
@@ -521,7 +521,7 @@ def get_surface(model, MSMS="msms"):
     # Make x,y,z,radius file
     atom_list = Selection.unfold_entities(model, "A")
 
-    xyz_tmp = tempfile.mktemp()
+    xyz_tmp = tempfile.NamedTemporaryFile(delete=False).name
     with open(xyz_tmp, "w") as pdb_to_xyzr:
         for atom in atom_list:
             x, y, z = atom.coord
@@ -529,8 +529,8 @@ def get_surface(model, MSMS="msms"):
             pdb_to_xyzr.write(f"{x:6.3f}\t{y:6.3f}\t{z:6.3f}\t{radius:1.2f}\n")
 
     # Make surface
-    surface_tmp = tempfile.mktemp()
-    msms_tmp = tempfile.mktemp()
+    surface_tmp = tempfile.NamedTemporaryFile(delete=False).name
+    msms_tmp = tempfile.NamedTemporaryFile(delete=False).name
     MSMS = MSMS + " -probe_radius 1.5 -if %s -of %s > " + msms_tmp
     make_surface = MSMS % (xyz_tmp, surface_tmp)
     subprocess.call(make_surface, shell=True)


Test patch:
diff --git a/Tests/test_PhyloXML.py b/Tests/test_PhyloXML.py
--- a/Tests/test_PhyloXML.py
+++ b/Tests/test_PhyloXML.py
@@ -23,7 +23,7 @@
 EX_DOLLO = "PhyloXML/o_tol_332_d_dollo.xml"
 
 # Temporary file name for Writer tests below
-DUMMY = tempfile.mktemp()
+DUMMY = tempfile.NamedTemporaryFile(delete=False).name
 
 
 # ---------------------------------------------------------
diff --git a/Tests/test_Phylo_CDAO.py b/Tests/test_Phylo_CDAO.py
--- a/Tests/test_Phylo_CDAO.py
+++ b/Tests/test_Phylo_CDAO.py
@@ -25,7 +25,7 @@
 cdao_files = ("test.cdao",)
 
 # Temporary file name for Writer tests below
-DUMMY = tempfile.mktemp()
+DUMMY = tempfile.NamedTemporaryFile(delete=False).name
 
 
 # ---------------------------------------------------------