From 94b696f983a2519e3940faed4546449063c79818 Mon Sep 17 00:00:00 2001 From: Maurits van Rees Date: Thu, 20 Aug 2026 12:47:59 +0200 Subject: [PATCH 1/7] Get own version using importlib.metadata. --- src/mr/developer/develop.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mr/developer/develop.py b/src/mr/developer/develop.py index 7feb851..f1c3757 100644 --- a/src/mr/developer/develop.py +++ b/src/mr/developer/develop.py @@ -7,9 +7,9 @@ import argparse import atexit +import importlib.metadata import logging import os -import pkg_resources import sys import textwrap @@ -60,7 +60,7 @@ def __call__(self, *args, **kwargs): ch.setFormatter(logging.Formatter("%(levelname)s: %(message)s")) logger.addHandler(ch) self.parser = ArgumentParser() - version = pkg_resources.get_distribution("mr.developer").version + version = importlib.metadata.version("mr.developer") self.parser.add_argument( "-v", "--version", action="version", version="mr.developer %s" % version ) From 020b8f6948db38a70b9cff32122c46991be2372e Mon Sep 17 00:00:00 2001 From: Maurits van Rees Date: Thu, 20 Aug 2026 12:53:17 +0200 Subject: [PATCH 2/7] Require zc.buildout 3.0.0 or higher. Got rid of code that tried to support `zc.buildout` 1.4. --- CHANGES.rst | 2 ++ setup.py | 2 +- src/mr/developer/common.py | 6 +----- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 6976bcd..316298e 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -5,6 +5,8 @@ Changelog 3.0.0 (unreleased) ------------------ +- Require ``zc.buildout`` 3.0.0 or higher. [maurits] + - Add support for Python 3.14 and 3.15. [maurits] - Require Python 3.10 or higher. [maurits] diff --git a/setup.py b/setup.py index 4fd426a..1ef03b5 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ install_requires = [ "setuptools", - "zc.buildout", + "zc.buildout>=3.0.0", ] tests_require = ["mock"] diff --git a/src/mr/developer/common.py b/src/mr/developer/common.py index 80880e6..b247123 100644 --- a/src/mr/developer/common.py +++ b/src/mr/developer/common.py @@ -394,11 +394,7 @@ def parse_buildout_args(args): debug=False, ) options = [] - version = pkg_resources.get_distribution("zc.buildout").version - if tuple(version.split(".")[:2]) <= ("1", "4"): - option_str = "vqhWUoOnNDA" - else: - option_str = "vqhWUoOnNDAs" + option_str = "vqhWUoOnNDAs" while args: if args[0][0] == "-": op = orig_op = args.pop(0) From b20eefa55c1bba1a69d44fc8810178a2471f3cab Mon Sep 17 00:00:00 2001 From: Maurits van Rees Date: Thu, 20 Aug 2026 13:03:39 +0200 Subject: [PATCH 3/7] Get entrypoints using importlib.metadata. --- CHANGES.rst | 2 ++ src/mr/developer/common.py | 14 +++++++------- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 316298e..0de6b1b 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -5,6 +5,8 @@ Changelog 3.0.0 (unreleased) ------------------ +- Replace our use of ``pkg_resources`` with ``importlib.metadata``. [maurits] + - Require ``zc.buildout`` 3.0.0 or higher. [maurits] - Add support for Python 3.14 and 3.15. [maurits] diff --git a/src/mr/developer/common.py b/src/mr/developer/common.py index b247123..54f8851 100644 --- a/src/mr/developer/common.py +++ b/src/mr/developer/common.py @@ -1,8 +1,8 @@ from configparser import RawConfigParser +from importlib.metadata import entry_points import logging import os -import pkg_resources import platform import queue import re @@ -190,10 +190,10 @@ def get_workingcopytypes(): group = "mr.developer.workingcopytypes" _workingcopytypes = {} addons = {} - for entrypoint in pkg_resources.iter_entry_points(group=group): + for entrypoint in entry_points().select(group=group): key = entrypoint.name workingcopytype = entrypoint.load() - if entrypoint.dist.project_name == "mr.developer": + if entrypoint.dist.name == "mr.developer": _workingcopytypes[key] = workingcopytype else: if key in addons: @@ -205,7 +205,7 @@ def get_workingcopytypes(): logger.info( "Overwriting '%s' with addon from '%s'.", key, - entrypoint.dist.project_name, + entrypoint.dist.name, ) addons[key] = workingcopytype _workingcopytypes.update(addons) @@ -216,10 +216,10 @@ def get_commands(): commands = {} group = "mr.developer.commands" addons = {} - for entrypoint in pkg_resources.iter_entry_points(group=group): + for entrypoint in entry_points().select(group=group): key = entrypoint.name command = entrypoint.load() - if entrypoint.dist.project_name == "mr.developer": + if entrypoint.dist.name == "mr.developer": commands[key] = command else: if key in addons: @@ -230,7 +230,7 @@ def get_commands(): logger.info( 'Overwriting "%s" with addon from "%s".', key, - entrypoint.dist.project_name, + entrypoint.dist.name, ) addons[key] = command commands.update(addons) From e837bd796632e2b4e31c2f113533f2f479d61b23 Mon Sep 17 00:00:00 2001 From: Maurits van Rees Date: Thu, 20 Aug 2026 13:14:42 +0200 Subject: [PATCH 4/7] Move to PEP-420 native namespaces. --- CHANGES.rst | 2 ++ setup.py | 4 ---- src/mr/__init__.py | 7 ------- src/mr/developer/__init__.py | 7 ------- 4 files changed, 2 insertions(+), 18 deletions(-) delete mode 100644 src/mr/__init__.py delete mode 100644 src/mr/developer/__init__.py diff --git a/CHANGES.rst b/CHANGES.rst index 0de6b1b..c5bbbd2 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -5,6 +5,8 @@ Changelog 3.0.0 (unreleased) ------------------ +- Move to PEP-420 native namespaces. [maurits] + - Replace our use of ``pkg_resources`` with ``importlib.metadata``. [maurits] - Require ``zc.buildout`` 3.0.0 or higher. [maurits] diff --git a/setup.py b/setup.py index 1ef03b5..0308b5d 100644 --- a/setup.py +++ b/setup.py @@ -4,7 +4,6 @@ install_requires = [ - "setuptools", "zc.buildout>=3.0.0", ] @@ -48,9 +47,6 @@ def get_text_from_file(fn): 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, diff --git a/src/mr/__init__.py b/src/mr/__init__.py deleted file mode 100644 index 05f0beb..0000000 --- a/src/mr/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages -try: - __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 deleted file mode 100644 index 05f0beb..0000000 --- a/src/mr/developer/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages -try: - __import__("pkg_resources").declare_namespace(__name__) -except ImportError: - from pkgutil import extend_path - - __path__ = extend_path(__path__, __name__) From 16775bedc858e1d0a239594b775e696bf844adcd Mon Sep 17 00:00:00 2001 From: Maurits van Rees Date: Thu, 20 Aug 2026 13:16:42 +0200 Subject: [PATCH 5/7] Remove ancient tests_requires and test_suite from setup.py. Move the remaining requirements inline, instead of defining them above the setup call. --- setup.py | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/setup.py b/setup.py index 0308b5d..d04e363 100644 --- a/setup.py +++ b/setup.py @@ -3,15 +3,6 @@ version = "3.0.0.dev0" -install_requires = [ - "zc.buildout>=3.0.0", -] - -tests_require = ["mock"] - -extras_require = {"test": tests_require} - - def get_text_from_file(fn): text = open(fn, "rb").read() return text.decode("utf-8") @@ -49,11 +40,11 @@ def get_text_from_file(fn): license="BSD", include_package_data=True, zip_safe=False, - install_requires=install_requires, - tests_require=tests_require, - extras_require=extras_require, + install_requires=[ + "zc.buildout>=3.0.0", + ], + extras_require={"test": "mock"}, python_requires=">=3.10", - test_suite="mr.developer.tests", entry_points=""" [console_scripts] develop = mr.developer.develop:develop From 1a7778de94cc9631be3ff4923734e9eb7d2270b9 Mon Sep 17 00:00:00 2001 From: Maurits van Rees Date: Thu, 20 Aug 2026 13:17:51 +0200 Subject: [PATCH 6/7] Remove Python 2.7 configparser env from tox.ini. --- tox.ini | 1 - 1 file changed, 1 deletion(-) diff --git a/tox.ini b/tox.ini index d58a9b1..9db4aea 100644 --- a/tox.ini +++ b/tox.ini @@ -12,7 +12,6 @@ commands = py.test --cov {envsitepackagesdir}/mr/developer --cov-report=term --c deps = {[base]deps} pytest-cov - configparser: configparser [testenv:lint] From 82b7369ca5537f80b6f3c718d85a3c9077760e54 Mon Sep 17 00:00:00 2001 From: Maurits van Rees Date: Thu, 20 Aug 2026 13:33:06 +0200 Subject: [PATCH 7/7] When bin/develop is called without arguments, show the help text. This is instead of an ugly error: ``` $ bin/develop Traceback (most recent call last): File "/Users/maurits/community/plone-coredev/6.1/bin/develop", line 15, in sys.exit(mr.developer.develop.develop()) File "/Users/maurits/shared-eggs/cp310/mr.developer-2.0.4-py3.10.egg/mr/developer/develop.py", line 103, in __call__ args.func(args) AttributeError: 'Namespace' object has no attribute 'func' ``` --- CHANGES.rst | 3 +++ src/mr/developer/develop.py | 9 +++++++++ 2 files changed, 12 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index c5bbbd2..2ec67e6 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -5,6 +5,9 @@ Changelog 3.0.0 (unreleased) ------------------ +- When ``bin/develop`` is called without arguments, show the help text instead of an ugly error. + [maurits] + - Move to PEP-420 native namespaces. [maurits] - Replace our use of ``pkg_resources`` with ``importlib.metadata``. [maurits] diff --git a/src/mr/developer/develop.py b/src/mr/developer/develop.py index f1c3757..c5a2761 100644 --- a/src/mr/developer/develop.py +++ b/src/mr/developer/develop.py @@ -73,6 +73,15 @@ def __call__(self, *args, **kwargs): args = None args = self.parser.parse_args(args) + # When you call `bin/develop` without any arguments, you will get an + # error later on because we call `args.func` and there is no `func`: + # AttributeError: 'Namespace' object has no attribute 'func' + if not hasattr(args, "func"): + # So pretend the user has asked for the help function. + args = self.parser.parse_args(["help"]) + args.func(args) + return + try: self.buildout_dir = find_base() except OSError: