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

Issue:
__eq__ for SeqFeature objects?
While writing test cases for my annotation pipeline, I discovered that I can't directly compare my expected vs actual SeqFeature objects. I've had to resort to comparing the location attributes and the qualifier dicts separately, but it'd be nice if I could test `expected_feature == output_feature`

many thanks for your consideration and all that you do

__eq__ for SeqFeature objects?
While writing test cases for my annotation pipeline, I discovered that I can't directly compare my expected vs actual SeqFeature objects. I've had to resort to comparing the location attributes and the qualifier dicts separately, but it'd be nice if I could test `expected_feature == output_feature`

many thanks for your consideration and all that you do



Discussion:
The underlying objects have ``__eq__`` (locations and references), so adding a ``SeqFeature`` object method comparing the location, qualifiers and type sounds reasonable. Would you like to try making a PR adding this?
The underlying objects have ``__eq__`` (locations and references), so adding a ``SeqFeature`` object method comparing the location, qualifiers and type sounds reasonable. Would you like to try making a PR adding this?

Resolving patch:
diff --git a/Bio/SeqFeature.py b/Bio/SeqFeature.py
--- a/Bio/SeqFeature.py
+++ b/Bio/SeqFeature.py
@@ -285,6 +285,15 @@ def _set_location_operator(self, value):
         doc="Location operator for compound locations (e.g. join).",
     )
 
+    def __eq__(self, other):
+        """Check if two SeqFeature objects should be considered equal."""
+        return (
+            self.id == other.id
+            and self.type == other.type
+            and self.location == other.location
+            and self.qualifiers == other.qualifiers
+        )
+
     def __repr__(self):
         """Represent the feature as a string for debugging."""
         answer = f"{self.__class__.__name__}({self.location!r}"


Test patch:
diff --git a/Tests/test_SeqFeature.py b/Tests/test_SeqFeature.py
--- a/Tests/test_SeqFeature.py
+++ b/Tests/test_SeqFeature.py
@@ -7,6 +7,7 @@
 """Tests Bio.SeqFeature."""
 import unittest
 
+from copy import deepcopy
 from os import path
 
 from Bio import Seq
@@ -172,6 +173,17 @@ def test_eq_not_identical(self):
 class TestSeqFeature(unittest.TestCase):
     """Tests for the SeqFeature.SeqFeature class."""
 
+    def test_eq_identical(self):
+        f1 = SeqFeature(
+            type="CDS",
+            location=FeatureLocation(0, 182, 1),
+            qualifiers={
+                "product": ["interferon beta, fibroblast"],
+            },
+        )
+        f2 = deepcopy(f1)
+        self.assertEqual(f1, f2)
+
     def test_translation_checks_cds(self):
         """Test that a CDS feature is subject to respective checks."""
         seq = Seq.Seq("GGTTACACTTACCGATAATGTCTCTGATGA")
Repository: biopython/biopython

Issue:
SeqFeature raises an unexpected AttributeError when compared to anything else than another SeqFeature
### 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__)
```

```bash
>>> import sys; print(sys.version)
3.10.4 (main, Apr  2 2022, 09:04:19) [GCC 11.2.0]
>>> import platform; print(platform.python_implementation()); print(platform.platform())
CPython
Linux-5.15.0-40-generic-x86_64-with-glibc2.35
>>> import Bio; print(Bio.__version__)
(...)
1.80.dev0
>>> 
```

### Expected behaviour

Comparing a SeqFeature object to any other Python object should always return a boolean - `True` or `False`.

### Actual behaviour

When comparing a SeqFeature object to a different object (for example, to a NoneType object), the operation raises an AttributeError instead of returning a simple False. The `__eq__` method is not prepared to handle any other objects that don't meet the SeqFeature interface.

### Steps to reproduce

```python
>>> from Bio.SeqFeature import SeqFeature
>>> seqfeature_obj = SeqFeature()
>>> seqfeature_obj2 = SeqFeature()
>>> seqfeature_obj == seqfeature_obj2
True
>>> seqfeature_obj == None
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/battlesheep/PycharmProjects/biopython/Bio/SeqFeature.py", line 292, in __eq__
    self.id == other.id
AttributeError: 'NoneType' object has no attribute 'id'
>>> 
```



Discussion:

Resolving patch:
diff --git a/Bio/SeqFeature.py b/Bio/SeqFeature.py
--- a/Bio/SeqFeature.py
+++ b/Bio/SeqFeature.py
@@ -288,7 +288,8 @@ def _set_location_operator(self, value):
     def __eq__(self, other):
         """Check if two SeqFeature objects should be considered equal."""
         return (
-            self.id == other.id
+            isinstance(other, SeqFeature)
+            and self.id == other.id
             and self.type == other.type
             and self.location == other.location
             and self.qualifiers == other.qualifiers


Test patch:
Repository: biopython/biopython

Issue:
Misleading statement in CompoundLocation.end docstring
I believe the text in parentheses `(minus one given how Python counts from zero)` is incorrect, and should be deleted.

https://github.com/biopython/biopython/blob/c0be3a0b477f9cce38f26d91af538b2b07ca4720/Bio/SeqFeature.py#L1849

When I load a circular record where the first features spans the origin.

```python
>>> int(rec.features[0].location.end) == len(rec)
True
```

This also makes sense with python slicing, because to slice an array/SeqRecord of size 1, you would do `a[0:1]` to get the entire array/SeqRecord, not `a[0:0]`.


Discussion:
That does look wrong at first glance, have a look at your favourite circular genome, or from our tests https://github.com/biopython/biopython/blob/master/Tests/GenBank/NC_000932.gb

Please confirm with the source feature (``.features[0]`` in the record). I don't have time right now.
```python
Python 3.9.9 | packaged by conda-forge | (main, Dec 20 2021, 02:40:17)
[GCC 9.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from Bio import SeqIO
>>> r = SeqIO.read("NC_000932.gb", "genbank")
>>> int(r.features[0].location.end) == len(r)
True
```

Yeah, it's true for that `NC_000932.gb` file.

I think it's not quite the latest version of biopython, probably 1.78 or so, but I guess numbering probably hasn't changed in a long time.
Good, can you make a pull request to correct the text then? Thanks!

Resolving patch:
diff --git a/Bio/SeqFeature.py b/Bio/SeqFeature.py
--- a/Bio/SeqFeature.py
+++ b/Bio/SeqFeature.py
@@ -1846,8 +1846,7 @@ def end(self):
         position.
 
         For the special case of a CompoundLocation wrapping the origin of
-        a circular genome this will match the genome length (minus one
-        given how Python counts from zero).
+        a circular genome this will match the genome length.
         """
         return max(loc.end for loc in self.parts)
 


Test patch:
Repository: biopython/biopython

Issue:
AttributeError: 'SeqFeature' object has no attribute 'strand'
## Setup
- **Biopython Version:** 1.82
- **Python Version:** 3.11.5 (main, Sep 27 2023, 11:42:37) [GCC 11.4.0]
- **Operating System:** Linux-5.15.0-91-generic-x86_64-with-glibc2.35
- **Python Implementation:** CPython

## Expected Behaviour
When processing GenBank files using Biopython, each gene feature should have a 'strand' attribute.

## Actual Behaviour
The 'strand' attributes are missing for gene features in GenBank files.

## Steps to Reproduce
1. Run the following script to parse a GenBank file and check for the presence of 'strand' attributes in gene features:
   ```python
   from Bio import SeqIO

   import sys; print(sys.version)
   import platform; print(platform.python_implementation()); print(platform.platform())
   import Bio; print(Bio.__version__)

   def check_strand_in_genes(genome_file):
       count = 0
       for record in SeqIO.parse(genome_file, "genbank"):
           for feature in record.features:
               if feature.type == "gene":
                   gene_name = feature.qualifiers.get('gene', ['Unknown'])[0]
                   if hasattr(feature, 'strand'):
                       print(f"'strand' attribute exists for {gene_name} in record {record.id}")
                       count += 1
                   else:
                       print(f"'strand' attribute does not exist for {gene_name} in record {record.id}")
                       count += 1
                   if count >= 5:
                       return

   # Replace 'genome_file.gb' with the path to your GenBank file
   # Example file: https://www.ncbi.nlm.nih.gov/nuccore/U00096.3/
   check_strand_in_genes('sequence.gb')
   ```

2. Note that the output indicates the absence of 'strand' attributes for the genes.

## Observed Output
```bash
3.11.5 (main, Sep 27 2023, 11:42:37) [GCC 11.4.0]
CPython
Linux-5.15.0-91-generic-x86_64-with-glibc2.35
1.82
'strand' attribute does not exist for thrL in record U00096.3
'strand' attribute does not exist for thrA in record U00096.3
'strand' attribute does not exist for thrB in record U00096.3
'strand' attribute does not exist for thrC in record U00096.3
'strand' attribute does not exist for yaaX in record U00096.3
```


Discussion:

Resolving patch:
diff --git a/Bio/__init__.py b/Bio/__init__.py
--- a/Bio/__init__.py
+++ b/Bio/__init__.py
@@ -15,7 +15,7 @@
 import os
 import warnings
 
-__version__ = "1.83.dev0"
+__version__ = "1.84.dev0"
 
 
 class MissingExternalDependencyError(Exception):


Test patch:
Repository: biopython/biopython

Issue:
Update Sphinx and associated modules used to build the docs
We would ideally use a recent Sphinx to build our documentation, currently at version 7.2.6. 

Due to https://github.com/sphinx-doc/sphinx/issues/11883 we are currently pinning the CI to build our documentation under Sphinx 4.3.2 (released September 2022).

(This also means pinning associated modules, e.g. #4581; cross reference #4583 for consolidating this configuration information somewhere user-facing)


Discussion:

Resolving patch:
diff --git a/Bio/PDB/internal_coords.py b/Bio/PDB/internal_coords.py
--- a/Bio/PDB/internal_coords.py
+++ b/Bio/PDB/internal_coords.py
@@ -302,7 +302,8 @@
 
 if TYPE_CHECKING:
     from Bio.PDB.Residue import Residue
-    from Bio.PDB.Chain import Chain
+
+    # from Bio.PDB.Chain import Chain
 
 HKT = Tuple["AtomKey", "AtomKey", "AtomKey"]  # Hedron key tuple
 DKT = Tuple["AtomKey", "AtomKey", "AtomKey", "AtomKey"]  # Dihedron Key Tuple
@@ -481,7 +482,7 @@ class IC_Chain:
     _dihedraSelect = np.array([True, True, True, False])
     _dihedraOK = np.array([True, True, True, True])
 
-    def __init__(self, parent: "Chain", verbose: bool = False) -> None:
+    def __init__(self, parent, verbose: bool = False) -> None:
         """Initialize IC_Chain object, with or without residue/Atom data.
 
         :param Bio.PDB.Chain parent: Biopython Chain object


Test patch:
Repository: biopython/biopython

Issue:
Fix motif.Motif.weblogo API version
Currently adapted to WebLogo v2.8.2 and the last version is 3.7.12!


Discussion:
You mean https://github.com/biopython/biopython/blob/biopython-182/Bio/motifs/__init__.py#L595 which has a default argument of 2.8.2 but the docstring says "Currently, this method uses WebLogo version 3.3."

In fact the version argument is unused (and hasn't been in years). We should probably change the function definition "version=None" and put up a deprecation warning if the argument is used.

Do you want to make a pull request doing this?
hey @peterjc I can take on adding the deprecation warning

Resolving patch:
diff --git a/Bio/motifs/__init__.py b/Bio/motifs/__init__.py
--- a/Bio/motifs/__init__.py
+++ b/Bio/motifs/__init__.py
@@ -592,11 +592,13 @@ def relative_entropy(self):
                 values[mask] += frequencies * np.log2(frequencies / background[letter])
         return values
 
-    def weblogo(self, fname, fmt="PNG", version="2.8.2", **kwds):
+    def weblogo(self, fname, fmt="PNG", version=None, **kwds):
         """Download and save a weblogo using the Berkeley weblogo service.
 
         Requires an internet connection.
 
+        The version parameter is deprecated and has no effect.
+
         The parameters from ``**kwds`` are passed directly to the weblogo server.
 
         Currently, this method uses WebLogo version 3.3.
@@ -639,6 +641,12 @@ def weblogo(self, fname, fmt="PNG", version="2.8.2", **kwds):
             'color4': '',
 
         """
+        if version is not None:
+            warnings.warn(
+                "The version parameter is deprecated and has no effect.",
+                BiopythonDeprecationWarning,
+            )
+
         if set(self.alphabet) == set("ACDEFGHIKLMNPQRSTVWY"):
             alpha = "alphabet_protein"
         elif set(self.alphabet) == set("ACGU"):


Test patch:
Repository: biopython/biopython

Issue:
`Blast.NCBIWWW.qblast` should return the `rid` of the submitted query to the caller 
When using `qblast` to automate blast searches on NCBI, the RID of the submitted request is not returned to the user.  The RID is also not accessible anywhere within the `xml`-formatted output.  

The RID may be useful for later retrieval from NCBI, using the URL `https://blast.ncbi.nlm.nih.gov/Blast.cgi?RID={{rid}}&CMD=Get`, especially for submitted jobs that take a while to perform, and where the user may wish to revisit the results in the more accessible webpage view.  

Within `qblast`, the RID is already accessed using 

```python
rid, rtoe = _parse_qblast_ref_page(handle)
```

At the moment, I am using a modified version of the `qblast` function that returns a dictionary of values, as a workaround: 

https://github.com/kamurani/biopython/blob/c58c401b7a94bf06e13fadc4f41d5076dd1c78f4/Bio/Blast/NCBIWWW.py#L302-L307

https://github.com/kamurani/biopython/commit/c58c401b7a94bf06e13fadc4f41d5076dd1c78f4

Is this something that I could modify further to be a useful feature? Would appreciate any advice, and if so happy to make a PR.




Discussion:
Duplicate of #4263. Your suggested change is an API break (so not acceptable), see also the proposal on #3342 was backward compatible which could be worth reconsidering.
@kamurani Have a look at the new qblast function in `Bio/Blast/__init__.py`. It contains a new qblast function that solves some of the issues of the old qblast function in `Bio/Blast/NCBIWWW.py`. As it has not yet been released, its API can still be changed.

Resolving patch:
diff --git a/Bio/Blast/__init__.py b/Bio/Blast/__init__.py
--- a/Bio/Blast/__init__.py
+++ b/Bio/Blast/__init__.py
@@ -1078,6 +1078,10 @@ def qblast(
     and passes the values to the server as is.  More help is available at:
     https://ncbi.github.io/blast-cloud/dev/api.html
 
+    The http.client.HTTPResponse object returned by this function has the
+    additional attributes rid and rtoe with the Request ID and Request Time Of
+    Execution for this BLAST search.
+
     """
     programs = ["blastn", "blastp", "blastx", "tblastn", "tblastx"]
     if program not in programs:
@@ -1241,6 +1245,8 @@ def qblast(
         assert data.startswith(b"<p><!--\nQBlastInfoBegin")
     elif format_type in ("XML2", "JSON2"):
         assert data.startswith(b"PK\x03\x04")  # zipped file
+    stream.rid = rid
+    stream.rtoe = rtoe
     return stream
 
 


Test patch:
Repository: biopython/biopython

Issue:
scipy 1.14.0 breaks Bio.phenotype
Spotted via a regression on the master branch. See https://docs.scipy.org/doc/scipy/release/1.14.0-notes.html which says scipy 1.14.0 (released 15 June 2024) removed deprecated function ``scipy.integrate.trapz`` in favour of ``trapezoid``.

This requires updating ``Bio.phenotype`` but also I would have expected the test to have been skipped rather than failed:

```
======================================================================
ERROR: test_WellRecord (test_phenotype_fit.TestPhenoMicro.test_WellRecord)
Test basic functionalities of WellRecord objects.
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages/Bio/phenotype/pm_fitting.py", line 27, in <module>
    from scipy.integrate import trapz
Skipping any tests requiring internet access
Python version: 3.11.9 (main, Jun 20 2024, 16:02:53) [GCC 11.4.0]
Operating system: posix linux
ImportError: cannot import name 'trapz' from 'scipy.integrate' (/opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages/scipy/integrate/__init__.py)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/runner/work/biopython/biopython/Tests/test_phenotype_fit.py", line 63, in test_WellRecord
    w.fit()
  File "/opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages/Bio/phenotype/phen_micro.py", line 882, in fit
    from .pm_fitting import fit, get_area
  File "/opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages/Bio/phenotype/pm_fitting.py", line 31, in <module>
    raise MissingPythonDependencyError("Install scipy to extract curve parameters.")
Bio.MissingPythonDependencyError: Install scipy to extract curve parameters.

----------------------------------------------------------------------
```


Discussion:
New function name looks to have been added in scipy 1.12.0 https://docs.scipy.org/doc/scipy/release/1.12.0-notes.html and is just a name change, so an easy fix.

Resolving patch:
diff --git a/Bio/phenotype/pm_fitting.py b/Bio/phenotype/pm_fitting.py
--- a/Bio/phenotype/pm_fitting.py
+++ b/Bio/phenotype/pm_fitting.py
@@ -24,12 +24,17 @@
 
 try:
     from scipy.optimize.minpack import curve_fit
-    from scipy.integrate import trapz
 except ImportError:
     from Bio import MissingPythonDependencyError
 
     raise MissingPythonDependencyError("Install scipy to extract curve parameters.")
 
+try:
+    from scipy.integrate import trapezoid
+except ImportError:
+    # Assume this is prior to scipy 1.12.0 and try old name:
+    from scipy.integrate import trapz as trapezoid
+
 
 def logistic(x, A, u, d, v, y0):
     """Logistic growth model.
@@ -143,4 +148,4 @@ def fit(function, x, y):
 
 def get_area(y, x):
     """Get the area under the curve."""
-    return trapz(y=y, x=x)
+    return trapezoid(y=y, x=x)


Test patch:
Repository: Qiskit/qiskit

Issue:
basis_gates not being passed to JSON unroller
Currently there the `basis_gates` argument of the `compile` function is ignored when compiling circuits to JSON. This fix simply passes the value of basis gates to the dag2json compiler so that the JSON can be compiled in a user specified set of basis_gates as intended.

## Expected Behavior
When you run `QuantumProgram.compile('circuit', basis_gates='a,b,c,d')` the resulting qobj should compile using the basis gates `a,b,c,d`.

## Current Behavior
When you run `QuantumProgram.compile('circuit', basis_gates='a,b,c,d')`  the JSON unroller is always passed `basis_gates='u1,u2,u3,cx,id` instead.

## Possible Solution
Will add pull request to fix this by adding basis_gates argument to the `dag2json` function in `_openquantumcompiler.py`.



Discussion:

Resolving patch:
diff --git a/qiskit/_openquantumcompiler.py b/qiskit/_openquantumcompiler.py
--- a/qiskit/_openquantumcompiler.py
+++ b/qiskit/_openquantumcompiler.py
@@ -122,7 +122,7 @@ def load_unroll_qasm_file(filename, basis_gates='u1,u2,u3,cx,id'):
     circuit_unrolled = unrolled_circuit.execute()
     return circuit_unrolled
     
-def dag2json(dag_circuit):
+def dag2json(dag_circuit, basis_gates='u1,u2,u3,cx,id'):
     """Make a Json representation of the circuit.
 
     Takes a circuit dag and returns json circuit obj. This is an internal
@@ -139,7 +139,6 @@ def dag2json(dag_circuit):
         circuit_string = dag_circuit.qasm(qeflag=True)
     except TypeError:
         circuit_string = dag_circuit.qasm()
-    basis_gates = "u1,u2,u3,cx,id"  # QE target basis
     unroller = unroll.Unroller(qasm.Qasm(data=circuit_string).parse(),
                                unroll.JsonBackend(basis_gates.split(",")))
     json_circuit = unroller.execute()
diff --git a/qiskit/_quantumprogram.py b/qiskit/_quantumprogram.py
--- a/qiskit/_quantumprogram.py
+++ b/qiskit/_quantumprogram.py
@@ -875,7 +875,8 @@ def compile(self, name_of_circuits, backend="local_qasm_simulator",
             else:
                 job["config"]["seed"] = seed
             # the compiled circuit to be run saved as a dag
-            job["compiled_circuit"] = openquantumcompiler.dag2json(dag_circuit)
+            job["compiled_circuit"] = openquantumcompiler.dag2json(dag_circuit,
+                                                                   basis_gates=basis_gates)
             job["compiled_circuit_qasm"] = dag_circuit.qasm(qeflag=True)
             # add job to the qobj
             qobj["circuits"].append(job)


Test patch:
Repository: Qiskit/qiskit

Issue:
Error in evaluating Pauli-list style Hamiltonian
tools.optimization.eval_hamiltonian() fails by error if hamiltonian is given as pauli list.

## Possible Solution
I found an obvious invalid source format, so I'll fix it.

## Steps to Reproduce (for bugs)
1. Open qiskit-tutorial/4_application/quantum_chemistry.ipynb (latest stable branch) with qiskit-sdk-py (latest stable branch)
2. Just before the first definition of cost_function(), insert `H = pauli_list`
3. Run the notebook
-> AttributeError: 'dict' object has no attribute 'conjugate' at line 344

## Context
Trying to understand tutorial more by running it with slightly modified parameters



Discussion:

Resolving patch:
diff --git a/qiskit/tools/apps/optimization.py b/qiskit/tools/apps/optimization.py
--- a/qiskit/tools/apps/optimization.py
+++ b/qiskit/tools/apps/optimization.py
@@ -317,11 +317,12 @@ def eval_hamiltonian(Q_program, hamiltonian, input_circuit, shots, device):
             Q_program.add_circuit(circuits_labels[0], circuits[0])
             # Execute trial circuit with final rotations for each Pauli in
             # hamiltonian and store from circuits[1] on
-            q = QuantumRegister("q", int(np.log2(len(hamiltonian))))
+            n_qubits = input_circuit.regs['q'].size
+            q = QuantumRegister("q", n_qubits)
             i = 1
             for p in hamiltonian:
                 circuits.append(copy.deepcopy(input_circuit))
-                for j in range(int(np.log2(len(hamiltonian)))):
+                for j in range(n_qubits):
                     if p[1].v[j] == 1 and p[1].w[j] == 0:
                         circuits[i].x(q[j])
                     elif p[1].v[j] == 0 and p[1].w[j] == 1:
@@ -334,12 +335,10 @@ def eval_hamiltonian(Q_program, hamiltonian, input_circuit, shots, device):
                 i += 1
             result = Q_program.execute(circuits_labels, device, shots=shots)
             # no Pauli final rotations
-            quantum_state_0 = result.get_data(circuits_labels[0])
-            ['quantum_state']
+            quantum_state_0 = result.get_data(circuits_labels[0])['quantum_state']
             i = 1
             for p in hamiltonian:
-                quantum_state_i = result.get_data(circuits_labels[i])
-                ['quantum_state']
+                quantum_state_i = result.get_data(circuits_labels[i])['quantum_state']
                 # inner product with final rotations of (i-1)-th Pauli
                 energy += p[0] * np.inner(np.conjugate(quantum_state_0),
                                           quantum_state_i)


Test patch: