5
\$\begingroup\$

I am a Python beginner (well, a newbie programmer). I am creating a small address book, just as a fun project, nothing too serious. I would appreciate if you review it and advise me on how to make it better (not complete yet). Here's the link:

https://github.com/volf52/address-book

Here's the code:

main.py

import contact
import addressBook
import re
from sys import exit
import random


__author__ = 'Muhammad Arslan <[email protected]>'

app = addressBook.addressBook(str(raw_input("Enter name of book  (Will be created if doesn't exist) \n> ")))
main_menu = '\n1. Show all contacts.\n2. Add contact.\n3. Search.\n4. Delete a contact.\n5.Update contact.\n6. Exit\n\n>'

def exitProg():
    exitMessages = ['You have my permission to die.']
    print random.choice(exitMessages)
    exit(0)

def getOption(prompt):
    inp = raw_input(prompt)
    try:
        inp = int(inp)
    except ValueError:
        print 'You should have selected a proper option.'
        return 13
    return inp


def showContacts():
    print 'show all'

def addContact():
    flag = 13
    while flag == 13:
        exp = map(lambda x: re.compile(x), [r'^([a-zA-Z]+)$', r'^(\+)?(\d)+$', r"(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)"])

        fName = str(raw_input('Enter first name : ')).strip()
        while not exp[0].match(fName):
            fName = str(raw_input('\nWrong Input\nEnter (proper) first name : ')).strip()

        lName = str(raw_input('Enter last name : ')).strip()
        while not exp[0].match(lName):
            lName = str(raw_input('\nWrong Input\nEnter (proper) last name : ')).strip()

        pNum = str(raw_input('Enter phone number : ')).strip()
        while not exp[1].match(pNum):
            pNum = str(raw_input('\nWrong Input\nEnter (proper) number : ')).strip()

        email = str(raw_input('Enter email(Blank for none) : ')).strip()
        while not exp[2].match(email):
            if not email:
                break
            email = str(raw_input('\nWrong Input\nEnter (proper) email : ')).strip()

        print app.addEntry(contact.Contact(fName, lName, pNum, email))

        while (flag < 1) or (flag > 3):
            flag = getOption('\n1. Add another.\n2. Go to main menu\n3. Exit.\n\n> ')
        if flag == 2:
            break
        elif flag == 3:
            exitProg()
        else:
            flag = 13

def searchContact():
    print 'search'

def removeContact():
    name = str(raw_input('Enter first name of the contact: '))
    print app.removeEntry(name)

def updateContact():
    name = str(raw_input('Enter the first name of the contact: '))
    msg, cont = app.searchEntry(name)
    print msg



funcs = [showContacts, addContact, searchContact, removeContact, updateContact, exitProg]

while True:
    inp = getOption(main_menu)
    while inp < 1 or inp > 6:
        print 'Input a proper number, moron.'
        inp = getOption(main_menu)
    funcs[inp - 1]()

contact.py

__author__ = 'Muhammad Arslan <[email protected]>'

class Contact(object):
    """Initialize a new contact object.
    Takes in name and phone number. Other arguments are optional."""
    def __init__(self, firstname, lastname, pNumber, email = ''):
        super(Contact, self).__init__()
        self.__firstName = firstname.lower()
        self.__lastName = lastname.lower()
        self.__pNumber = pNumber
        self.__email = email

    def __str__(self):
        return self.getName() + '\t' + self.getNumber()

    def __eq__(self , other):
        return (self.getName() == other.getName()) or (self.getNumber() == other.getNumber())

    def getName(self):
        return self.__firstName[0].upper()+self.__firstName[1:] + ' ' + self.__lastName[0].upper() + self.__lastName[1:]

    def getFirstName(self):
        return self.__firstName

    def getLastName(self):
        return self.__lastName

    def getNumber(self):
        return self.__pNumber

    def getEmail(self):
        return self.__email

    def setFirstName(self, newFName):
        self.__firstName = newFName

    def setLastName(self, newLName):
        self.__lastName = newLName

    def setName(self, fullName):
        self.__firstName, self.__lastName = fullName.split(' ')

    def setNumber(self, newNumber):
        self.__pNumber = newNumber

    def setEmail(self, newEmail):
        self.__email = newEmail

addressBook.py

try:
    import cPickle as pickle
except:
    import pickle
from hashlib import sha256

__author__ = 'Muhammad Arslan <[email protected]>'


class addressBook():
    """Class : Addressbook"""
    def __init__(self, name):
        try:
            self.__name = self.createName(name)+ '.db'
            self.__db = open(self.__name, 'rb')
            self.__entries = pickle.load(self.__db)
            self.__db.close()
        except:
            self.__db = open(self.__name, 'wb')
            self.__entries = {}
            self.__db.close()

    def __update(self):
        self.__db = open(self.__name, 'wb')
        pickle.dump(self.__entries, self.__db, -1)
        self.__db.close()

    def addEntry(self, contact):
        name = contact.getFirstName()
        if name in self.__entries:
            return '\nContact already present.\n'
        else:
            self.__entries[name] = contact
            self.__update()
            return '\nContact added successfully.\n'

    def removeEntry(self, name):
        if name in self.__entries:
            del self.__entries[name]
            self.__update()
            return '\nContact removed successfully.\n'
        else:
            return '\nName not found.\n'

    def searchEntry(self, name):
        name = name.lower()
        if name in self.__entries:
            return ('Contact found.', self.__entries[name])
        else:
            return ('Contact not found.', None)

    def updateEntry(self, name, param, val):
        name = name.lower()
        val = val.lower()

        if name in self.__entries:
            k = self.__entries[name]
            funcs = [k.setFirstName, k.setLastName, k.setName, k.setNumber, k.setEmail]
            funcs[param-1](val)
            return '\nContact updated successfully.\n'
        else:
            return '\nName not found.\n'

    @staticmethod
    def createName(mName):
        hsh = sha256(mName).hexdigest()
        return ''.join(hsh[1::3])
\$\endgroup\$
3
  • 9
    \$\begingroup\$ Why have you written all of those no-op getters and setters? Python isn't Java, see e.g. stackoverflow.com/q/2627002/3001761 and stackoverflow.com/q/6618002/3001761 for how you can make an attribute private if and when you actually need to. \$\endgroup\$
    – jonrsharpe
    Commented Apr 9, 2017 at 12:49
  • 1
    \$\begingroup\$ I wanted to restrict access to the "database" file, and make the code a bit more secure. (Although you are right ... I do come from a Java background, so thanks for providing the link to that awesome article). \$\endgroup\$
    – volf
    Commented Apr 9, 2017 at 20:29
  • 1
    \$\begingroup\$ That's reasonable (although I'm not sure __name_mangling is needed). I meant those like firstName where you have a getter and a setter for no reason; they just pass straight through. \$\endgroup\$
    – jonrsharpe
    Commented Apr 9, 2017 at 20:32

1 Answer 1

5
\$\begingroup\$

Like partially mentioned in the comments, you should use __setattr__(self, name, value) and __getattr__(self, name) for security if needed, and otherwise just allow direct access, instead of get_* and set_* functions.
You can also use @property on individual attributes.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.