Skip to content

Commit

Permalink
Update tests & constrain behavior in various ways. (#54)
Browse files Browse the repository at this point in the history
* require that Record objects have name, sequence
* new file for Record-specific tests
* remove 'quality' if set to None
  • Loading branch information
ctb authored and luizirber committed Dec 20, 2016
1 parent 6ad556b commit 3bc817c
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 9 deletions.
4 changes: 2 additions & 2 deletions screed/fasta.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ def fasta_iter(handle, parse_description=False, line=None):
line = handle.readline()

while line:
data = Record()
data = {}

line = to_str(line.strip())
if not line.startswith('>'):
Expand All @@ -45,4 +45,4 @@ def fasta_iter(handle, parse_description=False, line=None):
line = to_str(handle.readline())

data['sequence'] = ''.join(sequenceList)
yield data
yield Record(**data)
4 changes: 2 additions & 2 deletions screed/fastq.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def fastq_iter(handle, line=None, parse_description=False):
line = handle.readline()
line = to_str(line.strip())
while line:
data = Record()
data = {}

if line and not line.startswith('@'):
raise IOError("Bad FASTQ format: no '@' at beginning of line")
Expand Down Expand Up @@ -60,4 +60,4 @@ def fastq_iter(handle, line=None, parse_description=False):
raise IOError('sequence and quality strings must be '
'of equal length')

yield data
yield Record(**data)
24 changes: 19 additions & 5 deletions screed/screedRecord.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,22 @@ class Record(MutableMapping):
Simple dict-like record interface with bag behavior.
"""

def __init__(self, *args, **kwargs):
self.d = dict(*args, **kwargs)
def __init__(self, name=None, sequence=None, **kwargs):
d = dict()
if name is not None:
d['name'] = name
if sequence is not None:
d['sequence'] = sequence

d.update(kwargs)

if 'name' not in d:
raise TypeError("'name' must be specified")
if 'sequence' not in d:
raise TypeError("'sequence' must be specified")
if 'quality' in d and d['quality'] is None:
del d['quality']
self.d = d

def __setitem__(self, name, value):
self.d[name] = value
Expand All @@ -38,11 +52,11 @@ def keys(self):

def __getitem__(self, idx):
if isinstance(idx, slice):
trimmed = Record(self.d)
trimmed = dict(self.d)
trimmed['sequence'] = trimmed['sequence'][idx]
if 'quality' in trimmed:
trimmed['quality'] = trimmed['quality'][idx]
return Record(trimmed)
return Record(**trimmed)
return self.d[idx]

def __delitem__(self, key):
Expand Down Expand Up @@ -178,7 +192,7 @@ def _buildRecord(fieldTuple, dbObj, rowName, queryBy):
else:
hackedResult.append((key, value))

return Record(hackedResult)
return Record(**dict(hackedResult))


def write_fastx(record, fileobj):
Expand Down
1 change: 1 addition & 0 deletions screed/tests/test_fasta.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ def test_new_record():
records = list(iter(screed.fasta.fasta_iter(s)))
assert records[0]['name'] == '1'
assert records[1]['name'] == '2'
assert not hasattr(records[0], 'accuracy') # check for legacy attribute


class Test_fasta(object):
Expand Down
48 changes: 48 additions & 0 deletions screed/tests/test_record.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
from __future__ import absolute_import, unicode_literals, print_function
from screed import Record
import pytest


@pytest.mark.xfail(raises=TypeError)
def test_create_noname():
r = Record(sequence='ATGGAC')


@pytest.mark.xfail(raises=TypeError)
def test_create_noseq():
r = Record(name='somename')


def test_create_quality_none():
r = Record(name='foo', sequence='ATGACG', quality=None)
assert not hasattr(r, 'quality')


def test_len():
r = Record(name='foo', sequence='ATGACG')
assert len(r) == 6


# copied over from khmer tests/test_read_parsers.py
def test_read_type_basic():
# Constructing without mandatory arguments should raise an exception
with pytest.raises(TypeError):
Record()

name = "895:1:1:1246:14654 1:N:0:NNNNN"
sequence = "ACGT"
r = Record(name, sequence)

assert r.name == name
assert r.sequence == sequence
assert not hasattr(r, 'quality'), x
assert not hasattr(r, 'annotations'), x


# copied over from khmer tests/test_read_parsers.py
def test_read_type_attributes():
r = Record(sequence='ACGT', quality='good', name='1234', annotations='ann')
assert r.sequence == 'ACGT'
assert r.quality == 'good'
assert r.name == '1234'
assert r.annotations == 'ann'

0 comments on commit 3bc817c

Please sign in to comment.