pmt0512
pmt0512

Reputation: 79

Python programming help

I have this python file that I'm working on:

class Range:
    """ An object that has a non-negative start position and a non-negative length"""
    def __init__(self, start, end):
                """
                Function: generates a new Range
                Returns : a new range
                Args    : start - start position
                          end - end position
                Start and End must be non-negative """
                self.start = 0
                self.end = 10000
        self.setStart(start)
        self.setEnd(end)
    def getStart(self):
                """
                Function: get the start of the range
                Returns : a number or None
                Args    : start - the int index of the first nucleotide of this range """
        return self.start
    def setStart(self, s):
                """
                Function: set the start of the range
                Returns : None
                Args    : start - a non-negative int or None """
                if type(s) !=int:
                        raise TypeError ("Cannot set Start as this is not an interger")
                elif s < 0:
                        raise ValueError ("Cannot set Start as this is not a non-negative int")
                elif s > self.end:
                        raise ValueError("start cannot be larger than end")
                else:
                        self.start = s
    def getEnd(self):
                """
                Function: get the end of the range
                Returns : a number
                Args    : 
                """
        return self.end
    def setEnd(self, e):
                """
                Function: set the end of the range
                Returns : None
                Args    : end - a non-negative int or None
                """
                if type(e) !=int:
                        raise TypeError ("Cannot set End as this is not an interger")
                elif e < 0:
                        raise ValueError ("Cannot set End as this is not a non-negative int")
                elif e < self.start:
                        raise ValueError ("end has to be larger than start")
                else:
                        self.end = e
    def getLength(self):
                """
                Function: get the length of the range
                Returns : an int. the length of this range
                Args:
                """
                return self.end - self.start
    def overlaps(self, r):
                """
                Function: to test if two nucleotide is overlap
                Returns : True or False
                Args    : other - a Range object
                """
                start1 = self.getStart()
                end1 = start1 + self.getLength()
                start2 = r.getStart()
                end2 = start2 + self.getLength()
                max_start = max(start1,start2)
                min_end = min(end1,end2)
                return min_end - max_start > 0
        if self.getStart() == r.getStart():
                        return True
        else:
            return False

class DNAFeature(Range):
        """Represents a feature on a DNA sequence """
        def __init__(self, seq_name = None, strand = 0, **kwargs):
                """
                Function : represents a rane
                Returns  :
                Args     : strand, seqname, **kwargs
                """         
                Range.__init__(self, **kwargs)
                self.setStrand(strand)
                self.setSeqName(seq_name)
        def getSeqName(self):
                """
                Function: Gets object's Sequence Name
                Returns : seqname - string
                Args    : 
                """
                return self.seq_name
        def setSeqName(self, seq_name):
                """
                Function: Sets object's Sequence Name
                Returns : None
                Args    : seqname - mRNA accession name
                """
        self.seq_name = seq_name
        def getStrand(self):
                """
                Function: Retrieve the strand affiliation of this
                Returns : 1, 0, -1 - strand
                Args    : 
                """
                return self.strand
        def setStrand(self, strand):
                """
                Function: sets which strand the object is on
                Returns : None
                Args    : strand - one of ['+',1,'F','-',-1,'R']
                """
                StrandValues = [1, 0, -1]

        if not strand in StrandValues:
            raise ValueError("only able to setStrand if the values is 1, 0, or -1")
        else:
                        self.strand = strand
        def overlaps(self, other, ignore_strand = True): 
                """
                Function: tests if this overlaps other
                Returns : true if the ranges have same Seqname and overlap, false if not
                Args    : other - another Range object
                """
                if ignore_strand == True and self.getSeqName() == other.getSeqName():
                    return Range.overlaps(self,other)
                else:
                    return False

class GeneModel(DNAFeature):
        def __init__(self, transl_start=None, transl_stop=None, display_id = None, **kwargs):
               """
               Function : contains a group of DNAFeature objects representing exons
               Returns  :
               Args     : **kwargs
               """
               DNAFeature.__init__(self, **kwargs)
               self.setTranslStart(transl_start)
               self.setTranslStop(transl_stop)
               self.setDisplayId(display_id)
               self.exons = [ ]
        def getFeats(self):
                """
                Function: gets object's feats list
                Returns : list of feature keys
                Args    : feature_type - the type of strand the object holds
                """
                self.exons.sort(cmp=self.start)
                return self.exons
        def addFeat(self, feat):
                """
                Function: adds SeqFeature to feats keys
                Returns : None
                Args    : feat - a single SeqFeature object
                """
                if type(feat) == DNAFeature:
                        self.exons.append(feat)
                else:
                        raise TypeError("Cannot add feature as it is not a type of DNAFeature")
        def setTranslStart(self, transl_start):
               """
               Function : accepts an non-negative int, sets the start position of the initiating ATG
               Returns  :
               Args     : transl_start
               """
               if transl_start == None:
                   self.transl_start = None
                   return
               elif type(transl_start) !=int:
                   raise TypeError("TranslStart cannot be set since it is not a type of int")
               elif transl_start < 0:
                   raise ValueError("TranslStart cannot be set to a negative int")
               else:
                   self.translStart = transl_start
        def getTranslStart(self):
                """
                Function: the start position of initiating ATG codon
                Return  : an int.
                Args    :
                """
                return self.transl_start
        def setTranslStop(self, transl_stop):
                """
                Function: set the end position of initiating ATG codon
                Return : None
                Args   : a positive int
                """
                if transl_stop == None:
                   self.transl_stop = None
                   return
                elif type(transl_stop) !=int:
                   raise TypeError("TranslStop cannot be set since it is not a type of int")
                elif transl_stop < 0:
                   raise ValueError("TranslStop cannot be set to a negative int")
                else:
                   self.translStop = transl_stop
        def getTranslStop(self):
                """
                Function: the end position of initiating ATG codon
                Return  : an int.
                Args    :
                """
                return self.transl_stop
        def setDisplayId(self, display_id):
                """
                Function: set the display id
                Returns : None
                Args    : display_id - a string, a preferred name for this
                """
                if type(display_id) !=str:
                        raise TypeError("Cannot set displayId as it is not a type string")
                else:
                        self.display_id = display_id
        def getDisplayId(self):
                """
                Function: get the display id
                Returns : display_id - a string, a preferred name for this, e.g AT1G10555.1
                Args    : 
                """
                return self.display_id

Then, I got some code from my professor to test my file:

class TestGeneModelConstructor(unittest.TestCase):
    def testGeneModelConstructor(self):
        """GeneModel constructor supports named arguments display_id,transl_start,transl_stop"""
        p1.GeneModel(start=0,end=10,seq_name='something',strand=1,display_id='foobar',
                     transl_start=0,transl_stop=10)

    def testGeneModelConstructorDefaults(self):
        """Default values for display_id, transl_start, transl_stop should be None"""
        r = p1.GeneModel()
        self.assertEquals(r.getDisplayId(),None)
        self.assertEquals(r.getTranslStart(),None)
        self.assertEquals(r.getTranslStop(),None)

    def testGeneModelConstructorWrongTypeDisplayId(self):
        """Raise a TypeError if display_id is not a string."""
        self.assertRaises(TypeError,p1.GeneModel,display_id=0)

    def testGeneModelConstructorWrongTypeTranslStart(self):
        """Raise a TypeError if transl_start is not an int."""
        self.assertRaises(TypeError,p1.GeneModel,transl_start='0')

    def testGeneModelConstructorWrongTypeTranslStop(self):
        """Raise a TypeError if transl_stop is not an int."""
        self.assertRaises(TypeError,p1.GeneModel,transl_stop='0')

    def testGeneModelConstructorWrongValueTranslStart(self):
        """Raise a ValueError if transl_start is int < 0."""
        self.assertRaises(ValueError,p1.GeneModel,transl_start=-1)

    def testGeneModelConstructorWrongValueTranslStop(self):
        """Raise a ValueError if transl_stop is int < 0."""
        self.assertRaises(ValueError,p1.GeneModel,transl_stop=-1)

I have run it and got these errors:

ERROR: Default values for display_id, transl_start, transl_stop should be None
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/trungpham/binf_prog/class/test/testProject1.py", line 117, in testGeneModelConstructorDefaults
    r = p1.GeneModel()
TypeError: __init__() takes at least 3 arguments (1 given)

======================================================================
ERROR: Raise a ValueError if transl_start is int < 0.
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/trungpham/binf_prog/class/test/testProject1.py", line 136, in testGeneModelConstructorWrongValueTranslStart
    self.assertRaises(ValueError,p1.GeneModel,transl_start=-1)
  File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/unittest.py", line 336, in failUnlessRaises
TypeError: __init__() takes at least 3 non-keyword arguments (2 given)

======================================================================
ERROR: Raise a ValueError if transl_stop is int < 0.
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/trungpham/binf_prog/class/test/testProject1.py", line 140, in testGeneModelConstructorWrongValueTranslStop
    self.assertRaises(ValueError,p1.GeneModel,transl_stop=-1)
  File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/unittest.py", line 336, in failUnlessRaises
TypeError: __init__() takes at least 3 non-keyword arguments (1 given)

I'm not sure what is wrong, I have tried to fixed it couple times, but haven't figure out what is wrong in my codes.

Alright, I have change my code in DNAFeature like this:

class DNAFeature(Range):
    """Represents a feature on a DNA sequence """
    def __init__(self, seq_name = None, strand = 0, **kwargs):
            """
            Function : represents a rane
            Returns  :
            Args     : strand, seqname, **kwargs
            """         
            Range.__init__(self, 0,10000, **kwargs)
            self.setStrand(strand)
            self.setSeqName(seq_name)

And then, get 3 more errors and 1 failure like this:

ERROR: DNAFeature on different sequence don't overlap
----------------------------------------------------------------------
  Traceback (most recent call last):
     File "/Users/trungpham/binf_prog/class/test/testProject1.py", line 164, in testDiffSequenceOverlaps
    r1 = p1.DNAFeature(start=0,end=10,strand=1,seq_name="foo")
     File "/Users/trungpham/binf_prog/tpham22/project1/p1.py", line 95, in __init__
    Range.__init__(self, 0, 10000, **kwargs)
TypeError: __init__() got multiple values for keyword argument 'start'

======================================================================
 ERROR: DNAFeatures on the same strand can overlap if ignore_strand is True.
----------------------------------------------------------------------
  Traceback (most recent call last):
     File "/Users/trungpham/binf_prog/class/test/testProject1.py", line 185, in testDiffStrandsDontOverlap
    r1 = p1.DNAFeature(start=0,end=10,strand=1,seq_name="foo")
     File "/Users/trungpham/binf_prog/tpham22/project1/p1.py", line 95, in __init__
    Range.__init__(self, 0, 10000, **kwargs)
TypeError: __init__() got multiple values for keyword argument 'start'

======================================================================
ERROR: GeneModel constructor supports named arguments display_id,transl_start,transl_stop
----------------------------------------------------------------------
    Traceback (most recent call last):
      File "/Users/trungpham/binf_prog/class/test/testProject1.py", line 113, in testGeneModelConstructor
    transl_start=0,transl_stop=10)
     File "/Users/trungpham/binf_prog/tpham22/project1/p1.py", line 151, in __init__
    DNAFeature.__init__(self, **kwargs)
      File "/Users/trungpham/binf_prog/tpham22/project1/p1.py", line 95, in __init__
    Range.__init__(self, 0, 10000, **kwargs)
TypeError: __init__() got multiple values for keyword argument 'start'

FAIL: Raise a TypeError if seq_name is not a string.
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/trungpham/binf_prog/class/test/testProject1.py", line 98, in testDNAFeatureSeqNameConstructorWrongType
    self.assertRaises(TypeError,p1.DNAFeature,seq_name=0)
AssertionError: TypeError not raised

Upvotes: 4

Views: 1929

Answers (3)

Smashery
Smashery

Reputation: 59653

There are several things wrong:

Firstly:

In your test function, testGeneModelConstructorDefaults, you have the comment: "Default values for display_id, transl_start, transl_stop should be None".

The problem you are seeing is that you have only set up the defaults on 1 of the 3 arguments; whereas this test function assumes you have set up defaults on all three. To fix this, you need to define the constructor like this:

def __init__(self, transl_start=None, transl_stop=None, display_id = None, **kwargs)

By having the keyword arguments, it will use the default of None. If you don't specify those keyword arguments explicitly, Python will complain (as it is currently doing).

Secondly:

You have to consider your superclass constructors. The Range superclass asks for two parameters: start and end.

def __init__(self, start, end):

However, when the DNAFeature constructor calls the Range superclass, it doesn't pass in begin or end:

Range.__init__(self, **kwargs)

This is where I think the error is now (I think before it was at the p1.GeneModel() call - there are probably different error lines in your two error messages).

To fix this, make the values for start and end into keyword parameters also. So instead of:

def __init__(self, start, end):

make it:

def __init__(self, start=0, end=10000):

You can then delete the following lines of code in your range constructor:

self.start = 0
self.end = 10000

That should at least get you past this error - you may find more errors that you have.

Upvotes: 2

Hollister
Hollister

Reputation: 3908

Smashery is right. Try running this simplified code:

class GeneModel(object):
    def __init__(self, transl_start=None, transl_stop=None, display_id = None, **kwargs):
        pass

def testGeneModelConstructor():
    g = GeneModel(start=0,end=10,seq_name='something',strand=1,display_id='foobar', transl_start=0,transl_stop=10)

def testGeneModelConstructorDefaults():
    r = GeneModel()

testGeneModelConstructor()
testGeneModelConstructorDefaults()

Upvotes: 1

Bruce Armstrong
Bruce Armstrong

Reputation: 1602

It appears that the tests are assuming that all parameters are passed by value. You need to give the positional arguments defaults.

Upvotes: 1

Related Questions