diff --git a/bootstrapvz/base/fs/partitionmaps/gpt.py b/bootstrapvz/base/fs/partitionmaps/gpt.py index 1dbd943..89f5f9f 100644 --- a/bootstrapvz/base/fs/partitionmaps/gpt.py +++ b/bootstrapvz/base/fs/partitionmaps/gpt.py @@ -21,7 +21,7 @@ class GPTPartitionMap(AbstractPartitionMap): # Returns the last partition unless there is none def last_partition(): - return self.partitions[-1] if len(self.partitions) > 0 else None + return self.partitions[-1] if self.partitions else None if bootloader == 'grub': # If we are using the grub bootloader we need to create an unformatted partition diff --git a/bootstrapvz/base/fs/partitionmaps/msdos.py b/bootstrapvz/base/fs/partitionmaps/msdos.py index ebc04cc..2e80d92 100644 --- a/bootstrapvz/base/fs/partitionmaps/msdos.py +++ b/bootstrapvz/base/fs/partitionmaps/msdos.py @@ -23,7 +23,7 @@ class MSDOSPartitionMap(AbstractPartitionMap): # Returns the last partition unless there is none def last_partition(): - return self.partitions[-1] if len(self.partitions) > 0 else None + return self.partitions[-1] if self.partitions else None # The boot and swap partitions are optional if 'boot' in data: diff --git a/bootstrapvz/base/pkg/sourceslist.py b/bootstrapvz/base/pkg/sourceslist.py index 2539611..2a68f19 100644 --- a/bootstrapvz/base/pkg/sourceslist.py +++ b/bootstrapvz/base/pkg/sourceslist.py @@ -82,11 +82,11 @@ class Source(object): :rtype: str """ options = '' - if len(self.options) > 0: + if self.options: options = ' [{options}]'.format(options=' '.join(self.options)) components = '' - if len(self.components) > 0: + if self.components: components = ' {components}'.format(components=' '.join(self.components)) return ('{type}{options} {uri} {distribution}{components}' diff --git a/bootstrapvz/common/fsm_proxy.py b/bootstrapvz/common/fsm_proxy.py index 5db4036..6a44d4b 100644 --- a/bootstrapvz/common/fsm_proxy.py +++ b/bootstrapvz/common/fsm_proxy.py @@ -34,7 +34,7 @@ class FSMProxy(object): fn = getattr(fsm, event) def proxy(*args, **kwargs): - if len(args) > 0: + if args: raise FSMProxyError('FSMProxy event listeners only accept named arguments.') fn(**kwargs) return proxy diff --git a/bootstrapvz/common/tasks/bootstrap.py b/bootstrapvz/common/tasks/bootstrap.py index 6a79a04..436450e 100644 --- a/bootstrapvz/common/tasks/bootstrap.py +++ b/bootstrapvz/common/tasks/bootstrap.py @@ -34,9 +34,9 @@ def get_bootstrap_args(info): else: from bootstrapvz.common.exceptions import ManifestError raise ManifestError('force-check-gpg is only support in Stretch and newer releases') - if len(info.include_packages) > 0: + if info.include_packages: options.append('--include=' + ','.join(info.include_packages)) - if len(info.exclude_packages) > 0: + if info.exclude_packages: options.append('--exclude=' + ','.join(info.exclude_packages)) mirror = info.manifest.bootstrapper.get('mirror', info.apt_mirror) arguments = [info.manifest.system['release'], info.root, mirror] diff --git a/bootstrapvz/common/tasks/grub.py b/bootstrapvz/common/tasks/grub.py index edf03f5..a0281ea 100644 --- a/bootstrapvz/common/tasks/grub.py +++ b/bootstrapvz/common/tasks/grub.py @@ -211,7 +211,7 @@ class WriteGrubConfig(Task): elif isinstance(value, bool): grub_config_contents += '{}="{}"\n'.format(key, str(value).lower()) elif isinstance(value, list): - if len(value) > 0: + if value: args_list = ' '.join(map(str, value)) grub_config_contents += '{}="{}"\n'.format(key, args_list) elif value is not None: diff --git a/bootstrapvz/common/tasks/host.py b/bootstrapvz/common/tasks/host.py index 73d7d3d..8285b81 100644 --- a/bootstrapvz/common/tasks/host.py +++ b/bootstrapvz/common/tasks/host.py @@ -12,6 +12,8 @@ class CheckExternalCommands(Task): import re import os import logging + # https://github.com/PyCQA/pylint/issues/73 + # pylint: disable=no-name-in-module,import-error,useless-suppression from distutils.spawn import find_executable missing_packages = [] log = logging.getLogger(__name__) @@ -28,6 +30,6 @@ class CheckExternalCommands(Task): 'it is located in the package `{package}\'.' .format(command=command, package=package)) missing_packages.append(msg) - if len(missing_packages) > 0: + if missing_packages: msg = '\n'.join(missing_packages) raise TaskError(msg) diff --git a/bootstrapvz/common/tasks/logicalvolume.py b/bootstrapvz/common/tasks/logicalvolume.py index 2092ea0..f5d4566 100644 --- a/bootstrapvz/common/tasks/logicalvolume.py +++ b/bootstrapvz/common/tasks/logicalvolume.py @@ -12,7 +12,7 @@ class AddRequiredCommands(Task): @classmethod def run(cls, info): from bootstrapvz.common.fs.logicalvolume import LogicalVolume - if type(info.volume) is LogicalVolume: + if isinstance(info.volume, LogicalVolume): info.host_dependencies['lvcreate'] = 'lvm2' info.host_dependencies['losetup'] = 'mount' diff --git a/bootstrapvz/common/tasks/loopback.py b/bootstrapvz/common/tasks/loopback.py index 0de1764..25d4179 100644 --- a/bootstrapvz/common/tasks/loopback.py +++ b/bootstrapvz/common/tasks/loopback.py @@ -13,7 +13,7 @@ class AddRequiredCommands(Task): def run(cls, info): from ..fs.loopbackvolume import LoopbackVolume from ..fs.qemuvolume import QEMUVolume - if type(info.volume) is LoopbackVolume: + if isinstance(info.volume, LoopbackVolume): info.host_dependencies['losetup'] = 'mount' info.host_dependencies['truncate'] = 'coreutils' if isinstance(info.volume, QEMUVolume): diff --git a/bootstrapvz/common/tools.py b/bootstrapvz/common/tools.py index a80c8c6..e935a15 100644 --- a/bootstrapvz/common/tools.py +++ b/bootstrapvz/common/tools.py @@ -22,7 +22,7 @@ def log_call(command, stdin=None, env=None, shell=False, cwd=None): command_log = realpath(command[0]).replace('/', '.') log = logging.getLogger(__name__ + command_log) - if type(command) is list: + if isinstance(command, list): log.debug('Executing: {command}'.format(command=' '.join(command))) else: log.debug('Executing: {command}'.format(command=command)) diff --git a/bootstrapvz/plugins/cloud_init/__init__.py b/bootstrapvz/plugins/cloud_init/__init__.py index 5567251..7e7f714 100644 --- a/bootstrapvz/plugins/cloud_init/__init__.py +++ b/bootstrapvz/plugins/cloud_init/__init__.py @@ -30,7 +30,7 @@ def resolve_tasks(taskset, manifest): options = manifest.plugins['cloud_init'] if 'username' in options: taskset.add(tasks.SetUsername) - if 'groups' in options and len(options['groups']): + if 'groups' in options and options['groups']: taskset.add(tasks.SetGroups) if 'enable_modules' in options: taskset.add(tasks.EnableModules) diff --git a/bootstrapvz/plugins/docker_daemon/__init__.py b/bootstrapvz/plugins/docker_daemon/__init__.py index 05e5aea..4e47cde 100644 --- a/bootstrapvz/plugins/docker_daemon/__init__.py +++ b/bootstrapvz/plugins/docker_daemon/__init__.py @@ -23,5 +23,5 @@ def resolve_tasks(taskset, manifest): taskset.add(tasks.AddDockerBinary) taskset.add(tasks.AddDockerInit) taskset.add(tasks.EnableMemoryCgroup) - if len(manifest.plugins['docker_daemon'].get('pull_images', [])) > 0: + if manifest.plugins['docker_daemon'].get('pull_images', []): taskset.add(tasks.PullDockerImages) diff --git a/bootstrapvz/providers/oracle/apiclient.py b/bootstrapvz/providers/oracle/apiclient.py index d162bd4..0740936 100644 --- a/bootstrapvz/providers/oracle/apiclient.py +++ b/bootstrapvz/providers/oracle/apiclient.py @@ -5,7 +5,7 @@ import requests from bootstrapvz.common.bytes import Bytes -class OracleStorageAPIClient: +class OracleStorageAPIClient(object): def __init__(self, username, password, identity_domain, container): self.username = username self.password = password diff --git a/pylintrc b/pylintrc new file mode 100644 index 0000000..414f0f5 --- /dev/null +++ b/pylintrc @@ -0,0 +1,263 @@ +[MASTER] + +# Specify a configuration file. +#rcfile= + +# Python code to execute, usually for sys.path manipulation such as +# pygtk.require(). +#init-hook= + +# Profiled execution. +profile=no + +# Add to the black list. It should be a base name, not a +# path. You may set this option multiple times. +ignore= + +# Pickle collected data for later comparisons. +persistent=yes + +# List of plugins (as comma separated values of python modules names) to load, +# usually to register additional checkers. +load-plugins= + + +[MESSAGES CONTROL] + +# Enable the message, report, category or checker with the given id(s). You can +# either give multiple identifier separated by comma (,) or put this option +# multiple time. +enable=W0401,W0611 + +# Disable the message, report, category or checker with the given id(s). You +# can either give multiple identifier separated by comma (,) or put this option +# multiple time. +disable=C0111,I0011,I0020,R0201,R0801,R0914,R1704,R1705,R1710,W,E0632,E1101,E1121,E1601,E1608,C0103,C0301,C0325,C0326,C0330,C0411,R0401 +# C0111 mssing-docstring +# I0011 locally-disabled +# I0020 suppressed-message +# R0801 duplicate-code + +#TODO +# E0632(unbalanced-tuple-unpacking) +# E1101(no-member) +# E1121(too-many-function-args) +# E1601(print-statement) +# E1608(old-octal-literal) +# C0103(invalid-name) +# C0411(wrong-import-order) +# C0301(line-too-long) +# C0325(superfluous-parens) +# C0326(bad-whitespace) +# C0330(bad-continuation) +# R0201(no-self-use) +# R0401(cyclic-import) +# R0914(too-many-locals) +# R1704(redefined-argument-from-local) +# R1705(no-else-return) +# R1710(inconsistent-return-statements) +# W all warnings + + +[REPORTS] + +# Set the output format. Available formats are text, parseable, colorized, msvs +# (visual studio) and html +output-format=colorized + +# Include message's id in output +include-ids=yes + +# Put messages in a separate file for each module / package specified on the +# command line instead of printing them on stdout. Reports (if any) will be +# written in a file name "pylint_global.[txt|html]". +files-output= + +# Tells whether to display a full report or only the messages +reports=no + +# Python expression which should return a note less than 10 (10 is the highest +# note). You have access to the variables errors warning, statement which +# respectively contain the number of errors / warnings messages and the total +# number of statements analyzed. This is used by the global evaluation report +# (R0004). +evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) + +# Add a comment according to your evaluation note. This is used by the global +# evaluation report (R0004). +comment=no + +# Template used to display messages. This is a python new-style format string +# used to format the message information. See doc for all details +msg-template={msg_id}({symbol}) - {path}:{line},{column}:{obj} {msg} + +[VARIABLES] + +# Tells whether we should check for unused import in __init__ files. +init-import=no + +# A regular expression matching names used for dummy variables (i.e. not used). +dummy-variables-rgx=_|dummy + +# List of additional names supposed to be defined in builtins. Remember that +# you should avoid to define new builtins when possible. +additional-builtins= + + +[BASIC] + +# Required attributes for module, separated by a comma +required-attributes= + +# List of builtins function names that should not be used, separated by a comma +bad-functions=map,filter,apply,input + +# Regular expression which should only match correct module names +module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ + +# Regular expression which should only match correct module level names +const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__)|(assets))$ + +# Regular expression which should only match correct class names +class-rgx=[A-Z_][a-zA-Z0-9]+$ + +# Regular expression which should only match correct function names +function-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression which should only match correct method names +method-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression which should only match correct instance attribute names +attr-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression which should only match correct argument names +argument-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression which should only match correct variable names +variable-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression which should only match correct list comprehension / +# generator expression variable names +inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ + +# Good variable names which should always be accepted, separated by a comma +good-names=i,j,k,ex,Run,_ + +# Bad variable names which should always be refused, separated by a comma +bad-names=foo,bar,baz,toto,tutu,tata + +# Regular expression which should only match functions or classes name which do +# not require a docstring +no-docstring-rgx=__.*__ + + +[MISCELLANEOUS] + +# List of note tags to take in consideration, separated by a comma. +notes=FIXME,XXX,TODO + + +[FORMAT] + +# Maximum number of characters on a single line. +max-line-length=110 + +# Maximum number of lines in a module +max-module-lines=1000 + +# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 +# tab). +indent-string=' ' + + +[SIMILARITIES] + +# Minimum lines number of a similarity. +min-similarity-lines=4 + +# Ignore comments when computing similarities. +ignore-comments=yes + +# Ignore docstrings when computing similarities. +ignore-docstrings=yes + + +[TYPECHECK] + +# Tells whether missing members accessed in mixin class should be ignored. A +# mixin class is detected if its name ends with "mixin" (case insensitive). +ignore-mixin-members=yes + +# List of classes names for which member attributes should not be checked +# (useful for classes with attributes dynamically set). +ignored-classes=SQLObject + +# When zope mode is activated, add a predefined set of Zope acquired attributes +# to generated-members. +zope=no + +# List of members which are set dynamically and missed by pylint inference +# system, and so shouldn't trigger E0201 when accessed. +generated-members=REQUEST,acl_users,aq_parent + + +[DESIGN] + +# Maximum number of arguments for function / method +max-args=10 + +# Argument names that match this expression will be ignored. Default to name +# with leading underscore +ignored-argument-names=_.* + +# Maximum number of locals for function / method body +max-locals=15 + +# Maximum number of return / yield for function / method body +max-returns=6 + +# Maximum number of branch for function / method body +max-branchs=12 + +# Maximum number of statements in function / method body +max-statements=50 + +# Maximum number of parents for a class (see R0901). +max-parents=7 + +# Maximum number of attributes for a class (see R0902). +max-attributes=20 + +# Minimum number of public methods for a class (see R0903). +min-public-methods=0 + +# Maximum number of public methods for a class (see R0904). +max-public-methods=20 + + +[IMPORTS] + +# Deprecated modules which should not be used, separated by a comma +deprecated-modules=regsub,string,TERMIOS,Bastion,rexec + +# Create a graph of every (i.e. internal and external) dependencies in the +# given file (report RP0402 must not be disabled) +import-graph= + +# Create a graph of external dependencies in the given file (report RP0402 must +# not be disabled) +ext-import-graph= + +# Create a graph of internal dependencies in the given file (report RP0402 must +# not be disabled) +int-import-graph= + + +[CLASSES] + +# List of interface methods to ignore, separated by a comma. This is used for +# instance to not check methods defines in Zope's Interface base class. +ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by + +# List of method names used to declare (i.e. assign) instance attributes. +defining-attr-methods=__init__,__new__,setUp diff --git a/tox.ini b/tox.ini index 0e6c514..eaad4bc 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = flake8, yamllint, unit, integration, docs +envlist = flake8, pylint, yamllint, unit, integration, docs [flake8] ignore = E221,E241,E501 @@ -12,6 +12,13 @@ basepython = python2.7 deps = flake8 commands = flake8 bootstrapvz/ tests/ {posargs} +[testenv:pylint] +deps = + pylint + nose + pyvbox +commands = pylint bootstrapvz/ tests/ setup.py + [testenv:unit] deps = nose