Skip to content

Instantly share code, notes, and snippets.

@1328
Created July 11, 2014 20:37
Show Gist options
  • Select an option

  • Save 1328/5032be130167d1530f32 to your computer and use it in GitHub Desktop.

Select an option

Save 1328/5032be130167d1530f32 to your computer and use it in GitHub Desktop.
comments 7-11
import sqlite3
from collections import namedtuple
EMP = namedtuple('EMP', ['first_name','last_name','badge','hours'])
def yes_no(query):
'''
this is a simple func to as a y/n question and get back a valid y/n
response
this is the first of a few different ways to solve this same problem
'''
check = {'y':'y','yes':'y','n':'n','no':'n'}
while True:
q = input(query).lower()
if q in check:
return check[q]
print('please respond y/n')
def get_valid(query, checks, transform = None):
'''takes a query, runs checks, and returns a transform(input) if all
funcs in checks == False
note you can do the same thing with classes maybe more easily, but I will
let you work up to the object oriented programing version
also it is worth noting that this tends to be more trouble than it is worth
because the checks and transform all get so wonkie
'''
if transform is None:
transfor = lambda x:x
while True:
q = input(query)
if any(c(q) for c in checks):
print('invalid entry')
continue
return transform(q)
def yes_no_wrapper(query):
'''this is just yes_no but by using a wrapper around get_valid
see how complex something so simple looks?
one way to fix this is to have separate validation functions
'''
return get_valid(query,
[lambda x:x.lower() not in ['y','yes','no','n']],
lambda x: {'y':'y','yes':'y','n':'n','no':'n'}[x.lower()],
)
def other_get_valid(query, func):
'''
ok, maybe the others are busts. The first is too specific
The second too complex
how about we meet in the middle and just have a get_valid that takes in a
query and a function to validate
'''
while True:
q = func(input(query))
if q is not None:
return q
def validate_name(name):
'''
validate names
returns None for bad ones
prints a message maybe
returns name.title() for good names
'''
if ' ' in name:
print('no spaces in names!')
return None
if any(l.isdigit() for l in name):
print('no digits in names!')
return None
return name.title()
def validate_number(num):
if not num.isdigit():
return None
return int(num)
def get_employee():
'''lets break out get_employee into its own func
it will make sense when you see the control flow later
plus a lot is going on here with validations
'''
print("******** Add New Employee ********\n")
# lets use the new get_valid to force a good input
first_name = get_valid('Enter Firstname:',
[lambda x: any(i.isdigit() for i in x),
lambda x: ' ' in x,
],
lambda x:x.title()
)
# hmm, a bit complex for the unitiated. Maybe this is easier
last_name = other_get_valid("Enter Lastname: ", validate_name)
# complex
badge = get_valid("Enter Badge Number (unique): ",
[lambda x:not x.isdigit()],
lambda x:int(x))
# simple
hours = other_get_valid("Please enter Number of hours staff member works: ",
validate_number)
print("\n")
# return a new EMP record
return (EMP(first_name, last_name, badge, hours))
def confirm_employee(e):
'''not sure if this merits its own function, or just an expanded template
passed to yes_no function
'''
print("---- Are these details correct? ---- \n")
print("Employee name = {0} {1}\n Badge Number = {2}\n Hours Worked = {3}\n".format
(e.first_name, e.last_name, e.badge, e.hours))
confirm = yes_no("Press 'y' to confirm or 'n' to cancel : ")
return confirm == 'y'
def insert_employee(c, employee):
'''
this maybe gets its own function since there is lots of error handling to
do'''
# break up sql long line
sql ='''
INSERT INTO staff ("First Name", "last name", Badge, hours) VALUES (?,?,?,?)
'''
# wrap in try/except
try:
# check out how cool named tuples are
c.execute(sql, employee)
print("\n")
print("New Employee {0} {1} added successfully\n".format(
employee.first_name, employee.last_name))
return True
except sqlite3.IntegrityError as e:
# catch the unique execption
print('could not insert because badge {} already in db'.format(
employee.badge))
return False
except Exception as e:
# something else happens then raise it for debugging
print('\n')
print('failed on {}'.format(employee))
raise e
def add_employee(c, conn):
'''new add employee function
it merits its own function b/c you are probably going to want to do more
with the program than just add an employee
'''
while True:
new_guy = get_employee()
if confirm_employee(new_guy):
insert_employee(c, new_guy)
conn.commit()
keep_going = yes_no_wrapper('add another?')
if keep_going =='n':
return
def main():
conn = sqlite3.connect('clock.db')
c = conn.cursor()
'''
NOTE: I would confirm column names to pep8 and the variables in the
program. it keeps things more simple and it might help you in the future if
you want to use dict factories.
'''
c.execute('''CREATE TABLE if not exists staff (ID INTEGER PRIMARY KEY AUTOINCREMENT, "First Name", "Last Name",
Badge unique , Hours)''')
c.execute('''CREATE TABLE if not exists times (ID PRIMARY KEY,StaffId, ClockIn INTEGER, ClockOut INTEGER, Date INTEGER,
FOREIGN KEY(StaffID) REFERENCES staff(ID))''')
add_employee(c, conn)
conn.close()
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment