Initial version of the handler mixins

This commit is contained in:
Gavin M. Roy 2014-08-29 11:56:12 -04:00
parent 7eea6fb603
commit 7f4c1239fa
20 changed files with 727 additions and 26 deletions

26
.travis.yml Normal file
View file

@ -0,0 +1,26 @@
%YAML 1.1
---
language: python
python:
- 2.6
- 2.7
- pypy
- 3.2
- 3.3
- 3.4
install:
- if [[ $TRAVIS_PYTHON_VERSION == '2.6' ]]; then pip install unittest2; fi
- pip install -e .
- pip install -r test-requirements.txt
script: nosetests
after_success:
- coveralls
deploy:
provider: pypi
user: sprockets
on:
python: 2.7
tags: true
all_branches: true
password:
secure: JRmF7wfSuD3Aes2exf7x5mu9tqgkn5gmj1THacfcqqWntWW9odhVcdDfDzLltVsTpA8AKWkcSVBpUczZHWzq4J2lGfrkC5vzi9CHxepxWAduZ7YjmOi9UXxY5A0xjviZGObJjzpnnkeQD/M9dF0KcD/mm6ks94BLoeQeuHlUnPg=

39
LICENSE
View file

@ -1,28 +1,25 @@
Copyright (c) 2014, Sprockets
Copyright (c) 2014 AWeber Communications
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of Sprockets nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
* Neither the name of the {organization} nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

7
MANIFEST.in Normal file
View file

@ -0,0 +1,7 @@
include LICENSE
include README.rst
include *requirements.txt
graft docs
graft tests.py
global-exclude __pycache__
global-exclude *.pyc

View file

@ -1,2 +0,0 @@
sprockets.mixins.postgresql
===========================

97
README.rst Normal file
View file

@ -0,0 +1,97 @@
sprockets.mixins.postgresql
===========================
Handler mixins that automatically connect a PostgreSQL client session upon initialization.
|Version| |Downloads| |Status| |Coverage| |License|
Installation
------------
sprockets.mixins.postgresql is available on the
`Python Package Index <https://pypi.python.org/pypi/sprockets.mixins.postgresql>`_
and can be installed via ``pip`` or ``easy_install``:
.. code:: bash
pip install sprockets.mixins.postgresql
Documentation
-------------
https://sprocketsmixinspostgresql.readthedocs.org
Requirements
------------
- `sprockets <https://github.com/sprockets/sprockets>`_
- `sprockets.clients.postgresql <https://github.com/sprockets/sprockets.clients.postgresql>`_
Example
-------
The following example demonstrates using the ``HandlerMixin`` with a
synchronous Tornado ``RequestHandler <tornado.web.RequestHandler>`` for a
database named ``postgres``:
.. code:: python
import os
from sprockets.mixins import postgresql
from tornado import web
os.environ['POSTGRES_HOST'] = 'localhost'
os.environ['POSTGRES_USER'] = 'postgres'
os.environ['POSTGRES_PORT'] = 5432
os.environ['POSTGRES_DBNAME'] = 'postgres'
class PostgresRequestHandler(postgresql.HandlerMixin,
web.RequestHandler):
DBNAME = 'postgres'
def get(self, *args, **kwargs):
result = self.foo_session.query('SELECT * FROM bar')
self.finish({'data': result.items()})
The second example demonstrates using the ``AsyncHandlerMixin`` with an
asynchronous Tornado ``RequestHandler`` for a database named ``foo``:
.. code:: python
import os
from sprockets.mixins import postgresql
from tornado import web
os.environ['FOO_HOST'] = 'localhost'
os.environ['FOO_USER'] = 'postgres'
os.environ['FOO_PORT'] = 5432
os.environ['FOO_DBNAME'] = 'foo'
os.environ['FOO_PASSWORD'] = 'bar'
class FooRequestHandler(postgresql.HandlerMixin,
web.RequestHandler):
DBNAME = 'foo'
@web.asynchronous
def get(self, *args, **kwargs):
result = yield self.foo_session.query('SELECT * FROM baz')
self.finish({'data': result.items()})
result.free()
Version History
---------------
Available at https://sprocketsmixinspostgresql.readthedocs.org/en/latest/history.html
.. |Version| image:: https://badge.fury.io/py/sprockets.mixins.postgresql.svg?
:target: http://badge.fury.io/py/sprockets.mixins.postgresql
.. |Status| image:: https://travis-ci.org/sprockets/sprockets.mixins.postgresql.svg?branch=master
:target: https://travis-ci.org/sprockets/sprockets.mixins.postgresql
.. |Coverage| image:: https://img.shields.io/coveralls/sprockets/sprockets.mixins.postgresql.svg?
:target: https://coveralls.io/r/sprockets/sprockets.mixins.postgresql
.. |Downloads| image:: https://pypip.in/d/sprockets.mixins.postgresql/badge.svg?
:target: https://pypi.python.org/pypi/sprockets.mixins.postgresql
.. |License| image:: https://pypip.in/license/sprockets.mixins.postgresql/badge.svg?
:target: https://sprocketsmixinspostgresql.readthedocs.org

6
dev-requirements.txt Normal file
View file

@ -0,0 +1,6 @@
-r requirements.txt
-r test-requirements.txt
flake8>=2.1,<3
sphinx>=1.2,<2
sphinx-rtd-theme>=0.1,<1.0
sphinxcontrib-httpdomain>=1.2,<2

153
docs/Makefile Normal file
View file

@ -0,0 +1,153 @@
# Makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
PAPER =
BUILDDIR = _build
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
# the i18n builder cannot share the environment and doctrees with the others
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
help:
@echo "Please use \`make <target>' where <target> is one of"
@echo " html to make standalone HTML files"
@echo " dirhtml to make HTML files named index.html in directories"
@echo " singlehtml to make a single large HTML file"
@echo " pickle to make pickle files"
@echo " json to make JSON files"
@echo " htmlhelp to make HTML files and a HTML help project"
@echo " qthelp to make HTML files and a qthelp project"
@echo " devhelp to make HTML files and a Devhelp project"
@echo " epub to make an epub"
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@echo " latexpdf to make LaTeX files and run them through pdflatex"
@echo " text to make text files"
@echo " man to make manual pages"
@echo " texinfo to make Texinfo files"
@echo " info to make Texinfo files and run them through makeinfo"
@echo " gettext to make PO message catalogs"
@echo " changes to make an overview of all changed/added/deprecated items"
@echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
clean:
-rm -rf $(BUILDDIR)/*
html:
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
dirhtml:
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
singlehtml:
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
@echo
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
pickle:
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
@echo
@echo "Build finished; now you can process the pickle files."
json:
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
@echo
@echo "Build finished; now you can process the JSON files."
htmlhelp:
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
@echo
@echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in $(BUILDDIR)/htmlhelp."
qthelp:
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
@echo
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/rabbitpy.qhcp"
@echo "To view the help file:"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/rabbitpy.qhc"
devhelp:
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
@echo
@echo "Build finished."
@echo "To view the help file:"
@echo "# mkdir -p $$HOME/.local/share/devhelp/rabbitpy"
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/rabbitpy"
@echo "# devhelp"
epub:
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
@echo
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
latex:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
@echo "Run \`make' in that directory to run these through (pdf)latex" \
"(use \`make latexpdf' here to do that automatically)."
latexpdf:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through pdflatex..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
text:
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
@echo
@echo "Build finished. The text files are in $(BUILDDIR)/text."
man:
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
@echo
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
texinfo:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
@echo "Run \`make' in that directory to run these through makeinfo" \
"(use \`make info' here to do that automatically)."
info:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo "Running Texinfo files through makeinfo..."
make -C $(BUILDDIR)/texinfo info
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
gettext:
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
@echo
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
changes:
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
@echo
@echo "The overview file is in $(BUILDDIR)/changes."
linkcheck:
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
@echo
@echo "Link check complete; look for any errors in the above output " \
"or in $(BUILDDIR)/linkcheck/output.txt."
doctest:
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in $(BUILDDIR)/doctest/output.txt."

2
docs/api.rst Normal file
View file

@ -0,0 +1,2 @@
.. automodule:: sprockets.mixins.postgresql
:members:

32
docs/conf.py Normal file
View file

@ -0,0 +1,32 @@
#!/usr/bin/env python
import sphinx_rtd_theme
from sprockets.mixins.postgresql import version_info, __version__
needs_sphinx = '1.0'
extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.intersphinx',
'sphinxcontrib.httpdomain',
]
templates_path = []
source_suffix = '.rst'
master_doc = 'index'
project = 'sprockets.mixins.postgresql'
copyright = '2014, AWeber Communications'
version = '.'.join(__version__.split('.')[0:1])
release = __version__
if len(version_info) > 3:
release += '-{0}'.format(str(v) for v in version_info[3:])
exclude_patterns = []
pygments_style = 'sphinx'
html_theme = 'sphinx_rtd_theme'
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
intersphinx_mapping = {
'python': ('https://docs.python.org/', None),
'sprockets': ('https://sprockets.readthedocs.org/en/latest/', None),
'sprockets.clients.postgresql': (
'https://sprocketsclientspostgresql.readthedocs.org/en/latest/',
None),
'tornado': ('http://tornadoweb.org/en/stable/', None)
}

57
docs/examples.rst Normal file
View file

@ -0,0 +1,57 @@
Examples
========
The following example demonstrates using the
:py:class:`HandlerMixin <sprockets.mixins.postgresql.HandlerMixin>` with a
synchronous Tornado :py:class:`RequestHandler <tornado.web.RequestHandler>` for a database
named ``postgres``:
.. code:: python
import os
from sprockets.mixins import postgresql
from tornado import web
os.environ['POSTGRES_HOST'] = 'localhost'
os.environ['POSTGRES_USER'] = 'postgres'
os.environ['POSTGRES_PORT'] = 5432
os.environ['POSTGRES_DBNAME'] = 'postgres'
class PostgresRequestHandler(postgresql.HandlerMixin,
web.RequestHandler):
DBNAME = 'postgres'
def get(self, *args, **kwargs):
result = self.foo_session.query('SELECT * FROM bar')
self.finish({'data': result.items()})
The second example demonstrates using the
:py:class:`AsyncHandlerMixin <sprockets.mixins.postgresql.AsyncHandlerMixin>`
with an asynchronous Tornado :py:class:`RequestHandler <tornado.web.RequestHandler>`
for a database named ``foo``:
.. code:: python
import os
from sprockets.mixins import postgresql
from tornado import web
os.environ['FOO_HOST'] = 'localhost'
os.environ['FOO_USER'] = 'postgres'
os.environ['FOO_PORT'] = 5432
os.environ['FOO_DBNAME'] = 'foo'
os.environ['FOO_PASSWORD'] = 'bar'
class FooRequestHandler(postgresql.HandlerMixin,
web.RequestHandler):
DBNAME = 'foo'
@web.asynchronous
def get(self, *args, **kwargs):
result = yield self.foo_session.query('SELECT * FROM baz')
self.finish({'data': result.items()})
result.free()

5
docs/history.rst Normal file
View file

@ -0,0 +1,5 @@
Version History
---------------
- 0.0.0 [YYYY-MM-DD]
- Change 1
- Change 2

66
docs/index.rst Normal file
View file

@ -0,0 +1,66 @@
sprockets.mixins.postgresql
===========================
Handler mixins that automatically connect a PostgreSQL client session upon initialization.
|Version| |Downloads| |Status| |Coverage| |License|
Installation
------------
``sprockets.mixins.postgresql`` is available on the
`Python Package Index <https://pypi.python.org/pypi/sprockets.mixins.postgresql>`_
and can be installed via ``pip`` or ``easy_install``:
.. code:: bash
pip install sprockets.mixins.postgresql
Requirements
------------
- `sprockets <https://github.com/sprockets/sprockets>`_
- `sprockets.clients.postgresql <https://github.com/sprockets/sprockets.clients.postgresql>`_
API Documentation
-----------------
.. toctree::
:maxdepth: 2
api
examples
Version History
---------------
See :doc:`history`
Issues
------
Please report any issues to the Github project at `https://github.com/sprockets/sprockets.mixins.postgresql/issues <https://github.com/sprockets/sprockets.mixins.postgresql/issues>`_
Source
------
``sprockets.mixins.postgresql`` source is available on Github at `https://github.com/sprockets/sprockets.mixins.postgresql <https://github.com/sprockets/sprockets.mixins.postgresql>`_
License
-------
``sprockets.mixins.postgresql`` is released under the `3-Clause BSD license <https://github.com/sprockets/sprockets.mixins.postgresql/blob/master/LICENSE>`_.
Indices and tables
------------------
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
.. |Version| image:: https://badge.fury.io/py/sprockets.mixins.postgresql.svg?
:target: http://badge.fury.io/py/sprockets.mixins.postgresql
.. |Status| image:: https://travis-ci.org/sprockets/sprockets.mixins.postgresql.svg?branch=master
:target: https://travis-ci.org/sprockets/sprockets.mixins.postgresql
.. |Coverage| image:: https://img.shields.io/coveralls/sprockets/sprockets.mixins.postgresql.svg?
:target: https://coveralls.io/r/sprockets/sprockets.mixins.postgresql
.. |Downloads| image:: https://pypip.in/d/sprockets.mixins.postgresql/badge.svg?
:target: https://pypi.python.org/pypi/sprockets.mixins.postgresql
.. |License| image:: https://pypip.in/license/sprockets.mixins.postgresql/badge.svg?
:target: https://sprocketsmixinspostgresql.readthedocs.org

2
requirements.txt Normal file
View file

@ -0,0 +1,2 @@
sprockets<2
sprockets.clients.postgresql>=1.0.0

12
setup.cfg Normal file
View file

@ -0,0 +1,12 @@
[build_sphinx]
all-files = 1
source-dir = docs
build-dir = build/docs
[nosetests]
with-coverage = 1
cover-package = sprockets.mixins.postgresql
verbose = 1
[flake8]
exclude = build,dist,docs,env

68
setup.py Normal file
View file

@ -0,0 +1,68 @@
import codecs
import sys
import setuptools
def read_requirements_file(req_name):
requirements = []
try:
with codecs.open(req_name, encoding='utf-8') as req_file:
for req_line in req_file:
if '#' in req_line:
req_line = req_line[0:req_line.find('#')].strip()
if req_line:
requirements.append(req_line.strip())
except IOError:
pass
return requirements
install_requires = read_requirements_file('requirements.txt')
setup_requires = read_requirements_file('setup-requirements.txt')
tests_require = read_requirements_file('test-requirements.txt')
if sys.version_info < (2, 7):
tests_require.append('unittest2')
if sys.version_info < (3, 0):
tests_require.append('mock')
setuptools.setup(
name='sprockets.mixins.postgresql',
version='0.0.0',
description='A sprockets mixin that automatically connects to PostgreSQL',
long_description=codecs.open('README.rst', encoding='utf-8').read(),
url='https://github.com/sprockets/sprockets.mixins.postgresql.git',
author='AWeber Communications',
author_email='api@aweber.com',
license=codecs.open('LICENSE', encoding='utf-8').read(),
classifiers=[
'Development Status :: 4 - Beta',
'Intended Audience :: Developers',
'License :: OSI Approved :: BSD License',
'Natural Language :: English',
'Operating System :: OS Independent',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.2',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: Implementation :: CPython',
'Programming Language :: Python :: Implementation :: PyPy',
'Topic :: Software Development :: Libraries',
'Topic :: Software Development :: Libraries :: Python Modules'
],
packages=['sprockets',
'sprockets.mixins',
'sprockets.mixins.postgresql'],
package_data={'': ['LICENSE', 'README.md']},
include_package_data=True,
namespace_packages=['sprockets',
'sprockets.mixins'],
install_requires=install_requires,
setup_requires=setup_requires,
tests_require=tests_require,
test_suite='nose.collector',
zip_safe=False)

1
sprockets/__init__.py Normal file
View file

@ -0,0 +1 @@
__import__('pkg_resources').declare_namespace(__name__)

View file

@ -0,0 +1 @@
__import__('pkg_resources').declare_namespace(__name__)

View file

@ -0,0 +1,109 @@
"""
PostgreSQL Client Mixins
========================
Sprockets mixins that automatically connects to PostgreSQL using
`sprockets.clients.postgresql <http://sprocketsclientspostgresql.rtfd.org>`_.
Handlers implementing one of the mixins should set an attribute called
``DBNAME`` that specifies the database name to connect to. The value of
``DBNAME`` will be passed into the creation of the
:py:class:`Session <sprockets.clients.postgresql.Session>` or
:py:class:`TornadoSession <sprockets.clients.postgresql.TornadoSession>`
object.
The Session classes wrap the Queries :py:class:`Session <queries.Session>` or
:py:class:`TornadoSession <queries.tornado_session.TornadoSession>` providing
environment variable based configuration.
The environment variables should be set using the ``DBNAME_[VARIABLE]`` format
where ``[VARIABLE]`` is one of ``HOST``, ``PORT``, ``DBNAME``, ``USER``, and
``PASSWORD``.
"""
version_info = (1, 0, 0)
__version__ = '.'.join(str(v) for v in version_info)
from sprockets.clients import postgresql
class HandlerMixin(object):
"""A handler mixin for connecting to PostgreSQL. The mixin automatically
creates the database session using the DBNAME attribute of the class as
the database name for the
:py:class:`Session <sprockets.clients.postgresql.Session>` object
creation.
Using the mixin, the name of the session attribute will be
``<dbname>_session``, automatically created when initializing the object.
Example:
.. code:: python
from sprockets.mixins import postgresql
from tornado import web
class FooRequestHandler(postgresql.HandlerMixin,
web.RequestHandler,):
DBNAME = 'foo'
def get(self, *args, **kwargs):
result = self.foo_session.query('SELECT * FROM bar')
self.finish({'data': result.items()})
"""
DBNAME = 'postgres'
def initialize(self):
setattr(self,
'%s_session' % self.DBNAME,
postgresql.Session(self.DBNAME))
try:
super(HandlerMixin, self).initialize()
except AttributeError:
pass
class AsyncHandlerMixin(object):
"""A asynchronous Tornado handler mixin for connecting to PostgreSQL. The
mixin automatically creates the database session using the DBNAME attribute
of the class as the database name for the
:py:class:`TornadoSession <sprockets.clients.postgresql.TornadoSession>`
object creation.
Using the mixin, the name of the session attribute will be
``<dbname>_session``, automatically created when initializing the object.
Example:
.. code:: python
from sprockets.mixins import postgresql
from tornado import web
class FooRequestHandler(postgresql.AsyncHandlerMixin,
web.RequestHandler):
DBNAME = 'foo'
@web.asynchronous
def get(self, *args, **kwargs):
result = yield self.foo_session.query('SELECT * FROM bar')
self.finish({'data': result.items()})
result.free()
"""
DBNAME = 'postgres'
def initialize(self):
setattr(self,
'%s_session' % self.DBNAME,
postgresql.TornadoSession(self.DBNAME))
try:
super(AsyncHandlerMixin, self).initialize()
except AttributeError:
pass

3
test-requirements.txt Normal file
View file

@ -0,0 +1,3 @@
coverage>=3.7,<4
coveralls>=0.4,<1
nose>=1.3,<2

59
tests.py Normal file
View file

@ -0,0 +1,59 @@
"""
Tests for the sprockets.mixins.postgresql package
"""
import mock
import os
try:
import unittest2 as unittest
except ImportError:
import unittest
from sprockets.clients import postgresql as _postgresql
from sprockets.mixins import postgresql
class MixinRequestHandler(postgresql.HandlerMixin):
DBNAME = 'bar'
class AsyncMixinRequestHandler(postgresql.AsyncHandlerMixin):
DBNAME = 'baz'
class HandlerMixinTest(unittest.TestCase):
@mock.patch('queries.session.Session.__init__')
def setUp(self, mock_init):
self.mock_init = mock_init
os.environ['BAR_HOST'] = 'db1'
os.environ['BAR_PORT'] = '5433'
os.environ['BAR_DBNAME'] = 'bar'
os.environ['BAR_USER'] = 'foo'
os.environ['BAR_PASSWORD'] = 'baz'
self.mixin = MixinRequestHandler()
self.mixin.initialize()
def test_session_get_uri_value(self):
self.assertIsInstance(getattr(self.mixin, 'bar_session'),
_postgresql.Session)
class AsyncHandlerMixinTest(unittest.TestCase):
@mock.patch('queries.tornado_session.TornadoSession.__init__')
def setUp(self, mock_init):
self.mock_init = mock_init
os.environ['BAZ_HOST'] = 'db2'
os.environ['BAZ_PORT'] = '5434'
os.environ['BAZ_DBNAME'] = 'baz'
os.environ['BAZ_USER'] = 'qux'
os.environ['BAZ_PASSWORD'] = 'corgie'
self.mixin = AsyncMixinRequestHandler()
self.mixin.initialize()
def test_session_get_uri_value(self):
self.assertIsInstance(getattr(self.mixin, 'baz_session'),
_postgresql.TornadoSession)