docstring in Python code
This commit is contained in:
parent
0c65f0c87b
commit
910515b2e7
2 changed files with 119 additions and 19 deletions
77
backend.py
77
backend.py
|
@ -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)
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
Loading…
Reference in a new issue