Lab 5

Programming Exercise
  1. lab2q3WithErrorHandling.py
    
    import sys
    
    def isNumber(s):
        try:
            float(s)
            return True
        except ValueError:
            return False
        
    try:
    
        fileIn = open('datafile2.dat', 'r')
    
        clientDT=['Name','Address','Balance']
        clientDL=[]
        line = fileIn.readline()
    
        while line != '':
            clientRec=line.split('_')
            
            if len(clientRec) < 4:
                sys.stderr.write('Missing data : '+line+'\n')
            elif clientRec[0] == '' or clientRec[1] == '':
                sys.stderr.write('Invalid Name or Address : '+line+'\n')
            elif clientRec[2] != 'D' and clientRec[2] != 'C':
                sys.stderr.write('Invalid transaction code : '+line+'\n')
            elif not isNumber(clientRec[3]):
                sys.stderr.write('Transaction amt not number : '+line+'\n')
            elif float(clientRec[3]) < 0 or float(clientRec[3]) > 10000000 :
                sys.stderr.write('Invalid transaction amt : '+line+'\n')
            else:    
                if len(clientDL) == 0:
                    if clientRec[2] == 'D':
                        clientDL.append(dict(zip(clientDT,
                                         [clientRec[0],clientRec[1],float(clientRec[3])])))
                    else:
                        clientDL.append(dict(zip(clientDT,
                                         [clientRec[0],clientRec[1],-float(clientRec[3])])))            
                else: 
                    i = 0
                    while i < len(clientDL) and clientDL[i]['Name'] != clientRec[0]:
                        i += 1
                
                    if i == len(clientDL):
                        if clientRec[2] == 'D':   
                            clientDL.append(dict(zip(clientDT,
                                             [clientRec[0],clientRec[1],float(clientRec[3])])))
                        else:
                            clientDL.append(dict(zip(clientDT,
                                             [clientRec[0],clientRec[1],-float(clientRec[3])])))                
                    else:
                        if clientRec[2] == 'D':
                            clientDL[i]['Balance'] += float(clientRec[3])
                        else: clientDL[i]['Balance'] -= float(clientRec[3])
                
            line = fileIn.readline()
            
        if len(clientDL) == 0:
            sys.stderr.write('empty or invalid data only : '+line+'\n')
        else:                
            print('%-20s%-30s%10s'%(clientDT[0],clientDT[1],clientDT[2]))
            print('='*60)    
            for e in sorted(clientDL, key = lambda c: c['Name']):
                if e['Balance'] != 0:
                    print('%-20s%-30s%10.2f'%(e['Name'],e['Address'],e['Balance'])) 
              
        fileIn.close()
        
    except FileNotFoundError as error:
        sys.stderr.write(str(error)+'\n')
    
    
    Client.py
    
    class Client(object):
        '''
        Client class to represent each customer object
        '''
        numClient = 0 # class variable to record number of client
        
        def __init__(self, dataLine ):
            '''
            constructor method
            
            Parameters:
    	- dataLine with following data feilds
            	- name: name of customer
            	- address: name of customer
    		- transsaction code (not an attribute)
            	- balance: balance of customer
            '''
            
            clientRec=dataLine.split('_')
            if len(clientRec) < 4:
                raise ValueError('Missing data : ')
            elif clientRec[0] == '' or clientRec[1] == '':
                raise ValueError('Invalid Name or Address :')
            elif clientRec[2] != 'D' and clientRec[2] != 'C':
                raise ValueError('Invalid transaction code :')
            elif float(clientRec[3]) < 0 or float(clientRec[3]) > 10000000 :
                raise ValueError('Invalid transaction amt :')
           
            Client.numClient += 1
            
            self.name = clientRec[0]
            self.address = clientRec[1]
            if clientRec[2] == 'D':
                self.__balance = float(clientRec[3])
            else:
                self.__balance = -float(clientRec[3])
        
        def debit(self,amount):
            '''
            debit method to increase balance of liability account
            
            Parameters:
    
            - amount: amount to bebit     
            '''
            self.__balance += amount
            
        def credit(self,amount):
            '''
            credit method to increase balance of liability account
            
            Parameters:
    
            - amount: amount to credit     
            '''
            self.__balance -= amount
            
        def getBalance(self):
            '''
            accessor method to get balance
            '''
            return self.__balance
            
        def __str__(self):
            '''
            String representation of client object
            '''
            return '%-20s%-30s%10.2f'%\
                (self.name,self.address,self.__balance)
    
    sbUsingClientClassWithErrorhandling.py
    
    import sys
    from Client import Client
    
    try:             
        fileIn = open('datafile6.dat', 'r')
        
        clientDT=['Name','Address','Balance']
        clientDL=[]
        
        line = fileIn.readline()
        
        while line != '':
            clientRec=line.split('_')
            try:
                if Client.numClient == 0:
                    clientDL.append(Client(line))         
                else: 
                    i = 0
                    while i < Client.numClient and clientDL[i].name != clientRec[0]:
                        i += 1
                
                    if i == Client.numClient:
                        clientDL.append(Client(line))                
                    elif clientRec[2] != 'D' and clientRec[2] != 'C':
                        raise ValueError('Invalid transaction code :')
                    else:
                        if clientRec[2] == 'D':
                            clientDL[i].debit(float(clientRec[3]))
                        else: clientDL[i].credit(float(clientRec[3])) 
                        
            except ValueError as valueError:
                sys.stderr.write(str(valueError) + ' ' + line + '\n')
                
            line = fileIn.readline()
                
        if Client.numClient == 0:
            sys.stderr.write('empty or invalid data only : '+line+'\n')
        else:
            sys.stdout.flush()
                            
            print('%-20s%-30s%10s'%(clientDT[0],clientDT[1],clientDT[2]))
            print('='*60)    
            for e in sorted(clientDL, key = lambda c: c.name):
                if e.getBalance() != 0:
                    print(e) 
                  
        fileIn.close()
        
    except FileNotFoundError as e:
        sys.stderr.write(str(e))
    
    Test Report
    #Test dataExpected OutputPass
    1Fred Chan_213 Yuen Long Avenue_D_41.03
    Sue Wong_9102 Kowloon Circle_D_10.00
    Fred Chan_213 Yuen Long Avenue_C_0.01
    Baba Li_2000 E. 21st Street_D_450.00
    Sue Wong_9102 Kowloon Circle_C_5.50
    Jay Law_9103 Problem Area_C_25.00
    Fred Chan_213 Yuen Long Avenue_C_41.02
    Name Address Balance
    =====================================
    Baba Li 2000 E. 21st Street 450.00
    Jay Law 9103 Problem Area -25.00
    Sue Wong 9102 Kowloon Circle 4.50
    Yes
    2file not existNo such file or directory: 'datafileo.dat'yes
    3empty data fileempty or invalid data onlyyes
    4Fred Chan_213 Yuen Long Avenue_D_41.03
    Sue Wong_9102 Kowloon Circle_D_10.00
    _213 Yuen Long Avenue_C_0.01
    Baba Li__D_450.00
    Sue Wong_9102 Kowloon Circle_C_5.50
    Jay Law_9103 Problem Area_C_25.00
    Fred Chan_213 Yuen Long Avenue_C_41.02
    Invalid Name or Address :
    _213 Yuen Long Avenue_C_0.01

    Invalid Name or Address :
    Baba Li__D_450.00

    Name Address Balance
    =====================================
    Fred Chan 213 Yuen Long Avenue 0.01
    Jay Law 9103 Problem Area -25.00
    Sue Wong 9102 Kowloon Circle 4.50
    Yes
    5Fred Chan_213 Yuen Long Avenue_D_41.03
    Sue Wong_9102 Kowloon Circle_D_10.00
    Fred Chan_213 Yuen Long Avenue_C_0.01
    Baba Li_2000 E. 21st Street_X_450.00
    Sue Wong_9102 Kowloon Circle_X_5.50
    Jay Law_9103 Problem Area_C_25.00
    Fred Chan_213 Yuen Long Avenue_C_41.02
    Invalid transaction code :
    Baba Li_2000 E. 21st Street_X_450.00

    Invalid transaction code :
    Sue Wong_9102 Kowloon Circle_X_5.50

    Name Address Balance
    =====================================
    Jay Law 9103 Problem Area -25.00
    Sue Wong 9102 Kowloon Circle 10.00
    Yes
    6Fred Chan_213 Yuen Long Avenue_D_-41.03
    Sue Wong_9102 Kowloon Circle_D_10.00
    Fred Chan_213 Yuen Long Avenue_C_0.01
    Baba Li_2000 E. 21st Street_D_450.00
    Sue Wong_9102 Kowloon Circle_C_5.50
    Jay Law_9103 Problem Area_C_25.00
    Fred chan_213 Yuen Long Avenue_C_41.02
    Invalid transaction amt :
    Fred Chan_213 Yuen Long Avenue_D_-41.03

    Name Address Balance
    =====================================
    Baba Li 2000 E. 21st Street 450.00
    Fred Chan 213 Yuen Long Avenue -0.01
    Fred chan 213 Yuen Long Avenue -41.02
    Jay Law 9103 Problem Area -25.00
    Sue Wong 9102 Kowloon Circle 4.50
    Yes
    7Fred Chan_213 Yuen Long Avenue_D_41.03
    Sue Wong_9102 Kowloon Circle_D_10.00
    Fred Chan_213 Yuen Long Avenue_C_0.01
    Baba Li_2000 E. 21st Street_D_9999999999999999999999999
    Sue Wong_9102 Kowloon Circle_C_5.50
    Jay Law_9103 Problem Area_C_25..
    Fred Chan_213 Yuen Long Avenue_C_41.02
    Invalid transaction amt :
    Baba Li_2000 E. 21st Street_D_9999999999999999999999999

    Transaction amt not number :
    Jay Law_9103 Problem Area_C_25..

    Name Address Balance
    =====================================
    Sue Wong 9102 Kowloon Circle 4.50
    Yes
  2. lab5q2.py

    
    import doctest
    
    def isPalindrome(s):
        '''
        return if s is a palindrome
        
        >>> isPalindrome('')
        True
        >>> isPalindrome('a')
        True
        >>> isPalindrome('aa')
        True
        >>> isPalindrome('aba')
        True
        >>> isPalindrome('abba')
        True
        >>> isPalindrome('ababa')
        True
        >>> isPalindrome('ababb')
        False
        >>> isPalindrome('abab')
        False
        >>> isPalindrome('abc')
        False
        >>> isPalindrome('ab')
        False
        '''
        
        if len(s) <= 1:
            return True
        else:
            return bool(s[0] == s[len(s)-1] and isPalindrome(s[1:len(s)-1]))
    
    if __name__ == "__main__": 
        doctest.testmod()
    

    lab5q2UT.py

    
    import unittest
    
    from lab5q2 import isPalindrome
    
    class Test(unittest.TestCase):
    
        def testPalindrome(self):
            self.assertTrue(isPalindrome(''))
            self.assertTrue(isPalindrome('a'))        
            self.assertTrue(isPalindrome('aa'))
            self.assertTrue(isPalindrome('aba'))
            self.assertTrue(isPalindrome('abababa'))
            self.assertTrue(isPalindrome('able was i ele i saw elba'))
            
        def testNotaPalindrome(self):
            self.assertFalse(isPalindrome('ab'))
            self.assertFalse(isPalindrome('abc'))
            self.assertFalse(isPalindrome('abaa'))
            self.assertFalse(isPalindrome('aaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaa'))
              
    if __name__ == "__main__":
        unittest.main()
    
  3. lab5q3.py

    
    import sys
    
    def readFloat(s,inputType):
        while True:
            try:
                inputValue=float(input(s))
                if inputType == 1:
                    if inputValue < 1000 or inputValue > 100000:
                        raise ValueError('invalid loan amount')
                elif inputType == 2:
                    if inputValue < 0.1 or inputValue > 100:
                        raise ValueError('invalid interest rate')
                        
                return inputValue
            except ValueError as error:
                sys.stderr.write(str(error)+'\n')
     
    
    def main():
        try:
            loanAmount = readFloat("The loan amount is (1000 - 10000): ",1)
            annualInterestRate = readFloat("The annual interest rate is (0.1 - 100): ",2)
            monthlyPayment = readFloat("The monthly payment is (in less than 100 payment): ",3)
    
            month = 1;
            startingBalance = loanAmount;
            payment = monthlyPayment;
            middleBalance = loanAmount - payment;
            interest = middleBalance * annualInterestRate/12/100;
            endingBalance = middleBalance + interest;
            
            while startingBalance > 0:
                month+=1
                if month > 100:
                    raise ValueError('payment number > 100 ')
                
                startingBalance = endingBalance
                
                if endingBalance > monthlyPayment:
                    payment = monthlyPayment
                else: payment = endingBalance
                
                middleBalance =  startingBalance - payment
                interest = middleBalance * annualInterestRate/12/100
                endingBalance = middleBalance + interest
                
            month = 1;
            startingBalance = loanAmount;
            payment = monthlyPayment;
            middleBalance = loanAmount - payment;
            interest = middleBalance * annualInterestRate/12/100;
            endingBalance = middleBalance + interest;
                
            print("\n")
            print("%25s%30s%30s"%
                  ("Starting","Middle","Ending"))
            print("%10s%15s%15s%15s%15s%15s"%
                  ("Month","Balance","Payment","Balance","Interest","Balance"))
            print("-"*85)
                  
            while startingBalance > 0:
                print("%10d%15.2f%15.2f%15.2f%15.2f%15.2f"%
                  (month,startingBalance,payment,middleBalance,interest,endingBalance))
                
                month+=1
                startingBalance = endingBalance
                
                if endingBalance > monthlyPayment:
                    payment = monthlyPayment
                else: payment = endingBalance
                
                middleBalance =  startingBalance - payment
                interest = middleBalance * annualInterestRate/12/100
                endingBalance = middleBalance + interest
                
        except ValueError as error:
            sys.stderr.write(str(error)+'\n')
            
    if __name__ == "__main__":
        main()
    
  4. lab5q4.py

    
    import sys
    import currencyAPI
    
    instructions = """Enter one of the following:
       1 to reads the contents of a URL in XML
       2 to to print XML data in JSON format
       3 to to print forex rate table
       4 to fetch a currency rate
       5 to end \n"""
    
    while True:
        print (instructions)  
        choice = input( "Enter 1 to 5 " ) 
    
        if choice == "1":
            url='http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml'
            dictionary=currencyAPI.readXMLUrl(url)
        elif choice == "2":
            currencyAPI.printDictJson(dictionary)
        elif choice == "3":
            currencyAPI.printCurrencyList(dictionary)
        elif choice == "4":
            userCurrency = input('Enter Currency Code : ')
            
            if userCurrency == 'XDR':
                currencyFound = True
            else: currencyFound = False
            
            for e in dictionary['gesmes:Envelope']['Cube']['Cube']['Cube']:
                if e.get('@currency') == userCurrency:
                    currencyFound = True
                    break
                    
            if currencyFound:        
                print("On %15s One euro is %15s"% currencyAPI.getCurrencyData(dictionary, userCurrency))
            else:
                sys.stderr.write('invalid currency code')
                
        elif choice == "5":
            break
    
    print ("End currencyAPI test")