Permalink
Browse files

Merge pull request #9 from RonnyPfannschmidt/cleanups

Cleanups
  • Loading branch information...
2 parents 90b541d + d03ebbf commit 5af8dd9823af24573d92acc81e5101efbfdadea9 @sirn committed Apr 11, 2012
Showing with 158 additions and 112 deletions.
  1. +124 −0 flask_couchdbkit.py
  2. +0 −1 flaskext/__init__.py
  3. +0 −87 flaskext/couchdbkit.py
  4. +1 −2 setup.py
  5. +33 −22 tests/test_couchdbkit.py
View
@@ -0,0 +1,124 @@
+# -*- coding: utf-8 -*-
+"""
+ flaskext.couchdbkit
+ ~~~~~~~~~~~~~~~~~~~
+
+ Flask extension that provides integration with CouchDBKit.
+
+ :copyright: (c) 2010–2011 by Kridsada Thanabulpong.
+ :license: BSD, see LICENSE for more details.
+"""
+from __future__ import absolute_import
+import os
+import couchdbkit
+from werkzeug.utils import cached_property
+from couchdbkit import Server, Document as CouchDBKitDocument
+from couchdbkit.loaders import FileSystemDocsLoader
+from socketpool import ConnectionPool
+from restkit.conn import Connection
+
+from flask import current_app
+
+
+__all__ = ['CouchDBKit']
+
+
+
+class CouchdbkitFlaskAppExtension(object):
+ def __init__(self, app):
+ self.app = app
+
+ @cached_property
+ def pool(self):
+ pool_keepalive = int(self.app.config.get('COUCHDB_KEEPALIVE'))
+ pool_backend = self.app.config.get('COUCHDB_BACKEND')
+ return ConnectionPool(Connection,
+ max_size=pool_keepalive,
+ backend=pool_backend)
+
+ @cached_property
+ def server(self):
+ server_uri = self.app.config.get('COUCHDB_SERVER')
+ return Server(server_uri, pool=self.pool)
+
+ @cached_property
+ def db(self):
+ dbname = self.app.config.get('COUCHDB_DATABASE')
+ return self.server.get_or_create_db(dbname)
+
+ def _reset(self):
+ self.__dict__.pop('db', None)
+ self.__dict__.pop('server', None)
+ self.__dict__.pop('pool', None)
+
+
+def _include_couchdbkit(namespace):
+ module = couchdbkit.schema
+
+ props = [prop for prop in dir(module) if prop.endswith('Property')]
+ for key in props:
+ if hasattr(module, key) and key not in namespace:
+ namespace[key] = getattr(module, key)
+
+
+class Document(CouchDBKitDocument):
+ @classmethod
+ def get_db(cls):
+ if cls._db is not None:
+ return cls._db #XXX: warn?
+ return current_app.extensions['couchdbkit'].db
+
+class StaticDocument(Document):
+ _allow_dynamic_properties = False
+
+class CouchDBKit(object):
+ """This class is used to control CouchDB integration to a Flask
+ application.
+
+ :param app: The application to which this CouchDBKit should be bound. If an
+ app is not provided at initialization time, it may be provided later by
+ calling `init_app` manually.
+ """
+ from couchdbkit.schema import DocumentSchema
+ Document = Document
+ StaticDocument = StaticDocument
+
+ _include_couchdbkit(locals())
+
+ def __init__(self, app=None):
+ self.app = app
+ if app is not None:
+ self.init_app(app)
+
+ @property
+ def db(self):
+ return current_app.extensions['couchdbkit'].db
+
+ @property
+ def server(self):
+ return current_app.extensions['couchdbkit'].server
+
+
+ def init_app(self, app):
+ """Bind an app to a CouchDBKit instance and initialize the database.
+
+ :param app: The application to which the CouchDBKit instance should be
+ bound.
+ """
+ app.config.setdefault('COUCHDB_SERVER', 'http://localhost:5984/')
+ app.config.setdefault('COUCHDB_DATABASE', None)
+ app.config.setdefault('COUCHDB_KEEPALIVE', 10)
+ app.config.setdefault('COUCHDB_VIEWS', '_design')
+ app.config.setdefault('COUCHDB_BACKEND', 'thread')
+
+ app.extensions['couchdbkit'] = CouchdbkitFlaskAppExtension(app)
+
+ def sync(self, app=None):
+ """Sync the local views with CouchDB server."""
+ app = app or self.app
+ if app is None:
+ return #XXX
+ local_path = app.config.get('COUCHDB_VIEWS')
+ design_path = os.path.join(app.root_path, local_path)
+ loader = FileSystemDocsLoader(design_path)
+ loader.sync(app.extensions['couchdbkit'].db)
View
@@ -1 +0,0 @@
-__import__('pkg_resources').declare_namespace(__name__)
View
@@ -1,87 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
- flaskext.couchdbkit
- ~~~~~~~~~~~~~~~~~~~
-
- Flask extension that provides integration with CouchDBKit.
-
- :copyright: (c) 2010–2011 by Kridsada Thanabulpong.
- :license: BSD, see LICENSE for more details.
-"""
-from __future__ import absolute_import
-import os
-import couchdbkit
-from couchdbkit import Server
-from couchdbkit.loaders import FileSystemDocsLoader
-from socketpool import ConnectionPool
-from restkit.conn import Connection
-
-
-
-
-__all__ = ['CouchDBKit']
-
-
-def _include_couchdbkit(obj):
- module = couchdbkit.schema
- for key in (['Document', 'DocumentSchema', 'StaticDocument']
- + [prop for prop in dir(module) if prop.endswith('Property')]):
- if hasattr(module, key) and not hasattr(obj, key):
- setattr(obj, key, getattr(module, key))
-
-
-class CouchDBKit(object):
- """This class is used to control CouchDB integration to a Flask
- application.
-
- :param app: The application to which this CouchDBKit should be bound. If an
- app is not provided at initialization time, it may be provided later by
- calling `init_app` manually.
- """
- def __init__(self, app=None):
- _include_couchdbkit(self)
- if app is not None:
- self.init_app(app)
-
- def init_app(self, app):
- """Bind an app to a CouchDBKit instance and initialize the database.
-
- :param app: The application to which the CouchDBKit instance should be
- bound.
- """
- self.app = app
- self.app.config.setdefault('COUCHDB_SERVER', 'http://localhost:5984/')
- self.app.config.setdefault('COUCHDB_DATABASE', None)
- self.app.config.setdefault('COUCHDB_KEEPALIVE', 10)
- self.app.config.setdefault('COUCHDB_VIEWS', '_design')
- self.app.config.setdefault('COUCHDB_BACKEND', 'thread')
-
- server_uri = app.config.get('COUCHDB_SERVER')
-
- # define pool
- pool_keepalive = int(app.config.get('COUCHDB_KEEPALIVE'))
- pool_backend = app.config.get('COUCHDB_BACKEND')
- pool = ConnectionPool(Connection, max_size=pool_keepalive,
- backend=pool_backend)
-
- # set server connection
- server = Server(server_uri, pool=pool)
-
- self.server = server
- self.init_db()
-
- def init_db(self):
- """Initialize database object from the `COUCHDB_DATABASE`
- configuration variable. If the database does not already exists,
- it will be created.
- """
- dbname = self.app.config.get('COUCHDB_DATABASE')
- self.db = self.server.get_or_create_db(dbname)
- self.Document._db = self.db
-
- def sync(self):
- """Sync the local views with CouchDB server."""
- local_path = self.app.config.get('COUCHDB_VIEWS')
- design_path = os.path.join(self.app.root_path, local_path)
- loader = FileSystemDocsLoader(design_path)
- loader.sync(self.db)
View
@@ -31,8 +31,7 @@ def run_tests():
author_email='sirn@ogsite.net',
description='Flask extension that provides integration with CouchDBKit.',
long_description=__doc__,
- packages=['flaskext'],
- namespace_packages=['flaskext'],
+ py_modules=['flask_couchdbkit'],
zip_safe=False,
platforms='any',
install_requires=[
View
@@ -4,7 +4,7 @@
from datetime import datetime
import flask
-from flaskext.couchdbkit import CouchDBKit
+from flask.ext.couchdbkit import CouchDBKit
from couchdbkit.exceptions import BadValueError
@@ -28,24 +28,27 @@ def setUp(self):
self.app = app
self.couchdb = couchdb
- self.db = self.couchdb.server[self.app.config['COUCHDB_DATABASE']]
+ with app.app_context():
+ self.db = self.couchdb.db
def tearDown(self):
- del self.couchdb.server[self.app.config['COUCHDB_DATABASE']]
+ del self.db.server[self.db.dbname]
def test_create(self):
- todo = self.Todo(title='First Todo', text='Some text.')
- todo.save()
- self.assertTrue(self.db.doc_exist(todo._id))
+ with self.app.app_context():
+ todo = self.Todo(title='First Todo', text='Some text.')
+ todo.save()
+ self.assertTrue(self.db.doc_exist(todo._id))
def test_field_validation(self):
self.assertRaises(BadValueError, self.Todo, title=1, text='More text.')
def test_retrieve(self):
- todo = self.Todo(title='2nd Todo', text='Some text.')
- todo.save()
- retrieved = self.Todo.get(todo._id)
- self.assertEqual(retrieved.title, '2nd Todo')
+ with self.app.app_context():
+ todo = self.Todo(title='2nd Todo', text='Some text.')
+ todo.save()
+ retrieved = self.Todo.get(todo._id)
+ self.assertEqual(retrieved.title, '2nd Todo')
class InitializationTestCase(unittest.TestCase):
@@ -57,16 +60,20 @@ def setUp(self):
self.app = app
def tearDown(self):
- del self.couchdb.server[self.app.config['COUCHDB_DATABASE']]
+ with self.app.app_context():
+ del self.couchdb.db.server[self.app.config['COUCHDB_DATABASE']]
def test_init_db(self):
self.couchdb = CouchDBKit(self.app)
- self.assertTrue(self.couchdb.server.all_dbs().index('test_db_2'))
+ with self.app.app_context():
+ # the jump over db is needed, since get_or_create is done at first usage
+ self.assertTrue(self.couchdb.db.server.all_dbs().index('test_db_2'))
def test_late_initialization(self):
self.couchdb = CouchDBKit()
self.couchdb.init_app(self.app)
- self.assertTrue(self.couchdb.server.all_dbs().index('test_db_2'))
+ with self.app.app_context():
+ self.assertTrue(self.couchdb.db.server.all_dbs().index('test_db_2'))
class DocLoaderTestCase(unittest.TestCase):
@@ -76,22 +83,25 @@ def setUp(self):
app.config['COUCHDB_DATABASE'] = 'test_db_3'
app.config['TESTING'] = True
couchdb = CouchDBKit(app)
- self.Todo = make_todo_model(couchdb)
+
+ with app.app_context():
+ self.Todo = make_todo_model(couchdb)
- self.Todo(title='First Todo', text='Some text.').save()
- self.Todo(title='Second Todo', text='More text.', done=True).save()
- self.Todo(title='Third Todo', text='Even more text.').save()
+ self.Todo(title='First Todo', text='Some text.').save()
+ self.Todo(title='Second Todo', text='More text.', done=True).save()
+ self.Todo(title='Third Todo', text='Even more text.').save()
self.app = app
self.couchdb = couchdb
def tearDown(self):
- del self.couchdb.server[self.app.config['COUCHDB_DATABASE']]
+ with self.app.app_context():
+ del self.couchdb.db.server[self.app.config['COUCHDB_DATABASE']]
def test_doc_loader(self):
- self.couchdb.sync()
- results = [row for row in self.Todo.view('todos/status_count',
- group=True)]
+ with self.app.app_context():
+ self.couchdb.sync()
+ results = self.Todo.view('todos/status_count', group=True).all()
self.assertFalse(results[0]['key'])
self.assertEqual(results[0]['value'], 2)
@@ -122,7 +132,8 @@ def add():
self.couchdb.sync()
def tearDown(self):
- del self.couchdb.server[self.app.config['COUCHDB_DATABASE']]
+ with self.app.app_context():
+ del self.couchdb.server[self.app.config['COUCHDB_DATABASE']]
def test_basic_insert(self):
c = self.app.test_client()

0 comments on commit 5af8dd9

Please sign in to comment.