commit 13e26cefbda3c24ff7402fc2ecbcdf2d96942760 Author: Brian Korty Date: Wed May 6 14:51:41 2015 -0400 SYN diff --git a/.coveragerc b/.coveragerc new file mode 100644 index 0000000..4def366 --- /dev/null +++ b/.coveragerc @@ -0,0 +1,2 @@ +[run] +source=sprockets.clients.cassandra diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..643fde7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,85 @@ +# Python # +########## +*.EGG +*.EGG-INFO +*.egg +*.egg-info +*.mo +*.pyc +*.pyd +*.pyo +*.tmp* +develop-eggs +downloads +eggs +fake-eggs +parts + +# Packages # +############ +# it's better to unpack these files and commit the raw source +# git has its own built in compression methods +*.7z +*.deb +*.dmg +*.gz +*.iso +*.rar +*.tar +*.tgz +*.zip + +# Logs and databases # +###################### +*.log +*.sql +*.sqlite + +# OS generated files # +###################### +.DS_Store +Icon? +Thumbs.db +ehthumbs.db + +# Editor generated files # +########################## +*.bak +*.swm +*.swn +*.swo +*.swp +*~ +.ropeproject +*.sublime-* + +# Chef # +######## +/trace_stats +cookbooks/*/metadata.json + +# Tag files # +############# +TAGS + +# Generated by make targets # +############################# +/.coverage +/.nose-stopwatch-times +/.req +/RELEASE-VERSION +/build +/chef_script +/dist/ +/docs/doctrees +/docs/html +/docs/_build +/env/ +/htmlcov +/pip-log.txt +/reports/ +/.tests.pylintrc +/.tox +nosetests.xml + +/.tox/ diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..40bf056 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,24 @@ +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 -r requirements.txt -r test-requirements.txt +script: nosetests +after_success: + - coveralls +deploy: + provider: pypi + distributions: "sdist bdist_wheel" + user: johnb + password: + secure: "Q0XIvK1R4kv2uFoUDOARQ1swgcnWqlE0jO20Urc0RsuTejY4/uNgUxvp3wfnd+NKARHwrUQFYHGzI5ueVcppQzGzZArr/o3DB9Vh7OURBtbqrSReRsz9QXmV3pDAbSq3p1QbhCryZeEOU0V5DqlnYfVuiM27WWo+V8gg20qn5OY=" + on: + python: 2.7 + tags: true + all_branches: true diff --git a/HISTORY.rst b/HISTORY.rst new file mode 100644 index 0000000..af8629c --- /dev/null +++ b/HISTORY.rst @@ -0,0 +1,17 @@ +.. :changelog: + +.. Add an entry using the following format when you release a new +.. version of this package + +.. 0.0.0 (CCYY-MM-DD) +.. ------------------ +.. +.. - + +Release History +=============== + +Next Release +------------ + +- Implement greatness. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..0ab6ccf --- /dev/null +++ b/LICENSE @@ -0,0 +1,25 @@ +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: + + * 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, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of the copyright holder 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. diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..a165683 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,13 @@ +include .coveragerc +include HISTORY.rst +include LICENSE +include README.rst +include dev-requirements.txt +graft docs +include requirements.txt +include test-requirements.txt +graft tests +include tox.ini + +global-exclude __pycache__ +global-exclude *.pyc diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..33fc17c --- /dev/null +++ b/README.rst @@ -0,0 +1,48 @@ +sprockets.clients.cassandra +=========================== + +.. image:: https://coveralls.io/repos/aweber/sprockets.clients.cassandra/badge.png + :target: https://coveralls.io/r/aweber/sprockets.clients.cassandra + +.. image:: https://pypip.in/download/sprockets.clients.cassandra/badge.svg + :target: https://pypi.python.org/pypi/sprockets.clients.cassandra/ + +.. image:: https://pypip.in/license/sprockets.clients.cassandra/badge.svg + :target: https://pypi.python.org/pypi/sprockets.clients.cassandra/ + +.. image:: https://readthedocs.org/projects/sprockets.clients.cassandra/badge/?version=latest + :target: http://sprockets.clients.cassandra.readthedocs.org/en/latest/ + +----- + +.. important:: + + Please send email to api@aweber.com and them them to update this README! + +Quickstart Development Guide +---------------------------- + +1. Create a new virtual environment using `pyvenv`_ or `virtualenv`_ and + **activate it** +2. Install development requirements - `pip install -r dev-requirements` +3. `./setup.py nosetests` will run the test suite with coverage enabled +4. `detox`_ is installed and will run the test suite across all supported + python platforms +5. `./setup.py build_sphinx` will generate documentation into + *build/sphinx/html* + +TL;DR ++++++ + +:: + + $ pyvenv env + $ ./env/bin/pip install -qr dev-requirements.txt + $ source env/bin/activate + (env) $ ./setup.py nosetests + (env) $ ./setup.py build_sphinx + (env) $ detox + +.. _detox: https://testrun.org/tox/ +.. _pyvenv: https://docs.python.org/3/library/venv.html +.. _virtualenv: https://virtualenv.pypa.io/ diff --git a/dev-requirements.txt b/dev-requirements.txt new file mode 100644 index 0000000..b496392 --- /dev/null +++ b/dev-requirements.txt @@ -0,0 +1,16 @@ +# Add dependencies required to develop and test your package. +# will be added into `setup.py` as the `tests_require` keyword. +# +# Unless otherwise noted, we expect that the dependencies +# follow semantic versioning, and will loosely pin them to +# minimize breakage to our dev environment. +-r requirements.txt +-r test-requirements.txt +detox>=0.9.3 +flake8>=2.2,<3.0 +nosy>=1.1.2,<2.0.0 +pyyaml>=3.11,<4.0 +pylint>=1.3.1,<2.0.0 +Sphinx>=1.2,<2.0 +sphinx-rtd-theme>=0.1,<1.0 +tox>=1.6.0,<2.0.0 diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 0000000..5eba9ab --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- +import sphinx_rtd_theme +import sprockets.clients.cassandra + +project = 'sprockets.clients.cassandra' +copyright = 'AWeber Communications, Inc.' +version = sprockets.clients.cassandra.__version__ +release = '.'.join(str(v) for v in sprockets.clients.cassandra.version_info) + +needs_sphinx = '1.0' +extensions = [ + 'sphinx.ext.autodoc', + 'sphinx.ext.intersphinx', + 'sphinx.ext.viewcode', +] + +templates_path = [] +source_suffix = '.rst' +source_encoding = 'utf-8-sig' +master_doc = 'index' +exclude_patterns = [] +pygments_style = 'sphinx' +html_theme = 'sphinx_rtd_theme' +html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] +html_static_path = [] + +intersphinx_mapping = { + 'python': ('http://docs.python.org/3/', None), +} diff --git a/docs/contributing.rst b/docs/contributing.rst new file mode 100644 index 0000000..d3d4c03 --- /dev/null +++ b/docs/contributing.rst @@ -0,0 +1,121 @@ +How to Contribute +================= +Do you want to contribute fixes or improvements? + + **AWesome!** *Thank you very much, and let's get started.* + +This project is released under the permissive BSD license so you don't have +to push changes back unless you want to. Since you are reading this, you +have probably made the right decision. + +Set up a development environment +-------------------------------- +The first thing that you need is a development environment so that you can +run the test suite, update the documentation, and everything else that is +involved in contributing. The easiest way to do that is to create a virtual +environment for your endevours:: + + $ pyvenv env + +Don't worry about writing code against previous versions of Python unless +you you don't have a choice. That is why we run our tests through `tox`_. +If you don't have a choice, then install `virtualenv`_ to create the +environment instead. The next step is to install the development tools +that this project uses. These are listed in *dev-requirements.txt*:: + + $ env/bin/pip install -qr dev-requirements.txt + +At this point, you will have everything that you need to develop at your +disposal. *setup.py* is the swiss-army knife in your development tool +chest. It provides the following commands: + +**./setup.py nosetests** + Run the test suite using `nose`_ and generate a nice coverage report. + +**./setup.py build_sphinx** + Generate the documentation using `sphinx`_. + +**./setup.py flake8** + Run `flake8`_ over the code and report style violations. + +If any of the preceding commands give you problems, then you will have to +fix them **before** your pull request will be accepted. + +Running Tests +------------- +The easiest (and quickest) way to run the test suite is to use the +*nosetests* command. It will run the test suite against the currently +installed python version and report not only the test result but the +test coverage as well:: + + $ ./setup.py nosetests + + running nosetests + running egg_info + writing dependency_links to sprockets.clients.cassandra.egg-info/dependency_links.txt + writing top-level names to sprockets.clients.cassandra.egg-info/top_level.txt + writing sprockets.clients.cassandra.egg-info/PKG-INFO + reading manifest file 'sprockets.clients.cassandra.egg-info/SOURCES.txt' + reading manifest template 'MANIFEST.in' + warning: no previously-included files matching '__pycache__'... + warning: no previously-included files matching '*.swp' found ... + writing manifest file 'sprockets.clients.cassandra.egg-info/SOURCES.txt' + ... + + Name Stmts Miss Branch BrMiss Cover Missing + ---------------------------------------------------------------------- + ... + ---------------------------------------------------------------------- + TOTAL 95 2 59 2 97% + ---------------------------------------------------------------------- + Ran 44 tests in 0.054s + + OK + +That's the quick way to run tests. The slightly longer way is to run +the `detox`_ utility. It will run the test suite against all of the +supported python versions in parallel. This is essentially what Travis-CI +will do when you issue a pull request anyway:: + + $ env/bin/detox + py27 recreate: /.../sprockets.clients.cassandra/build/tox/py27 + GLOB sdist-make: /.../sprockets.clients.cassandra/setup.py + py33 recreate: /.../sprockets.clients.cassandra/build/tox/py33 + py34 recreate: /.../sprockets.clients.cassandra/build/tox/py34 + py27 installdeps: -rtest-requirements.txt, mock + py33 installdeps: -rtest-requirements.txt + py34 installdeps: -rtest-requirements.txt + py27 inst: /.../sprockets.clients.cassandra/build/tox/dist/sprockets.clients.cassandra-0.0.0.zip + py27 runtests: PYTHONHASHSEED='2156646470' + py27 runtests: commands[0] | /../sprockets.clients.cassandra/build/tox/py27/bin/nosetests + py33 inst: /../sprockets.clients.cassandra/.build/tox/dist/sprockets.clients.cassandra-0.0.0.zip + py34 inst: /../sprockets.clients.cassandra/.build/tox/dist/sprockets.clients.cassandra-0.0.0.zip + py33 runtests: PYTHONHASHSEED='2156646470' + py33 runtests: commands[0] | /.../sprockets.clients.cassandra/build/tox/py33/bin/nosetests + py34 runtests: PYTHONHASHSEED='2156646470' + py34 runtests: commands[0] | /.../sprockets.clients.cassandra/build/tox/py34/bin/nosetests + _________________________________ summary _________________________________ + py27: commands succeeded + py33: commands succeeded + py34: commands succeeded + congratulations :) + +This is what you want to see. Now you can make your modifications and keep +the tests passing. + +Submitting a Pull Request +------------------------- +Once you have made your modifications, gotten all of the tests to pass, +and added any necessary documentation, it is time to contribute back for +posterity. You've probably already cloned this repository and created a +new branch. If you haven't, then checkout what you have as a branch and +roll back *master* to where you found it. Then push your repository up +to github and issue a pull request. Describe your changes in the request, +if Travis isn't too annoyed someone will review it, and eventually merge +it back. + +.. _flake8: http://flake8.readthedocs.org/ +.. _nose: http://nose.readthedocs.org/ +.. _sphinx: http://sphinx-doc.org/ +.. _tox: http://testrun.org/tox/ +.. _virtualenv: http://virtualenv.pypa.io/ diff --git a/docs/index.rst b/docs/index.rst new file mode 100644 index 0000000..74e271d --- /dev/null +++ b/docs/index.rst @@ -0,0 +1,18 @@ +.. include:: ../README.rst + +Documentation +============= + +.. toctree:: + :maxdepth: 2 + + contributing + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` + +.. include:: ../HISTORY.rst diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..fd63dd2 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +# Add dependencies that are required to install your package. These will +# be passed into `setup` as the `install_requires` keyword. +# diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..2fd743a --- /dev/null +++ b/setup.cfg @@ -0,0 +1,17 @@ +[build_sphinx] +all_files=1 + +[nosetests] +with-coverage=1 +cover-package=sprockets.clients.cassandra +match=^When|^should|^[Tt]est +nocapture=1 +cover-branches=1 +cover-tests=1 + +[nosy] +tests=tests/unit --cover-package=sprockets.clients.cassandra +glob_patterns=*.py + +[bdist_wheel] +universal = 1 diff --git a/setup.py b/setup.py new file mode 100755 index 0000000..fdc9edc --- /dev/null +++ b/setup.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python +import codecs +import sys + +from setuptools import setup, find_packages + +import sprockets.clients.cassandra + + +def read_requirements_file(filename): + """Read pip-formatted requirements from a file.""" + with open(filename, 'r') as f: + return [line.strip() for line in f.readlines() + if not line.startswith('#')] + +requirements = read_requirements_file('requirements.txt') +test_requirements = read_requirements_file('test-requirements.txt') +if sys.version_info < (3, ): + requirements.append('six>=1.7,<2.0') + test_requirements.append('mock>=1.0.1,<2.0') +if sys.version_info < (2, 7): + test_requirements.append('unittest2==0.5.1') + +setup( + name='sprockets.clients.cassandra', + description='Base functioanlity for accessing/modifying data in Cassandra', + version=sprockets.clients.cassandra.__version__, + packages=find_packages(exclude=['tests', 'tests.*']), + test_suite='nose.collector', + include_package_data=True, + long_description=codecs.open('README.rst', encoding='utf-8').read(), + install_requires=requirements, + tests_require=test_requirements, + author='AWeber Communications, Inc.', + author_email='api@aweber.com', + url='https://github.com/aweber/sprockets.clients.cassandra', + classifiers=[ + 'Development Status :: 1 - Planning', + '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', + ], +) diff --git a/sprockets.clients.cassandra/__init__.py b/sprockets.clients.cassandra/__init__.py new file mode 100644 index 0000000..9afb70c --- /dev/null +++ b/sprockets.clients.cassandra/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- +version_info = (0, 0, 0) +__version__ = '.'.join(str(v) for v in version_info[:3]) diff --git a/test-requirements.txt b/test-requirements.txt new file mode 100644 index 0000000..28aec1f --- /dev/null +++ b/test-requirements.txt @@ -0,0 +1,12 @@ +# Add dependencies that are required to test your package. These +# will be installed when ``setup.py test`` is run. They will also +# be installed into the test environment generated by Travis CI. +# Development tools that are not absolutely required for testing +# should be placed into dev-requirements.txt +# +# Unless otherwise noted, we expect that the dependencies +# follow semantic versioning, and will loosely pin them to +# minimize breakage to our dev environment. +coveralls>=0.4,<1.0 +nose>=1.3.1,<2.0.0 +test-helpers>=1.5.1,<2.0.0 diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/tests/__init__.py @@ -0,0 +1 @@ + diff --git a/tests/acceptance/__init__.py b/tests/acceptance/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/tests/acceptance/__init__.py @@ -0,0 +1 @@ + diff --git a/tests/integration/__init__.py b/tests/integration/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/tests/integration/__init__.py @@ -0,0 +1 @@ + diff --git a/tests/unit/__init__.py b/tests/unit/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/tests/unit/__init__.py @@ -0,0 +1 @@ + diff --git a/tests/unit/test_example.py b/tests/unit/test_example.py new file mode 100644 index 0000000..8319b63 --- /dev/null +++ b/tests/unit/test_example.py @@ -0,0 +1,58 @@ +from test_helpers import bases +from test_helpers.compat import mock +from test_helpers.mixins import patch_mixin + + +class App(object): + """Quick example app for testing.""" + + def first(self, fail): + """Example method under test.""" + self.do_db_lookup('random') + if fail: + raise AttributeError + + def do_db_lookup(self, name): + """Method that reaches out to a database.""" + raise NotImplementedError + + +class _BaseFirstTestCase(patch_mixin.PatchMixin, bases.BaseTest): + """Example base test showing current test style.""" + + patch_prefix = 'tests.unit.test_example' + + @classmethod + def configure(cls): + cls.app = App() + + cls.do_db_lookup = cls.create_patch('App.do_db_lookup') + + @classmethod + def execute(cls): + try: + cls.app.first(cls.fail) + except AttributeError as exc: + cls.exception = exc + + def should_do_db_lookup(self): + self.do_db_lookup.assert_called_once_with(mock.ANY) + + +class WhenFirstAppSuccessful(_BaseFirstTestCase): + + @classmethod + def configure(cls): + cls.fail = False + super(WhenFirstAppSuccessful, cls).configure() + + +class WhenFirstAppFails(_BaseFirstTestCase): + + @classmethod + def configure(cls): + cls.fail = True + super(WhenFirstAppFails, cls).configure() + + def should_raise_AttributeError(self): + self.assertIsInstance(self.exception, AttributeError) diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..3a25764 --- /dev/null +++ b/tox.ini @@ -0,0 +1,16 @@ +[tox] +envlist = py26,py27,py32,py33,py34 + +[testenv] +commands = nosetests [] +deps = -rtest-requirements.txt + +[testenv:py27] +deps = + mock>=1.0.1,<2.0 + {[testenv]deps} + +[testenv:py26] +deps = + unittest2==0.5.1 + {[testenv:py27]deps}