From c3a396dabac624f677d9c5391178f1da538ad957 Mon Sep 17 00:00:00 2001 From: Major Hayden Date: Thu, 9 Mar 2017 15:48:18 -0600 Subject: [PATCH] Add PEP257 checks (#15) Check for docstrings. --- monitorstack/__init__.py | 15 +++++++++++++++ monitorstack/cli.py | 5 ----- monitorstack/common/__init__.py | 15 +++++++++++++++ monitorstack/common/formatters.py | 5 ----- monitorstack/plugins/__init__.py | 15 +++++++++++++++ monitorstack/plugins/kvm.py | 8 +++++--- monitorstack/plugins/os_vm_quota_instance.py | 2 ++ monitorstack/plugins/os_vm_quota_ram.py | 2 ++ monitorstack/plugins/os_vm_used_cores.py | 2 ++ monitorstack/plugins/os_vm_used_disk.py | 2 ++ monitorstack/plugins/os_vm_used_instance.py | 2 ++ monitorstack/plugins/os_vm_used_ram.py | 2 ++ monitorstack/plugins/uptime.py | 7 ++++--- monitorstack/utils/__init__.py | 8 ++++++-- monitorstack/utils/os_utils.py | 10 ++++++++++ setup.py | 1 + test-requirements.txt | 2 +- tests/__init__.py | 15 +++++++++++++++ tests/test_plugin_kvm.py | 3 +-- tests/test_utils.py | 14 +++++++++----- tox.ini | 2 ++ 21 files changed, 111 insertions(+), 26 deletions(-) diff --git a/monitorstack/__init__.py b/monitorstack/__init__.py index e69de29..2e8298c 100644 --- a/monitorstack/__init__.py +++ b/monitorstack/__init__.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python +# Copyright 2017, Major Hayden +# +# 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 +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""This an __init__.py.""" diff --git a/monitorstack/cli.py b/monitorstack/cli.py index a45e1fe..ef0e4f8 100755 --- a/monitorstack/cli.py +++ b/monitorstack/cli.py @@ -51,7 +51,6 @@ class MonitorStackCLI(click.MultiCommand): @property def cmd_folder(self): """Get the path to the plugin directory.""" - return os.path.abspath( os.path.join( os.path.dirname(__file__), @@ -61,7 +60,6 @@ class MonitorStackCLI(click.MultiCommand): def list_commands(self, ctx): """Get a list of all available commands.""" - rv = list() for _, pkg_name, _ in pkgutil.iter_modules([self.cmd_folder]): rv.append(pkg_name) @@ -70,7 +68,6 @@ class MonitorStackCLI(click.MultiCommand): def get_command(self, ctx, name): """Load a command and run it.""" - for _, pkg_name, _ in pkgutil.iter_modules([self.cmd_folder]): if pkg_name == name: mod = importlib.import_module( @@ -102,7 +99,6 @@ VALID_OUTPUT_FORMATS = [ @pass_context def cli(ctx, output_format, verbose): """A complex command line interface.""" - ctx.verbose = verbose pass @@ -110,7 +106,6 @@ def cli(ctx, output_format, verbose): @cli.resultcallback(replace=True) def process_result(result, output_format, verbose): """Render the output into the proper format.""" - module_name = 'monitorstack.common.formatters' method_name = 'write_{}'.format(output_format) output_formatter = getattr( diff --git a/monitorstack/common/__init__.py b/monitorstack/common/__init__.py index e69de29..2e8298c 100644 --- a/monitorstack/common/__init__.py +++ b/monitorstack/common/__init__.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python +# Copyright 2017, Major Hayden +# +# 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 +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""This an __init__.py.""" diff --git a/monitorstack/common/formatters.py b/monitorstack/common/formatters.py index 894571e..6f5ea8f 100644 --- a/monitorstack/common/formatters.py +++ b/monitorstack/common/formatters.py @@ -20,7 +20,6 @@ import click def write_json(result): """Output in raw JSON format.""" - output = json.dumps(result, indent=2) click.echo(output) return True @@ -28,7 +27,6 @@ def write_json(result): def write_line(result): """Output in line format.""" - for key, value in result['variables'].items(): click.echo("{} {}".format(key, value)) @@ -37,13 +35,11 @@ def write_line(result): def _current_time(): """Return the current time in nanoseconds.""" - return int(time.time() * 1000000000) def _telegraf_line_format(sets, quote=False): """Return a comma separated string.""" - store = list() for k, v in sets.items(): k = k.replace(' ', '_') @@ -63,7 +59,6 @@ def _telegraf_line_format(sets, quote=False): def write_telegraf(result): """Output in telegraf format.""" - resultant = [result['measurement_name']] if 'meta' in result: resultant.append(_telegraf_line_format(sets=result['meta'])) diff --git a/monitorstack/plugins/__init__.py b/monitorstack/plugins/__init__.py index e69de29..2e8298c 100644 --- a/monitorstack/plugins/__init__.py +++ b/monitorstack/plugins/__init__.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python +# Copyright 2017, Major Hayden +# +# 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 +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""This an __init__.py.""" diff --git a/monitorstack/plugins/kvm.py b/monitorstack/plugins/kvm.py index 93d6171..7ef5b9e 100644 --- a/monitorstack/plugins/kvm.py +++ b/monitorstack/plugins/kvm.py @@ -11,7 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -"""Plugin for KVM metrics.""" +"""Get metrics from a KVM hypervisor.""" import platform import socket @@ -21,12 +21,14 @@ import click from monitorstack.cli import pass_context -DOC = """Get metrics from a KVM hypervisor""" +DOC = """Get metrics from a KVM hypervisor.""" +COMMAND = 'kvm' -@click.command('kvm', short_help=DOC.split('\n')[0]) +@click.command(COMMAND, short_help=DOC.split('\n')[0]) @pass_context def cli(ctx): + """Get metrics from a KVM hypervisor.""" setattr(cli, '__doc__', DOC) # Lower level import because we only want to load this module diff --git a/monitorstack/plugins/os_vm_quota_instance.py b/monitorstack/plugins/os_vm_quota_instance.py index b864d5e..6c3d431 100644 --- a/monitorstack/plugins/os_vm_quota_instance.py +++ b/monitorstack/plugins/os_vm_quota_instance.py @@ -11,6 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +"""Get nova instance quotas.""" import click @@ -29,6 +30,7 @@ COMMAND_NAME = 'os_vm_quota_instance' default='openstack.ini') @pass_context def cli(ctx, config_file): + """Get nova instance quotas.""" setattr(cli, '__doc__', DOC) output = { diff --git a/monitorstack/plugins/os_vm_quota_ram.py b/monitorstack/plugins/os_vm_quota_ram.py index 556ea14..b67b991 100644 --- a/monitorstack/plugins/os_vm_quota_ram.py +++ b/monitorstack/plugins/os_vm_quota_ram.py @@ -11,6 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +"""Get nova ram quotas.""" import click @@ -29,6 +30,7 @@ COMMAND_NAME = 'os_vm_quota_ram' default='openstack.ini') @pass_context def cli(ctx, config_file): + """Get nova ram quotas.""" setattr(cli, '__doc__', DOC) output = { diff --git a/monitorstack/plugins/os_vm_used_cores.py b/monitorstack/plugins/os_vm_used_cores.py index 955558c..6e96ddc 100644 --- a/monitorstack/plugins/os_vm_used_cores.py +++ b/monitorstack/plugins/os_vm_used_cores.py @@ -11,6 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +"""Get the number of cores used by this tenant.""" import collections @@ -31,6 +32,7 @@ COMMAND_NAME = 'os_vm_used_cores' default='openstack.ini') @pass_context def cli(ctx, config_file): + """Get nova used cores.""" setattr(cli, '__doc__', DOC) output = { diff --git a/monitorstack/plugins/os_vm_used_disk.py b/monitorstack/plugins/os_vm_used_disk.py index b91435e..050880e 100644 --- a/monitorstack/plugins/os_vm_used_disk.py +++ b/monitorstack/plugins/os_vm_used_disk.py @@ -11,6 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +"""Get nova used disk.""" import collections @@ -31,6 +32,7 @@ COMMAND_NAME = 'os_vm_used_disk' default='openstack.ini') @pass_context def cli(ctx, config_file): + """Get nova used disk.""" setattr(cli, '__doc__', DOC) output = { diff --git a/monitorstack/plugins/os_vm_used_instance.py b/monitorstack/plugins/os_vm_used_instance.py index 53ef0b9..130a123 100644 --- a/monitorstack/plugins/os_vm_used_instance.py +++ b/monitorstack/plugins/os_vm_used_instance.py @@ -11,6 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +"""Get nova used instances.""" import collections @@ -31,6 +32,7 @@ COMMAND_NAME = 'os_vm_used_instance' default='openstack.ini') @pass_context def cli(ctx, config_file): + """Get nova used instances.""" setattr(cli, '__doc__', DOC) output = { diff --git a/monitorstack/plugins/os_vm_used_ram.py b/monitorstack/plugins/os_vm_used_ram.py index 461d4ed..2d2ce85 100644 --- a/monitorstack/plugins/os_vm_used_ram.py +++ b/monitorstack/plugins/os_vm_used_ram.py @@ -11,6 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +"""Get nova used ram.""" import collections @@ -31,6 +32,7 @@ COMMAND_NAME = 'os_vm_used_ram' default='openstack.ini') @pass_context def cli(ctx, config_file): + """Get nova used ram.""" setattr(cli, '__doc__', DOC) output = { diff --git a/monitorstack/plugins/uptime.py b/monitorstack/plugins/uptime.py index 9d9f0d0..7213c22 100644 --- a/monitorstack/plugins/uptime.py +++ b/monitorstack/plugins/uptime.py @@ -19,12 +19,14 @@ import click from monitorstack.cli import pass_context +DOC = """Get system uptime.""" +COMMAND_NAME = 'uptime' -@click.command('uptime', short_help='Get system uptime') + +@click.command(COMMAND_NAME, short_help=DOC) @pass_context def cli(ctx): """Get system uptime.""" - uptime = get_uptime() output = { 'exit_code': 0, @@ -42,7 +44,6 @@ def cli(ctx): def get_uptime(): """Read the uptime from the proc filesystem.""" - with open('/proc/uptime', 'r') as f: output = f.read() diff --git a/monitorstack/utils/__init__.py b/monitorstack/utils/__init__.py index 523149a..84a2193 100644 --- a/monitorstack/utils/__init__.py +++ b/monitorstack/utils/__init__.py @@ -11,6 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +"""Common code for utils.""" import os import shelve @@ -28,6 +29,7 @@ except ImportError: def is_int(value): + """Check if a variable is an integer.""" for v_type in [int, float]: try: value = v_type(value) @@ -43,6 +45,7 @@ class LocalCache(object): """Context Manager for opening and closing access to the DBM.""" def __init__(self): + """Initialization method for class.""" """Set the Path to the DBM to create/Open.""" self.db_cache = os.path.join( @@ -55,12 +58,10 @@ class LocalCache(object): :return: Open DBM """ - return self.open_shelve def __exit__(self, type, value, traceback): """Close DBM Connection.""" - self.close_shelve() def _open_shelve(self): @@ -68,13 +69,16 @@ class LocalCache(object): @property def open_shelve(self): + """Open shelved data.""" return self._open_shelve() def close_shelve(self): + """Close shelved data.""" self.open_shelve.close() def read_config(config_file): + """Read an OpenStack configuration.""" cfg = os.path.abspath(os.path.expanduser(config_file)) if not os.path.isfile(cfg): raise IOError('Config file "{}" was not found'.format(cfg)) diff --git a/monitorstack/utils/os_utils.py b/monitorstack/utils/os_utils.py index 7ad2464..91d59e6 100644 --- a/monitorstack/utils/os_utils.py +++ b/monitorstack/utils/os_utils.py @@ -11,6 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +"""OpenStack-related utilities.""" try: from openstack import connection as os_conn @@ -24,14 +25,19 @@ from monitorstack import utils class OpenStack(object): + """Class for reusable OpenStack utility methods.""" + def __init__(self, os_auth_args): + """Initialization method for class.""" self.os_auth_args = os_auth_args @property def conn(self): + """Return an OpenStackSDK connection.""" return os_conn.Connection(**self.os_auth_args) def get_consumer_usage(self, servers=None, marker=None, limit=512): + """Retrieve current usage by an OpenStack cloud consumer.""" tenant_kwargs = {'details': True, 'all_tenants': True, 'limit': limit} if not servers: servers = list() @@ -53,6 +59,7 @@ class OpenStack(object): return servers def get_compute_limits(self, project_id, interface='internal'): + """Determine limits of compute resources.""" url = self.conn.compute.session.get_endpoint( interface=interface, service_type='compute' @@ -63,6 +70,7 @@ class OpenStack(object): return quota_data.json() def get_project_name(self, project_id): + """Retrieve the name of a project.""" with utils.LocalCache() as c: try: project_name = c.get(project_id) @@ -75,6 +83,7 @@ class OpenStack(object): return project_name def get_projects(self): + """Retrieve a list of projects.""" _consumers = list() with utils.LocalCache() as c: for project in self.conn.identity.projects(): @@ -83,6 +92,7 @@ class OpenStack(object): return _consumers def get_flavors(self): + """Retrieve a list of flavors.""" flavor_cache = dict() for flavor in self.conn.compute.flavors(): entry = flavor_cache[flavor['id']] = dict() diff --git a/setup.py b/setup.py index 782bb21..7a641e2 100644 --- a/setup.py +++ b/setup.py @@ -12,6 +12,7 @@ # implied. # See the License for the specific language governing permissions and # limitations under the License. +"""The setup script.""" # THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT import setuptools diff --git a/test-requirements.txt b/test-requirements.txt index 4ef3f7e..510109e 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1,3 +1,3 @@ +mock>=2.0.0 pytest tox -mock>=2.0.0 \ No newline at end of file diff --git a/tests/__init__.py b/tests/__init__.py index e69de29..2e8298c 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python +# Copyright 2017, Major Hayden +# +# 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 +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""This an __init__.py.""" diff --git a/tests/test_plugin_kvm.py b/tests/test_plugin_kvm.py index 23d7667..1015d11 100644 --- a/tests/test_plugin_kvm.py +++ b/tests/test_plugin_kvm.py @@ -38,7 +38,7 @@ class LibvirtStub(object): class lookupByID(object): # noqa """Stubbed lookupByID class.""" - def __init__(self, *args, **kwargs): + def __init__(self, *args, **kwargs): # noqa pass def maxVcpus(self): # noqa @@ -50,7 +50,6 @@ class TestKvm(object): def test_run(self): """Ensure the run() method works.""" - sys.modules['libvirt'] = LibvirtStub runner = CliRunner() diff --git a/tests/test_utils.py b/tests/test_utils.py index e572f13..9ba84bf 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -24,6 +24,7 @@ class TestUtils(unittest.TestCase): """Tests for the utilities.""" def setUp(self): + """Initial setup for class.""" os_config_file = os.path.expanduser( os.path.abspath(__file__ + '/../../etc/openstack.ini') ) @@ -33,6 +34,7 @@ class TestUtils(unittest.TestCase): self.config_defaults = conf.defaults() def tearDown(self): + """Destroy the local cache.""" local_cache = os.path.join( tempfile.gettempdir(), 'monitorstack.openstack.dbm' @@ -40,31 +42,33 @@ class TestUtils(unittest.TestCase): if os.path.exists(local_cache): os.remove(local_cache) - def test_is_int_is_int(self): + def test_is_int_is_int(self): # noqa self.assertTrue(isinstance(utils.is_int(value=1), int)) - def test_is_int_is_int_str(self): + def test_is_int_is_int_str(self): # noqa self.assertTrue(isinstance(utils.is_int(value='1'), int)) - def test_is_int_is_not_int(self): + def test_is_int_is_not_int(self): # noqa self.assertTrue(isinstance(utils.is_int(value='a'), str)) - def test_read_config_not_found(self): + def test_read_config_not_found(self): # noqa self.assertRaises( IOError, utils.read_config, 'not-a-file' ) - def test_read_config_found_dict_return(self): + def test_read_config_found_dict_return(self): # noqa self.assertTrue(isinstance(self.config, dict)) def test_read_config_found_defaults_in_sections(self): + """Read config defaults from each section.""" for k, v in self.config.items(): for key in self.config_defaults.keys(): self.assertTrue(key in v.keys()) def test_local_cache(self): + """Test local cache.""" with utils.LocalCache() as c: c['test_key'] = True self.assertTrue('test_key' in c) diff --git a/tox.ini b/tox.ini index 0ec375f..3476afa 100644 --- a/tox.ini +++ b/tox.ini @@ -15,6 +15,7 @@ commands = deps = flake8 flake8-import-order + flake8-docstrings pep8-naming commands = flake8 . @@ -24,6 +25,7 @@ basepython = python3.3 deps = flake8 flake8-import-order + flake8-docstrings pep8-naming commands = flake8 .