From 7e0df6eabd85aa260de26c8092a117d9f4a74595 Mon Sep 17 00:00:00 2001 From: Maurits van Rees Date: Thu, 20 Aug 2026 12:32:01 +0200 Subject: [PATCH 1/6] Add code quality configuration files. --- .editorconfig | 56 +++++++++++++++++++++++++++++++++++++++++ .flake8 | 11 ++++++++ .pre-commit-config.yaml | 35 ++++++++++++++++++++++++++ MANIFEST.in | 1 - pyproject.toml | 23 ++++++++++++----- setup.cfg | 13 ---------- 6 files changed, 119 insertions(+), 20 deletions(-) create mode 100644 .editorconfig create mode 100644 .flake8 create mode 100644 .pre-commit-config.yaml delete mode 100644 setup.cfg diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..55bfb6d0 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,56 @@ +# Generated from: +# https://github.com/plone/meta/tree/2.x/src/plone/meta/default +# See the inline comments on how to expand/tweak this configuration file +# +# EditorConfig Configuration file, for more details see: +# http://EditorConfig.org +# EditorConfig is a convention description, that could be interpreted +# by multiple editors to enforce common coding conventions for specific +# file types + +# top-most EditorConfig file: +# Will ignore other EditorConfig files in Home directory or upper tree level. +root = true + + +[*] +# Default settings for all files. +# Unix-style newlines with a newline ending every file +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true +# Set default charset +charset = utf-8 +# Indent style default +indent_style = space +# Max Line Length - a hard line wrap, should be disabled +max_line_length = off + +[*.{py,cfg,ini}] +# 4 space indentation +indent_size = 4 + +[*.{yml,zpt,pt,dtml,zcml,html,xml}] +# 2 space indentation +indent_size = 2 + +[*.{json,jsonl,js,jsx,ts,tsx,css,less,scss}] +# Frontend development +# 2 space indentation +indent_size = 2 +max_line_length = 80 + +[{Makefile,.gitmodules}] +# Tab indentation (no size specified, but view as 4 spaces) +indent_style = tab +indent_size = unset +tab_width = unset + + +## +# Add extra configuration options in .meta.toml: +# [editorconfig] +# extra_lines = """ +# _your own configuration lines_ +# """ +## diff --git a/.flake8 b/.flake8 new file mode 100644 index 00000000..972bb416 --- /dev/null +++ b/.flake8 @@ -0,0 +1,11 @@ +[flake8] +doctests = 1 +ignore = + # black takes care of line length + E501, + # black takes care of where to break lines + W503, + # black takes care of spaces within slicing (list[:]) + E203, + # black takes care of spaces after commas + E231, diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..76f49c20 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,35 @@ +ci: + autofix_prs: false + autoupdate_schedule: monthly + +repos: +- repo: https://github.com/asottile/pyupgrade + rev: v3.21.2 + hooks: + - id: pyupgrade + args: [--py310-plus] +- repo: https://github.com/pycqa/isort + rev: 9.0.0b1 + hooks: + - id: isort +- repo: https://github.com/psf/black-pre-commit-mirror + rev: 26.5.1 + hooks: + - id: black +- repo: https://github.com/PyCQA/flake8 + rev: 7.3.0 + hooks: + - id: flake8 +- repo: https://github.com/mgedmin/check-manifest + rev: "0.51" + hooks: + - id: check-manifest +- repo: https://github.com/regebro/pyroma + rev: "5.1b1" + hooks: + - id: pyroma +- repo: https://github.com/mgedmin/check-python-versions + rev: "0.24.2" + hooks: + - id: check-python-versions + args: ['--only', 'setup.py,tox.ini'] diff --git a/MANIFEST.in b/MANIFEST.in index c80f692f..bb37a272 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,2 +1 @@ include *.rst -include *.ini diff --git a/pyproject.toml b/pyproject.toml index ea9e0d70..a68e1c54 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,8 +1,19 @@ [build-system] -# We still support older Pythons, and that means it is better to use an -# older setuptools to create the distributions. -# requires = ["setuptools<69"] -# But with such an old version, I get a BadRequest error when uploading to PyPI: -# Filename 'mr.developer-2.1.0.tar.gz' is invalid, should be 'mr_developer-2.1.0.tar.gz'. -# So require a newer one. requires = ["setuptools>=75.3.2"] +build-backend = "setuptools.build_meta" + +[tool.black] +target-version = ["py310"] + +[tool.check-manifest] +ignore = [ + ".editorconfig", + ".flake8", + ".pre-commit-config.yaml", + "tox.ini", + "build_git.sh", + "buildout.cfg", +] + +[tool.isort] +profile = "plone" diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index a49c5939..00000000 --- a/setup.cfg +++ /dev/null @@ -1,13 +0,0 @@ -[zest.releaser] -version-levels = 2 - -[devpi:upload] -formats = sdist.tgz,bdist_wheel - -[flake8] -extend-ignore = E501 - -[check-manifest] -ignore = - build_git.sh - buildout.cfg From 607d1f3173b870ef563b98e2abfd35bce2f7b943 Mon Sep 17 00:00:00 2001 From: Maurits van Rees Date: Thu, 20 Aug 2026 12:35:34 +0200 Subject: [PATCH 2/6] isort --- setup.py | 1 - src/mr/developer/bazaar.py | 1 + src/mr/developer/commands.py | 6 +++++- src/mr/developer/common.py | 4 ++-- src/mr/developer/cvs.py | 1 + src/mr/developer/darcs.py | 2 +- src/mr/developer/develop.py | 7 +++++-- src/mr/developer/extension.py | 7 +++++-- src/mr/developer/filesystem.py | 1 + src/mr/developer/git.py | 4 ++-- src/mr/developer/gitsvn.py | 2 +- src/mr/developer/mercurial.py | 3 ++- src/mr/developer/svn.py | 7 ++++--- src/mr/developer/tests/test_commands.py | 1 + src/mr/developer/tests/test_common.py | 8 ++++++-- src/mr/developer/tests/test_cvs.py | 2 +- src/mr/developer/tests/test_extension.py | 3 ++- src/mr/developer/tests/test_git.py | 17 ++++++++--------- src/mr/developer/tests/test_git_submodules.py | 12 ++++++++---- src/mr/developer/tests/test_mercurial.py | 9 ++++----- src/mr/developer/tests/test_svn.py | 3 ++- src/mr/developer/tests/utils.py | 4 +++- 22 files changed, 65 insertions(+), 40 deletions(-) diff --git a/setup.py b/setup.py index cf4be768..30b50503 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,5 @@ from setuptools import setup - version = '3.0.0.dev0' diff --git a/src/mr/developer/bazaar.py b/src/mr/developer/bazaar.py index a3af4561..cc5bab4a 100644 --- a/src/mr/developer/bazaar.py +++ b/src/mr/developer/bazaar.py @@ -1,4 +1,5 @@ from mr.developer import common + import os import subprocess diff --git a/src/mr/developer/commands.py b/src/mr/developer/commands.py index 4b494484..ef63241e 100644 --- a/src/mr/developer/commands.py +++ b/src/mr/developer/commands.py @@ -1,4 +1,8 @@ -from mr.developer.common import logger, memoize, WorkingCopies, yesno +from mr.developer.common import logger +from mr.developer.common import memoize +from mr.developer.common import WorkingCopies +from mr.developer.common import yesno + import argparse import errno import os diff --git a/src/mr/developer/common.py b/src/mr/developer/common.py index 4e71ef1e..6c1f8f3e 100644 --- a/src/mr/developer/common.py +++ b/src/mr/developer/common.py @@ -1,3 +1,5 @@ +from configparser import RawConfigParser + import logging import os import pkg_resources @@ -6,8 +8,6 @@ import re import sys import threading -from configparser import RawConfigParser - logger = logging.getLogger("mr.developer") diff --git a/src/mr/developer/cvs.py b/src/mr/developer/cvs.py index facb91a2..4f26eca9 100644 --- a/src/mr/developer/cvs.py +++ b/src/mr/developer/cvs.py @@ -1,4 +1,5 @@ from mr.developer import common + import os import re import subprocess diff --git a/src/mr/developer/darcs.py b/src/mr/developer/darcs.py index c1e6aa6d..d3dfcfc0 100755 --- a/src/mr/developer/darcs.py +++ b/src/mr/developer/darcs.py @@ -1,8 +1,8 @@ from mr.developer import common + import os import subprocess - logger = common.logger diff --git a/src/mr/developer/develop.py b/src/mr/developer/develop.py index b595bc31..c83b2607 100644 --- a/src/mr/developer/develop.py +++ b/src/mr/developer/develop.py @@ -1,12 +1,15 @@ -from mr.developer.common import logger, Config, get_commands from mr.developer.commands import CmdHelp +from mr.developer.common import Config +from mr.developer.common import get_commands +from mr.developer.common import logger from mr.developer.extension import Extension from zc.buildout.buildout import Buildout + import argparse import atexit -import pkg_resources import logging import os +import pkg_resources import sys import textwrap diff --git a/src/mr/developer/extension.py b/src/mr/developer/extension.py index d8c5107e..69909f5e 100644 --- a/src/mr/developer/extension.py +++ b/src/mr/developer/extension.py @@ -1,10 +1,13 @@ -from mr.developer.common import memoize, WorkingCopies, Config, get_workingcopytypes +from mr.developer.common import Config +from mr.developer.common import get_workingcopytypes +from mr.developer.common import memoize +from mr.developer.common import WorkingCopies + import logging import os import re import sys - FAKE_PART_ID = '_mr.developer' logger = logging.getLogger("mr.developer") diff --git a/src/mr/developer/filesystem.py b/src/mr/developer/filesystem.py index 7556f319..bddb41cb 100644 --- a/src/mr/developer/filesystem.py +++ b/src/mr/developer/filesystem.py @@ -1,4 +1,5 @@ from mr.developer import common + import os logger = common.logger diff --git a/src/mr/developer/git.py b/src/mr/developer/git.py index 965eab98..7988d4bd 100644 --- a/src/mr/developer/git.py +++ b/src/mr/developer/git.py @@ -1,10 +1,10 @@ from mr.developer import common + import os -import subprocess import re +import subprocess import sys - logger = common.logger diff --git a/src/mr/developer/gitsvn.py b/src/mr/developer/gitsvn.py index 7d532799..5771b247 100644 --- a/src/mr/developer/gitsvn.py +++ b/src/mr/developer/gitsvn.py @@ -1,7 +1,7 @@ from mr.developer import common from mr.developer.svn import SVNWorkingCopy -import subprocess +import subprocess logger = common.logger diff --git a/src/mr/developer/mercurial.py b/src/mr/developer/mercurial.py index 775bc24b..2056bdc0 100644 --- a/src/mr/developer/mercurial.py +++ b/src/mr/developer/mercurial.py @@ -1,6 +1,7 @@ from mr.developer import common -import re + import os +import re import subprocess logger = common.logger diff --git a/src/mr/developer/svn.py b/src/mr/developer/svn.py index 233d0a77..d1fe1efd 100644 --- a/src/mr/developer/svn.py +++ b/src/mr/developer/svn.py @@ -1,12 +1,13 @@ from mr.developer import common -from urllib.parse import urlparse, urlunparse -import xml.etree.ElementTree as etree +from urllib.parse import urlparse +from urllib.parse import urlunparse + import getpass import os import re import subprocess import sys - +import xml.etree.ElementTree as etree logger = common.logger diff --git a/src/mr/developer/tests/test_commands.py b/src/mr/developer/tests/test_commands.py index 9f7df507..a715d9bb 100644 --- a/src/mr/developer/tests/test_commands.py +++ b/src/mr/developer/tests/test_commands.py @@ -1,4 +1,5 @@ from unittest.mock import patch + import pytest diff --git a/src/mr/developer/tests/test_common.py b/src/mr/developer/tests/test_common.py index 01ab1754..0b3f61b1 100644 --- a/src/mr/developer/tests/test_common.py +++ b/src/mr/developer/tests/test_common.py @@ -1,5 +1,9 @@ -from mr.developer.common import Config, Rewrite -from mr.developer.common import get_commands, parse_buildout_args, version_sorted +from mr.developer.common import Config +from mr.developer.common import get_commands +from mr.developer.common import parse_buildout_args +from mr.developer.common import Rewrite +from mr.developer.common import version_sorted + import pytest diff --git a/src/mr/developer/tests/test_cvs.py b/src/mr/developer/tests/test_cvs.py index d1ca27d7..a7644a90 100644 --- a/src/mr/developer/tests/test_cvs.py +++ b/src/mr/developer/tests/test_cvs.py @@ -1,6 +1,6 @@ -import unittest import doctest import mr.developer.cvs +import unittest def test_suite(): diff --git a/src/mr/developer/tests/test_extension.py b/src/mr/developer/tests/test_extension.py index 520ea663..de0cf9b6 100644 --- a/src/mr/developer/tests/test_extension.py +++ b/src/mr/developer/tests/test_extension.py @@ -1,8 +1,9 @@ from copy import deepcopy -from unittest.mock import patch from mr.developer.extension import Extension from mr.developer.tests.utils import MockConfig +from unittest.mock import patch from zc.buildout.buildout import MissingSection + import os import pytest diff --git a/src/mr/developer/tests/test_git.py b/src/mr/developer/tests/test_git.py index 415a132c..67f234dd 100644 --- a/src/mr/developer/tests/test_git.py +++ b/src/mr/developer/tests/test_git.py @@ -1,11 +1,10 @@ -import os -import shutil - -import pytest -from unittest.mock import patch - from mr.developer.extension import Source from mr.developer.tests.utils import Process +from unittest.mock import patch + +import os +import pytest +import shutil class TestGit: @@ -49,8 +48,8 @@ def testUpdateWithRevisionPin(self, develop, mkgitrepo, src): def testUpdateWithBranch(self, develop, mkgitrepo, src): from mr.developer.commands import CmdCheckout - from mr.developer.commands import CmdUpdate from mr.developer.commands import CmdStatus + from mr.developer.commands import CmdUpdate repository = mkgitrepo('repository') self.createDefaultContent(repository) @@ -102,8 +101,8 @@ def testRaiseExceptionUpdateWithRevisionAndBranch(self, develop, mkgitrepo, src) def testUpdateWithoutRevisionPin(self, develop, mkgitrepo, src, capsys): from mr.developer.commands import CmdCheckout - from mr.developer.commands import CmdUpdate from mr.developer.commands import CmdStatus + from mr.developer.commands import CmdUpdate repository = mkgitrepo('repository') repository.add_file('foo') repository.add_file('bar') @@ -138,8 +137,8 @@ def testUpdateWithoutRevisionPin(self, develop, mkgitrepo, src, capsys): def testUpdateVerbose(self, develop, mkgitrepo, src, capsys): from mr.developer.commands import CmdCheckout - from mr.developer.commands import CmdUpdate from mr.developer.commands import CmdStatus + from mr.developer.commands import CmdUpdate repository = mkgitrepo('repository') repository.add_file('foo') repository.add_file('bar') diff --git a/src/mr/developer/tests/test_git_submodules.py b/src/mr/developer/tests/test_git_submodules.py index 45a34726..575030f5 100644 --- a/src/mr/developer/tests/test_git_submodules.py +++ b/src/mr/developer/tests/test_git_submodules.py @@ -1,6 +1,7 @@ -from unittest.mock import patch from mr.developer.extension import Source from mr.developer.tests.utils import GitRepo +from unittest.mock import patch + import os @@ -78,7 +79,8 @@ def testUpdateWithSubmodule(self, develop, mkgitrepo, src): Tests the checkout of a module 'egg' with a submodule 'submodule_a' in it. Add a new 'submodule_b' to 'egg' and check it succesfully initializes. """ - from mr.developer.commands import CmdCheckout, CmdUpdate + from mr.developer.commands import CmdCheckout + from mr.developer.commands import CmdUpdate submodule_name = 'submodule_a' submodule = mkgitrepo(submodule_name) submodule.add_file('foo') @@ -253,7 +255,8 @@ def testUpdateWithSubmoduleCheckout(self, develop, mkgitrepo, src): Tests the checkout of a module 'egg' with a submodule 'submodule_a' in it. Add a new 'submodule_b' to 'egg' and check it doesn't get initialized. """ - from mr.developer.commands import CmdCheckout, CmdUpdate + from mr.developer.commands import CmdCheckout + from mr.developer.commands import CmdUpdate submodule_name = 'submodule_a' submodule = mkgitrepo(submodule_name) submodule.add_file('foo') @@ -302,7 +305,8 @@ def testUpdateWithSubmoduleDontUpdatePreviousSubmodules(self, develop, mkgitrepo Commits changes in the detached submodule, and checks update didn't break the changes. """ - from mr.developer.commands import CmdCheckout, CmdUpdate + from mr.developer.commands import CmdCheckout + from mr.developer.commands import CmdUpdate submodule_name = 'submodule_a' submodule = mkgitrepo(submodule_name) submodule.add_file('foo') diff --git a/src/mr/developer/tests/test_mercurial.py b/src/mr/developer/tests/test_mercurial.py index 3e416cdc..8baf0eb9 100644 --- a/src/mr/developer/tests/test_mercurial.py +++ b/src/mr/developer/tests/test_mercurial.py @@ -1,10 +1,9 @@ -import os - -import pytest -from unittest.mock import patch - from mr.developer.extension import Source from mr.developer.tests.utils import Process +from unittest.mock import patch + +import os +import pytest class TestMercurial: diff --git a/src/mr/developer/tests/test_svn.py b/src/mr/developer/tests/test_svn.py index 0432bd5e..f7bf6db9 100644 --- a/src/mr/developer/tests/test_svn.py +++ b/src/mr/developer/tests/test_svn.py @@ -1,6 +1,7 @@ -from unittest.mock import patch from mr.developer.extension import Source from mr.developer.tests.utils import Process +from unittest.mock import patch + import os import pytest diff --git a/src/mr/developer/tests/utils.py b/src/mr/developer/tests/utils.py index f7c8c8d6..987f6cef 100644 --- a/src/mr/developer/tests/utils.py +++ b/src/mr/developer/tests/utils.py @@ -1,4 +1,6 @@ -from subprocess import Popen, PIPE +from subprocess import PIPE +from subprocess import Popen + import os import sys import threading From 516ea7d440c549bf6edfe467a709f0f0badc4351 Mon Sep 17 00:00:00 2001 From: Maurits van Rees Date: Thu, 20 Aug 2026 12:36:29 +0200 Subject: [PATCH 3/6] black --- setup.py | 96 +- src/mr/__init__.py | 3 +- src/mr/developer/__init__.py | 3 +- src/mr/developer/bazaar.py | 108 ++- src/mr/developer/commands.py | 835 +++++++++++------- src/mr/developer/common.py | 373 ++++---- src/mr/developer/cvs.py | 141 +-- src/mr/developer/darcs.py | 106 ++- src/mr/developer/develop.py | 33 +- src/mr/developer/extension.py | 177 ++-- src/mr/developer/filesystem.py | 41 +- src/mr/developer/git.py | 230 ++--- src/mr/developer/gitsvn.py | 29 +- src/mr/developer/mercurial.py | 202 +++-- src/mr/developer/svn.py | 280 +++--- src/mr/developer/tests/conftest.py | 8 +- src/mr/developer/tests/test_commands.py | 121 +-- src/mr/developer/tests/test_common.py | 81 +- src/mr/developer/tests/test_extension.py | 451 ++++++---- src/mr/developer/tests/test_git.py | 249 +++--- src/mr/developer/tests/test_git_submodules.py | 504 +++++++---- src/mr/developer/tests/test_mercurial.py | 127 +-- src/mr/developer/tests/test_svn.py | 76 +- src/mr/developer/tests/utils.py | 32 +- 24 files changed, 2508 insertions(+), 1798 deletions(-) diff --git a/setup.py b/setup.py index 30b50503..4fd426ab 100644 --- a/setup.py +++ b/setup.py @@ -1,61 +1,64 @@ from setuptools import setup -version = '3.0.0.dev0' +version = "3.0.0.dev0" install_requires = [ - 'setuptools', - 'zc.buildout', + "setuptools", + "zc.buildout", ] -tests_require = [ - 'mock'] +tests_require = ["mock"] -extras_require = { - 'test': tests_require} +extras_require = {"test": tests_require} def get_text_from_file(fn): - text = open(fn, 'rb').read() - return text.decode('utf-8') + text = open(fn, "rb").read() + return text.decode("utf-8") -setup(name='mr.developer', - version=version, - description="A zc.buildout extension to ease the development of large projects with lots of packages.", - long_description="\n\n".join([ - get_text_from_file("README.rst"), - get_text_from_file("HELP.rst"), - get_text_from_file("CHANGES.rst")]), - # Get more strings from https://pypi.org/classifiers/ - classifiers=[ - "Development Status :: 5 - Production/Stable", - "Programming Language :: Python", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", - "Programming Language :: Python :: 3.12", - "Programming Language :: Python :: 3.13", - "Programming Language :: Python :: 3.14", - "Programming Language :: Python :: 3.15", - "Framework :: Buildout", - "Topic :: Software Development :: Libraries :: Python Modules"], - keywords='buildout extension vcs git develop', - author='Florian Schulze', - author_email='florian.schulze@gmx.net', - url='https://github.com/fschulze/mr.developer', - license='BSD', - packages=['mr', 'mr.developer', 'mr.developer.tests'], - package_dir={'': 'src'}, - namespace_packages=['mr', 'mr.developer'], - include_package_data=True, - zip_safe=False, - install_requires=install_requires, - tests_require=tests_require, - extras_require=extras_require, - python_requires=">=3.10", - test_suite='mr.developer.tests', - entry_points=""" +setup( + name="mr.developer", + version=version, + description="A zc.buildout extension to ease the development of large projects with lots of packages.", + long_description="\n\n".join( + [ + get_text_from_file("README.rst"), + get_text_from_file("HELP.rst"), + get_text_from_file("CHANGES.rst"), + ] + ), + # Get more strings from https://pypi.org/classifiers/ + classifiers=[ + "Development Status :: 5 - Production/Stable", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", + "Programming Language :: Python :: 3.15", + "Framework :: Buildout", + "Topic :: Software Development :: Libraries :: Python Modules", + ], + keywords="buildout extension vcs git develop", + author="Florian Schulze", + author_email="florian.schulze@gmx.net", + url="https://github.com/fschulze/mr.developer", + license="BSD", + packages=["mr", "mr.developer", "mr.developer.tests"], + package_dir={"": "src"}, + namespace_packages=["mr", "mr.developer"], + include_package_data=True, + zip_safe=False, + install_requires=install_requires, + tests_require=tests_require, + extras_require=extras_require, + python_requires=">=3.10", + test_suite="mr.developer.tests", + entry_points=""" [console_scripts] develop = mr.developer.develop:develop [zc.buildout.extension] @@ -83,4 +86,5 @@ def get_text_from_file(fn): reset = mr.developer.commands:CmdReset status = mr.developer.commands:CmdStatus update = mr.developer.commands:CmdUpdate - """) + """, +) diff --git a/src/mr/__init__.py b/src/mr/__init__.py index f48ad105..05f0bebb 100644 --- a/src/mr/__init__.py +++ b/src/mr/__init__.py @@ -1,6 +1,7 @@ # See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages try: - __import__('pkg_resources').declare_namespace(__name__) + __import__("pkg_resources").declare_namespace(__name__) except ImportError: from pkgutil import extend_path + __path__ = extend_path(__path__, __name__) diff --git a/src/mr/developer/__init__.py b/src/mr/developer/__init__.py index f48ad105..05f0bebb 100644 --- a/src/mr/developer/__init__.py +++ b/src/mr/developer/__init__.py @@ -1,6 +1,7 @@ # See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages try: - __import__('pkg_resources').declare_namespace(__name__) + __import__("pkg_resources").declare_namespace(__name__) except ImportError: from pkgutil import extend_path + __path__ = extend_path(__path__, __name__) diff --git a/src/mr/developer/bazaar.py b/src/mr/developer/bazaar.py index cc5bab4a..bbea7ae2 100644 --- a/src/mr/developer/bazaar.py +++ b/src/mr/developer/bazaar.py @@ -14,98 +14,110 @@ class BazaarWorkingCopy(common.BaseWorkingCopy): def __init__(self, source): super().__init__(source) - self.bzr_executable = common.which('bzr') + self.bzr_executable = common.which("bzr") def bzr_branch(self, **kwargs): - name = self.source['name'] - path = self.source['path'] - url = self.source['url'] + name = self.source["name"] + path = self.source["path"] + url = self.source["url"] if os.path.exists(path): - self.output( - (logger.info, 'Skipped branching existing package %r.' % name)) + self.output((logger.info, "Skipped branching existing package %r." % name)) return - self.output((logger.info, 'Branched %r with bazaar.' % name)) + self.output((logger.info, "Branched %r with bazaar." % name)) env = dict(os.environ) - env.pop('PYTHONPATH', None) + env.pop("PYTHONPATH", None) cmd = subprocess.Popen( - [self.bzr_executable, 'branch', '--quiet', url, path], - env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + [self.bzr_executable, "branch", "--quiet", url, path], + env=env, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) stdout, stderr = cmd.communicate() if cmd.returncode != 0: - raise BazaarError( - f'bzr branch for {name!r} failed.\n{stderr}') - if kwargs.get('verbose', False): + raise BazaarError(f"bzr branch for {name!r} failed.\n{stderr}") + if kwargs.get("verbose", False): return stdout def bzr_pull(self, **kwargs): - name = self.source['name'] - path = self.source['path'] - url = self.source['url'] - self.output((logger.info, 'Updated %r with bazaar.' % name)) + name = self.source["name"] + path = self.source["path"] + url = self.source["url"] + self.output((logger.info, "Updated %r with bazaar." % name)) env = dict(os.environ) - env.pop('PYTHONPATH', None) + env.pop("PYTHONPATH", None) cmd = subprocess.Popen( - [self.bzr_executable, 'pull', url], cwd=path, - env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + [self.bzr_executable, "pull", url], + cwd=path, + env=env, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) stdout, stderr = cmd.communicate() if cmd.returncode != 0: - raise BazaarError( - f'bzr pull for {name!r} failed.\n{stderr}') - if kwargs.get('verbose', False): + raise BazaarError(f"bzr pull for {name!r} failed.\n{stderr}") + if kwargs.get("verbose", False): return stdout def checkout(self, **kwargs): - name = self.source['name'] - path = self.source['path'] + name = self.source["name"] + path = self.source["path"] update = self.should_update(**kwargs) if os.path.exists(path): if update: self.update(**kwargs) elif self.matches(): self.output( - (logger.info, 'Skipped checkout of existing package %r.' % name)) + (logger.info, "Skipped checkout of existing package %r." % name) + ) else: raise BazaarError( - 'Source URL for existing package %r differs. ' - 'Expected %r.' % (name, self.source['url'])) + "Source URL for existing package %r differs. " + "Expected %r." % (name, self.source["url"]) + ) else: return self.bzr_branch(**kwargs) def matches(self): - name = self.source['name'] - path = self.source['path'] + name = self.source["name"] + path = self.source["path"] env = dict(os.environ) - env.pop('PYTHONPATH', None) + env.pop("PYTHONPATH", None) cmd = subprocess.Popen( - [self.bzr_executable, 'info'], cwd=path, - env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + [self.bzr_executable, "info"], + cwd=path, + env=env, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) stdout, stderr = cmd.communicate() if cmd.returncode != 0: - raise BazaarError( - f'bzr info for {name!r} failed.\n{stderr}') - return (self.source['url'] in stdout.split()) + raise BazaarError(f"bzr info for {name!r} failed.\n{stderr}") + return self.source["url"] in stdout.split() def status(self, **kwargs): - path = self.source['path'] + path = self.source["path"] env = dict(os.environ) - env.pop('PYTHONPATH', None) + env.pop("PYTHONPATH", None) cmd = subprocess.Popen( - [self.bzr_executable, 'status'], cwd=path, - env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + [self.bzr_executable, "status"], + cwd=path, + env=env, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) stdout, stderr = cmd.communicate() - status = stdout and 'dirty' or 'clean' - if kwargs.get('verbose', False): + status = stdout and "dirty" or "clean" + if kwargs.get("verbose", False): return status, stdout else: return status def update(self, **kwargs): - name = self.source['name'] + name = self.source["name"] if not self.matches(): raise BazaarError( - "Can't update package %r because its URL doesn't match." % - name) - if self.status() != 'clean' and not kwargs.get('force', False): - raise BazaarError( - "Can't update package %r because it's dirty." % name) + "Can't update package %r because its URL doesn't match." % name + ) + if self.status() != "clean" and not kwargs.get("force", False): + raise BazaarError("Can't update package %r because it's dirty." % name) return self.bzr_pull(**kwargs) diff --git a/src/mr/developer/commands.py b/src/mr/developer/commands.py index ef63241e..7b729ca6 100644 --- a/src/mr/developer/commands.py +++ b/src/mr/developer/commands.py @@ -18,15 +18,19 @@ class ChoicesPseudoAction(argparse.Action): def __init__(self, *args, **kwargs): sup = super() - sup.__init__(dest=args[0], option_strings=list(args), help=kwargs.get('help'), nargs=0) + sup.__init__( + dest=args[0], option_strings=list(args), help=kwargs.get("help"), nargs=0 + ) class ArgumentParser(argparse.ArgumentParser): def _check_value(self, action, value): # converted value must be one of the choices (if specified) if action.choices is not None and value not in action.choices: - tup = value, ', '.join([repr(x) for x in sorted(action.choices) if x != 'pony']) - msg = argparse._('invalid choice: %r (choose from %s)') % tup + tup = value, ", ".join( + [repr(x) for x in sorted(action.choices) if x != "pony"] + ) + msg = argparse._("invalid choice: %r (choose from %s)") % tup raise argparse.ArgumentError(action, msg) @@ -50,8 +54,7 @@ def get_workingcopies(self, sources): return WorkingCopies(sources, threads=self.develop.threads) @memoize - def get_packages(self, args, auto_checkout=False, - develop=False, checked_out=False): + def get_packages(self, args, auto_checkout=False, develop=False, checked_out=False): if auto_checkout: packages = set(self.develop.auto_checkout) else: @@ -73,7 +76,9 @@ def get_packages(self, args, auto_checkout=False, if len(result) == 0: if len(args) > 1: - regexps = "{} or '{}'".format(", ".join("'%s'" % x for x in args[:-1]), args[-1]) + regexps = "{} or '{}'".format( + ", ".join("'%s'" % x for x in args[:-1]), args[-1] + ) else: regexps = "'%s'" % args[0] logger.error("No package matched %s." % regexps) @@ -87,48 +92,71 @@ def __init__(self, develop): Command.__init__(self, develop) description = "Add packages to the list of development packages." self.parser = self.develop.parsers.add_parser( - "activate", - description=description) - self.develop.parsers._name_parser_map["a"] = self.develop.parsers._name_parser_map["activate"] - self.develop.parsers._choices_actions.append(ChoicesPseudoAction( - "activate", "a", help=description)) - self.parser.add_argument( - "-a", "--auto-checkout", dest="auto_checkout", - action="store_true", default=False, - help="""Only considers packages declared by auto-checkout. If you don't specify a then all declared packages are processed.""") - self.parser.add_argument( - "-c", "--checked-out", dest="checked_out", - action="store_true", default=False, - help="""Only considers packages currently checked out. If you don't specify a then all checked out packages are processed.""") - self.parser.add_argument( - "-d", "--develop", dest="develop", - action="store_true", default=False, - help="""Only considers packages currently in development mode. If you don't specify a then all develop packages are processed.""") - self.parser.add_argument( - "package-regexp", nargs="+", - help="A regular expression to match package names.") + "activate", description=description + ) + self.develop.parsers._name_parser_map["a"] = ( + self.develop.parsers._name_parser_map["activate"] + ) + self.develop.parsers._choices_actions.append( + ChoicesPseudoAction("activate", "a", help=description) + ) + self.parser.add_argument( + "-a", + "--auto-checkout", + dest="auto_checkout", + action="store_true", + default=False, + help="""Only considers packages declared by auto-checkout. If you don't specify a then all declared packages are processed.""", + ) + self.parser.add_argument( + "-c", + "--checked-out", + dest="checked_out", + action="store_true", + default=False, + help="""Only considers packages currently checked out. If you don't specify a then all checked out packages are processed.""", + ) + self.parser.add_argument( + "-d", + "--develop", + dest="develop", + action="store_true", + default=False, + help="""Only considers packages currently in development mode. If you don't specify a then all develop packages are processed.""", + ) + self.parser.add_argument( + "package-regexp", + nargs="+", + help="A regular expression to match package names.", + ) self.parser.set_defaults(func=self) def __call__(self, args): config = self.develop.config - packages = self.get_packages(getattr(args, 'package-regexp'), - auto_checkout=args.auto_checkout, - checked_out=args.checked_out, - develop=args.develop) + packages = self.get_packages( + getattr(args, "package-regexp"), + auto_checkout=args.auto_checkout, + checked_out=args.checked_out, + develop=args.develop, + ) changed = False for name in sorted(packages): source = self.develop.sources[name] if not source.exists(): - logger.warning("The package '%s' matched, but isn't checked out." % name) + logger.warning( + "The package '%s' matched, but isn't checked out." % name + ) continue - if not source.get('egg', True): + if not source.get("egg", True): logger.warning("The package '%s' isn't an egg." % name) continue config.develop[name] = True logger.info("Activated '%s'." % name) changed = True if changed: - logger.warn("Don't forget to run buildout again, so the actived packages are actually used.") + logger.warn( + "Don't forget to run buildout again, so the actived packages are actually used." + ) config.save() @@ -137,11 +165,14 @@ def __init__(self, develop): Command.__init__(self, develop) description = "Print arguments used by last buildout which will be used with the 'rebuild' command." self.parser = self.develop.parsers.add_parser( - "arguments", - description=description) - self.develop.parsers._name_parser_map["args"] = self.develop.parsers._name_parser_map["arguments"] - self.develop.parsers._choices_actions.append(ChoicesPseudoAction( - "arguments", "args", help=description)) + "arguments", description=description + ) + self.develop.parsers._name_parser_map["args"] = ( + self.develop.parsers._name_parser_map["arguments"] + ) + self.develop.parsers._choices_actions.append( + ChoicesPseudoAction("arguments", "args", help=description) + ) self.parser.set_defaults(func=self) def __call__(self, args): @@ -154,40 +185,59 @@ def __init__(self, develop): Command.__init__(self, develop) self.parser = self.develop.parsers.add_parser( "checkout", - description="Make a checkout of the packages matching the regular expressions and add them to the list of development packages.") - self.develop.parsers._name_parser_map["co"] = self.develop.parsers._name_parser_map["checkout"] - self.develop.parsers._choices_actions.append(ChoicesPseudoAction( - "checkout", "co", help="Checkout packages")) + description="Make a checkout of the packages matching the regular expressions and add them to the list of development packages.", + ) + self.develop.parsers._name_parser_map["co"] = ( + self.develop.parsers._name_parser_map["checkout"] + ) + self.develop.parsers._choices_actions.append( + ChoicesPseudoAction("checkout", "co", help="Checkout packages") + ) self.parser.add_argument( - "-a", "--auto-checkout", dest="auto_checkout", - action="store_true", default=False, - help="""Only considers packages declared by auto-checkout. If you don't specify a then all declared packages are processed.""") + "-a", + "--auto-checkout", + dest="auto_checkout", + action="store_true", + default=False, + help="""Only considers packages declared by auto-checkout. If you don't specify a then all declared packages are processed.""", + ) self.parser.add_argument( - "-v", "--verbose", dest="verbose", - action="store_true", default=False, - help="""Show output of VCS command.""") + "-v", + "--verbose", + dest="verbose", + action="store_true", + default=False, + help="""Show output of VCS command.""", + ) self.parser.add_argument( - "package-regexp", nargs="+", - help="A regular expression to match package names.") + "package-regexp", + nargs="+", + help="A regular expression to match package names.", + ) self.parser.set_defaults(func=self) def __call__(self, args): config = self.develop.config - packages = self.get_packages(getattr(args, 'package-regexp'), - auto_checkout=args.auto_checkout) + packages = self.get_packages( + getattr(args, "package-regexp"), auto_checkout=args.auto_checkout + ) try: workingcopies = self.get_workingcopies(self.develop.sources) - workingcopies.checkout(sorted(packages), - verbose=args.verbose, - submodules=self.develop.update_git_submodules, - always_accept_server_certificate=self.develop.always_accept_server_certificate) + workingcopies.checkout( + sorted(packages), + verbose=args.verbose, + submodules=self.develop.update_git_submodules, + always_accept_server_certificate=self.develop.always_accept_server_certificate, + ) for name in sorted(packages): source = self.develop.sources[name] - if not source.get('egg', True): + if not source.get("egg", True): continue config.develop[name] = True logger.info("Activated '%s'." % name) - logger.warning("Don't forget to run buildout again, so the checked out packages are used as develop eggs.") + logger.warning( + "Don't forget to run buildout again, so the checked out packages are used as develop eggs." + ) config.save() except (ValueError, KeyError): logger.error(sys.exc_info()[1]) @@ -199,41 +249,62 @@ def __init__(self, develop): Command.__init__(self, develop) description = "Remove packages from the list of development packages." self.parser = self.develop.parsers.add_parser( - "deactivate", - description=description) - self.develop.parsers._name_parser_map["d"] = self.develop.parsers._name_parser_map["deactivate"] - self.develop.parsers._choices_actions.append(ChoicesPseudoAction( - "deactivate", "d", help=description)) - self.parser.add_argument( - "-a", "--auto-checkout", dest="auto_checkout", - action="store_true", default=False, - help="""Only considers packages declared by auto-checkout. If you don't specify a then all declared packages are processed.""") - self.parser.add_argument( - "-c", "--checked-out", dest="checked_out", - action="store_true", default=False, - help="""Only considers packages currently checked out. If you don't specify a then all checked out packages are processed.""") - self.parser.add_argument( - "-d", "--develop", dest="develop", - action="store_true", default=False, - help="""Only considers packages currently in development mode. If you don't specify a then all develop packages are processed.""") - self.parser.add_argument( - "package-regexp", nargs="+", - help="A regular expression to match package names.") + "deactivate", description=description + ) + self.develop.parsers._name_parser_map["d"] = ( + self.develop.parsers._name_parser_map["deactivate"] + ) + self.develop.parsers._choices_actions.append( + ChoicesPseudoAction("deactivate", "d", help=description) + ) + self.parser.add_argument( + "-a", + "--auto-checkout", + dest="auto_checkout", + action="store_true", + default=False, + help="""Only considers packages declared by auto-checkout. If you don't specify a then all declared packages are processed.""", + ) + self.parser.add_argument( + "-c", + "--checked-out", + dest="checked_out", + action="store_true", + default=False, + help="""Only considers packages currently checked out. If you don't specify a then all checked out packages are processed.""", + ) + self.parser.add_argument( + "-d", + "--develop", + dest="develop", + action="store_true", + default=False, + help="""Only considers packages currently in development mode. If you don't specify a then all develop packages are processed.""", + ) + self.parser.add_argument( + "package-regexp", + nargs="+", + help="A regular expression to match package names.", + ) self.parser.set_defaults(func=self) def __call__(self, args): config = self.develop.config - packages = self.get_packages(getattr(args, 'package-regexp'), - auto_checkout=args.auto_checkout, - checked_out=args.checked_out, - develop=args.develop) + packages = self.get_packages( + getattr(args, "package-regexp"), + auto_checkout=args.auto_checkout, + checked_out=args.checked_out, + develop=args.develop, + ) changed = False for name in sorted(packages): source = self.develop.sources[name] if not source.exists(): - logger.warning("The package '%s' matched, but isn't checked out." % name) + logger.warning( + "The package '%s' matched, but isn't checked out." % name + ) continue - if not source.get('egg', True): + if not source.get("egg", True): logger.warning("The package '%s' isn't an egg." % name) continue if config.develop.get(name) is not False: @@ -241,7 +312,9 @@ def __call__(self, args): logger.info("Deactivated '%s'." % name) changed = True if changed: - logger.warn("Don't forget to run buildout again, so the deactived packages are actually not used anymore.") + logger.warn( + "Don't forget to run buildout again, so the deactived packages are actually not used anymore." + ) config.save() @@ -250,34 +323,42 @@ def __init__(self, develop): Command.__init__(self, develop) self.parser = self.develop.parsers.add_parser( "help", - description="Show help on the given command or about the whole script if none given.") - self.develop.parsers._name_parser_map["h"] = self.develop.parsers._name_parser_map["help"] - self.develop.parsers._choices_actions.append(ChoicesPseudoAction( - "help", "h", help="Show help")) - self.parser.add_argument( - "--rst", dest="rst", - action="store_true", default=False, - help="""Print help for all commands in reStructuredText format.""") - self.parser.add_argument( - '-z', '--zsh', - action='store_true', - help="Print info for zsh autocompletion") - self.parser.add_argument("command", nargs="?", help="The command you want to see the help of.") + description="Show help on the given command or about the whole script if none given.", + ) + self.develop.parsers._name_parser_map["h"] = ( + self.develop.parsers._name_parser_map["help"] + ) + self.develop.parsers._choices_actions.append( + ChoicesPseudoAction("help", "h", help="Show help") + ) + self.parser.add_argument( + "--rst", + dest="rst", + action="store_true", + default=False, + help="""Print help for all commands in reStructuredText format.""", + ) + self.parser.add_argument( + "-z", "--zsh", action="store_true", help="Print info for zsh autocompletion" + ) + self.parser.add_argument( + "command", nargs="?", help="The command you want to see the help of." + ) self.parser.set_defaults(func=self) def __call__(self, args): develop = self.develop choices = develop.parsers.choices if args.zsh: - choices = [x for x in choices if x != 'pony'] + choices = [x for x in choices if x != "pony"] if args.command is None: print("\n".join(choices)) else: - if args.command == 'help': + if args.command == "help": print("\n".join(choices)) - elif args.command in ('purge', 'up', 'update'): + elif args.command in ("purge", "up", "update"): print("\n".join(self.get_packages(None, checked_out=True))) - elif args.command not in ('pony', 'rebuild'): + elif args.command not in ("pony", "rebuild"): print("\n".join(self.get_packages(None))) return if args.command in choices: @@ -285,7 +366,7 @@ def __call__(self, args): return cmds = {} for name in choices: - if name == 'pony': + if name == "pony": continue cmds.setdefault(choices[name], set()).add(name) for cmd, names in list(cmds.items()): @@ -303,8 +384,8 @@ def __call__(self, args): print() for name in sorted(cmds): cmd = cmds[name] - if len(cmd['aliases']): - header = "{} ({})".format(name, ", ".join(cmd['aliases'])) + if len(cmd["aliases"]): + header = "{} ({})".format(name, ", ".join(cmd["aliases"])) else: header = name print(header) @@ -312,7 +393,7 @@ def __call__(self, args): print() print("::") print() - for line in cmd['cmd'].format_help().split('\n'): + for line in cmd["cmd"].format_help().split("\n"): print(" %s" % line) print() else: @@ -320,8 +401,8 @@ def __call__(self, args): print("Available commands:") for name in sorted(cmds): cmd = cmds[name] - if len(cmd['aliases']): - print(" {} ({})".format(name, ", ".join(cmd['aliases']))) + if len(cmd["aliases"]): + print(" {} ({})".format(name, ", ".join(cmd["aliases"]))) else: print(" %s" % name) @@ -331,70 +412,99 @@ def __init__(self, develop): Command.__init__(self, develop) description = "Lists informations about packages." self.parser = self.develop.parsers.add_parser( - "info", - help=description, - description=description) + "info", help=description, description=description + ) self.parser.add_argument( - "-a", "--auto-checkout", dest="auto_checkout", - action="store_true", default=False, - help="""Only considers packages declared by auto-checkout. If you don't specify a then all declared packages are processed.""") + "-a", + "--auto-checkout", + dest="auto_checkout", + action="store_true", + default=False, + help="""Only considers packages declared by auto-checkout. If you don't specify a then all declared packages are processed.""", + ) self.parser.add_argument( - "-c", "--checked-out", dest="checked_out", - action="store_true", default=False, - help="""Only considers packages currently checked out. If you don't specify a then all declared packages are processed.""") + "-c", + "--checked-out", + dest="checked_out", + action="store_true", + default=False, + help="""Only considers packages currently checked out. If you don't specify a then all declared packages are processed.""", + ) self.parser.add_argument( - "-d", "--develop", dest="develop", - action="store_true", default=False, - help="""Only considers packages currently in development mode. If you don't specify a then all declared packages are processed.""") + "-d", + "--develop", + dest="develop", + action="store_true", + default=False, + help="""Only considers packages currently in development mode. If you don't specify a then all declared packages are processed.""", + ) info_opts = self.parser.add_argument_group( "Output options", - """The following options are used to print just the info you want, the order they are specified reflects the order in which the information will be printed.""") + """The following options are used to print just the info you want, the order they are specified reflects the order in which the information will be printed.""", + ) info_opts.add_argument( - "--name", dest="info", - action="append_const", const="name", - help="""Prints the name of the package.""") + "--name", + dest="info", + action="append_const", + const="name", + help="""Prints the name of the package.""", + ) info_opts.add_argument( - "-p", "--path", dest="info", - action="append_const", const="path", - help="""Prints the absolute path of the package.""") + "-p", + "--path", + dest="info", + action="append_const", + const="path", + help="""Prints the absolute path of the package.""", + ) info_opts.add_argument( - "--type", dest="info", - action="append_const", const="type", - help="""Prints the repository type of the package.""") + "--type", + dest="info", + action="append_const", + const="type", + help="""Prints the repository type of the package.""", + ) info_opts.add_argument( - "--url", dest="info", - action="append_const", const="url", - help="""Prints the URL of the package.""") + "--url", + dest="info", + action="append_const", + const="url", + help="""Prints the URL of the package.""", + ) self.parser.add_argument_group(info_opts) self.parser.add_argument( - "package-regexp", nargs="*", - help="A regular expression to match package names.") + "package-regexp", + nargs="*", + help="A regular expression to match package names.", + ) self.parser.set_defaults(func=self) def __call__(self, args): - packages = self.get_packages(getattr(args, 'package-regexp'), - auto_checkout=args.auto_checkout, - develop=args.develop, - checked_out=args.checked_out) + packages = self.get_packages( + getattr(args, "package-regexp"), + auto_checkout=args.auto_checkout, + develop=args.develop, + checked_out=args.checked_out, + ) for name in sorted(packages): source = self.develop.sources[name] if args.info: info = [] for key in args.info: - if key == 'name': + if key == "name": info.append(name) - elif key == 'path': - info.append(source['path']) - elif key == 'type': - info.append(source['kind']) - elif key == 'url': - info.append(source['url']) + elif key == "path": + info.append(source["path"]) + elif key == "type": + info.append(source["kind"]) + elif key == "url": + info.append(source["url"]) print(" ".join(info)) else: print("Name: %s" % name) - print("Path: %s" % source['path']) - print("Type: %s" % source['kind']) - print("URL: %s" % source['url']) + print("Path: %s" % source["path"]) + print("Type: %s" % source["kind"]) + print("URL: %s" % source["url"]) print() @@ -403,31 +513,52 @@ def __init__(self, develop): Command.__init__(self, develop) description = "Lists tracked packages." self.parser = self.develop.parsers.add_parser( - "list", - formatter_class=HelpFormatter, - description=description) - self.develop.parsers._name_parser_map["ls"] = self.develop.parsers._name_parser_map["list"] - self.develop.parsers._choices_actions.append(ChoicesPseudoAction( - "list", "ls", help=description)) + "list", formatter_class=HelpFormatter, description=description + ) + self.develop.parsers._name_parser_map["ls"] = ( + self.develop.parsers._name_parser_map["list"] + ) + self.develop.parsers._choices_actions.append( + ChoicesPseudoAction("list", "ls", help=description) + ) self.parser.add_argument( - "-a", "--auto-checkout", dest="auto_checkout", - action="store_true", default=False, - help="""Only show packages in auto-checkout list.""") + "-a", + "--auto-checkout", + dest="auto_checkout", + action="store_true", + default=False, + help="""Only show packages in auto-checkout list.""", + ) self.parser.add_argument( - "-c", "--checked-out", dest="checked_out", - action="store_true", default=False, - help="""Only considers packages currently checked out. If you don't specify a then all checked out packages are processed.""") + "-c", + "--checked-out", + dest="checked_out", + action="store_true", + default=False, + help="""Only considers packages currently checked out. If you don't specify a then all checked out packages are processed.""", + ) self.parser.add_argument( - "-d", "--develop", dest="develop", - action="store_true", default=False, - help="""Only considers packages currently in development mode. If you don't specify a then all develop packages are processed.""") + "-d", + "--develop", + dest="develop", + action="store_true", + default=False, + help="""Only considers packages currently in development mode. If you don't specify a then all develop packages are processed.""", + ) self.parser.add_argument( - "-l", "--long", dest="long", - action="store_true", default=False, - help="""Show URL and kind of package.""") + "-l", + "--long", + dest="long", + action="store_true", + default=False, + help="""Show URL and kind of package.""", + ) self.parser.add_argument( - "-s", "--status", dest="status", - action="store_true", default=False, + "-s", + "--status", + dest="status", + action="store_true", + default=False, help=textwrap.dedent("""\ Show checkout status. The first column in the output shows the checkout status: @@ -435,18 +566,24 @@ def __init__(self, develop): ' ' in auto-checkout list and checked out '~' not in auto-checkout list, but checked out '!' in auto-checkout list, but not checked out - 'C' the repository URL doesn't match""")) - self.parser.add_argument("package-regexp", nargs="*", - help="A regular expression to match package names.") + 'C' the repository URL doesn't match"""), + ) + self.parser.add_argument( + "package-regexp", + nargs="*", + help="A regular expression to match package names.", + ) self.parser.set_defaults(func=self) def __call__(self, args): sources = self.develop.sources auto_checkout = self.develop.auto_checkout - packages = self.get_packages(getattr(args, 'package-regexp'), - auto_checkout=args.auto_checkout, - checked_out=args.checked_out, - develop=args.develop) + packages = self.get_packages( + getattr(args, "package-regexp"), + auto_checkout=args.auto_checkout, + checked_out=args.checked_out, + develop=args.develop, + ) workingcopies = self.get_workingcopies(sources) for name in sorted(packages): source = sources[name] @@ -466,7 +603,7 @@ def __call__(self, args): else: info.append("#") if args.long: - info.append("({}) {} {}".format(source['kind'], name, source['url'])) + info.append("({}) {} {}".format(source["kind"], name, source["url"])) else: info.append(name) print(" ".join(info)) @@ -476,8 +613,8 @@ class CmdPony(Command): def __init__(self, develop): Command.__init__(self, develop) self.parser = self.develop.parsers.add_parser( - "pony", - description="It should be easy to develop a pony!") + "pony", description="It should be easy to develop a pony!" + ) self.parser.set_defaults(func=self) def __call__(self, args): @@ -502,6 +639,7 @@ def __call__(self, args): `""""` `""""` ;' ''' import time + logger.info("Starting to develop a pony.") for line in pony.split("\n"): time.sleep(0.25) @@ -512,27 +650,39 @@ def __call__(self, args): class CmdPurge(Command): def __init__(self, develop): Command.__init__(self, develop) - description = textwrap.dedent("""\ + description = textwrap.dedent( + """\ Remove checked out packages which aren't active anymore. - Only 'svn' packages can be purged, because other repositories may contain unrecoverable files even when not marked as 'dirty'.""") + Only 'svn' packages can be purged, because other repositories may contain unrecoverable files even when not marked as 'dirty'.""" + ) self.parser = self.develop.parsers.add_parser( - "purge", - formatter_class=HelpFormatter, - description=description) - self.develop.parsers._choices_actions.append(ChoicesPseudoAction( - "purge", help=description)) + "purge", formatter_class=HelpFormatter, description=description + ) + self.develop.parsers._choices_actions.append( + ChoicesPseudoAction("purge", help=description) + ) self.parser.add_argument( - "-n", "--dry-run", dest="dry_run", - action="store_true", default=False, - help="""Don't actually remove anything, just print the paths which would be removed.""") + "-n", + "--dry-run", + dest="dry_run", + action="store_true", + default=False, + help="""Don't actually remove anything, just print the paths which would be removed.""", + ) self.parser.add_argument( - "-f", "--force", dest="force", - action="store_true", default=False, - help="""Force purge even if the working copy is dirty or unknown (non-svn).""") + "-f", + "--force", + dest="force", + action="store_true", + default=False, + help="""Force purge even if the working copy is dirty or unknown (non-svn).""", + ) self.parser.add_argument( - "package-regexp", nargs="*", - help="A regular expression to match package names.") + "package-regexp", + nargs="*", + help="A regular expression to match package names.", + ) self.parser.set_defaults(func=self) def handle_remove_readonly(self, func, path, exc): @@ -545,8 +695,7 @@ def handle_remove_readonly(self, func, path, exc): def __call__(self, args): buildout_dir = self.develop.buildout_dir - packages = self.get_packages(getattr(args, 'package-regexp'), - checked_out=True) + packages = self.get_packages(getattr(args, "package-regexp"), checked_out=True) packages = packages - self.develop.auto_checkout packages = packages - set(self.develop.develeggs) force = args.force @@ -556,16 +705,21 @@ def __call__(self, args): logger.info("Dry run, nothing will be removed.") for name in packages: source = self.develop.sources[name] - path = source['path'] + path = source["path"] if path.startswith(buildout_dir): - path = path[len(buildout_dir) + 1:] + path = path[len(buildout_dir) + 1 :] need_force = False - if source['kind'] != 'svn': + if source["kind"] != "svn": need_force = True - logger.warn(f"The directory of package '{name}' at '{path}' might contain unrecoverable files and will not be removed without --force.") - if workingcopies.status(source) != 'clean': + logger.warn( + f"The directory of package '{name}' at '{path}' might contain unrecoverable files and will not be removed without --force." + ) + if workingcopies.status(source) != "clean": need_force = True - logger.warn("The package '%s' is dirty and will not be removed without --force." % name) + logger.warn( + "The package '%s' is dirty and will not be removed without --force." + % name + ) if need_force: if not force: continue @@ -573,18 +727,22 @@ def __call__(self, args): # have actually added the --force argument on the # command line. if not force_all: - answer = yesno("Do you want to purge it anyway?", default=False, all=True) + answer = yesno( + "Do you want to purge it anyway?", default=False, all=True + ) if not answer: logger.info("Skipped purge of '%s'." % name) continue - if answer == 'all': + if answer == "all": force_all = True logger.info(f"Removing package '{name}' at '{path}'.") if not args.dry_run: - shutil.rmtree(source['path'], - ignore_errors=False, - onerror=self.handle_remove_readonly) + shutil.rmtree( + source["path"], + ignore_errors=False, + onerror=self.handle_remove_readonly, + ) class CmdRebuild(Command): @@ -592,11 +750,14 @@ def __init__(self, develop): Command.__init__(self, develop) description = "Run buildout with the last used arguments." self.parser = self.develop.parsers.add_parser( - "rebuild", - description=description) - self.develop.parsers._name_parser_map["rb"] = self.develop.parsers._name_parser_map["rebuild"] - self.develop.parsers._choices_actions.append(ChoicesPseudoAction( - "rebuild", "rb", help=description)) + "rebuild", description=description + ) + self.develop.parsers._name_parser_map["rb"] = ( + self.develop.parsers._name_parser_map["rebuild"] + ) + self.develop.parsers._choices_actions.append( + ChoicesPseudoAction("rebuild", "rb", help=description) + ) self.parser.set_defaults(func=self) def __call__(self, args): @@ -614,30 +775,47 @@ def __init__(self, develop): self.parser = self.develop.parsers.add_parser( "reset", help="Resets the packages develop status.", - description="Resets the packages develop status. This is useful when switching to a new buildout configuration.") + description="Resets the packages develop status. This is useful when switching to a new buildout configuration.", + ) self.parser.add_argument( - "-a", "--auto-checkout", dest="auto_checkout", - action="store_true", default=False, - help="""Only considers packages declared by auto-checkout. If you don't specify a then all declared packages are processed.""") + "-a", + "--auto-checkout", + dest="auto_checkout", + action="store_true", + default=False, + help="""Only considers packages declared by auto-checkout. If you don't specify a then all declared packages are processed.""", + ) self.parser.add_argument( - "-c", "--checked-out", dest="checked_out", - action="store_true", default=False, - help="""Only considers packages currently checked out. If you don't specify a then all checked out packages are processed.""") + "-c", + "--checked-out", + dest="checked_out", + action="store_true", + default=False, + help="""Only considers packages currently checked out. If you don't specify a then all checked out packages are processed.""", + ) self.parser.add_argument( - "-d", "--develop", dest="develop", - action="store_true", default=False, - help="""Only considers packages currently in development mode. If you don't specify a then all develop packages are processed.""") + "-d", + "--develop", + dest="develop", + action="store_true", + default=False, + help="""Only considers packages currently in development mode. If you don't specify a then all develop packages are processed.""", + ) self.parser.add_argument( - "package-regexp", nargs="*", - help="A regular expression to match package names.") + "package-regexp", + nargs="*", + help="A regular expression to match package names.", + ) self.parser.set_defaults(func=self) def __call__(self, args): config = self.develop.config - packages = self.get_packages(getattr(args, 'package-regexp'), - auto_checkout=args.auto_checkout, - checked_out=args.checked_out, - develop=args.develop) + packages = self.get_packages( + getattr(args, "package-regexp"), + auto_checkout=args.auto_checkout, + checked_out=args.checked_out, + develop=args.develop, + ) changed = False for name in sorted(packages): if name in config.develop: @@ -645,7 +823,9 @@ def __call__(self, args): logger.info("Reset develop state of '%s'." % name) changed = True if changed: - logger.warn("Don't forget to run buildout again, so the deactived packages are actually not used anymore.") + logger.warn( + "Don't forget to run buildout again, so the deactived packages are actually not used anymore." + ) config.save() @@ -655,7 +835,8 @@ def __init__(self, develop): self.parser = self.develop.parsers.add_parser( "status", formatter_class=HelpFormatter, - description=textwrap.dedent("""\ + description=textwrap.dedent( + """\ Shows the status of tracked packages, filtered if is given. The first column in the output shows the checkout status: ' ' in auto-checkout list @@ -672,41 +853,70 @@ def __init__(self, develop): '-' deactivated '!' deactivated, but the package is in the auto-checkout list 'A' activated, but not in list of development packages (run buildout) - 'D' deactivated, but still in list of development packages (run buildout)""")) - self.develop.parsers._name_parser_map["stat"] = self.develop.parsers._name_parser_map["status"] - self.develop.parsers._name_parser_map["st"] = self.develop.parsers._name_parser_map["status"] - self.develop.parsers._choices_actions.append(ChoicesPseudoAction( - "status", "stat", "st", help="Shows the status of tracked packages.")) - self.parser.add_argument( - "-a", "--auto-checkout", dest="auto_checkout", - action="store_true", default=False, - help="""Only considers packages declared by auto-checkout. If you don't specify a then all declared packages are processed.""") - self.parser.add_argument( - "-c", "--checked-out", dest="checked_out", - action="store_true", default=False, - help="""Only considers packages currently checked out. If you don't specify a then all checked out packages are processed.""") - self.parser.add_argument( - "-d", "--develop", dest="develop", - action="store_true", default=False, - help="""Only considers packages currently in development mode. If you don't specify a then all develop packages are processed.""") - self.parser.add_argument( - "-v", "--verbose", dest="verbose", - action="store_true", default=False, - help="""Show output of VCS command.""") - self.parser.add_argument( - "package-regexp", nargs="*", - help="A regular expression to match package names.") + 'D' deactivated, but still in list of development packages (run buildout)""" + ), + ) + self.develop.parsers._name_parser_map["stat"] = ( + self.develop.parsers._name_parser_map["status"] + ) + self.develop.parsers._name_parser_map["st"] = ( + self.develop.parsers._name_parser_map["status"] + ) + self.develop.parsers._choices_actions.append( + ChoicesPseudoAction( + "status", "stat", "st", help="Shows the status of tracked packages." + ) + ) + self.parser.add_argument( + "-a", + "--auto-checkout", + dest="auto_checkout", + action="store_true", + default=False, + help="""Only considers packages declared by auto-checkout. If you don't specify a then all declared packages are processed.""", + ) + self.parser.add_argument( + "-c", + "--checked-out", + dest="checked_out", + action="store_true", + default=False, + help="""Only considers packages currently checked out. If you don't specify a then all checked out packages are processed.""", + ) + self.parser.add_argument( + "-d", + "--develop", + dest="develop", + action="store_true", + default=False, + help="""Only considers packages currently in development mode. If you don't specify a then all develop packages are processed.""", + ) + self.parser.add_argument( + "-v", + "--verbose", + dest="verbose", + action="store_true", + default=False, + help="""Show output of VCS command.""", + ) + self.parser.add_argument( + "package-regexp", + nargs="*", + help="A regular expression to match package names.", + ) self.parser.set_defaults(func=self) def __call__(self, args): auto_checkout = self.develop.auto_checkout sources_dir = self.develop.sources_dir develeggs = self.develop.develeggs - package_regexp = getattr(args, 'package-regexp') - packages = self.get_packages(package_regexp, - auto_checkout=args.auto_checkout, - checked_out=args.checked_out, - develop=args.develop) + package_regexp = getattr(args, "package-regexp") + packages = self.get_packages( + package_regexp, + auto_checkout=args.auto_checkout, + checked_out=args.checked_out, + develop=args.develop, + ) workingcopies = self.get_workingcopies(self.develop.sources) paths = [] for name in sorted(packages): @@ -715,7 +925,7 @@ def __call__(self, args): if name in auto_checkout: print("! %s" % name) continue - paths.append(source['path']) + paths.append(source["path"]) info = [] if not workingcopies.matches(source): info.append("C") @@ -728,9 +938,9 @@ def __call__(self, args): status, output = workingcopies.status(source, verbose=True) else: status = workingcopies.status(source) - if status == 'clean': + if status == "clean": info.append(" ") - elif status == 'ahead': + elif status == "ahead": info.append(">") else: info.append("M") @@ -738,20 +948,20 @@ def __call__(self, args): if name in develeggs: info.append(" ") else: - if source.get('egg', True): + if source.get("egg", True): info.append("A") else: info.append(" ") else: if name not in develeggs: - if not source.get('egg', True): + if not source.get("egg", True): info.append(" ") elif name in auto_checkout: info.append("!") else: info.append("-") else: - if source.get('egg', True): + if source.get("egg", True): info.append("D") else: info.append(" ") @@ -759,10 +969,10 @@ def __call__(self, args): print(" ".join(info)) if args.verbose: if isinstance(output, bytes): - output = output.decode('utf8') + output = output.decode("utf8") output = output.strip() if output: - for line in output.split('\n'): + for line in output.split("\n"): print(" %s" % line) print() @@ -777,42 +987,65 @@ class CmdUpdate(Command): def __init__(self, develop): Command.__init__(self, develop) description = "Updates all known packages currently checked out." - self.parser = self.develop.parsers.add_parser( - "update", - description=description) - self.develop.parsers._name_parser_map["up"] = self.develop.parsers._name_parser_map["update"] - self.develop.parsers._choices_actions.append(ChoicesPseudoAction( - "update", "up", help=description)) - self.parser.add_argument( - "-a", "--auto-checkout", dest="auto_checkout", - action="store_true", default=False, - help="""Only considers packages declared by auto-checkout. If you don't specify a then all declared packages are processed.""") - self.parser.add_argument( - "-d", "--develop", dest="develop", - action="store_true", default=False, - help="""Only considers packages currently in development mode. If you don't specify a then all develop packages are processed.""") - self.parser.add_argument( - "-f", "--force", dest="force", - action="store_true", default=False, - help="""Force update even if the working copy is dirty.""") - self.parser.add_argument( - "-v", "--verbose", dest="verbose", - action="store_true", default=False, - help="""Show output of VCS command.""") - self.parser.add_argument( - "package-regexp", nargs="*", - help="A regular expression to match package names.") + self.parser = self.develop.parsers.add_parser("update", description=description) + self.develop.parsers._name_parser_map["up"] = ( + self.develop.parsers._name_parser_map["update"] + ) + self.develop.parsers._choices_actions.append( + ChoicesPseudoAction("update", "up", help=description) + ) + self.parser.add_argument( + "-a", + "--auto-checkout", + dest="auto_checkout", + action="store_true", + default=False, + help="""Only considers packages declared by auto-checkout. If you don't specify a then all declared packages are processed.""", + ) + self.parser.add_argument( + "-d", + "--develop", + dest="develop", + action="store_true", + default=False, + help="""Only considers packages currently in development mode. If you don't specify a then all develop packages are processed.""", + ) + self.parser.add_argument( + "-f", + "--force", + dest="force", + action="store_true", + default=False, + help="""Force update even if the working copy is dirty.""", + ) + self.parser.add_argument( + "-v", + "--verbose", + dest="verbose", + action="store_true", + default=False, + help="""Show output of VCS command.""", + ) + self.parser.add_argument( + "package-regexp", + nargs="*", + help="A regular expression to match package names.", + ) self.parser.set_defaults(func=self) def __call__(self, args): - packages = self.get_packages(getattr(args, 'package-regexp'), - auto_checkout=args.auto_checkout, - checked_out=True, - develop=args.develop) + packages = self.get_packages( + getattr(args, "package-regexp"), + auto_checkout=args.auto_checkout, + checked_out=True, + develop=args.develop, + ) workingcopies = self.get_workingcopies(self.develop.sources) force = args.force or self.develop.always_checkout - workingcopies.update(sorted(packages), - force=force, - verbose=args.verbose, - submodules=self.develop.update_git_submodules, - always_accept_server_certificate=self.develop.always_accept_server_certificate) + workingcopies.update( + sorted(packages), + force=force, + verbose=args.verbose, + submodules=self.develop.update_git_submodules, + always_accept_server_certificate=self.develop.always_accept_server_certificate, + ) diff --git a/src/mr/developer/common.py b/src/mr/developer/common.py index 6c1f8f3e..6cf07a1d 100644 --- a/src/mr/developer/common.py +++ b/src/mr/developer/common.py @@ -14,7 +14,7 @@ def print_stderr(s): sys.stderr.write(s) - sys.stderr.write('\n') + sys.stderr.write("\n") sys.stderr.flush() @@ -24,11 +24,11 @@ def which(name_root, default=None): def is_exe(fpath): return os.path.exists(fpath) and os.access(fpath, os.X_OK) - if platform.system() == 'Windows': + if platform.system() == "Windows": # http://www.voidspace.org.uk/python/articles/command_line.shtml#pathext - pathext = os.environ['PATHEXT'] + pathext = os.environ["PATHEXT"] # example: ['.py', '.pyc', '.pyo', '.pyw', '.COM', '.EXE', '.BAT', '.CMD'] - names = [name_root + ext for ext in pathext.split(';')] + names = [name_root + ext for ext in pathext.split(";")] else: names = [name_root] @@ -52,7 +52,7 @@ def version_sorted(inp, *args, **kwargs): Eg.: version-1-0-1 < version-1-0-2 < version-1-0-10 """ - num_reg = re.compile(r'([0-9]+)') + num_reg = re.compile(r"([0-9]+)") def int_str(val): try: @@ -64,7 +64,7 @@ def split_item(item): return tuple([int_str(j) for j in num_reg.split(item)]) def join_item(item): - return ''.join([str(j) for j in item]) + return "".join([str(j) for j in item]) output = [split_item(i) for i in inp] return [join_item(i) for i in sorted(output, *args, **kwargs)] @@ -72,17 +72,18 @@ def join_item(item): def memoize(f, _marker=[]): def g(*args, **kwargs): - name = '_memoize_%s' % f.__name__ + name = "_memoize_%s" % f.__name__ value = getattr(args[0], name, _marker) if value is _marker: value = f(*args, **kwargs) setattr(args[0], name, value) return value + return g class WCError(Exception): - """ A working copy error. """ + """A working copy error.""" class BaseWorkingCopy: @@ -92,14 +93,14 @@ def __init__(self, source): self.source = source def should_update(self, **kwargs): - offline = kwargs.get('offline', False) + offline = kwargs.get("offline", False) if offline: return False - update = self.source.get('update', kwargs.get('update', False)) + update = self.source.get("update", kwargs.get("update", False)) if not isinstance(update, bool): - if update.lower() in ('true', 'yes'): + if update.lower() in ("true", "yes"): update = True - elif update.lower() in ('false', 'no'): + elif update.lower() in ("false", "no"): update = False else: raise ValueError("Unknown value for 'update': %s" % update) @@ -110,17 +111,17 @@ def yesno(question, default=True, all=True): if default: question = "%s [Yes/no" % question answers = { - False: ('n', 'no'), - True: ('', 'y', 'yes'), + False: ("n", "no"), + True: ("", "y", "yes"), } else: question = "%s [yes/No" % question answers = { - False: ('', 'n', 'no'), - True: ('y', 'yes'), + False: ("", "n", "no"), + True: ("y", "yes"), } if all: - answers['all'] = ('a', 'all') + answers["all"] = ("a", "all") question = "%s/all] " % question else: question = "%s] " % question @@ -152,7 +153,7 @@ def worker(working_copies, the_queue): output_lock.acquire() for lvl, msg in wc._output: lvl(msg) - for line in sys.exc_info()[1].args[0].split('\n'): + for line in sys.exc_info()[1].args[0].split("\n"): logger.error(line) working_copies.errors = True output_lock.release() @@ -169,12 +170,12 @@ def worker(working_copies, the_queue): # then all messages are joined. for item in wc._output: lvl = item[0] - msg = ','.join(item[1:]) + msg = ",".join(item[1:]) lvl(msg) - if kwargs.get('verbose', False) and output is not None and output.strip(): + if kwargs.get("verbose", False) and output is not None and output.strip(): if isinstance(output, bytes): - output = output.decode('utf8') + output = output.decode("utf8") print(output) output_lock.release() @@ -186,19 +187,26 @@ def get_workingcopytypes(): global _workingcopytypes if _workingcopytypes is not None: return _workingcopytypes - group = 'mr.developer.workingcopytypes' + group = "mr.developer.workingcopytypes" _workingcopytypes = {} addons = {} for entrypoint in pkg_resources.iter_entry_points(group=group): key = entrypoint.name workingcopytype = entrypoint.load() - if entrypoint.dist.project_name == 'mr.developer': + if entrypoint.dist.project_name == "mr.developer": _workingcopytypes[key] = workingcopytype else: if key in addons: - logger.error("There already is a working copy type addon registered for '%s'.", key) + logger.error( + "There already is a working copy type addon registered for '%s'.", + key, + ) sys.exit(1) - logger.info("Overwriting '%s' with addon from '%s'.", key, entrypoint.dist.project_name) + logger.info( + "Overwriting '%s' with addon from '%s'.", + key, + entrypoint.dist.project_name, + ) addons[key] = workingcopytype _workingcopytypes.update(addons) return _workingcopytypes @@ -206,19 +214,24 @@ def get_workingcopytypes(): def get_commands(): commands = {} - group = 'mr.developer.commands' + group = "mr.developer.commands" addons = {} for entrypoint in pkg_resources.iter_entry_points(group=group): key = entrypoint.name command = entrypoint.load() - if entrypoint.dist.project_name == 'mr.developer': + if entrypoint.dist.project_name == "mr.developer": commands[key] = command else: if key in addons: - logger.error('There already is a command addon registered for "%s".', key) + logger.error( + 'There already is a command addon registered for "%s".', key + ) sys.exit(1) - logger.info('Overwriting "%s" with addon from "%s".', - key, entrypoint.dist.project_name) + logger.info( + 'Overwriting "%s" with addon from "%s".', + key, + entrypoint.dist.project_name, + ) addons[key] = command commands.update(addons) return commands.values() @@ -250,23 +263,28 @@ def process(self, the_queue): def checkout(self, packages, **kwargs): the_queue = queue.Queue() - if 'update' in kwargs: - if isinstance(kwargs['update'], bool): + if "update" in kwargs: + if isinstance(kwargs["update"], bool): pass - elif kwargs['update'].lower() in ('true', 'yes', 'on', 'force'): - if kwargs['update'].lower() == 'force': - kwargs['force'] = True - kwargs['update'] = True - elif kwargs['update'].lower() in ('false', 'no', 'off'): - kwargs['update'] = False + elif kwargs["update"].lower() in ("true", "yes", "on", "force"): + if kwargs["update"].lower() == "force": + kwargs["force"] = True + kwargs["update"] = True + elif kwargs["update"].lower() in ("false", "no", "off"): + kwargs["update"] = False else: - logger.error("Unknown value '%s' for always-checkout option." % kwargs['update']) + logger.error( + "Unknown value '%s' for always-checkout option." % kwargs["update"] + ) sys.exit(1) - kwargs.setdefault('submodules', 'always') - if kwargs['submodules'] in ['always', 'never', 'checkout']: + kwargs.setdefault("submodules", "always") + if kwargs["submodules"] in ["always", "never", "checkout"]: pass else: - logger.error("Unknown value '%s' for update-git-submodules option." % kwargs['submodules']) + logger.error( + "Unknown value '%s' for update-git-submodules option." + % kwargs["submodules"] + ) sys.exit(1) for name in packages: kw = kwargs.copy() @@ -274,7 +292,7 @@ def checkout(self, packages, **kwargs): logger.error("Checkout failed. No source defined for '%s'." % name) sys.exit(1) source = self.sources[name] - kind = source['kind'] + kind = source["kind"] wc = self.workingcopytypes.get(kind)(source) if wc is None: logger.error("Unknown repository type '%s'." % kind) @@ -282,16 +300,18 @@ def checkout(self, packages, **kwargs): update = wc.should_update(**kwargs) if not source.exists(): pass - elif os.path.islink(source['path']): + elif os.path.islink(source["path"]): logger.info("Skipped update of linked '%s'." % name) continue - elif update and wc.status() != 'clean' and not kw.get('force', False): + elif update and wc.status() != "clean" and not kw.get("force", False): print_stderr("The package '%s' is dirty." % name) - answer = yesno("Do you want to update it anyway?", default=False, all=True) + answer = yesno( + "Do you want to update it anyway?", default=False, all=True + ) if answer: - kw['force'] = True - if answer == 'all': - kwargs['force'] = True + kw["force"] = True + if answer == "all": + kwargs["force"] = True else: logger.info("Skipped update of '%s'." % name) continue @@ -300,38 +320,38 @@ def checkout(self, packages, **kwargs): self.process(the_queue) def matches(self, source): - name = source['name'] + name = source["name"] if name not in self.sources: logger.error("Checkout failed. No source defined for '%s'." % name) sys.exit(1) source = self.sources[name] try: - kind = source['kind'] + kind = source["kind"] wc = self.workingcopytypes.get(kind)(source) if wc is None: logger.error("Unknown repository type '%s'." % kind) sys.exit(1) return wc.matches() except WCError: - for line in sys.exc_info()[1].args[0].split('\n'): + for line in sys.exc_info()[1].args[0].split("\n"): logger.error(line) sys.exit(1) def status(self, source, **kwargs): - name = source['name'] + name = source["name"] if name not in self.sources: logger.error("Status failed. No source defined for '%s'." % name) sys.exit(1) source = self.sources[name] try: - kind = source['kind'] + kind = source["kind"] wc = self.workingcopytypes.get(kind)(source) if wc is None: logger.error("Unknown repository type '%s'." % kind) sys.exit(1) return wc.status(**kwargs) except WCError: - for line in sys.exc_info()[1].args[0].split('\n'): + for line in sys.exc_info()[1].args[0].split("\n"): logger.error(line) sys.exit(1) @@ -342,18 +362,20 @@ def update(self, packages, **kwargs): if name not in self.sources: continue source = self.sources[name] - kind = source['kind'] + kind = source["kind"] wc = self.workingcopytypes.get(kind)(source) if wc is None: logger.error("Unknown repository type '%s'." % kind) sys.exit(1) - if wc.status() != 'clean' and not kw.get('force', False): + if wc.status() != "clean" and not kw.get("force", False): print_stderr("The package '%s' is dirty." % name) - answer = yesno("Do you want to update it anyway?", default=False, all=True) + answer = yesno( + "Do you want to update it anyway?", default=False, all=True + ) if answer: - kw['force'] = True - if answer == 'all': - kwargs['force'] = True + kw["force"] = True + if answer == "all": + kwargs["force"] = True else: logger.info("Skipped update of '%s'." % name) continue @@ -364,7 +386,7 @@ def update(self, packages, **kwargs): def parse_buildout_args(args): settings = dict( - config_file='buildout.cfg', + config_file="buildout.cfg", verbosity=0, options=[], windows_restart=False, @@ -373,72 +395,76 @@ def parse_buildout_args(args): ) options = [] version = pkg_resources.get_distribution("zc.buildout").version - if tuple(version.split('.')[:2]) <= ('1', '4'): - option_str = 'vqhWUoOnNDA' + if tuple(version.split(".")[:2]) <= ("1", "4"): + option_str = "vqhWUoOnNDA" else: - option_str = 'vqhWUoOnNDAs' + option_str = "vqhWUoOnNDAs" while args: - if args[0][0] == '-': + if args[0][0] == "-": op = orig_op = args.pop(0) op = op[1:] while op and op[0] in option_str: - if op[0] == 'v': - settings['verbosity'] = settings['verbosity'] + 10 - elif op[0] == 'q': - settings['verbosity'] = settings['verbosity'] - 10 - elif op[0] == 'W': - settings['windows_restart'] = True - elif op[0] == 'U': - settings['user_defaults'] = False - elif op[0] == 'o': - options.append(('buildout', 'offline', 'true')) - elif op[0] == 'O': - options.append(('buildout', 'offline', 'false')) - elif op[0] == 'n': - options.append(('buildout', 'newest', 'true')) - elif op[0] == 'N': - options.append(('buildout', 'newest', 'false')) - elif op[0] == 'D': - settings['debug'] = True - elif op[0] == 's': - settings['ignore_broken_dash_s'] = True + if op[0] == "v": + settings["verbosity"] = settings["verbosity"] + 10 + elif op[0] == "q": + settings["verbosity"] = settings["verbosity"] - 10 + elif op[0] == "W": + settings["windows_restart"] = True + elif op[0] == "U": + settings["user_defaults"] = False + elif op[0] == "o": + options.append(("buildout", "offline", "true")) + elif op[0] == "O": + options.append(("buildout", "offline", "false")) + elif op[0] == "n": + options.append(("buildout", "newest", "true")) + elif op[0] == "N": + options.append(("buildout", "newest", "false")) + elif op[0] == "D": + settings["debug"] = True + elif op[0] == "s": + settings["ignore_broken_dash_s"] = True else: raise ValueError("Unkown option '%s'." % op[0]) op = op[1:] - if op[:1] in ('c', 't'): + if op[:1] in ("c", "t"): op_ = op[:1] op = op[1:] - if op_ == 'c': + if op_ == "c": if op: - settings['config_file'] = op + settings["config_file"] = op else: if args: - settings['config_file'] = args.pop(0) + settings["config_file"] = args.pop(0) else: - raise ValueError("No file name specified for option", orig_op) - elif op_ == 't': + raise ValueError( + "No file name specified for option", orig_op + ) + elif op_ == "t": try: int(args.pop(0)) except IndexError: - raise ValueError("No timeout value specified for option", orig_op) + raise ValueError( + "No timeout value specified for option", orig_op + ) except ValueError: raise ValueError("No timeout value must be numeric", orig_op) - settings['socket_timeout'] = op + settings["socket_timeout"] = op elif op: - if orig_op == '--help': - return 'help' - raise ValueError("Invalid option", '-' + op[0]) - elif '=' in args[0]: - option, value = args.pop(0).split('=', 1) - parts = option.split(':') + if orig_op == "--help": + return "help" + raise ValueError("Invalid option", "-" + op[0]) + elif "=" in args[0]: + option, value = args.pop(0).split("=", 1) + parts = option.split(":") if len(parts) == 2: section, option = parts elif len(parts) == 1: - section = 'buildout' + section = "buildout" else: - raise ValueError('Invalid option:', option) + raise ValueError("Invalid option:", option) options.append((section.strip(), option.strip(), value.strip())) else: # We've run out of command-line options and option assignnemnts @@ -451,7 +477,7 @@ class Rewrite: _matcher = re.compile(r"(?P