Merge commit 'public/master' into ceod

This commit is contained in:
Michael Spang 2009-07-29 13:29:42 -04:00
commit 5ce11709ff
4 changed files with 236 additions and 4 deletions

View File

@ -150,6 +150,12 @@ def create_member(username, password, name, program):
addmember = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = addmember.communicate(password)
status = addmember.wait()
# # If the user was created, consider adding them to the mailing list
# if not status:
# listadmin_cfg_file = "/path/to/the/listadmin/config/file"
# mail = subprocess.Popen(["/usr/bin/listadmin", "-f", listadmin_cfg_file, "--add-member", username + "@csclub.uwaterloo.ca"])
# status2 = mail.wait() # Fuck if I care about errors!
except OSError, e:
raise MemberException(e)

134
ceo/pymazon.py Normal file
View File

@ -0,0 +1,134 @@
#!/usr/bin/python
from xml.dom import minidom, Node
import urllib
import time
class PyMazonError(Exception):
"""Holds information about an error that occured during a pymazon request"""
def __init__(self, messages):
self.__message = '\n'.join(messages)
def __get_message(self):
return self.__message
def __str__(self):
return repr(self.__message)
message = property(fget=__get_message)
class PyMazonBook:
"""Stores information about a book retrieved via PyMazon."""
def __init__(self, title, authors, publisher, year, isbn10, isbn13, edition):
self.__title = title
self.__authors = authors
self.__publisher = publisher
self.__year = year
self.__isbn10 = isbn10
self.__isbn13 = isbn13
self.__edition = edition
def __str__(self):
return 'Title: ' + self.title + '\n' + \
'Author(s): ' + ', '.join(self.authors) + '\n' \
'Publisher: ' + self.publisher + '\n' + \
'Year: ' + self.year + '\n' + \
'ISBN-10: ' + self.isbn10 + '\n' + \
'ISBN-13: ' + self.isbn13 + '\n' + \
'Edition: ' + self.edition
def __get_title(self):
return self.__title
def __get_authors(self):
return self.__authors
def __get_publisher(self):
return self.__publisher
def __get_year(self):
return self.__year
def __get_isbn10(self):
return self.__isbn10
def __get_isbn13(self):
return self.__isbn13
def __get_edition(self):
return self.__edition
title = property(fget=__get_title)
authors = property(fget=__get_authors)
publisher = property(fget=__get_publisher)
year = property(fget=__get_year)
isbn10 = property(fget=__get_isbn10)
isbn13 = property(fget=__get_isbn13)
edition = property(fget=__get_edition)
class PyMazon:
"""A method of looking up book information on Amazon."""
def __init__(self, accesskey):
self.__key = accesskey
self.__last_query_time = 0
def __form_request(self, isbn):
return 'http://webservices.amazon.com/onca/xml?' + \
'Service=AWSECommerceService' + \
'&Version=2008-08-19' + \
'&AWSAccessKeyId=' + self.__key + \
'&Operation=ItemLookup' + \
'&ResponseGroup=ItemAttributes' + \
'&IdType=ISBN' + \
'&SearchIndex=Books' + \
'&ItemId=' + isbn
def __elements_text(self, element, name):
result = []
matching = element.getElementsByTagName(name)
for match in matching:
if len(match.childNodes) != 1:
continue
child = match.firstChild
if child.nodeType != Node.TEXT_NODE:
continue
result.append(child.nodeValue.strip())
return result
def __format_errors(self, errors):
error_list = []
for error in errors:
error_list.extend(self.__elements_text(error, 'Message'))
return error_list
def __extract_single(self, element, name):
matches = self.__elements_text(element, name)
if len(matches) == 0:
return ''
return matches[0]
def lookup(self, isbn):
file = urllib.urlretrieve(self.__form_request(isbn))[0]
xmldoc = minidom.parse(file)
cur_time = time.time()
while cur_time - self.__last_query_time < 1.0:
sleep(cur_time - self.__last_query_time)
cur_time = time.time()
self.__last_query_time = cur_time
errors = xmldoc.getElementsByTagName('Errors')
if len(errors) != 0:
raise PyMazonError, self.__format_errors(errors)
title = self.__extract_single(xmldoc, 'Title')
authors = self.__elements_text(xmldoc, 'Author')
publisher = self.__extract_single(xmldoc, 'Publisher')
year = self.__extract_single(xmldoc, 'PublicationDate')[0:4]
isbn10 = self.__extract_single(xmldoc, 'ISBN')
isbn13 = self.__extract_single(xmldoc, 'EAN')
edition = self.__extract_single(xmldoc, 'Edition')
return PyMazonBook(title, authors, publisher, year, isbn10, isbn13, edition)

View File

@ -5,12 +5,26 @@ from ceo.urwid.widgets import *
from ceo.urwid.window import *
from sqlobject.sqlbuilder import *
from datetime import datetime, timedelta
from ceo.pymazon import PyMazon
from ceo.pymazon import PyMazonError
from ceo import conf
from ceo import terms
import ceo.library as lib
CONFIG_FILE = "/etc/csc/library.cf"
cfg = {}
def configure():
"""
Load configuration
"""
cfg_fields = [ "aws_account_key" ]
temp_cfg = conf.read(CONFIG_FILE)
conf.check_string_fields(CONFIG_FILE, cfg_fields, temp_cfg)
cfg.update(temp_cfg)
def library(data):
"""
@ -20,7 +34,7 @@ def library(data):
("Checkout Book", checkout_book, None),
("Return Book", return_book, None),
("Search Books", search_books, None),
# ("Add Book", add_book, None),
("Add Book", add_book, None),
("Back", raise_back, None),
])
push_window(menu, "Library")
@ -35,12 +49,18 @@ def search_books(data):
])
push_window(menu, "Book Search")
def add_book(data):
"""
Add book to library. Also stab Sapphyre.
"""
push_wizard("Add Book", [BookAddPage])
def overdue_books(data):
"""
Display a list of all books that are overdue.
"""
oldest = datetime.today() - timedelta(weeks=2)
overdue = lib.Signout.select(lib.Signout.q.outdate<oldest)
overdue = lib.Signout.select(AND(lib.Signout.q.outdate<oldest, lib.Signout.q.indate==None))
widgets = []
@ -83,6 +103,45 @@ def return_book(data):
"""
push_wizard("Checkout", [CheckinPage, ConfirmPage])
class BookAddPage(WizardPanel):
"""
Thingy for going on screen to add books.
"""
def init_widgets(self):
"""
Make some widgets.
"""
self.isbn = SingleEdit("ISBN: ")
self.widgets = [
urwid.Text("Adding New Book"),
urwid.Divider(),
self.isbn
]
def check(self):
"""
Do black magic.
"""
configure()
isbn = self.isbn.get_edit_text()
try:
pymazon = PyMazon(cfg["aws_account_key"])
book = pymazon.lookup(isbn)
currents = lib.Book.select(lib.Book.q.isbn==isbn)
if currents.count() == 0:
lib.Book(isbn=isbn, title=book.title,
year=book.year, publisher=book.publisher)
pop_window()
else:
set_status("Book already exists, fucker.")
except PyMazonError, e:
set_status("Amazon thinks this is not a book. Take it up with them.")
return False
class BookSearchPage(WizardPanel):
"""
The page used when searching for books.
@ -216,10 +275,14 @@ class SearchPage(urwid.WidgetWrap):
books = lib.Book.select(LIKE(lib.Book.q.title, "%" + title + "%"))
elif not isbn is None and not isbn=="":
books = lib.Book.select(lib.Book.q.isbn==isbn)
elif not user is None and not user=="":
elif (not (user is None)) and (not (user=="")):
st = lib.Signout.select(AND(lib.Signout.q.username==user, lib.Signout.q.indate==None))
for s in st:
books.append(s.book)
else:
st = lib.Signout.select(lib.Signout.q.indate==None)
for s in st:
books.append(s.book)
for b in books:
widgets.append(urwid.AttrWrap(ButtonText(self.select, b, str(b)),

31
debian/changelog vendored
View File

@ -1,8 +1,37 @@
ceo (0.4.19) stable testing; urgency=low
ceo (0.4.24) stable testing; urgency=low
* Bump standards version.
-- Michael Spang <mspang@uwaterloo.ca> Wed, 29 Jul 2009 07:31:24 -0400
ceo (0.4.23) stable testing; urgency=low
* CEO library now only finds books that are signed out as being overdue.
-- Michael Gregson <mgregson@csclub.uwaterloo.ca> Wed, 11 Mar 2009 03:30:01 -0500
ceo (0.4.22) stable testing; urgency=low
* CEO now closes window when it should. (Sorry)
-- Michael Gregson <mgregson@csclub.uwaterloo.ca> Wed, 11 Mar 2009 02:25:01 -0500
ceo (0.4.21) stable testing; urgency=low
* CEO Library can now add boox.
-- Michael Gregson <mgregson@csclub.uwaterloo.ca> Wed, 11 Mar 2009 02:09:01 -0500
ceo (0.4.20) stable testing; urgency=low
* Update kadmin headers
-- David Bartley <dtbartle@csclub.uwaterloo.ca> Tue, 24 Feb 2009 16:08:12 -0500
ceo (0.4.19) stable testing; urgency=low
* Rebuild for lenny.
-- Michael Spang <mspang@uwaterloo.ca> Tue, 17 Feb 2009 22:23:30 -0500
ceo (0.4.18) stable testing; urgency=low