diff --git a/.coveragerc b/.coveragerc index 3beb320..0a3f8a1 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,7 +1,7 @@ [run] branch = True source = satori -omit = satori/openstack/* +omit = satori/tests/* [report] ignore-errors = True diff --git a/.gitignore b/.gitignore index 20c3d0a..8c7bc68 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,7 @@ pip-log.txt # Unit test / coverage reports .coverage +.coverage.* cover covhtml .tox @@ -46,11 +47,11 @@ nosetests.xml *.swo *.swp *~ -.coverage .satori-venv .testrepository .tox .venv +venv AUTHORS build ChangeLog diff --git a/.testr.conf b/.testr.conf index ba81d5c..6f0e8ca 100644 --- a/.testr.conf +++ b/.testr.conf @@ -2,7 +2,7 @@ test_command=OS_STDOUT_CAPTURE=${OS_STDOUT_CAPTURE:-1} \ OS_STDERR_CAPTURE=${OS_STDERR_CAPTURE:-1} \ OS_TEST_TIMEOUT=${OS_TEST_TIMEOUT:-60} \ - ${PYTHON:-python} -m subunit.run discover -t ./ ./satori/tests $LISTOPT $IDOPTION + ${PYTHON:-python} -m subunit.run discover -t . ./satori/tests $LISTOPT $IDOPTION test_id_option=--load-list $IDFILE test_list_option=--list diff --git a/MANIFEST.in b/MANIFEST.in index 9103603..c2334cc 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,4 +1,5 @@ graft satori/formats include setup.py include setup.cfg +prune satori/tests global-exclude *.pyc *.sdx *.log *.db *.swp diff --git a/README.rst b/README.rst index 2c0010e..eca6de5 100644 --- a/README.rst +++ b/README.rst @@ -108,7 +108,31 @@ uses the `install virtualenv`_ script to create the virtualenv:: Unit tests can be ran simply by running:: - $ run_tests.sh + $ tox + + # or, just style checks + $ tox -e pep8 + + # or, just python 2.7 checks + $ tox -e py27 + + +Running a test coverage report: + + # cleanup previous runs + $ rm -rf cover && rm -rf covhtml && rm .coverage + + # Run tests and generate the report + $ tox -ecover && coverage html -d covhtml -i + + # open it in a broweser + $ open covhtml/index.html + +Checking test coverage:: + + $ tox -ecover + $ coverage html -d covhtml -i + $ open covhtml/index.html # opens the report in a browser Links diff --git a/pylintrc b/pylintrc new file mode 100644 index 0000000..99ed3a7 --- /dev/null +++ b/pylintrc @@ -0,0 +1,11 @@ +[Messages Control] +# W0511: TODOs in code comments are fine. +# W0142: *args and **kwargs are fine. +disable-msg=W0511,W0142 + +# Don't require docstrings on tests. +no-docstring-rgx=((__.*__)|([tT]est.*)|setUp|tearDown)$ + +[Design] +min-public-methods=0 +max-args=6 diff --git a/requirements.txt b/requirements.txt index 21e1b4a..218cf1c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,6 +5,6 @@ https://github.com/paramiko/paramiko/archive/python3.zip#egg=paramiko-1.13.0 pbr>=0.5.21,<1.0 python-novaclient==2.15.0 # pythonwhois with python 3.3 readiness patch --e git://github.com/joepie91/python-whois.git@655d1ca37497f0f6407c6bdbe0d2bbd0caac8544#egg=pythonwhois +-e git://github.com/ziadsawalha/python-whois.git@17aa17c1c71805df1cb7fa053fe90b6dc9ba6d4b#egg=pythonwhois six==1.5.2 tldextract==1.3.1 diff --git a/satori/__init__.py b/satori/__init__.py index 33d5caf..c5a2d94 100644 --- a/satori/__init__.py +++ b/satori/__init__.py @@ -9,15 +9,14 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. -# """Satori main module.""" -__all__ = ['__version__'] +__all__ = ('__version__') import pbr.version -from satori.shell import main +from satori import shell version_info = pbr.version.VersionInfo('satori') @@ -32,5 +31,5 @@ def discover(address=None): TODO(zns): make it real """ - main(argv=[address]) + shell.main(argv=[address]) return {'address': address, 'other info': '...'} diff --git a/satori/common/logging.py b/satori/common/logging.py index 59c6a07..6bed54a 100644 --- a/satori/common/logging.py +++ b/satori/common/logging.py @@ -31,6 +31,11 @@ class DebugFormatter(logging.Formatter): Outputs any 'data' values passed in the 'extra' parameter if provided. + **Example**: + + .. code-block:: python + + LOG.debug("My message", extra={'data': locals()}) """ def format(self, record): @@ -46,7 +51,8 @@ def init_logging(config, default_config=None): Turn on console logging if no logging files found - :param config: object with configuration namespace (argparse parser) + :param config: object with configuration namespace (ex. argparse parser) + :keyword default_config: path to a python logging configuration file """ if config.logconfig and os.path.isfile(config.logconfig): logging.config.fileConfig(config.logconfig, @@ -74,6 +80,8 @@ def log_level(config): --verbose: turn up logging output (logging.DEBUG) --quiet: turn down logging output (logging.WARNING) default is logging.INFO + + :param config: object with configuration namespace (ex. argparse parser) """ if config.debug is True: return logging.DEBUG @@ -95,6 +103,7 @@ def get_debug_formatter(config): --quiet: turn down logging output (logging.WARNING) default is logging.INFO + :param config: object with configuration namespace (ex. argparse parser) """ if config.debug is True: return DebugFormatter('%(pathname)s:%(lineno)d: %(levelname)-8s ' @@ -109,7 +118,10 @@ def get_debug_formatter(config): def init_console_logging(config): - """Log to console.""" + """Enable logging to the console. + + :param config: object with configuration namespace (ex. argparse parser) + """ # define a Handler which writes messages to the sys.stderr console = find_console_handler(logging.getLogger()) if not console: diff --git a/satori/common/templating.py b/satori/common/templating.py index bfd614c..8c15f93 100644 --- a/satori/common/templating.py +++ b/satori/common/templating.py @@ -18,7 +18,7 @@ import json import logging import jinja2 -from jinja2.sandbox import ImmutableSandboxedEnvironment +from jinja2 import sandbox import six CODE_CACHE = {} @@ -79,8 +79,9 @@ def preserve_linefeeds(value): def get_jinja_environment(template, extra_globals=None): """Return a sandboxed jinja environment.""" template_map = {'template': template} - env = ImmutableSandboxedEnvironment(loader=jinja2.DictLoader(template_map), - bytecode_cache=CompilerCache()) + env = sandbox.ImmutableSandboxedEnvironment( + loader=jinja2.DictLoader(template_map), + bytecode_cache=CompilerCache()) env.filters['prepend'] = do_prepend env.filters['preserve'] = preserve_linefeeds env.globals['json'] = json diff --git a/satori/discovery.py b/satori/discovery.py index abd9693..de50e3a 100644 --- a/satori/discovery.py +++ b/satori/discovery.py @@ -9,7 +9,7 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. -# + """Discovery Module. TODO(zns): testing, refactoring, etc... just using this to demonstrate diff --git a/satori/tests/test_shell.py b/satori/tests/test_shell.py index 90f90aa..ae5894f 100644 --- a/satori/tests/test_shell.py +++ b/satori/tests/test_shell.py @@ -1,5 +1,3 @@ -# pylint: disable=C0103,R0904 - # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at @@ -76,6 +74,11 @@ class TestArgParsing(utils.TestCase): """Test Argument Parsing.""" + def setUp(self): + super(TestArgParsing, self).setUp() + self.mock_os = shell.os + self.mock_os.environ = {} + def make_env(self, exclude=None, fake_env=FAKE_ENV): """Create a patched os.environ. @@ -85,7 +88,7 @@ class TestArgParsing(utils.TestCase): env = dict((k, v) for k, v in fake_env.items() if k != exclude) self.useFixture(fixtures.MonkeyPatch('os.environ', env)) - def shell(self, argstr, exitcodes=(0,)): + def run_shell(self, argstr, exitcodes=(0,)): """Simulate a user shell. Borrowed from python-novaclient/novaclient/tests/test_shell.py. @@ -128,7 +131,7 @@ class TestArgParsing(utils.TestCase): fields_copy.append('domain.com') self.assertRaises( errors.SatoriShellException, - self.shell, + self.run_shell, ' '.join(fields_copy), exitcodes=[0, 2] ) diff --git a/satori/tests/utils.py b/satori/tests/utils.py index caa4452..2d7e544 100644 --- a/satori/tests/utils.py +++ b/satori/tests/utils.py @@ -15,9 +15,9 @@ # import os +import sys import fixtures -import sys import testtools diff --git a/setup.cfg b/setup.cfg index 9eee4d1..4412a31 100644 --- a/setup.cfg +++ b/setup.cfg @@ -17,6 +17,10 @@ classifier = Programming Language :: Python :: 2.7 Programming Language :: Python :: 2.6 Programming Language :: Python :: 3 + Programming Language :: Python :: 3.3 + Programming Language :: Python :: Implementation + Programming Language :: Python :: Implementation :: CPython + Programming Language :: Python :: Implementation :: PyPy [files] packages = diff --git a/test-requirements.txt b/test-requirements.txt index 4451d79..7d66a13 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1,29 +1,17 @@ # pep8 with support for empty files through flake8 -e git://github.com/ziadsawalha/pep8.git@19b64e1d6b52cb814e482188369f4db24e0e82c2#egg=pep8 -# pep257 tool with fix for updated PEP-257 and __all__ as a list -# Two PR pending to upstream --e git://github.com/ziadsawalha/pep257.git@7752b1c9977e5dfca70f7635e5bfc12442c540a6#egg=pep257 - -# PEP-257 plugin for flake8 with pending upstream change for support for latest pep257 tool -# -# Should be -e hg+https://bitbucket.org/ziadsawalha/flake8-docstrings@51864b0e7451bc0a43ab6fb0303e8a69961cb401#egg=flake8-docstring -# ... but mercurial (hg) doesn't seem to be installed on openstack infrastructure. So, using a github temporary fork --e git://github.com/ziadsawalha/flake8_docstrings@v0.1.5#egg=flake8-docstring - # Newer hacking # Includes two fixes for handling blank lines in files and for handling egg-linked libraries -e git://github.com/ziadsawalha/hacking.git@76ff3d0c8b116df147b7e4ca00afda67a9537f2a#egg=hacking - coverage>=3.6 discover +flake8_docstrings>=0.2.0 fixtures>=0.3.14 +freezegun mock>=1.0 +pep257>=0.3.2 sphinx>=1.1.2,<1.2 testrepository>=0.0.17 testtools>=0.9.32 -WebOb>=1.2.3,<1.3 - -Babel>=1.3 -freezegun diff --git a/tox.ini b/tox.ini index e741192..256ddf0 100644 --- a/tox.ini +++ b/tox.ini @@ -18,12 +18,12 @@ commands = flake8 commands = {posargs} [testenv:cover] -commands = python setup.py test --coverage --testr-args='{posargs}' +commands = python setup.py test --coverage --testr-args='^(?!.*test.*coverage).*$' [tox:jenkins] downloadcache = ~/cache/pip [flake8] -ignore = E126,E202,W602,H302,H402 show-source = True exclude = .venv,.git,.tox,dist,doc,*openstack/common*,*lib/python*,*egg,build,tools,*satori/contrib*,*.ropeproject,*satori/tests*,setup.py +max-complexity = 12