diff --git a/.travis.yml b/.travis.yml index 31fe4e4..67d2121 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,11 +2,13 @@ language: python python: - '3.4' - '3.3' +- '3.2' - '2.7' - '2.6' - pypy +- pypy3 install: -- pip install biopython +- pip install biopython || true - pip install -e . script: nosetests deploy: diff --git a/pyfaidx/__init__.py b/pyfaidx/__init__.py index e7b1860..37cbaab 100644 --- a/pyfaidx/__init__.py +++ b/pyfaidx/__init__.py @@ -391,6 +391,7 @@ class FastaRecord(object): def __init__(self, name, fa): self.name = name self._fa = fa + self._len = self._fa.faidx.index[self.name].rlen def __getitem__(self, n): """Return sequence from region [start, end) @@ -416,12 +417,23 @@ def __getitem__(self, n): except FetchError: raise + def __iter__(self): + line_len = self._fa.faidx.index[self.name].lenc + start = 0 + while True: + end = start + line_len + if end < len(self): + yield self[start:end] + else: + yield self[start:] + raise StopIteration + start += line_len + def __repr__(self): return 'FastaRecord("%s")' % (self.name) def __len__(self): - """ Return length of chromosome """ - return self._fa.faidx.index[self.name].rlen + return self._len def __str__(self): return str(self[:]) diff --git a/tests/test_FastaRecord_iter.py b/tests/test_FastaRecord_iter.py new file mode 100644 index 0000000..467f265 --- /dev/null +++ b/tests/test_FastaRecord_iter.py @@ -0,0 +1,19 @@ +import os +from pyfaidx import Fasta + +path = os.path.dirname(__file__) +os.chdir(path) + +class TestFastaRecordIter: + def __init__(self): + self.genes = os.path.join(path, 'data/genes.fasta') + self.fasta = Fasta(self.genes) + + def test_fetch_whole_fasta(self): + expect = open(self.genes).read() + result = ''.join(['>' + record.name + '\n' + ''.join([line.seq + '\n' for line in record]) for record in self.fasta]).rstrip() + assert expect == result + + def test_line_len(self): + for record in self.fasta: + assert len(next(iter(record))) == self.fasta.faidx.index[record.name].lenc diff --git a/tests/test_bio_seqio.py b/tests/test_bio_seqio.py index 96b833d..0becb0c 100644 --- a/tests/test_bio_seqio.py +++ b/tests/test_bio_seqio.py @@ -1,6 +1,11 @@ import os from pyfaidx import Fasta, FetchError -from Bio import SeqIO +from nose.plugins.skip import Skip, SkipTest +try: + from Bio import SeqIO + test_bio = True +except ImportError: + test_bio = False path = os.path.dirname(__file__) os.chdir(path) @@ -9,15 +14,25 @@ class TestBioSeqIO: def __init__(self): self.genes = os.path.join(path, 'data/genes.fasta') self.fasta = Fasta(self.genes) - with open(self.genes, "rU") as fh: - self.seqio = SeqIO.to_dict(SeqIO.parse(fh, "fasta")) + if test_bio: + with open(self.genes, "rU") as fh: + self.seqio = SeqIO.to_dict(SeqIO.parse(fh, "fasta")) def test_fetch_whole_entry(self): - assert str(self.fasta['KF435150.1']) == str(self.seqio['KF435150.1'].seq) - assert self.fasta['KF435150.1'].name == str(self.seqio['KF435150.1'].name) + if test_bio: + assert str(self.fasta['KF435150.1']) == str(self.seqio['KF435150.1'].seq) + assert self.fasta['KF435150.1'].name == str(self.seqio['KF435150.1'].name) + else: + raise SkipTest def test_slice_whole_entry(self): - assert str(self.fasta['KF435150.1'][::3]) == str(self.seqio['KF435150.1'].seq[::3]) + if test_bio: + assert str(self.fasta['KF435150.1'][::3]) == str(self.seqio['KF435150.1'].seq[::3]) + else: + raise SkipTest def test_revcomp_whole_entry(self): - assert str(self.fasta['KF435150.1'][:].reverse.complement) == str(self.seqio['KF435150.1'].reverse_complement().seq) + if test_bio: + assert str(self.fasta['KF435150.1'][:].reverse.complement) == str(self.seqio['KF435150.1'].reverse_complement().seq) + else: + raise SkipTest