From 13e26cefbda3c24ff7402fc2ecbcdf2d96942760 Mon Sep 17 00:00:00 2001 From: Brian Korty Date: Wed, 6 May 2015 14:51:41 -0400 Subject: [PATCH] SYN --- .coveragerc | 2 + .gitignore | 85 +++++++++++++++++ .travis.yml | 24 +++++ HISTORY.rst | 17 ++++ LICENSE | 25 +++++ MANIFEST.in | 13 +++ README.rst | 48 ++++++++++ dev-requirements.txt | 16 ++++ docs/conf.py | 29 ++++++ docs/contributing.rst | 121 ++++++++++++++++++++++++ docs/index.rst | 18 ++++ requirements.txt | 3 + setup.cfg | 17 ++++ setup.py | 52 ++++++++++ sprockets.clients.cassandra/__init__.py | 3 + test-requirements.txt | 12 +++ tests/__init__.py | 1 + tests/acceptance/__init__.py | 1 + tests/integration/__init__.py | 1 + tests/unit/__init__.py | 1 + tests/unit/test_example.py | 58 ++++++++++++ tox.ini | 16 ++++ 22 files changed, 563 insertions(+) create mode 100644 .coveragerc create mode 100644 .gitignore create mode 100644 .travis.yml create mode 100644 HISTORY.rst create mode 100644 LICENSE create mode 100644 MANIFEST.in create mode 100644 README.rst create mode 100644 dev-requirements.txt create mode 100644 docs/conf.py create mode 100644 docs/contributing.rst create mode 100644 docs/index.rst create mode 100644 requirements.txt create mode 100644 setup.cfg create mode 100755 setup.py create mode 100644 sprockets.clients.cassandra/__init__.py create mode 100644 test-requirements.txt create mode 100644 tests/__init__.py create mode 100644 tests/acceptance/__init__.py create mode 100644 tests/integration/__init__.py create mode 100644 tests/unit/__init__.py create mode 100644 tests/unit/test_example.py create mode 100644 tox.ini 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}