You are going to implement software for your local library. The user of the software will be the librarian, who uses your program to issue library cards, check books out to patrons, check books back in, send out overdue notices, and open and close the library.
In a number of methods, we will make a distinction between what the program appears to do (its behavior), and what it actually does (its implementation). For example, when we "issue a library card" to a person, we don't create some kind of a "library_card object"; the program can implement this by creating a Patron object. The visible behavior is the same: A person who has been "issued a library card" will be a Patron who is able to check out books. Don't let yourself be confused by the terminology.
You should not need any additional classes, but if you would like additional methods, feel free to write (and test!) them.
Create the following classes. All classes should be defined in a file
named library.py, and all test classes should be on a
separate file named library_test.py.
class Calendar(object)date class, but it's too complicated
for our needs. To keep things simple, we will just use an integer to
keep track of how many days have passed. This class needs only a couple
of methods:
__init__(self)get_date(self)advance(self)class Book(object)id, title,
author (only one author per book), and due_date.
The due date is None if the book is not checked out.
__init__(self, id, title, author)get_id(self)get_title(self)get_author(self)get_due_date(self)check_out(self, due_date)check_in(self)None. Doesn't
return anything.__str__(self)"id: title,
by author".class Patron(object)__init__(self, name, library)get_name(self)check_out(self, book)give_back(self, book)return, but I hope you can see
why I can't do that.) get_books(self)Book objects checked out to this
patron (may be the empty set, set([])).get_overdue_books(self)Book objects
checked out to this patron (may be the empty set, set([])).class Library(object)__init__(self)collection.txt,
a list of (title, author)
tuples, Create a Book from each tuple, and save
these books in some appropriate data structure of your choice.
Give each book a unique id number (starting from 1, not 0). You
may have many copies of the "same" book (same title and author),
but each will have its own id.None.open(self)Exception
with the message "The library is already open!". Otherwise,
starts the day by advancing the Calendar, and setting the flag to
indicate that the library is open. ()."Today is day n."find_all_overdue_books(self)"No books are
overdue.".issue_card(self, name_of_patron)"Library card issued to name_of_patron."
or "name_of_patron already has a library card.".Exception: "The library is not open.".
serve(self, name_of_patron)"Now serving name_of_patron."
or "name_of_patron does not have a library card.".
Exception: "The library is not open."find_overdue_books(self)__str__ method), of the books
that have been checked out by the patron currently being served, and
which are overdue. If the patron has no overdue books, the value None
is returned.Exception with an appropriate message:
"The library is not open.""No patron is currently being served."check_in(self, *book_ids)book_ids
are taken from the list returned by the get_books
method in the Patron object. Checking in a Book will
involve both telling the Book that it is checked in and
returning the Book to this library's collection of available Books."name_of_patron has returned
n books.".Exception with an appropriate message:
"The library is not open.""No patron is currently being served.""The patron does not have book id."search(self, string)Books whose title or author (or both)
contains this string. For example, the string "tact"
might return, among other things, the book Contact, by
Carl Sagan. The search should be case-insensitive; that is, "saga"
would also return this book. Only books which are currently
available (not checked out) will be found. If there is more than one
copy of a book (with the same title and same author), only one will
be found. In addition, to keep from returning too many books,
require that the search string be at least 4 characters long."No books found.""Search string must contain at least four characters."__str__ method.) check_out(self, *book_ids)book_ids
could have been found by a recent call to the search
method. Checking out a book will involve both telling the
book that it is checked out and removing the book from
this library's collection of available books. "n books have been checked
out to name_of_patron.".Exception with an appropriate message:
"The library is not open.""No patron is currently being served.""The library does not have book id.""Patron cannot have more than three books."
(added October 8)renew(self, *book_ids)"n books have been renewed
for name_of_patron.".Exception with an appropriate message:
"The library is not open.""No patron is currently being served.""The patron does not have book id."close(self)quit) can be used when the library
is closed."Good night.".Exception with the message "The
library is not open." quit(self)"The
library is now closed for renovations.".serve
the patron. This will print a list of books (with id numbers) checked
out to that patron.check_in the books by the
numbers given above.serve
the patron. You can ignore the list of books that this will print out.search for a book wanted
by the patron (unless you already know its id).check_out zero or more
books by the book ids returned from the search command.search.main function, not in any class, which
starts up automatically when you load the program. It should:Library object.>>>) main method is acting as a REPL. The commands it
accepts will be space-separated words and numbers. (Hint: Use split()).openopen method.)overduefind_all_overdue_books.)card Person's namePatron.)
The person's name may contain spaces.serve Person's nameserve.)
Also lists the id, title, and author of all books currently checked out
to the Patron, and indicates which are overdue.checkin id numberscheckout id numbersrenew id numberssearch stringclosequitmain, and the associated message printed. Exceptions
should not terminate the program!Instance variables are variables that
belong to an object, and instance methods
are methods that are defined for an object. Instance variables and methods
must be prefixed with self. , when used by the object
itself. Local variables (including parameters) and global variables should
not be prefixed with self. When an object uses the
methods of another object, those methods must be prefixed by a variable
that refers to the object; for example, book.get_title().
Three of the methods above, check_out, check_in,
and renew, have an asterisk in front of the last parameter.
That asterisk is new syntax--it means that, when you call
the method, you can give as many book numbers as you please; you don't
have to give just one. Inside the method, the parameter
book_ids is a tuple of all the numbers
(zero or more) that you gave it. To call these methods,
you need to either (1) give zero or more integers as arguments, or (2)
break up a set or list into separate arguments by prefixing it with an
asterisk (for example, library.check_out(*arglist)).
Many of these methods return strings, and in general it's a nuisance to
test for particular strings, because changing the wording of a message
slightly won't affect whether the program is working, but it can cause
tests to fail. In these cases it will be acceptable to perform simpler
tests, such as "card" in result, or even type(result)
is str. You should at least test whether the correct type of
result (string or None) is being returned, and you should
test that all exceptions are raised when they should be.
You can test __init__ methods, not by calling them, but by
creating an object and testing whether it was initialized correctly. You
can test __str__ methods by calling the str function
on an object.
You don't need to test the assorted "getter" methods (those named get_something).
Those are so trivial that it's probably safe to assume that they work.
Zip together and turn in two files: library.py, containing
all of the above classes, and library_test.py, containing
all the unit tests.
Your program is due before