From 0f7edd60e67d32438a8be42002faacde4e4a7649 Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Fri, 9 Aug 2013 16:45:45 -0400 Subject: testsuite: fixed most pylint complaints --- src/lib/Bcfg2/Client/Tools/Action.py | 2 - src/lib/Bcfg2/Client/Tools/DebInit.py | 5 +- src/lib/Bcfg2/Client/Tools/POSIXUsers.py | 1 + src/lib/Bcfg2/Options/Actions.py | 4 +- src/lib/Bcfg2/Options/Common.py | 2 + src/lib/Bcfg2/Options/OptionGroups.py | 7 +-- src/lib/Bcfg2/Options/Options.py | 10 ++-- src/lib/Bcfg2/Options/Parser.py | 22 ++++++--- src/lib/Bcfg2/Options/Types.py | 2 + src/lib/Bcfg2/Server/Admin.py | 56 ++++++++++++++++------ src/lib/Bcfg2/Server/Encryption.py | 5 +- src/lib/Bcfg2/Server/Info.py | 26 ++++++---- src/lib/Bcfg2/Server/Lint/Bundler.py | 3 ++ src/lib/Bcfg2/Server/Lint/Cfg.py | 12 +++-- src/lib/Bcfg2/Server/Lint/Genshi.py | 1 + src/lib/Bcfg2/Server/Lint/GroupPatterns.py | 3 ++ src/lib/Bcfg2/Server/Lint/MergeFiles.py | 8 ++-- src/lib/Bcfg2/Server/Lint/Metadata.py | 3 ++ src/lib/Bcfg2/Server/Lint/Pkgmgr.py | 3 ++ src/lib/Bcfg2/Server/Lint/TemplateHelper.py | 3 ++ src/lib/Bcfg2/Server/Lint/__init__.py | 3 +- src/lib/Bcfg2/Server/MultiprocessingCore.py | 3 -- src/lib/Bcfg2/Server/Plugin/__init__.py | 2 + src/lib/Bcfg2/Server/Plugin/helpers.py | 1 - src/lib/Bcfg2/Server/Plugins/Cfg/__init__.py | 11 ++++- src/lib/Bcfg2/Server/Plugins/FileProbes.py | 4 +- src/lib/Bcfg2/Server/Plugins/Metadata.py | 8 ++++ .../Bcfg2/Server/Plugins/Packages/Collection.py | 1 - src/lib/Bcfg2/Server/Plugins/Packages/Source.py | 1 - src/lib/Bcfg2/Server/Plugins/Packages/YumHelper.py | 17 ++++++- src/lib/Bcfg2/Server/Plugins/Packages/__init__.py | 3 +- src/lib/Bcfg2/Server/Plugins/Probes.py | 5 ++ src/lib/Bcfg2/Server/Plugins/SSHbase.py | 4 -- src/lib/Bcfg2/Server/Test.py | 2 + 34 files changed, 175 insertions(+), 68 deletions(-) (limited to 'src') diff --git a/src/lib/Bcfg2/Client/Tools/Action.py b/src/lib/Bcfg2/Client/Tools/Action.py index 921d5723e..db1ff500e 100644 --- a/src/lib/Bcfg2/Client/Tools/Action.py +++ b/src/lib/Bcfg2/Client/Tools/Action.py @@ -1,7 +1,5 @@ """Action driver""" -import os -import sys import Bcfg2.Client.Tools from Bcfg2.Utils import safe_input from Bcfg2.Client import matches_white_list, passes_black_list diff --git a/src/lib/Bcfg2/Client/Tools/DebInit.py b/src/lib/Bcfg2/Client/Tools/DebInit.py index b544e44d4..0433ac80d 100644 --- a/src/lib/Bcfg2/Client/Tools/DebInit.py +++ b/src/lib/Bcfg2/Client/Tools/DebInit.py @@ -3,6 +3,7 @@ import glob import os import re +import Bcfg2.Options import Bcfg2.Client.Tools # Debian squeeze and beyond uses a dependecy based boot sequence @@ -137,10 +138,10 @@ class DebInit(Bcfg2.Client.Tools.SvcTool): bootcmd = '/usr/sbin/update-rc.d -f %s remove' % \ entry.get('name') bootcmdrv = self.cmd.run(bootcmd) - if self.setup['servicemode'] == 'disabled': + if Bcfg2.Options.setup.service_mode == 'disabled': # 'disabled' means we don't attempt to modify running svcs return bootcmdrv and seqcmdrv - buildmode = self.setup['servicemode'] == 'build' + buildmode = Bcfg2.Options.setup.service_mode == 'build' if (entry.get('status') == 'on' and not buildmode) and \ entry.get('current_status') == 'off': svccmdrv = self.start_service(entry) diff --git a/src/lib/Bcfg2/Client/Tools/POSIXUsers.py b/src/lib/Bcfg2/Client/Tools/POSIXUsers.py index 19657f12a..aeafc3817 100644 --- a/src/lib/Bcfg2/Client/Tools/POSIXUsers.py +++ b/src/lib/Bcfg2/Client/Tools/POSIXUsers.py @@ -9,6 +9,7 @@ from Bcfg2.Utils import PackedDigitRange def uid_range_type(val): + """ Option type to unpack a list of numerical ranges """ return PackedDigitRange(*Bcfg2.Options.Types.comma_list(val)) diff --git a/src/lib/Bcfg2/Options/Actions.py b/src/lib/Bcfg2/Options/Actions.py index 7a30d9623..637a09577 100644 --- a/src/lib/Bcfg2/Options/Actions.py +++ b/src/lib/Bcfg2/Options/Actions.py @@ -2,7 +2,7 @@ import sys import argparse -from Parser import get_parser +from Parser import get_parser # pylint: disable=W0403 __all__ = ["ConfigFileAction", "ComponentAction", "PluginsAction"] @@ -88,6 +88,8 @@ class ComponentAction(argparse.Action): argparse.Action.__init__(self, *args, **kwargs) def _import(self, module, name): + """ Import the given name from the given module, handling + errors """ try: return getattr(__import__(module, fromlist=[name]), name) except (AttributeError, ImportError): diff --git a/src/lib/Bcfg2/Options/Common.py b/src/lib/Bcfg2/Options/Common.py index 302be61f4..b44c58990 100644 --- a/src/lib/Bcfg2/Options/Common.py +++ b/src/lib/Bcfg2/Options/Common.py @@ -1,9 +1,11 @@ """ Common options used in multiple different contexts. """ +# pylint: disable=W0403 import Types from Actions import PluginsAction, ComponentAction from Parser import repository as _repository_option from Options import Option, PathOption, BooleanOption +# pylint: enable=W0403 __all__ = ["Common"] diff --git a/src/lib/Bcfg2/Options/OptionGroups.py b/src/lib/Bcfg2/Options/OptionGroups.py index 537deaa61..6cbe1a8e3 100644 --- a/src/lib/Bcfg2/Options/OptionGroups.py +++ b/src/lib/Bcfg2/Options/OptionGroups.py @@ -3,17 +3,12 @@ import re import copy import fnmatch -from Options import Option +from Options import Option # pylint: disable=W0403 from itertools import chain __all__ = ["OptionGroup", "ExclusiveOptionGroup", "Subparser", "WildcardSectionGroup"] -#: A dict that records a mapping of argparse action name (e.g., -#: "store_true") to the argparse Action class for it. See -#: :func:`_get_action_class` -_action_map = dict() - class OptionContainer(list): """ Parent class of all option groups """ diff --git a/src/lib/Bcfg2/Options/Options.py b/src/lib/Bcfg2/Options/Options.py index ca0261907..d60c536cf 100644 --- a/src/lib/Bcfg2/Options/Options.py +++ b/src/lib/Bcfg2/Options/Options.py @@ -4,7 +4,7 @@ need to be associated with an option parser; it exists on its own.""" import os import copy -import Types +import Types # pylint: disable=W0403 import fnmatch import argparse from Bcfg2.Compat import ConfigParser @@ -15,7 +15,7 @@ __all__ = ["Option", "BooleanOption", "PathOption", "PositionalArgument"] #: A dict that records a mapping of argparse action name (e.g., #: "store_true") to the argparse Action class for it. See #: :func:`_get_action_class` -_action_map = dict() +_action_map = dict() # pylint: disable=C0103 def _get_action_class(action_name): @@ -82,7 +82,7 @@ class Option(object): #: The tuple giving the section and option name for this #: option in the config file - self.cf = None + self.cf = None # pylint: disable=C0103 #: The environment variable that this option can take its #: value from @@ -214,9 +214,11 @@ class Option(object): self.default = val def _get_default(self): + """ Getter for the ``default`` property """ return self._default def _set_default(self, value): + """ Setter for the ``default`` property """ self._default = value for action in self.actions.values(): action.default = value @@ -225,9 +227,11 @@ class Option(object): default = property(_get_default, _set_default) def _get_dest(self): + """ Getter for the ``dest`` property """ return self._dest def _set_dest(self, value): + """ Setter for the ``dest`` property """ self._dest = value for action in self.actions.values(): action.dest = value diff --git a/src/lib/Bcfg2/Options/Parser.py b/src/lib/Bcfg2/Options/Parser.py index 343399db9..dd7874d35 100644 --- a/src/lib/Bcfg2/Options/Parser.py +++ b/src/lib/Bcfg2/Options/Parser.py @@ -5,7 +5,7 @@ import sys import argparse from Bcfg2.version import __version__ from Bcfg2.Compat import ConfigParser -from Options import Option, PathOption, BooleanOption +from Options import Option, PathOption, BooleanOption # pylint: disable=W0403 __all__ = ["setup", "OptionParserException", "Parser", "get_parser"] @@ -13,14 +13,14 @@ __all__ = ["setup", "OptionParserException", "Parser", "get_parser"] #: The repository option. This is specified here (and imported into #: :module:`Bcfg2.Options.Common`) rather than vice-versa due to #: circular imports. -repository = PathOption( +repository = PathOption( # pylint: disable=C0103 '-Q', '--repository', cf=('server', 'repository'), default='var/lib/bcfg2', help="Server repository path") #: A module-level :class:`argparse.Namespace` object that stores all #: configuration for Bcfg2. -setup = argparse.Namespace(version=__version__, +setup = argparse.Namespace(version=__version__, # pylint: disable=C0103 name="Bcfg2", uri='http://trac.mcs.anl.gov/projects/bcfg2') @@ -115,6 +115,9 @@ class Parser(argparse.ArgumentParser): self.add_options(getattr(component, "options")) def _set_defaults(self): + """ Set defaults from the config file for all options that can + come from the config file, but haven't yet had their default + set """ for opt in self.option_list: if opt not in self._defaults_set: opt.default_from_config(self._cfp) @@ -137,10 +140,16 @@ class Parser(argparse.ArgumentParser): setattr(self.namespace, opt.dest, value) def _finalize(self): + """ Finalize the value of any options that require that + additional post-processing step. (Mostly + :class:`Bcfg2.Options.Actions.ComponentAction` subclasses.) + """ for opt in self.option_list[:]: opt.finalize(self.namespace) def _reset_namespace(self): + """ Delete all options from the namespace except for a few + predefined values and config file options. """ self.parsed = False for attr in dir(self.namespace): if (not attr.startswith("_") and @@ -200,11 +209,10 @@ class Parser(argparse.ArgumentParser): # components, until all components have been loaded. On each # iteration, set defaults from config file/environment # variables - remaining = self.argv while not self.parsed: self.parsed = True self._set_defaults() - self.parse_known_args(namespace=self.namespace)[1] + self.parse_known_args(namespace=self.namespace) self._parse_config_options() self._finalize() self._parse_config_options() @@ -227,7 +235,7 @@ class Parser(argparse.ArgumentParser): #: A module-level :class:`Bcfg2.Options.Parser` object that is used #: for all parsing -_parser = Parser() +_parser = Parser() # pylint: disable=C0103 #: Track whether or not the module-level parser has been initialized #: yet. We track this separately because some things (e.g., modules @@ -235,7 +243,7 @@ _parser = Parser() #: been initialized, so we can't just set #: :attr:`Bcfg2.Options._parser` to None and wait for #: :func:`Bcfg2.Options.get_parser` to be called. -_parser_initialized = False +_parser_initialized = False # pylint: disable=C0103 def get_parser(description=None, components=None, namespace=None): diff --git a/src/lib/Bcfg2/Options/Types.py b/src/lib/Bcfg2/Options/Types.py index 5769d674a..2f0fd7d52 100644 --- a/src/lib/Bcfg2/Options/Types.py +++ b/src/lib/Bcfg2/Options/Types.py @@ -83,6 +83,7 @@ def timeout(value): return rv +# pylint: disable=C0103 _bytes_multipliers = dict(k=1, m=2, g=3, @@ -90,6 +91,7 @@ _bytes_multipliers = dict(k=1, _suffixes = "".join(_bytes_multipliers.keys()).lower() _suffixes += _suffixes.upper() _bytes_re = re.compile(r'(?P\d+)(?P[%s])?' % _suffixes) +# pylint: enable=C0103 def size(value): diff --git a/src/lib/Bcfg2/Server/Admin.py b/src/lib/Bcfg2/Server/Admin.py index 7c2241f58..62b5cd0ac 100644 --- a/src/lib/Bcfg2/Server/Admin.py +++ b/src/lib/Bcfg2/Server/Admin.py @@ -39,7 +39,8 @@ except ImportError: HAS_REPORTS = False -class ccolors: +class ccolors: # pylint: disable=C0103 + """ ANSI color escapes to make colorizing text easier """ # pylint: disable=W1401 ADDED = '\033[92m' CHANGED = '\033[93m' @@ -47,8 +48,9 @@ class ccolors: ENDC = '\033[0m' # pylint: enable=W1401 - @staticmethod + @classmethod def disable(cls): + """ Disable all coloration """ cls.ADDED = '' cls.CHANGED = '' cls.REMOVED = '' @@ -94,6 +96,7 @@ def print_table(rows, justify='left', hdr=True, vdelim=" ", padding=1): class AdminCmd(Bcfg2.Options.Subcommand): + """ Base class for all bcfg2-admin modes """ def setup(self): """ Perform post-init (post-options parsing), pre-run setup tasks """ @@ -106,12 +109,16 @@ class AdminCmd(Bcfg2.Options.Subcommand): class _ServerAdminCmd(AdminCmd): - """Base class for admin modes that run a Bcfg2 server.""" + """ Base class for admin modes that run a Bcfg2 server. """ __plugin_whitelist__ = None __plugin_blacklist__ = None options = AdminCmd.options + Bcfg2.Server.Core.Core.options + def __init__(self): + AdminCmd.__init__(self) + self.metadata = None + def setup(self): if self.__plugin_whitelist__ is not None: Bcfg2.Options.setup.plugins = [ @@ -224,23 +231,28 @@ class Compare(AdminCmd): changes = dict() def removed(self, msg, host): + """ Record a removed element """ self.record("%sRemoved: %s%s" % (ccolors.REMOVED, msg, ccolors.ENDC), host) def added(self, msg, host): + """ Record an removed element """ self.record("%sAdded: %s%s" % (ccolors.ADDED, msg, ccolors.ENDC), host) def changed(self, msg, host): + """ Record a changed element """ self.record("%sChanged: %s%s" % (ccolors.CHANGED, msg, ccolors.ENDC), host) def record(self, msg, host): + """ Record a new removed/added/changed message for the given + host """ if msg not in self.changes: self.changes[msg] = [host] else: self.changes[msg].append(host) - def udiff(self, l1, l2, **kwargs): + def udiff(self, lines1, lines2, **kwargs): """ get a unified diff with control lines stripped """ lines = None if "lines" in kwargs: @@ -251,7 +263,7 @@ class Compare(AdminCmd): return [] kwargs['n'] = 0 diff = [] - for line in difflib.unified_diff(l1, l2, **kwargs): + for line in difflib.unified_diff(lines1, lines2, **kwargs): if (line.startswith("--- ") or line.startswith("+++ ") or line.startswith("@@ ")): continue @@ -259,24 +271,23 @@ class Compare(AdminCmd): diff.append(" ...") break if line.startswith("+"): - for l in line.splitlines(): - diff.append(" %s%s%s" % (ccolors.ADDED, l, ccolors.ENDC)) + diff.extend(" %s%s%s" % (ccolors.ADDED, l, ccolors.ENDC) + for l in line.splitlines()) elif line.startswith("-"): - for l in line.splitlines(): - diff.append(" %s%s%s" % (ccolors.REMOVED, l, - ccolors.ENDC)) + diff.extend(" %s%s%s" % (ccolors.REMOVED, l, ccolors.ENDC) + for l in line.splitlines()) return diff def _bundletype(self, el): + """ Get a human-friendly representation of the type of the + given bundle -- independent or not """ if el.get("tag") == "Independent": return "Independent bundle" else: return "Bundle" - def run(self, setup): - if not sys.stdout.isatty() and not setup.color: - ccolors.disable(ccolors) - + def _get_filelists(self, setup): + """ Get a list of 2-tuples of files to compare """ files = [] if os.path.isdir(setup.path1) and os.path.isdir(setup.path1): for fpath in glob.glob(os.path.join(setup.path1, '*')): @@ -302,8 +313,13 @@ class Compare(AdminCmd): files.append((setup.path1, setup.path2)) else: self.errExit("Cannot diff a file and a directory") + return files + + def run(self, setup): # pylint: disable=R0912,R0914,R0915 + if not sys.stdout.isatty() and not setup.color: + ccolors.disable(ccolors) - for file1, file2 in files: + for file1, file2 in self._get_filelists(): host = None if os.path.basename(file1) == os.path.basename(file2): fname = os.path.basename(file1) @@ -400,6 +416,9 @@ class Help(AdminCmd, Bcfg2.Options.HelpCommand): def command_registry(self): return CLI.commands + def run(self, setup): + Bcfg2.Options.HelpCommand.run(self, setup) + class Init(AdminCmd): """Interactively initialize a new repository.""" @@ -480,6 +499,8 @@ bcfg2 = %s self.data['certpath'] = os.path.join(basepath, 'bcfg2.crt') def input_with_default(self, msg, default_name): + """ Prompt for input with the given message, taking the + default from ``self.data`` """ val = safe_input("%s [%s]: " % (msg, self.data[default_name])) if val: self.data[default_name] = val @@ -803,6 +824,8 @@ class Pull(_ServerAdminCmd): class _ReportsCmd(AdminCmd): + """ Base command for all admin modes dealing with the reporting + subsystem """ def __init__(self): AdminCmd.__init__(self) self.reports_entries = () @@ -832,6 +855,8 @@ class _ReportsCmd(AdminCmd): if HAS_DJANGO: class _DjangoProxyCmd(AdminCmd): + """ Base for admin modes that proxy a command through the + Django management system """ command = None args = [] @@ -1151,5 +1176,6 @@ class CLI(Bcfg2.Options.CommandRegistry): parser.parse() def run(self): + """ Run bcfg2-admin """ self.commands[Bcfg2.Options.setup.subcommand].setup() return self.runcommand() diff --git a/src/lib/Bcfg2/Server/Encryption.py b/src/lib/Bcfg2/Server/Encryption.py index 7e1294587..e64a6627f 100755 --- a/src/lib/Bcfg2/Server/Encryption.py +++ b/src/lib/Bcfg2/Server/Encryption.py @@ -32,6 +32,8 @@ IV = r'\0' * 16 class _OptionContainer(object): + """ Container for options loaded at import-time to configure + encryption """ options = [ Bcfg2.Options.BooleanOption( cf=("encryption", "lax_decryption"), @@ -371,7 +373,7 @@ class PropertiesCryptoMixin(object): if pname: self.logger.warning("Passphrase %s not found in %s, " "using passphrase given on command line" % - (pname, Bcfg2.Option.setup.configfile)) + (pname, Bcfg2.Options.setup.configfile)) passphrase = self.passphrase pname = self.pname else: @@ -502,6 +504,7 @@ class CLI(object): return False def run(self): # pylint: disable=R0912,R0915 + """ Run bcfg2-crypt """ for fname in Bcfg2.Options.setup.files: if not os.path.exists(fname): self.logger.error("%s does not exist, skipping" % fname) diff --git a/src/lib/Bcfg2/Server/Info.py b/src/lib/Bcfg2/Server/Info.py index 24d7cc637..2b2149606 100644 --- a/src/lib/Bcfg2/Server/Info.py +++ b/src/lib/Bcfg2/Server/Info.py @@ -89,6 +89,8 @@ class InfoCmd(Bcfg2.Options.Subcommand): """ Base class for bcfg2-info subcommands """ def _expand_globs(self, globs, candidates): + """ Given a list of globs, select the items from candidates + that match the globs """ # special cases to speed things up: if globs is None or '*' in globs: return candidates @@ -264,6 +266,7 @@ class BuildAllMixin(object): return cls def run(self, setup): + """ Run the command """ try: os.makedirs(setup.directory) except OSError: @@ -278,6 +281,8 @@ class BuildAllMixin(object): self._parent.run(self, csetup) # pylint: disable=E1101 def _get_setup(self, client, setup): + """ This can be overridden by children to populate individual + setup options on a per-client basis """ raise NotImplementedError @@ -335,7 +340,7 @@ class Buildbundle(InfoCmd): pretty_print=True).decode('UTF-8')) except: # pylint: disable=W0702 print("Failed to render bundle %s for host %s: %s" % - (setup.bundle, client, sys.exc_info()[1])) + (setup.bundle, setup.hostname, sys.exc_info()[1])) raise @@ -379,10 +384,10 @@ class ExpireCache(InfoCmd): def run(self, setup): if setup.clients: for client in self.get_client_list(setup.clients): - self.expire_caches_by_type(Bcfg2.Server.Plugin.Metadata, - key=client) + self.core.expire_caches_by_type(Bcfg2.Server.Plugin.Metadata, + key=client) else: - self.expire_caches_by_type(Bcfg2.Server.Plugin.Metadata) + self.core.expire_caches_by_type(Bcfg2.Server.Plugin.Metadata) class Bundles(InfoCmd): @@ -506,6 +511,7 @@ class Groups(InfoCmd): options = [Bcfg2.Options.PositionalArgument("group", nargs='*')] def _profile_flag(self, group): + """ Whether or not the group is a profile group """ if self.core.metadata.groups[group].is_profile: return 'yes' else: @@ -681,7 +687,6 @@ class Shell(InfoCmd): 'Type "help" for more information') except KeyboardInterrupt: print("Ctrl-C pressed, exiting...") - loop = False class ProfileTemplates(InfoCmd): @@ -699,6 +704,7 @@ class ProfileTemplates(InfoCmd): help="Profile the named templates instead of all templates")] def profile_entry(self, entry, metadata, runs=5): + """ Profile a single entry """ times = [] for i in range(runs): # pylint: disable=W0612 start = time.time() @@ -715,6 +721,7 @@ class ProfileTemplates(InfoCmd): return times def profile_struct(self, struct, metadata, templates=None, runs=5): + """ Profile all entries in a given structure """ times = dict() entries = struct.xpath("//Path") entry_count = 0 @@ -730,6 +737,7 @@ class ProfileTemplates(InfoCmd): return times def profile_client(self, metadata, templates=None, runs=5): + """ Profile all structures for a given client """ structs = self.core.GetStructures(metadata) struct_count = 0 times = dict() @@ -744,6 +752,7 @@ class ProfileTemplates(InfoCmd): return times def stdev(self, nums): + """ Calculate the standard deviation of a list of numbers """ mean = float(sum(nums)) / len(nums) return math.sqrt(sum((n - mean) ** 2 for n in nums) / float(len(nums))) @@ -804,6 +813,8 @@ class InfoCore(cmd.Cmd, self.prompt = 'bcfg2-info> ' def get_locals(self): + """ Expose the local variables of the core to subcommands that + need to reference them (i.e., the interactive interpreter) """ return locals() def do_quit(self, _): @@ -827,9 +838,6 @@ class InfoCore(cmd.Cmd, self.load_plugins() self.block_for_fam_events(handle_events=True) - def _daemonize(self): - pass - def _run(self): pass @@ -842,6 +850,7 @@ class InfoCore(cmd.Cmd, class CLI(object): + """ The bcfg2-info CLI """ options = [Bcfg2.Options.BooleanOption("-p", "--profile", help="Profile")] def __init__(self): @@ -865,6 +874,7 @@ class CLI(object): command.core = self.core def run(self): + """ Run bcfg2-info """ if Bcfg2.Options.setup.subcommand != 'help': self.core.run() return self.core.runcommand() diff --git a/src/lib/Bcfg2/Server/Lint/Bundler.py b/src/lib/Bcfg2/Server/Lint/Bundler.py index b41313349..0caf4d7ed 100644 --- a/src/lib/Bcfg2/Server/Lint/Bundler.py +++ b/src/lib/Bcfg2/Server/Lint/Bundler.py @@ -1,3 +1,6 @@ +""" ``bcfg2-lint`` plugin for :ref:`Bundler +` """ + from Bcfg2.Server.Lint import ServerPlugin diff --git a/src/lib/Bcfg2/Server/Lint/Cfg.py b/src/lib/Bcfg2/Server/Lint/Cfg.py index 4cdf5c48a..2cdb1f7b8 100644 --- a/src/lib/Bcfg2/Server/Lint/Cfg.py +++ b/src/lib/Bcfg2/Server/Lint/Cfg.py @@ -1,4 +1,10 @@ +""" ``bcfg2-lint`` plugin for :ref:`Cfg +` """ + + import os +import Bcfg2.Options +from fnmatch import fnmatch from Bcfg2.Server.Lint import ServerPlugin @@ -55,7 +61,7 @@ class Cfg(ServerPlugin): # first, collect ignore patterns from handlers ignore = set() - for hdlr in handlers(): + for hdlr in cfg.handlers(): ignore.update(hdlr.__ignore__) # next, get a list of all non-ignored files on the filesystem @@ -67,9 +73,9 @@ class Cfg(ServerPlugin): # global FAM ignore list if (not any(fname.endswith("." + i) for i in ignore) and not any(fnmatch(fpath, p) - for p in self.config['ignore']) and + for p in Bcfg2.Options.setup.ignore_files) and not any(fnmatch(c, p) - for p in self.config['ignore'] + for p in sBcfg2.Options.setup.ignore_files for c in self._list_path_components(fpath))): all_files.add(fpath) diff --git a/src/lib/Bcfg2/Server/Lint/Genshi.py b/src/lib/Bcfg2/Server/Lint/Genshi.py index 76e1986f9..e3a0004a6 100755 --- a/src/lib/Bcfg2/Server/Lint/Genshi.py +++ b/src/lib/Bcfg2/Server/Lint/Genshi.py @@ -22,6 +22,7 @@ class Genshi(Bcfg2.Server.Lint.ServerPlugin): "unknown-genshi-error": "error"} def check_template(self, loader, fname, cls=None): + """ Generic check for all genshi templates (XML and text) """ try: loader.load(fname, cls=cls) except TemplateSyntaxError: diff --git a/src/lib/Bcfg2/Server/Lint/GroupPatterns.py b/src/lib/Bcfg2/Server/Lint/GroupPatterns.py index 8a0ab4f18..d8142cab9 100644 --- a/src/lib/Bcfg2/Server/Lint/GroupPatterns.py +++ b/src/lib/Bcfg2/Server/Lint/GroupPatterns.py @@ -1,3 +1,6 @@ +""" ``bcfg2-lint`` plugin for :ref:`GroupPatterns +` """ + import sys from Bcfg2.Server.Lint import ServerPlugin from Bcfg2.Server.Plugins.GroupPatterns import PatternMap diff --git a/src/lib/Bcfg2/Server/Lint/MergeFiles.py b/src/lib/Bcfg2/Server/Lint/MergeFiles.py index dff95fbf3..972475d91 100644 --- a/src/lib/Bcfg2/Server/Lint/MergeFiles.py +++ b/src/lib/Bcfg2/Server/Lint/MergeFiles.py @@ -11,10 +11,10 @@ from Bcfg2.Server.Plugins.Cfg import CfgGenerator def threshold(val): """ Option type processor to accept either a percentage (e.g., "threshold=75") or a ratio (e.g., "threshold=.75") """ - threshold = float(val) - if threshold > 1: - threshold /= 100 - return threshold + rv = float(val) + if rv > 1: + rv /= 100 + return rv class MergeFiles(Bcfg2.Server.Lint.ServerPlugin): diff --git a/src/lib/Bcfg2/Server/Lint/Metadata.py b/src/lib/Bcfg2/Server/Lint/Metadata.py index a349805fd..3c8f2831d 100644 --- a/src/lib/Bcfg2/Server/Lint/Metadata.py +++ b/src/lib/Bcfg2/Server/Lint/Metadata.py @@ -1,3 +1,6 @@ +""" ``bcfg2-lint`` plugin for :ref:`Metadata +` """ + from Bcfg2.Server.Lint import ServerPlugin diff --git a/src/lib/Bcfg2/Server/Lint/Pkgmgr.py b/src/lib/Bcfg2/Server/Lint/Pkgmgr.py index 54f6f07d1..6b718d8b5 100644 --- a/src/lib/Bcfg2/Server/Lint/Pkgmgr.py +++ b/src/lib/Bcfg2/Server/Lint/Pkgmgr.py @@ -1,3 +1,6 @@ +""" ``bcfg2-lint`` plugin for :ref:`Pkgmgr +` """ + import os import glob import lxml.etree diff --git a/src/lib/Bcfg2/Server/Lint/TemplateHelper.py b/src/lib/Bcfg2/Server/Lint/TemplateHelper.py index a24d70cab..1b4642a95 100644 --- a/src/lib/Bcfg2/Server/Lint/TemplateHelper.py +++ b/src/lib/Bcfg2/Server/Lint/TemplateHelper.py @@ -1,3 +1,6 @@ +""" ``bcfg2-lint`` plugin for :ref:`TemplateHelper +` """ + import sys import imp from Bcfg2.Server.Lint import ServerPlugin diff --git a/src/lib/Bcfg2/Server/Lint/__init__.py b/src/lib/Bcfg2/Server/Lint/__init__.py index 4f64fd006..c8cdb5be1 100644 --- a/src/lib/Bcfg2/Server/Lint/__init__.py +++ b/src/lib/Bcfg2/Server/Lint/__init__.py @@ -346,7 +346,6 @@ class CLI(object): except ImportError: # no lint plugin for this server plugin self.logger.debug("No lint plugin for %s" % plugin.__name__) - pass except AttributeError: self.logger.error("Failed to load plugin %s: %s" % (plugin.__name__, sys.exc_info()[1])) @@ -369,6 +368,7 @@ class CLI(object): self.serverlessplugins.append(plugin) def run(self): + """ Run bcfg2-lint """ if Bcfg2.Options.setup.list_errors: for plugin in self.serverplugins + self.serverlessplugins: self.errorhandler.RegisterErrors(getattr(plugin, 'Errors')()) @@ -441,6 +441,7 @@ class CLI(object): core.shutdown() def _run_plugin(self, plugin, args=None): + """ Run a single bcfg2-lint plugin """ if args is None: args = [] start = time.time() diff --git a/src/lib/Bcfg2/Server/MultiprocessingCore.py b/src/lib/Bcfg2/Server/MultiprocessingCore.py index d83080058..cce6bc0c3 100644 --- a/src/lib/Bcfg2/Server/MultiprocessingCore.py +++ b/src/lib/Bcfg2/Server/MultiprocessingCore.py @@ -225,9 +225,6 @@ class ChildCore(Core): def _run(self): return True - def _daemonize(self): - return True - def _dispatch(self, address, data): """ Method dispatcher used for commands received from the RPC queue. """ diff --git a/src/lib/Bcfg2/Server/Plugin/__init__.py b/src/lib/Bcfg2/Server/Plugin/__init__.py index a85867134..6599aa7a5 100644 --- a/src/lib/Bcfg2/Server/Plugin/__init__.py +++ b/src/lib/Bcfg2/Server/Plugin/__init__.py @@ -25,6 +25,8 @@ from Bcfg2.Server.Plugin.exceptions import * class _OptionContainer(object): + """ Container for plugin options that are loaded at import time + """ options = [ Bcfg2.Options.Common.default_paranoid, Bcfg2.Options.Option( diff --git a/src/lib/Bcfg2/Server/Plugin/helpers.py b/src/lib/Bcfg2/Server/Plugin/helpers.py index 186837923..225b3491c 100644 --- a/src/lib/Bcfg2/Server/Plugin/helpers.py +++ b/src/lib/Bcfg2/Server/Plugin/helpers.py @@ -13,7 +13,6 @@ import lxml.etree import Bcfg2.Server import Bcfg2.Options import Bcfg2.Server.FileMonitor -from Bcfg2.Utils import ClassName from Bcfg2.Logger import Debuggable from Bcfg2.Compat import CmpMixin, wraps from Bcfg2.Server.Plugin.base import Plugin diff --git a/src/lib/Bcfg2/Server/Plugins/Cfg/__init__.py b/src/lib/Bcfg2/Server/Plugins/Cfg/__init__.py index a7fa92201..99afac7eb 100644 --- a/src/lib/Bcfg2/Server/Plugins/Cfg/__init__.py +++ b/src/lib/Bcfg2/Server/Plugins/Cfg/__init__.py @@ -763,6 +763,7 @@ class CfgEntrySet(Bcfg2.Server.Plugin.EntrySet): class CfgHandlerAction(Bcfg2.Options.ComponentAction): + """ Option parser action to load Cfg handlers """ bases = ['Bcfg2.Server.Plugins.Cfg'] @@ -796,10 +797,18 @@ class Cfg(Bcfg2.Server.Plugin.GroupSpool, global CFG # pylint: disable=W0603 Bcfg2.Server.Plugin.GroupSpool.__init__(self, core, datastore) Bcfg2.Server.Plugin.PullTarget.__init__(self) - + self._handlers = None CFG = self __init__.__doc__ = Bcfg2.Server.Plugin.GroupSpool.__init__.__doc__ + @property + def handlers(self): + """ A list of Cfg handler classes. """ + if self._handlers is None: + self._handlers = Bcfg2.Options.setup.cfg_handlers + self._handlers.sort(key=operator.attrgetter("__priority__")) + return self._handlers + def has_generator(self, entry, metadata): """ Return True if the given entry can be generated for the given metadata; False otherwise diff --git a/src/lib/Bcfg2/Server/Plugins/FileProbes.py b/src/lib/Bcfg2/Server/Plugins/FileProbes.py index 45511eb52..51eb6e09a 100644 --- a/src/lib/Bcfg2/Server/Plugins/FileProbes.py +++ b/src/lib/Bcfg2/Server/Plugins/FileProbes.py @@ -147,7 +147,7 @@ class FileProbes(Bcfg2.Server.Plugin.Plugin, self.write_file(fileloc, contents) self.verify_file(filename, contents, metadata) infoxml = os.path.join(cfg.data, filename.lstrip("/"), "info.xml") - self.write_infoxml(infoxml, entry, data) + self.write_infoxml(infoxml, data) elif entrydata == contents: self.debug_log("Existing %s contents match probed contents" % filename) @@ -213,7 +213,7 @@ class FileProbes(Bcfg2.Server.Plugin.Plugin, updated = True tries += 1 - def write_infoxml(self, infoxml, entry, data): + def write_infoxml(self, infoxml, data): """ write an info.xml for the file """ if os.path.exists(infoxml): return diff --git a/src/lib/Bcfg2/Server/Plugins/Metadata.py b/src/lib/Bcfg2/Server/Plugins/Metadata.py index f27910eb8..e2da2a6d4 100644 --- a/src/lib/Bcfg2/Server/Plugins/Metadata.py +++ b/src/lib/Bcfg2/Server/Plugins/Metadata.py @@ -20,12 +20,18 @@ from Bcfg2.Compat import MutableMapping, all, wraps # pylint: disable=W0622 from Bcfg2.version import Bcfg2VersionInfo +# pylint: disable=C0103 +ClientVersions = None MetadataClientModel = None +# pylint: enable=C0103 HAS_DJANGO = False def load_django_models(): + """ Load models for Django after option parsing has completed """ + # pylint: disable=W0602 global MetadataClientModel, ClientVersions, HAS_DJANGO + # pylint: enable=W0602 try: from django.db import models @@ -674,7 +680,9 @@ class Metadata(Bcfg2.Server.Plugin.Metadata, try: client = MetadataClientModel.objects.get(hostname=client_name) except MetadataClientModel.DoesNotExist: + # pylint: disable=E1102 client = MetadataClientModel(hostname=client_name) + # pylint: enable=E1102 client.save() self.clients = self.list_clients() return client diff --git a/src/lib/Bcfg2/Server/Plugins/Packages/Collection.py b/src/lib/Bcfg2/Server/Plugins/Packages/Collection.py index 0df8624f6..8b20df58a 100644 --- a/src/lib/Bcfg2/Server/Plugins/Packages/Collection.py +++ b/src/lib/Bcfg2/Server/Plugins/Packages/Collection.py @@ -595,7 +595,6 @@ def get_collection_class(source_type): :type source_type: string :returns: type - the Collection subclass that should be used to instantiate an object to contain sources of the given type. """ - cls = None for mod in Bcfg2.Options.setup.packages_backends: if mod.__name__.endswith(".%s" % source_type.title()): return getattr(mod, "%sCollection" % source_type.title()) diff --git a/src/lib/Bcfg2/Server/Plugins/Packages/Source.py b/src/lib/Bcfg2/Server/Plugins/Packages/Source.py index e1659dbb3..4b6130f72 100644 --- a/src/lib/Bcfg2/Server/Plugins/Packages/Source.py +++ b/src/lib/Bcfg2/Server/Plugins/Packages/Source.py @@ -49,7 +49,6 @@ in your ``Source`` subclass. For an example of this kind of import os import re import sys -import Bcfg2.Server.Plugin from Bcfg2.Logger import Debuggable from Bcfg2.Compat import HTTPError, HTTPBasicAuthHandler, \ HTTPPasswordMgrWithDefaultRealm, install_opener, build_opener, urlopen, \ diff --git a/src/lib/Bcfg2/Server/Plugins/Packages/YumHelper.py b/src/lib/Bcfg2/Server/Plugins/Packages/YumHelper.py index 32db0b32d..dcb8718a0 100644 --- a/src/lib/Bcfg2/Server/Plugins/Packages/YumHelper.py +++ b/src/lib/Bcfg2/Server/Plugins/Packages/YumHelper.py @@ -266,6 +266,8 @@ class CacheManager(YumHelper): class HelperSubcommand(Bcfg2.Options.Subcommand): + """ Base class for all yum helper subcommands """ + # the value to JSON encode and print out if the command fails fallback = None @@ -300,10 +302,14 @@ class HelperSubcommand(Bcfg2.Options.Subcommand): return 0 def _run(self, setup, data): + """ Actually run the command """ raise NotImplementedError class DepSolverSubcommand(HelperSubcommand): + """ Base class for helper commands that use the depsolver (i.e., + only resolve dependencies, don't modify the cache) """ + def __init__(self): HelperSubcommand.__init__(self) self.depsolver = DepSolver(Bcfg2.Options.setup.yum_config, @@ -311,6 +317,8 @@ class DepSolverSubcommand(HelperSubcommand): class CacheManagerSubcommand(HelperSubcommand): + """ Base class for helper commands that use the cachemanager + (i.e., modify the cache) """ fallback = False accept_input = False @@ -321,18 +329,22 @@ class CacheManagerSubcommand(HelperSubcommand): class Clean(CacheManagerSubcommand): + """ Clean the cache """ def _run(self, setup, data): # pylint: disable=W0613 self.cachemgr.clean_cache() return True class MakeCache(CacheManagerSubcommand): + """ Update the on-disk cache """ def _run(self, setup, data): # pylint: disable=W0613 self.cachemgr.populate_cache() return True class Complete(DepSolverSubcommand): + """ Given an initial set of packages, get a complete set of + packages with all dependencies resolved """ fallback = dict(packages=[], unknown=[]) def _run(self, _, data): @@ -344,6 +356,7 @@ class Complete(DepSolverSubcommand): class GetGroups(DepSolverSubcommand): + """ Resolve the given package groups """ def _run(self, _, data): rv = dict() for gdata in data: @@ -356,10 +369,11 @@ class GetGroups(DepSolverSubcommand): return rv -Get_Groups = GetGroups +Get_Groups = GetGroups # pylint: disable=C0103 class CLI(Bcfg2.Options.CommandRegistry): + """ The bcfg2-yum-helper CLI """ options = [ Bcfg2.Options.PathOption( "-c", "--yum-config", help="Yum config file"), @@ -377,6 +391,7 @@ class CLI(Bcfg2.Options.CommandRegistry): self.logger = logging.getLogger(parser.prog) def run(self): + """ Run bcfg2-yum-helper """ if not os.path.exists(Bcfg2.Options.setup.yum_config): self.logger.error("Config file %s not found" % Bcfg2.Options.setup.yum_config) diff --git a/src/lib/Bcfg2/Server/Plugins/Packages/__init__.py b/src/lib/Bcfg2/Server/Plugins/Packages/__init__.py index e6240f39a..efd0bbe4a 100644 --- a/src/lib/Bcfg2/Server/Plugins/Packages/__init__.py +++ b/src/lib/Bcfg2/Server/Plugins/Packages/__init__.py @@ -124,7 +124,8 @@ class Packages(Bcfg2.Server.Plugin.Plugin, Bcfg2.Options.PathOption( cf=("packages", "apt_config"), help="The default path for generated apt configs", - default="/etc/apt/sources.list.d/bcfg2-packages-generated-sources.list")] + default= + "/etc/apt/sources.list.d/bcfg2-packages-generated-sources.list")] #: Packages is an alternative to #: :mod:`Bcfg2.Server.Plugins.Pkgmgr` and conflicts with it. diff --git a/src/lib/Bcfg2/Server/Plugins/Probes.py b/src/lib/Bcfg2/Server/Plugins/Probes.py index 21bb331cd..012c1958a 100644 --- a/src/lib/Bcfg2/Server/Plugins/Probes.py +++ b/src/lib/Bcfg2/Server/Plugins/Probes.py @@ -13,12 +13,17 @@ import Bcfg2.Server.FileMonitor from Bcfg2.Server.Statistics import track_statistics HAS_DJANGO = False +# pylint: disable=C0103 ProbesDataModel = None ProbesGroupsModel = None +# pylint: enable=C0103 def load_django_models(): + """ Load models for Django after option parsing has completed """ + # pylint: disable=W0602 global ProbesDataModel, ProbesGroupsModel, HAS_DJANGO + # pylint: enable=W0602 try: from django.db import models HAS_DJANGO = True diff --git a/src/lib/Bcfg2/Server/Plugins/SSHbase.py b/src/lib/Bcfg2/Server/Plugins/SSHbase.py index c858b881b..8ce4e8a54 100644 --- a/src/lib/Bcfg2/Server/Plugins/SSHbase.py +++ b/src/lib/Bcfg2/Server/Plugins/SSHbase.py @@ -76,10 +76,6 @@ class HostKeyEntrySet(Bcfg2.Server.Plugin.EntrySet): else: self.metadata['mode'] = '0600' - def get_keydata_object(self, filepath, specificity): - return KeyData(filepath, specificity, - self.encoding or Bcfg2.Options.setup.encoding) - class KnownHostsEntrySet(Bcfg2.Server.Plugin.EntrySet): """ EntrySet to handle the ssh_known_hosts file """ diff --git a/src/lib/Bcfg2/Server/Test.py b/src/lib/Bcfg2/Server/Test.py index 912a8f19c..08b4665aa 100644 --- a/src/lib/Bcfg2/Server/Test.py +++ b/src/lib/Bcfg2/Server/Test.py @@ -165,6 +165,7 @@ class ClientTest(TestCase): class CLI(object): + """ The bcfg2-test CLI """ options = [ Bcfg2.Options.PositionalArgument( "clients", help="Specific clients to build", nargs="*"), @@ -230,6 +231,7 @@ class CLI(object): core.shutdown() def run(self): + """ Run bcfg2-test """ core = self.get_core() clients = Bcfg2.Options.setup.clients or core.metadata.clients ignore = self.get_ignore() -- cgit v1.2.3-1-g7c22