docstring in Python code

This commit is contained in:
Davide Alberani 2015-03-22 08:58:25 +01:00
parent 0c65f0c87b
commit 910515b2e7
2 changed files with 119 additions and 19 deletions

View file

@ -1,6 +1,6 @@
"""Event Man(ager) backend
"""Event Man(ager) database backend
Classes and functions used to manage events and attendants.
Classes and functions used to manage events and attendants database.
"""
import pymongo
@ -8,15 +8,29 @@ from bson.objectid import ObjectId
class EventManDB(object):
"""MongoDB connector."""
db = None
connection = None
def __init__(self, url=None, dbName='eventman'):
"""Initialize the instance, connecting to the database.
:param url: URL of the database
:type url: str (or None to connect to localhost)
"""
self._url = url
self._dbName = dbName
self.connect(url)
def connect(self, url=None, dbName=None):
"""Connect to the database.
:param url: URL of the database
:type url: str (or None to connect to localhost)
:return: the database we're connected to
:rtype: :class:`~pymongo.database.Database`
"""
if self.db is not None:
return self.db
if url:
@ -28,12 +42,32 @@ class EventManDB(object):
return self.db
def get(self, collection, _id):
"""Get a single document with the specified `_id`.
:param collection: search the document in this collection
:type collection: str
:param _id: unique ID of the document
:type _id: str or :class:`~bson.objectid.ObjectId`
:return: the document with the given `_id`
:rtype: dict
"""
if not isinstance(_id, ObjectId):
_id = ObjectId(_id)
results = self.query(collection, {'_id': _id})
return results and results[0] or {}
def query(self, collection, query=None):
"""Get multiple documents matching a query.
:param collection: search for documents in this collection
:type collection: str
:param query: search for documents with those attributes
:type query: dict or None
:return: list of matching documents
:rtype: list
"""
db = self.connect()
query = query or {}
if'_id' in query and not isinstance(query['_id'], ObjectId):
@ -44,11 +78,33 @@ class EventManDB(object):
return results
def add(self, collection, data):
"""Insert a new document.
:param collection: insert the document in this collection
:type collection: str
:param data: the document to store
:type data: dict
:return: the document, as created in the database
:rtype: dict
"""
db = self.connect()
_id = db[collection].insert(data)
return self.get(collection, _id)
def update(self, collection, _id, data):
"""Update an existing document.
:param collection: update a document in this collection
:type collection: str
:param _id: unique ID of the document to be updatd
:type _id: str or :class:`~bson.objectid.ObjectId`
:param data: the updated information to store
:type data: dict
:return: the document, after the update
:rtype: dict
"""
db = self.connect()
data = data or {}
if '_id' in data:
@ -56,3 +112,20 @@ class EventManDB(object):
db[collection].update({'_id': ObjectId(_id)}, {'$set': data})
return self.get(collection, _id)
def delete(self, collection, _id_or_query=None, force=False):
"""Remove one or more documents from a collection.
:param collection: search the documents in this collection
:type collection: str
:param _id_or_query: unique ID of the document or query to match multiple documents
:type _id_or_query: str or :class:`~bson.objectid.ObjectId` or dict
:param force: force the deletion of all documents, when `_id_or_query` is empty
:type force: bool
"""
if not _id_or_query and not force:
return
db = self.connect()
if not isinstance(_id_or_query, (ObjectId, dict)):
_id_or_query = ObjectId(_id_or_query)
db[collection].remove(_id_or_query)

View file

@ -18,58 +18,84 @@ from tornado import gen, escape
import backend
class BaseHandler(tornado.web.RequestHandler):
def initialize(self, **kwargs):
for key, value in kwargs.iteritems():
setattr(self, key, value)
class RootHandler(BaseHandler):
angular_app_path = os.path.join(os.path.dirname(__file__), "angular_app")
@gen.coroutine
def get(self):
with open(self.angular_app_path + "/index.html", 'r') as fd:
self.write(fd.read())
class ImprovedEncoder(json.JSONEncoder):
"""Enhance the default JSON encoder to serialize datetime objects."""
def default(self, o):
if isinstance(o, datetime.datetime):
if isinstance(o, (datetime.datetime, datetime.date,
datetime.time, datetime.timedelta)):
return str(o)
return json.JSONEncoder.default(self, o)
json._default_encoder = ImprovedEncoder()
class BaseHandler(tornado.web.RequestHandler):
"""Base class for request handlers."""
def initialize(self, **kwargs):
"""Add every passed (key, value) as attributes of the instance."""
for key, value in kwargs.iteritems():
setattr(self, key, value)
class RootHandler(BaseHandler):
"""Handler for the / path."""
angular_app_path = os.path.join(os.path.dirname(__file__), "angular_app")
@gen.coroutine
def get(self):
# serve the ./angular_app/index.html file
with open(self.angular_app_path + "/index.html", 'r') as fd:
self.write(fd.read())
class CollectionHandler(BaseHandler):
"""Base class for handlers that need to interact with the database backend.
Introduce basic CRUD operations."""
# set of documents we're managing (a collection in MongoDB or a table in a SQL database)
collection = None
@gen.coroutine
def get(self, id_=None):
if id_ is not None:
# read a single document
self.write(self.db.get(self.collection, id_))
else:
# return an object containing the list of all objects in the collection;
# e.g.: {'events': [{'_id': 'obj1-id, ...}, {'_id': 'obj2-id, ...}, ...]}
# Please, never return JSON lists that are not encapsulated in an object,
# to avoid XSS vulnerabilities.
self.write({self.collection: self.db.query(self.collection)})
@gen.coroutine
def post(self, id_=None, **kwargs):
data = escape.json_decode(self.request.body or {})
if id_ is None:
# insert a new document
newData = self.db.add(self.collection, data)
else:
# update an existing document
newData = self.db.update(self.collection, id_, data)
self.write(newData)
# PUT is handled by the POST method
put = post
class PersonsHandler(CollectionHandler):
"""Handle requests for Persons."""
collection = 'persons'
class EventsHandler(CollectionHandler):
"""Handle requests for Events."""
collection = 'events'
def main():
def run():
"""Run the Tornado web application."""
# command line arguments; can also be written in a configuration file,
# specified with the --config argument.
define("port", default=5242, help="run on the given port", type=int)
define("data", default=os.path.join(os.path.dirname(__file__), "data"),
help="specify the directory used to store the data")
@ -82,6 +108,7 @@ def main():
callback=lambda path: tornado.options.parse_config_file(path, final=False))
tornado.options.parse_command_line()
# database backend connector
db_connector = backend.EventManDB(url=options.mongodbURL, dbName=options.dbName)
init_params = dict(db=db_connector)
@ -100,5 +127,5 @@ def main():
if __name__ == '__main__':
main()
run()