Repository: biopython/biopython

Issue:
SeqRecord broken on Debian packages when -sql package is not installed
### Setup

I am reporting a problem with Biopython version, Python version, and operating
system as follows:

```
2.7.13 (default, Jan 19 2017, 14:48:08) 
[GCC 6.3.0 20170118]
CPython
Linux-4.4.0-93-generic-x86_64-with-debian-9.1
1.68
```

This is a Debian 9 (stretch), with `python-biopython` installed and `python-biopython-sql` not installed.

### Expected behaviour

Calling `extract` on a `SeqFeature` that's coming from a `SeqRecord` loaded from a GenBank file on disk works.

### Actual behaviour

`__getitem__` in `SeqRecord` imports `BioSQL.BioSeq` without a `try/except` block, causing the script to crash.

```
Traceback (most recent call last):
  File "/usr/local/bin/run_antismash.py", line 1210, in <module>
    main()
  File "/usr/local/bin/run_antismash.py", line 556, in main
    run_analyses(seq_record, options, plugins)
  File "/usr/local/bin/run_antismash.py", line 640, in run_analyses
    cluster_specific_analysis(plugins, seq_record, options)
  File "/usr/local/bin/run_antismash.py", line 1191, in cluster_specific_analysis
    plugin.specific_analysis(seq_record, options)
  File "/antismash-dev/antismash/specific_modules/nrpspks/specific_analysis.py", line 81, in specific_analysis
    pksnrpsvars = annotate_pksnrps(pksnrpsvars, seq_record, options)
  File "/antismash-dev/antismash/specific_modules/nrpspks/nrpspksdomains.py", line 28, in annotate_pksnrps
    name_nrpspks(seq_record, pksnrpsvars, withinclustergenes, options)
  File "/antismash-dev/antismash/specific_modules/nrpspks/nrpspksdomains.py", line 163, in name_nrpspks
    quals['translation'] = [str(motifFeature.extract(seq_record).seq.translate(table=transl_table))]
  File "/usr/lib/python2.7/dist-packages/Bio/SeqFeature.py", line 329, in extract
    return self.location.extract(parent_sequence)
  File "/usr/lib/python2.7/dist-packages/Bio/SeqFeature.py", line 936, in extract
    f_seq = parent_sequence[self.nofuzzy_start:self.nofuzzy_end]
  File "/usr/lib/python2.7/dist-packages/Bio/SeqRecord.py", line 439, in __getitem__
    from BioSQL.BioSeq import DBSeqRecord
ImportError: No module named BioSQL.BioSeq
```

### Steps to reproduce

Set up a pristine Debian install like this:

```bash
docker run --rm -it debian:stretch
apt update && apt install -y python-biopython
```
Then run the following python script:

```python
from Bio.Seq import Seq
from Bio.SeqRecord import SeqRecord
seq = Seq("ATGGCAGGCATCTGCTAG")
rec = SeqRecord(seq)
rec[:5]
```


Discussion:
Just to confirm, installing `python-biopython-sql` in addition to `python-biopython` makes this problem go away, at the cost of pulling in client-side MariaDB.
As discussed on Twitter, due to change in Biopython 1.68 onwards https://github.com/biopython/biopython/commit/48cd6bc1 - CC @ctSkennerton

Ideally all the ``Bio`` code would work without importing from ``BioSQL`` (as per the Debian split packaging approach).

We could implement ``__getitem__`` on the ``DBSeqRecord`` object (more code duplication for all the annotation handling), or perhaps make that isinstance check pass if the import fails (if the import fails, it can't be a ``DBSeqRecord`` object anyway)?
Cross reference https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=883860 (filed by @kblin)
I'm a bit stumped on how to write a meaningful test for this, otherwise I'd propose a patch that'd only do the `DBSeqRecord` logic if the import worked.

Resolving patch:
diff --git a/Bio/SeqRecord.py b/Bio/SeqRecord.py
--- a/Bio/SeqRecord.py
+++ b/Bio/SeqRecord.py
@@ -437,8 +437,13 @@ def __getitem__(self, index):
             if self.seq is None:
                 raise ValueError("If the sequence is None, we cannot slice it.")
             parent_length = len(self)
-            from BioSQL.BioSeq import DBSeqRecord
-            if isinstance(self, DBSeqRecord):
+            try:
+                from BioSQL.BioSeq import DBSeqRecord
+                biosql_available = True
+            except ImportError:
+                biosql_available = False
+
+            if biosql_available and isinstance(self, DBSeqRecord):
                 answer = SeqRecord(self.seq[index],
                                         id=self.id,
                                         name=self.name,


Test patch: