diff --git a/.drone.jsonnet b/.drone.jsonnet index d2b803a..ba0e9b6 100644 --- a/.drone.jsonnet +++ b/.drone.jsonnet @@ -6,7 +6,7 @@ local PythonVersion(pyversion="3.5") = { PY_COLORS: 1 }, commands: [ - "pip install -r test-requirements.txt -qq", + "pip install -r dev-requirements.txt -qq", "pip install -qq .", "git-batch --help", ], @@ -25,13 +25,13 @@ local PipelineLint = { steps: [ { name: "flake8", - image: "python:3.7", + image: "python:3.8", pull: "always", environment: { PY_COLORS: 1 }, commands: [ - "pip install -r test-requirements.txt -qq", + "pip install -r dev-requirements.txt -qq", "pip install -qq .", "flake8 ./gitbatch", ], @@ -73,13 +73,13 @@ local PipelineSecurity = { steps: [ { name: "bandit", - image: "python:3.7", + image: "python:3.8", pull: "always", environment: { PY_COLORS: 1 }, commands: [ - "pip install -r test-requirements.txt -qq", + "pip install -r dev-requirements.txt -qq", "pip install -qq .", "bandit -r ./gitbatch -x ./gitbatch/tests", ], @@ -103,7 +103,7 @@ local PipelineBuildContainer(arch="amd64") = { steps: [ { name: "build", - image: "python:3.7", + image: "python:3.8", pull: "always", commands: [ "python setup.py bdist_wheel", diff --git a/.drone.yml b/.drone.yml index e1e0765..f662521 100644 --- a/.drone.yml +++ b/.drone.yml @@ -9,9 +9,9 @@ platform: steps: - name: flake8 pull: always - image: python:3.7 + image: python:3.8 commands: - - pip install -r test-requirements.txt -qq + - pip install -r dev-requirements.txt -qq - pip install -qq . - flake8 ./gitbatch environment: @@ -36,7 +36,7 @@ steps: pull: always image: python:3.5 commands: - - pip install -r test-requirements.txt -qq + - pip install -r dev-requirements.txt -qq - pip install -qq . - git-batch --help environment: @@ -48,7 +48,7 @@ steps: pull: always image: python:3.6 commands: - - pip install -r test-requirements.txt -qq + - pip install -r dev-requirements.txt -qq - pip install -qq . - git-batch --help environment: @@ -60,7 +60,7 @@ steps: pull: always image: python:3.7 commands: - - pip install -r test-requirements.txt -qq + - pip install -r dev-requirements.txt -qq - pip install -qq . - git-batch --help environment: @@ -72,7 +72,7 @@ steps: pull: always image: python:3.8 commands: - - pip install -r test-requirements.txt -qq + - pip install -r dev-requirements.txt -qq - pip install -qq . - git-batch --help environment: @@ -100,9 +100,9 @@ platform: steps: - name: bandit pull: always - image: python:3.7 + image: python:3.8 commands: - - pip install -r test-requirements.txt -qq + - pip install -r dev-requirements.txt -qq - pip install -qq . - bandit -r ./gitbatch -x ./gitbatch/tests environment: @@ -128,7 +128,7 @@ platform: steps: - name: build pull: always - image: python:3.7 + image: python:3.8 commands: - python setup.py bdist_wheel @@ -184,7 +184,7 @@ platform: steps: - name: build pull: always - image: python:3.7 + image: python:3.8 commands: - python setup.py bdist_wheel @@ -240,7 +240,7 @@ platform: steps: - name: build pull: always - image: python:3.7 + image: python:3.8 commands: - python setup.py bdist_wheel @@ -366,6 +366,6 @@ depends_on: --- kind: signature -hmac: c8a46e748269c79caf345ebfcb117a5bd78b6e62a40de8ce492a165a0fa7789d +hmac: b0b80a9e961c9d56a25b583c0e5404b09039a725be5e635670d7c2ef346add5e ... diff --git a/.flake8 b/.flake8 index 2dba324..83ef6c0 100644 --- a/.flake8 +++ b/.flake8 @@ -1,8 +1,18 @@ [flake8] -# Temp disable Docstring checks D101, D102, D103, D107 -ignore = E501, W503, F401, N813, D101, D102, D103, D107 -max-line-length = 110 +ignore = D102, D103, D107, D202, W503 +max-line-length = 99 inline-quotes = double -exclude = .git,.tox,__pycache__,build,dist,tests,*.pyc,*.egg-info,.cache,.eggs,env* +exclude = + .git + .tox + __pycache__ + build + dist + tests + *.pyc + *.egg-info + .cache + .eggs + env* application-import-names = ansiblelater format = ${cyan}%(path)s:%(row)d:%(col)d${reset}: ${red_bold}%(code)s${reset} %(text)s diff --git a/test-requirements.txt b/dev-requirements.txt similarity index 72% rename from test-requirements.txt rename to dev-requirements.txt index 25c2aaf..8a7cdfe 100644 --- a/test-requirements.txt +++ b/dev-requirements.txt @@ -1,19 +1,18 @@ -# open issue -# https://gitlab.com/pycqa/flake8-docstrings/issues/36 pydocstyle<4.0.0 flake8 flake8-colors flake8-blind-except flake8-builtins -flake8-colors flake8-docstrings<=3.0.0 flake8-isort flake8-logging-format flake8-polyfill flake8-quotes +flake8-eradicate; python_version >= "3.6" pep8-naming wheel pytest pytest-mock pytest-cov bandit +yapf diff --git a/gitbatch/Cli.py b/gitbatch/Cli.py index c978d01..986ef45 100644 --- a/gitbatch/Cli.py +++ b/gitbatch/Cli.py @@ -2,9 +2,7 @@ """Main program.""" import argparse -import logging import os -import sys from collections import defaultdict from urllib.parse import urlparse @@ -17,6 +15,7 @@ from gitbatch.Utils import to_bool class GitBatch: + """Handles git operations.""" def __init__(self): self.log = SingleLog() @@ -27,8 +26,11 @@ class GitBatch: def _cli_args(self): parser = argparse.ArgumentParser( - description=("Clone single branch from all repositories listed in a file")) - parser.add_argument("--version", action="version", version="%(prog)s {}".format(__version__)) + description=("Clone single branch from all repositories listed in a file") + ) + parser.add_argument( + "--version", action="version", version="%(prog)s {}".format(__version__) + ) return parser.parse_args() @@ -52,8 +54,11 @@ class GitBatch: try: url, branch, dest = [x.strip() for x in line.split(";")] except ValueError as e: - self.log.sysexit_with_message("Wrong numer of delimiters in line {line_num}: {exp}".format( - line_num=num, exp=e)) + self.log.sysexit_with_message( + "Wrong numer of delimiters in line {line_num}: {exp}".format( + line_num=num, exp=e + ) + ) if url: url_parts = urlparse(url) @@ -61,21 +66,21 @@ class GitBatch: repo["url"] = url repo["branch"] = branch or "master" repo["name"] = os.path.basename(url_parts.path) - repo["dest"] = normalize_path(dest) or normalize_path("./{}".format(repo["name"])) + repo["dest"] = normalize_path(dest) or normalize_path( + "./{}".format(repo["name"]) + ) repos.append(repo) else: - self.log.sysexit_with_message("Repository Url is not set on line {line_num}".format( - line_num=num)) + self.log.sysexit_with_message( + "Repository Url is not set on line {line_num}".format(line_num=num) + ) return repos def _repos_clone(self, repos, ignore_existing): for repo in repos: try: - options = [ - "--branch={}".format(repo["branch"]), - "--single-branch" - ] + options = ["--branch={}".format(repo["branch"]), "--single-branch"] git.Repo.clone_from(repo["url"], repo["dest"], multi_options=options) except git.exc.GitCommandError as e: passed = False @@ -98,5 +103,8 @@ class GitBatch: repos = self._repos_from_file(self.config["input_file"]) self._repos_clone(repos, self.config["ignore_existing"]) else: - self.log.sysexit_with_message("The given batch file at '{}' does not exist".format( - os.path.relpath(os.path.join("./", self.config["input_file"])))) + self.log.sysexit_with_message( + "The given batch file at '{}' does not exist".format( + os.path.relpath(os.path.join("./", self.config["input_file"])) + ) + ) diff --git a/gitbatch/Logging.py b/gitbatch/Logging.py index e835ac5..a1c562f 100644 --- a/gitbatch/Logging.py +++ b/gitbatch/Logging.py @@ -8,7 +8,6 @@ import sys import colorama from pythonjsonlogger import jsonlogger -import gitbatch.Utils from gitbatch.Utils import Singleton from gitbatch.Utils import to_bool @@ -48,7 +47,7 @@ class LogFilter(object): class MultilineFormatter(logging.Formatter): """Logging Formatter to reset color after newline characters.""" - def format(self, record): # noqa + def format(self, record): # noqa record.msg = record.msg.replace("\n", "\n{}... ".format(colorama.Style.RESET_ALL)) return logging.Formatter.format(self, record) @@ -56,12 +55,14 @@ class MultilineFormatter(logging.Formatter): class MultilineJsonFormatter(jsonlogger.JsonFormatter): """Logging Formatter to remove newline characters.""" - def format(self, record): # noqa + def format(self, record): # noqa record.msg = record.msg.replace("\n", " ") return jsonlogger.JsonFormatter.format(self, record) class Log: + """Base logging object.""" + def __init__(self, level=logging.WARN, name="ansibledoctor", json=False): self.logger = logging.getLogger(name) self.logger.setLevel(level) @@ -76,8 +77,11 @@ class Log: handler = logging.StreamHandler(sys.stderr) handler.setLevel(logging.ERROR) handler.addFilter(LogFilter(logging.ERROR)) - handler.setFormatter(MultilineFormatter( - self.error(CONSOLE_FORMAT.format(colorama.Fore.RED, colorama.Style.RESET_ALL)))) + handler.setFormatter( + MultilineFormatter( + self.error(CONSOLE_FORMAT.format(colorama.Fore.RED, colorama.Style.RESET_ALL)) + ) + ) if json: handler.setFormatter(MultilineJsonFormatter(JSON_FORMAT)) @@ -88,8 +92,11 @@ class Log: handler = logging.StreamHandler(sys.stdout) handler.setLevel(logging.WARN) handler.addFilter(LogFilter(logging.WARN)) - handler.setFormatter(MultilineFormatter( - self.warn(CONSOLE_FORMAT.format(colorama.Fore.YELLOW, colorama.Style.RESET_ALL)))) + handler.setFormatter( + MultilineFormatter( + self.warn(CONSOLE_FORMAT.format(colorama.Fore.YELLOW, colorama.Style.RESET_ALL)) + ) + ) if json: handler.setFormatter(MultilineJsonFormatter(JSON_FORMAT)) @@ -100,8 +107,11 @@ class Log: handler = logging.StreamHandler(sys.stdout) handler.setLevel(logging.INFO) handler.addFilter(LogFilter(logging.INFO)) - handler.setFormatter(MultilineFormatter( - self.info(CONSOLE_FORMAT.format(colorama.Fore.CYAN, colorama.Style.RESET_ALL)))) + handler.setFormatter( + MultilineFormatter( + self.info(CONSOLE_FORMAT.format(colorama.Fore.CYAN, colorama.Style.RESET_ALL)) + ) + ) if json: handler.setFormatter(MultilineJsonFormatter(JSON_FORMAT)) @@ -112,8 +122,11 @@ class Log: handler = logging.StreamHandler(sys.stderr) handler.setLevel(logging.CRITICAL) handler.addFilter(LogFilter(logging.CRITICAL)) - handler.setFormatter(MultilineFormatter( - self.critical(CONSOLE_FORMAT.format(colorama.Fore.RED, colorama.Style.RESET_ALL)))) + handler.setFormatter( + MultilineFormatter( + self.critical(CONSOLE_FORMAT.format(colorama.Fore.RED, colorama.Style.RESET_ALL)) + ) + ) if json: handler.setFormatter(MultilineJsonFormatter(JSON_FORMAT)) @@ -124,8 +137,11 @@ class Log: handler = logging.StreamHandler(sys.stderr) handler.setLevel(logging.DEBUG) handler.addFilter(LogFilter(logging.DEBUG)) - handler.setFormatter(MultilineFormatter( - self.critical(CONSOLE_FORMAT.format(colorama.Fore.BLUE, colorama.Style.RESET_ALL)))) + handler.setFormatter( + MultilineFormatter( + self.critical(CONSOLE_FORMAT.format(colorama.Fore.BLUE, colorama.Style.RESET_ALL)) + ) + ) if json: handler.setFormatter(MultilineJsonFormatter(JSON_FORMAT)) @@ -175,4 +191,6 @@ class Log: class SingleLog(Log, metaclass=Singleton): + """Singleton logger object.""" + pass diff --git a/gitbatch/Utils.py b/gitbatch/Utils.py index ef83d59..61421e4 100644 --- a/gitbatch/Utils.py +++ b/gitbatch/Utils.py @@ -2,7 +2,6 @@ """Global utility methods and classes.""" import os -import sys from distutils.util import strtobool @@ -16,6 +15,8 @@ def to_bool(string): class Singleton(type): + """Meta singleton class.""" + _instances = {} def __call__(cls, *args, **kwargs): diff --git a/setup.cfg b/setup.cfg index c067cbb..511d028 100644 --- a/setup.cfg +++ b/setup.cfg @@ -10,11 +10,21 @@ default_section = THIRDPARTY known_first_party = gitbatch sections = FUTURE,STDLIB,THIRDPARTY,FIRSTPARTY,LOCALFOLDER force_single_line = true -line_length = 110 -skip_glob = **/env/* +line_length = 99 +skip_glob = **/.env*,**/env/*,**/docs/* + +[yapf] +based_on_style = google +column_limit = 99 +dedent_closing_brackets = true +coalesce_brackets = true +split_before_logical_operator = true [tool:pytest] filterwarnings = ignore::FutureWarning ignore:.*collections.*:DeprecationWarning ignore:.*pep8.*:FutureWarning + +[coverage:run] +omit = **/test/* diff --git a/setup.py b/setup.py index 18a00d8..525cacd 100644 --- a/setup.py +++ b/setup.py @@ -30,28 +30,31 @@ setup( name=get_property("__project__", PACKAGE_NAME), version=get_property("__version__", PACKAGE_NAME), description="Clone single branch from all repositories listed in a file.", + keywords="git, batch, automation", author=get_property("__author__", PACKAGE_NAME), author_email=get_property("__email__", PACKAGE_NAME), url=get_property("__url__", PACKAGE_NAME), license=get_property("__license__", PACKAGE_NAME), long_description=get_readme(), long_description_content_type="text/markdown", - packages=find_packages(exclude=["*.tests", "tests", "tests.*"]), + packages=find_packages(exclude=["*.test", "test", "test.*"]), include_package_data=True, zip_safe=False, - python_requires=">=3.5", + python_requires=">=3.5,<4", classifiers=[ "Development Status :: 5 - Production/Stable", "Environment :: Console", + "License :: OSI Approved :: MIT License", "Intended Audience :: Developers", "Intended Audience :: Information Technology", "Intended Audience :: System Administrators", - "License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)", "Natural Language :: English", "Operating System :: POSIX", - "Programming Language :: Python :: 3 :: Only", - "Topic :: System :: Installation/Setup", - "Topic :: System :: Systems Administration", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.5", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", "Topic :: Utilities", "Topic :: Software Development", "Topic :: Software Development :: Documentation", @@ -66,5 +69,4 @@ setup( "git-batch = gitbatch.__main__:main" ] }, - test_suite="tests" )