Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-lazr.delegates for 
openSUSE:Factory checked in at 2026-09-28 10:38:59
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-lazr.delegates (Old)
 and      /work/SRC/openSUSE:Factory/.python-lazr.delegates.new.383539 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-lazr.delegates"

Mon Sep 28 10:38:59 2026 rev:5 rq:1380287 version:4.0.0

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/python-lazr.delegates/python-lazr.delegates.changes  
    2026-03-11 20:53:52.750381228 +0100
+++ 
/work/SRC/openSUSE:Factory/.python-lazr.delegates.new.383539/python-lazr.delegates.changes
  2026-09-28 10:40:15.733390704 +0200
@@ -1,0 +2,10 @@
+Fri Sep 25 02:45:10 UTC 2026 - Steve Kowalik <[email protected]>
+
+- Update to 4.0.0:
+  * Replace pkg_resources namespace with a PEP 420 native namespace.
+  * Consolidate packaging into a single pyproject.toml (remove setup.py,
+    setup.cfg).
+  * Add support for Python 3.14.
+  * Update security auditing and linting.
+
+-------------------------------------------------------------------

Old:
----
  lazr_delegates-2.1.1.tar.gz

New:
----
  lazr_delegates-4.0.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-lazr.delegates.spec ++++++
--- /var/tmp/diff_new_pack.T2mB0j/_old  2026-09-28 10:40:16.262412887 +0200
+++ /var/tmp/diff_new_pack.T2mB0j/_new  2026-09-28 10:40:16.266413055 +0200
@@ -18,7 +18,7 @@
 
 %{?sle15_python_module_pythons}
 Name:           python-lazr.delegates
-Version:        2.1.1
+Version:        4.0.0
 Release:        0
 Summary:        Easily write objects that delegate behavior
 License:        LGPL-3.0-only
@@ -44,7 +44,6 @@
 %setup -q -n lazr_delegates-%{version}
 
 %build
-sed -i "/'nose'/d" setup.py
 %pyproject_wheel
 
 %install
@@ -59,6 +58,5 @@
 %license COPYING.txt
 %dir %{python_sitelib}/lazr
 %{python_sitelib}/lazr/delegates
-%{python_sitelib}/lazr[._]delegates-%{version}*-info
-%{python_sitelib}/lazr[._]delegates-%{version}*nspkg.pth
+%{python_sitelib}/lazr[._]delegates-%{version}.dist-info
 

++++++ lazr_delegates-2.1.1.tar.gz -> lazr_delegates-4.0.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lazr_delegates-2.1.1/.flake8 
new/lazr_delegates-4.0.0/.flake8
--- old/lazr_delegates-2.1.1/.flake8    1970-01-01 01:00:00.000000000 +0100
+++ new/lazr_delegates-4.0.0/.flake8    2026-08-01 20:49:21.000000000 +0200
@@ -0,0 +1,5 @@
+[flake8]
+ignore =
+    # Incompatible with Black.
+    E203,
+    W503
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lazr_delegates-2.1.1/.launchpad.yaml 
new/lazr_delegates-4.0.0/.launchpad.yaml
--- old/lazr_delegates-2.1.1/.launchpad.yaml    2024-12-04 21:37:08.000000000 
+0100
+++ new/lazr_delegates-4.0.0/.launchpad.yaml    2026-08-01 20:49:21.000000000 
+0200
@@ -1,9 +1,66 @@
 pipeline:
-    - test
+  - test-focal
+  - test-jammy
+  - test-noble
+  # - test-resolute
+  - lint
+  - docs
+  - audit
 
 jobs:
-    test:
-        series: focal
-        architectures: amd64
-        packages: [git]
-        plugin: tox
+  # focal's apt tox (3.13.2) cannot build a pyproject-only sdist
+  # ("error: option --formats not recognized"), so install a modern tox in a
+  # throwaway venv. skip_install envs (lint/docs/audit on noble) are 
unaffected.
+  test-focal:
+    series: focal
+    architectures: amd64
+    packages: [git, python3-venv, python3.9]
+    run: |
+      python3 -m venv /tmp/tox
+      /tmp/tox/bin/pip install --upgrade pip
+      # 4.26.0 dropped Python 3.8 (which runs this venv); 4.25.0 is the newest
+      # tox that still runs on 3.8. focal ships both 3.8 (default) and 3.9.
+      /tmp/tox/bin/pip install "tox<4.26"
+      /tmp/tox/bin/tox -e py38,py39
+
+  test-jammy:
+    series: jammy
+    architectures: amd64
+    packages: [git, python3-venv, python3.11]
+    # jammy's apt tox (3.x) also cannot build a pyproject-only sdist, so use a
+    # throwaway venv with a modern tox. jammy ships both 3.10 (default) and 
3.11.
+    run: |
+      python3 -m venv /tmp/tox
+      /tmp/tox/bin/pip install --upgrade pip
+      /tmp/tox/bin/pip install tox
+      /tmp/tox/bin/tox -e py310,py311
+
+  test-noble:
+    series: noble
+    architectures: amd64
+    packages: [git, tox]
+    run: tox -e py312
+
+  test-resolute:
+    series: resolute
+    architectures: amd64
+    packages: [git, tox]
+    run: tox -e py314
+
+  lint:
+    series: noble  # align with Python versions used in tox configuration
+    architectures: amd64
+    packages: [tox, git]
+    run: tox -e lint
+
+  docs:
+    series: noble  # align with Python versions used in tox configuration
+    architectures: amd64
+    packages: [tox, git]
+    run: tox -e docs
+
+  audit:
+    series: noble  # align with Python versions used in tox configuration
+    architectures: amd64
+    packages: [tox, git]
+    run: tox -e audit
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lazr_delegates-2.1.1/.pre-commit-config.yaml 
new/lazr_delegates-4.0.0/.pre-commit-config.yaml
--- old/lazr_delegates-2.1.1/.pre-commit-config.yaml    2024-12-05 
13:31:31.000000000 +0100
+++ new/lazr_delegates-4.0.0/.pre-commit-config.yaml    2026-08-01 
20:49:21.000000000 +0200
@@ -2,21 +2,40 @@
 # See https://pre-commit.com/hooks.html for more hooks
 repos:
 -   repo: https://github.com/pre-commit/pre-commit-hooks
-    rev: v5.0.0
+    rev: v6.0.0
     hooks:
     -   id: check-added-large-files
-    -   id: check-ast
-    -   id: end-of-file-fixer
-    -   id: check-json
     -   id: check-merge-conflict
     -   id: check-xml
     -   id: check-yaml
     -   id: debug-statements
--   repo: https://github.com/get-woke/woke
-    rev: v0.19.0
+-   repo: https://github.com/PyCQA/isort
+    rev: 9.0.0a3
     hooks:
-    -   id: woke-from-source
+    -   id: isort
+-   repo: https://github.com/PyCQA/flake8
+    rev: 7.3.0
+    hooks:
+    -   id: flake8
 -   repo: https://github.com/asottile/pyupgrade
-    rev: v3.19.0
+    rev: v3.21.2
     hooks:
     -   id: pyupgrade
+-   repo: https://github.com/mgedmin/check-manifest
+    rev: "0.51"
+    hooks:
+    -   id: check-manifest
+-   repo: https://github.com/psf/black
+    rev: 26.5.1
+    hooks:
+    -   id: black
+-   repo: https://github.com/PyCQA/bandit
+    rev: 1.9.4
+    hooks:
+    -   id: bandit
+        args: ["--severity-level", "high"]
+-   repo: https://github.com/pypa/pip-audit
+    rev: v2.10.1
+    hooks:
+    -   id: pip-audit
+        additional_dependencies: ["pip>=26.1.2"]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lazr_delegates-2.1.1/.woke.yaml 
new/lazr_delegates-4.0.0/.woke.yaml
--- old/lazr_delegates-2.1.1/.woke.yaml 2024-12-04 21:37:08.000000000 +0100
+++ new/lazr_delegates-4.0.0/.woke.yaml 1970-01-01 01:00:00.000000000 +0100
@@ -1,228 +0,0 @@
-
-# Based on Canonical's Guidelines
-# 
https://docs.google.com/document/d/1mJUa1VJHOMWa723dmKmNjSKGW-nlBv9xktzGZZwacVo/edit#heading=h.5efudb237qdb
-rules:
-  - name: whitelist
-    terms:
-      - whitelist
-      - white-list
-      - whitelisted
-      - white-listed
-    alternatives:
-      - allowlist
-      - inclusion list
-    severity: warning
-    note: "The underlying assumption of the whitelist/blacklist metaphor is 
that white = good and black = bad. Because colors in and of themselves have no 
predetermined meaning, any meaning we assign to them is cultural: for example, 
the color red in many Southeast Asian countries is lucky, and is often 
associated with events like marriages, whereas the color white carries the same 
connotations in many European countries. In the case of whitelist/blacklist, 
the terms originate in the publishing industry – one dominated by the USA and 
England, two countries which participated in slavery and which grapple with 
their racist legacies to this day."
-
-  - name: blacklist
-    terms:
-      - blacklist
-      - black-list
-      - blacklisted
-      - black-listed
-    alternatives:
-      - denylist
-      - blocklist
-      - exclusion list
-    severity: warning
-    note: "The underlying assumption of the whitelist/blacklist metaphor is 
that white = good and black = bad. Because colors in and of themselves have no 
predetermined meaning, any meaning we assign to them is cultural: for example, 
the color red in many Southeast Asian countries is lucky, and is often 
associated with events like marriages, whereas the color white carries the same 
connotations in many European countries. In the case of whitelist/blacklist, 
the terms originate in the publishing industry – one dominated by the USA and 
England, two countries which participated in slavery and which grapple with 
their racist legacies to this day."
-
-  - name: master-slave
-    terms:
-      - master-slave
-      - master/slave
-    alternatives:
-      - leader/follower
-      - main/replica
-      - primary/replica
-      - primary/standby
-      - primary/secondary
-
-  - name: slave
-    terms:
-      - slave
-    alternatives:
-      - follower
-      - replica
-      - standby
-
-  - name: grandfathered
-    terms:
-      - grandfathered
-    alternatives:
-      - legacy status
-      - legacied
-      - exempted
-      - carried
-      - brought forward
-      - rolled over
-
-  - name: man-hours
-    terms:
-      - man hours
-      - man-hours
-    alternatives:
-      - person hours
-      - engineer hours
-
-  - name: sanity
-    terms:
-      - sanity
-    alternatives:
-      - confidence
-      - quick check
-      - coherence check
-
-  - name: dummy
-    terms:
-      - dummy
-    alternatives:
-      - placeholder
-      - sample
-
-  - name: guys
-    terms:
-      - guys
-    alternatives:
-      - folks
-      - people
-      - you all
-      - y'all
-      - yinz
-
-  - name: whitebox
-    terms:
-      - white-box
-      - whitebox
-      - white box
-    alternatives:
-      - open-box
-
-  - name: blackbox
-    terms:
-      - black-box
-      - blackbox
-      - black box
-    alternatives:
-      - closed-box
-
-  - name: blackhat
-    terms:
-      - blackhat
-      - black-hat
-      - black hat
-    alternatives:
-      - attacker
-      - malicious actor
-
-  - name: whitehat
-    terms:
-      - whitehat
-      - white-hat
-      - white hat
-    alternatives:
-      - researcher
-      - security specialist
-
-  - name: illegal characters
-    terms:
-      - illegal characters
-    alternatives:
-      - invalid characters
-      - unsupported characters
-      - special characters
-
-  - name: native feature
-    terms:
-      - native feature
-    alternatives:
-      - core feature
-      - built-in feature
-
-  - name: native feature
-    terms:
-      - native feature
-    alternatives:
-      - core feature
-      - built-in feature
-
-  - name: chairman/foreman
-    terms:
-      - chairman
-      - foreman
-    alternatives:
-      - chair
-      - foreperson
-
-  - name: man in the middle
-    terms:
-      - man in the middle
-      - man-in-the-middle
-    alternatives:
-      - machine-in-the-middle
-      - person-in-the-middle
-      - system-in-the-middle
-      - intermediary attack
-
-  - name: middleman
-    terms:
-      - middleman
-    alternatives:
-      - middleperson
-      - intermediary
-
-  - name: manned
-    terms:
-      - manned
-    alternatives:
-      - crewed
-      - staffed
-      - monitored
-      - human operated
-
-  - name: mom test / girlfriend test
-    terms:
-      - mom test
-      - girlfriend test
-    alternatives:
-      - user test
-      - user friendly
-
-  - name: crazy
-    terms:
-      - crazy
-    alternatives:
-      - baffling
-      - unexplained
-      - errant
-
-  - name: cripples
-    terms:
-      - cripples
-    alternatives:
-      - slows down
-      - hinders
-      - obstructs
-
-  - name: crippling 
-    terms:
-      - crippling
-    alternatives:
-      - attenuating
-      - incapacitating
-
-  - name: stonith/stomith 
-    terms:
-      - stonith
-      - stomith
-    alternatives:
-      - fence failed nodes
-      - machines
-
-  - name: demilitarized zone 
-    terms:
-      - demilitarized zone
-      - dmz
-    alternatives:
-      - perimeter network
-      - passthrough network
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lazr_delegates-2.1.1/CONTRIBUTING.rst 
new/lazr_delegates-4.0.0/CONTRIBUTING.rst
--- old/lazr_delegates-2.1.1/CONTRIBUTING.rst   2024-12-04 21:37:08.000000000 
+0100
+++ new/lazr_delegates-4.0.0/CONTRIBUTING.rst   2026-08-01 20:49:21.000000000 
+0200
@@ -5,45 +5,53 @@
     under the terms of the GNU Lesser General Public License as published by
     the Free Software Foundation, version 3 of the License.
 
-    lazr.delegates is distributed in the hope that it will be useful, but
-    WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-    or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+    lazr.delegates is distributed in the hope that it will be useful, but 
WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
     License for more details.
 
     You should have received a copy of the GNU Lesser General Public License
     along with lazr.delegates.  If not, see <http://www.gnu.org/licenses/>.
 
-=========================
-Hacking on lazr.delegates
-=========================
+============
+Contributing
+============
 
-These are guidelines for hacking on the lazr.delegates project.  But first,
-please see the common hacking guidelines at:
+Getting the code
+----------------
 
-    http://dev.launchpad.net/Hacking
+The source is maintained in git::
 
+    git clone https://git.launchpad.net/lazr.delegates
 
-============
-Contributing
-============
+Running the tests
+-----------------
+
+Use `tox <https://tox.readthedocs.io/en/latest/>`_::
+
+    tox
+
+This runs the linters, the test suite across supported Python versions, the
+documentation build, and a dependency audit.
 
-To run this project's tests, use `tox 
<https://tox.readthedocs.io/en/latest/>`_.
+Documentation
+-------------
 
 To update the `project's documentation
-<https://lazrdelegates.readthedocs.io/en/latest/>`_ you need to trigger a 
manual
-build on the project's dashboard on https://readthedocs.org.
+<https://lazrdelegates.readthedocs.io/en/latest/>`_ trigger a manual build on 
the
+project's dashboard at https://readthedocs.org.
 
 Getting help
 ------------
 
-If you find bugs in this package, you can report them here:
+If you find bugs in this package, report them at:
 
     https://launchpad.net/lazr.delegates
 
-If you want to discuss this package, join the team and mailing list here:
+To discuss this package, join the team and mailing list at:
 
     https://launchpad.net/~lazr-developers
 
-or send a message to:
+or email:
 
     [email protected]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lazr_delegates-2.1.1/MANIFEST.in 
new/lazr_delegates-4.0.0/MANIFEST.in
--- old/lazr_delegates-2.1.1/MANIFEST.in        2024-12-04 21:37:08.000000000 
+0100
+++ new/lazr_delegates-4.0.0/MANIFEST.in        2026-08-01 20:49:21.000000000 
+0200
@@ -1,4 +1,5 @@
-include *.py *.txt *.rst MANIFEST.in *.ini
+include *.txt *.rst *.md MANIFEST.in *.ini
 recursive-include src/lazr *.rst
 exclude .bzrignore
 include *.yaml
+include .flake8
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lazr_delegates-2.1.1/NEWS.rst 
new/lazr_delegates-4.0.0/NEWS.rst
--- old/lazr_delegates-2.1.1/NEWS.rst   2024-12-05 13:31:45.000000000 +0100
+++ new/lazr_delegates-4.0.0/NEWS.rst   2026-08-01 20:49:21.000000000 +0200
@@ -2,6 +2,16 @@
 NEWS for lazr.delegates
 =======================
 
+4.0.0 (unreleased)
+==================
+
+- Replace ``pkg_resources`` namespace with a PEP 420 native namespace.
+- Consolidate packaging into a single ``pyproject.toml`` (remove ``setup.py``,
+  ``setup.cfg``).
+- Add support for Python 3.14.
+- Update security auditing and linting.
+- Standardize tox, Launchpad CI, pre-commit, and contributor documentation.
+
 2.1.1 (2024-12-05)
 ==================
 - Add support for Python 3.12 and 3.13.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lazr_delegates-2.1.1/PKG-INFO 
new/lazr_delegates-4.0.0/PKG-INFO
--- old/lazr_delegates-2.1.1/PKG-INFO   2024-12-05 13:34:46.206344000 +0100
+++ new/lazr_delegates-4.0.0/PKG-INFO   2026-08-01 20:57:15.553557000 +0200
@@ -1,110 +1,40 @@
-Metadata-Version: 2.1
+Metadata-Version: 2.4
 Name: lazr.delegates
-Version: 2.1.1
+Version: 4.0.0
 Summary: Easily write objects that delegate behavior
-Home-page: https://launchpad.net/lazr.delegates
-Download-URL: https://launchpad.net/lazr.delegates/+download
 Maintainer: LAZR Developers
-Maintainer-email: [email protected]
 License: LGPL v3
+Project-URL: Homepage, https://launchpad.net/lazr.delegates
+Project-URL: Source, https://code.launchpad.net/lazr.delegates
+Project-URL: Issue Tracker, https://bugs.launchpad.net/lazr.delegates
+Project-URL: Documentation, https://lazrdelegates.readthedocs.io/en/latest/
+Project-URL: Download, https://launchpad.net/lazr.delegates/+download
 Classifier: Development Status :: 5 - Production/Stable
 Classifier: Intended Audience :: Developers
 Classifier: License :: OSI Approved :: GNU Library or Lesser General Public 
License (LGPL)
 Classifier: Operating System :: OS Independent
 Classifier: Programming Language :: Python
 Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3 :: Only
 Classifier: Programming Language :: Python :: 3.8
 Classifier: Programming Language :: Python :: 3.9
 Classifier: Programming Language :: Python :: 3.10
 Classifier: Programming Language :: Python :: 3.11
 Classifier: Programming Language :: Python :: 3.12
 Classifier: Programming Language :: Python :: 3.13
+Classifier: Programming Language :: Python :: 3.14
 Requires-Python: >=3.8
 Description-Content-Type: text/x-rst
 License-File: COPYING.txt
-Requires-Dist: setuptools
 Requires-Dist: zope.interface
 Provides-Extra: docs
 Requires-Dist: Sphinx; extra == "docs"
+Provides-Extra: test
+Requires-Dist: zope.testing>=4.6.0; extra == "test"
+Requires-Dist: zope.testrunner>=6.6.1; extra == "test"
+Dynamic: license-file
 
 The ``lazr.delegates`` package makes it easy to write objects that delegate
 behavior to another object. The new object adds some property or behavior on
 to the other object, while still providing the underlying interface, and
 delegating behavior.
-
-=======================
-NEWS for lazr.delegates
-=======================
-
-2.1.1 (2024-12-05)
-==================
-- Add support for Python 3.12 and 3.13.
-- Drop support for Python 3.5, 3.6 and 3.7.
-
-
-2.1.0 (2023-03-20)
-==================
-- Officially add support for Python 3.6, 3.7, 3.8, 3.9, 3.10 and 3.11.
-- Drop support for Python 2, 3.2, 3.3, and 3.4.
-- Test using ``zope.testrunner`` rather than ``nose``.
-- Bring coverage to 100%.
-- Switch to declarative ``setuptools`` configuration.
-- Add linters.
-- Fix the `woke` linter.
-
-
-2.0.4 (2017-10-20)
-==================
-- Adjust versioning strategy to avoid importing pkg_resources, which is slow
-  in large environments.
-
-
-2.0.3 (2015-07-08)
-==================
-- Restore the public import of ``lazr.delegates.Passthrough`` which was
-  inadvertently lost during the port to Python 3.
-- Officially add support for Python 3.5.
-- Drop official Python 2.6 support.
-
-
-2.0.2 (2015-01-05)
-==================
-- Always use old-style namespace package registration in ``lazr/__init__.py``
-  since the mere presence of this file subverts PEP 420 style namespace
-  packages.  (LP: #1407816)
-
-
-2.0.1 (2014-08-21)
-==================
-- Drop the use of `distribute` in favor of `setuptools`.  (LP: #1359927)
-- Run the test suite with `tox`.
-
-
-2.0 (2013-01-10)
-================
-- Port to Python 3, which requires the use of the ``@delegate_to`` class
-  decorator instead of the ``delegates()`` function call.  Officially support
-  Python 2.6, 2.7, 3.2, and 3.3.
-
-
-1.2.0 (2010-07-16)
-==================
-- Extend Passthrough so that it takes an extra (optional) callable argument,
-  used to adapt the context before accessing the delegated attribute.
-
-
-1.1.0 (2009-08-31)
-==================
-- Remove build dependencies on bzr and egg_info
-- remove sys.path hack in setup.py for __version__
-
-
-1.0.1 (2009-03-24)
-==================
-- specify only v3 of LGPL
-- build/developer improvements
-
-
-1.0 (2008-12-19)
-================
-- Initial release
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lazr_delegates-2.1.1/SECURITY.md 
new/lazr_delegates-4.0.0/SECURITY.md
--- old/lazr_delegates-2.1.1/SECURITY.md        1970-01-01 01:00:00.000000000 
+0100
+++ new/lazr_delegates-4.0.0/SECURITY.md        2026-07-03 19:52:30.000000000 
+0200
@@ -0,0 +1,15 @@
+# Launchpad Security Policy
+
+If you discover a security vulnerability, please follow the steps outlined 
below to report it:
+
+1. **Do not** publicly disclose the vulnerability before discussing it with us.
+2. Contact us via email at 
[[email protected]](mailto:[email protected]).
+3. Provide detailed information about the vulnerability, including:
+   - A description of the vulnerability.
+   - Steps to reproduce the issue.
+   - Potential impact and affected versions.
+   - Suggested mitigations, if possible.
+
+The [Ubuntu Security disclosure and embargo 
policy](https://ubuntu.com/security/disclosure-policy) contains more 
information about what you can expect when you contact us and what we expect 
from you.
+
+The Launchpad team will be notified of the issue and review the vulnerability. 
We may reach out to you for further information or clarification if needed. If 
the issue is confirmed as a valid security vulnerability, we will assign a CVE 
and coordinate the release of the fix.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lazr_delegates-2.1.1/pyproject.toml 
new/lazr_delegates-4.0.0/pyproject.toml
--- old/lazr_delegates-2.1.1/pyproject.toml     1970-01-01 01:00:00.000000000 
+0100
+++ new/lazr_delegates-4.0.0/pyproject.toml     2026-08-01 20:49:21.000000000 
+0200
@@ -0,0 +1,70 @@
+[build-system]
+requires = ["setuptools>=61.0"]
+build-backend = "setuptools.build_meta"
+
+[project]
+name = "lazr.delegates"
+version = "4.0.0"
+description = "Easily write objects that delegate behavior"
+readme = "README.rst"
+requires-python = ">=3.8"
+license = { text = "LGPL v3" }
+maintainers = [
+    { name = "LAZR Developers" },
+]
+classifiers = [
+    "Development Status :: 5 - Production/Stable",
+    "Intended Audience :: Developers",
+    "License :: OSI Approved :: GNU Library or Lesser General Public License 
(LGPL)",
+    "Operating System :: OS Independent",
+    "Programming Language :: Python",
+    "Programming Language :: Python :: 3",
+    "Programming Language :: Python :: 3 :: Only",
+    "Programming Language :: Python :: 3.8",
+    "Programming Language :: Python :: 3.9",
+    "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",
+]
+dependencies = [
+    "zope.interface",
+]
+
+[project.optional-dependencies]
+docs = ["Sphinx"]
+test = [
+    "zope.testing>=4.6.0",
+    "zope.testrunner>=6.6.1",
+]
+
+[project.urls]
+Homepage = "https://launchpad.net/lazr.delegates";
+Source = "https://code.launchpad.net/lazr.delegates";
+"Issue Tracker" = "https://bugs.launchpad.net/lazr.delegates";
+Documentation = "https://lazrdelegates.readthedocs.io/en/latest/";
+Download = "https://launchpad.net/lazr.delegates/+download";
+
+[tool.setuptools]
+include-package-data = true
+
+[tool.setuptools.packages.find]
+where = ["src"]
+namespaces = true
+
+[tool.black]
+line-length = 79
+target-version = ["py38"]
+
+[tool.isort]
+known_first_party = "lazr.delegates"
+line_length = 79
+profile = "black"
+
+[tool.coverage.run]
+source = ["lazr.delegates"]
+omit = ["*/docs/conf.py"]
+
+[tool.coverage.paths]
+source = ["src", ".tox/*/site-packages"]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lazr_delegates-2.1.1/setup.cfg 
new/lazr_delegates-4.0.0/setup.cfg
--- old/lazr_delegates-2.1.1/setup.cfg  2024-12-05 13:34:46.206736800 +0100
+++ new/lazr_delegates-4.0.0/setup.cfg  2026-08-01 20:57:15.553702400 +0200
@@ -1,45 +1,3 @@
-[metadata]
-name = lazr.delegates
-version = 2.1.1
-maintainer = LAZR Developers
-maintainer_email = [email protected]
-description = Easily write objects that delegate behavior
-long_description = file: README.rst, NEWS.rst
-long_description_content_type = text/x-rst
-license = LGPL v3
-url = https://launchpad.net/lazr.delegates
-download_url = https://launchpad.net/lazr.delegates/+download
-classifiers = 
-       Development Status :: 5 - Production/Stable
-       Intended Audience :: Developers
-       License :: OSI Approved :: GNU Library or Lesser General Public License 
(LGPL)
-       Operating System :: OS Independent
-       Programming Language :: Python
-       Programming Language :: Python :: 3
-       Programming Language :: Python :: 3.8
-       Programming Language :: Python :: 3.9
-       Programming Language :: Python :: 3.10
-       Programming Language :: Python :: 3.11
-       Programming Language :: Python :: 3.12
-       Programming Language :: Python :: 3.13
-
-[options]
-namespace_packages = lazr
-packages = find:
-package_dir = =src
-include_package_data = True
-zip_safe = False
-install_requires = 
-       setuptools
-       zope.interface
-python_requires = >=3.8
-
-[options.packages.find]
-where = src
-
-[options.extras_require]
-docs = Sphinx
-
 [egg_info]
 tag_build = 
 tag_date = 0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lazr_delegates-2.1.1/setup.py 
new/lazr_delegates-4.0.0/setup.py
--- old/lazr_delegates-2.1.1/setup.py   2024-12-04 21:37:08.000000000 +0100
+++ new/lazr_delegates-4.0.0/setup.py   1970-01-01 01:00:00.000000000 +0100
@@ -1,19 +0,0 @@
-# Copyright 2008-2022 Canonical Ltd.  All rights reserved.
-#
-# This file is part of lazr.delegates.
-#
-# lazr.delegates is free software: you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation, version 3 of the License.
-#
-# lazr.delegates is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
-# License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with lazr.delegates.  If not, see <http://www.gnu.org/licenses/>.
-
-from setuptools import setup
-
-setup()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lazr_delegates-2.1.1/src/lazr/__init__.py 
new/lazr_delegates-4.0.0/src/lazr/__init__.py
--- old/lazr_delegates-2.1.1/src/lazr/__init__.py       2024-12-04 
21:37:08.000000000 +0100
+++ new/lazr_delegates-4.0.0/src/lazr/__init__.py       1970-01-01 
01:00:00.000000000 +0100
@@ -1,23 +0,0 @@
-# Copyright 2008-2015 Canonical Ltd.  All rights reserved.
-#
-# This file is part of lazr.delegates.
-#
-# lazr.delegates is free software: you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation, version 3 of the License.
-#
-# lazr.delegates is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
-# License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with lazr.delegates.  If not, see <http://www.gnu.org/licenses/>.
-
-# This is a namespace package.
-try:
-    import pkg_resources
-    pkg_resources.declare_namespace(__name__)
-except ImportError:
-    import pkgutil
-    __path__ = pkgutil.extend_path(__path__, __name__)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lazr_delegates-2.1.1/src/lazr/delegates/__init__.py 
new/lazr_delegates-4.0.0/src/lazr/delegates/__init__.py
--- old/lazr_delegates-2.1.1/src/lazr/delegates/__init__.py     2024-12-04 
21:37:08.000000000 +0100
+++ new/lazr_delegates-4.0.0/src/lazr/delegates/__init__.py     2026-08-01 
20:49:21.000000000 +0200
@@ -17,9 +17,9 @@
 """Decorator helpers that simplify class composition."""
 
 __all__ = [
-    'Passthrough',
-    'delegate_to',
-    ]
+    "Passthrough",
+    "delegate_to",
+]
 
 try:
     import importlib.metadata as importlib_metadata
@@ -29,6 +29,9 @@
 from lazr.delegates._delegates import (
     Passthrough,
     delegate_to,
-    )
+)
 
-__version__ = importlib_metadata.version("lazr.delegates")
+try:
+    __version__ = importlib_metadata.version("lazr.delegates")
+except importlib_metadata.PackageNotFoundError:  # pragma: no cover
+    __version__ = importlib_metadata.version("lazr-delegates")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/lazr_delegates-2.1.1/src/lazr/delegates/_delegates.py 
new/lazr_delegates-4.0.0/src/lazr/delegates/_delegates.py
--- old/lazr_delegates-2.1.1/src/lazr/delegates/_delegates.py   2024-12-05 
13:31:31.000000000 +0100
+++ new/lazr_delegates-4.0.0/src/lazr/delegates/_delegates.py   2026-08-01 
20:49:21.000000000 +0200
@@ -17,14 +17,14 @@
 """Decorator helpers that simplify class composition."""
 
 __all__ = [
-    'Passthrough',
-    'delegate_to',
-    ]
+    "Passthrough",
+    "delegate_to",
+]
 
 from zope.interface import classImplements
 
 
-def delegate_to(*interfaces, context='context'):
+def delegate_to(*interfaces, context="context"):
     """Make an adapter into a decorator.
 
     Use like:
@@ -60,7 +60,7 @@
             self.context = context
     """
     if len(interfaces) == 0:
-        raise TypeError('At least one interface is required')
+        raise TypeError("At least one interface is required")
 
     def _decorator(cls):
         missing = object()
@@ -70,6 +70,7 @@
                 if getattr(cls, name, missing) is missing:
                     setattr(cls, name, Passthrough(name, context))
         return cls
+
     return _decorator
 
 
@@ -81,6 +82,7 @@
     have the delegated attribute. The ``adaptation`` argument is expected to
     be used with an interface, to adapt the context.
     """
+
     def __init__(self, name, contextvar, adaptation=None):
         self.name = name
         self.contextvar = contextvar
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lazr_delegates-2.1.1/src/lazr/delegates/docs/conf.py 
new/lazr_delegates-4.0.0/src/lazr/delegates/docs/conf.py
--- old/lazr_delegates-2.1.1/src/lazr/delegates/docs/conf.py    2024-12-04 
21:37:08.000000000 +0100
+++ new/lazr_delegates-4.0.0/src/lazr/delegates/docs/conf.py    2026-08-01 
20:49:21.000000000 +0200
@@ -1,229 +1,47 @@
-# lazr.delegates documentation build configuration file, created by
-# sphinx-quickstart on Mon Jan  7 10:37:37 2013.
+#!/usr/bin/env python3
 #
-# This file is execfile()d with the current directory set to its containing 
dir.
+# lazr.delegates documentation build configuration file.
 #
-# Note that not all possible configuration values are present in this
-# autogenerated file.
-#
-# All configuration values have a default; values that are commented out
-# serve to show the default.
-
-# If extensions (or modules to document with autodoc) are in another directory,
-# add these directories to sys.path here. If the directory is relative to the
-# documentation root, use os.path.abspath to make it absolute, like shown here.
-#sys.path.insert(0, os.path.abspath('.'))
+# This file is execfile()d with the current directory set to its
+# containing dir.
 
-# -- General configuration 
-----------------------------------------------------
+from lazr.delegates import __version__
 
-# If your documentation needs a minimal Sphinx version, state it here.
-#needs_sphinx = '1.0'
+# -- General configuration ------------------------------------------------
 
-# Add any Sphinx extension module names here, as strings. They can be 
extensions
-# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
 extensions = []
 
-# Add any paths that contain templates here, relative to this directory.
-templates_path = ['_templates']
-
-# The suffix of source filenames.
-source_suffix = '.rst'
+templates_path = ["_templates"]
 
-# The encoding of source files.
-#source_encoding = 'utf-8-sig'
+source_suffix = ".rst"
 
-# The master toctree document.
-master_doc = 'index'
+master_doc = "index"
 
-# General information about the project.
-project = 'lazr.delegates'
-copyright = '2013-2021, LAZR developers'
+project = "lazr.delegates"
+copyright = "2013-2021, LAZR developers"
+author = "LAZR Developers <[email protected]>"
 
-# The version info for the project you're documenting, acts as replacement for
-# |version| and |release|, also used in various other places throughout the
-# built documents.
-#
-# The short X.Y version.
-from lazr.delegates import __version__
 version = __version__
-# The full version, including alpha/beta/rc tags.
-release = version
+release = __version__
 
-# The language for content autogenerated by Sphinx. Refer to documentation
-# for a list of supported languages.
 language = "en"
 
-# There are two options for replacing |today|: either, you set today to some
-# non-false value, then it is used:
-#today = ''
-# Else, today_fmt is used as the format for a strftime call.
-#today_fmt = '%B %d, %Y'
-
-# List of patterns, relative to source directory, that match files and
-# directories to ignore when looking for source files.
-exclude_patterns = ['_build', 'eggs']
-
-# The reST default role (used for this markup: `text`) to use for all 
documents.
-#default_role = None
-
-# If true, '()' will be appended to :func: etc. cross-reference text.
-#add_function_parentheses = True
-
-# If true, the current module name will be prepended to all description
-# unit titles (such as .. function::).
-#add_module_names = True
-
-# If true, sectionauthor and moduleauthor directives will be shown in the
-# output. They are ignored by default.
-#show_authors = False
-
-# The name of the Pygments (syntax highlighting) style to use.
-pygments_style = 'sphinx'
-
-# A list of ignored prefixes for module index sorting.
-#modindex_common_prefix = []
+exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
 
+pygments_style = "sphinx"
 
-# -- Options for HTML output 
---------------------------------------------------
 
-# The theme to use for HTML and HTML Help pages.  See the documentation for
-# a list of builtin themes.
-html_theme = 'alabaster'
+# -- Options for HTML output ----------------------------------------------
 
-# Theme options are theme-specific and customize the look and feel of a theme
-# further.  For a list of options available for each theme, see the
-# documentation.
-#html_theme_options = {}
+html_theme = "alabaster"
 
-# Add any paths that contain custom themes here, relative to this directory.
-#html_theme_path = []
-
-# The name for this set of Sphinx documents.  If None, it defaults to
-# "<project> v<release> documentation".
-#html_title = None
-
-# A shorter title for the navigation bar.  Default is the same as html_title.
-#html_short_title = None
-
-# The name of an image file (relative to this directory) to place at the top
-# of the sidebar.
-#html_logo = None
-
-# The name of an image file (within the static path) to use as favicon of the
-# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
-# pixels large.
-#html_favicon = None
-
-# Add any paths that contain custom static files (such as style sheets) here,
-# relative to this directory. They are copied after the builtin static files,
-# so a file named "default.css" will overwrite the builtin "default.css".
 html_static_path = []
 
-# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
-# using the given strftime format.
-#html_last_updated_fmt = '%b %d, %Y'
-
-# If true, SmartyPants will be used to convert quotes and dashes to
-# typographically correct entities.
-#html_use_smartypants = True
-
-# Custom sidebar templates, maps document names to template names.
 html_sidebars = {
-    '**': [
-        'globaltoc.html',
+    "**": [
+        "relations.html",
+        "searchbox.html",
     ]
 }
-# Additional templates that should be rendered to pages, maps page names to
-# template names.
-#html_additional_pages = {}
-
-# If false, no module index is generated.
-#html_domain_indices = True
-
-# If false, no index is generated.
-#html_use_index = True
-
-# If true, the index is split into individual pages for each letter.
-#html_split_index = False
-
-# If true, links to the reST sources are added to the pages.
-#html_show_sourcelink = True
-
-# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
-#html_show_sphinx = True
-
-# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
-#html_show_copyright = True
-
-# If true, an OpenSearch description file will be output, and all pages will
-# contain a <link> tag referring to it.  The value of this option must be the
-# base URL from which the finished HTML is served.
-#html_use_opensearch = ''
-
-# This is the file name suffix for HTML files (e.g. ".xhtml").
-#html_file_suffix = None
-
-# Output file base name for HTML help builder.
-htmlhelp_basename = 'lazrdelegatesdoc'
-
-
-# -- Options for LaTeX output 
--------------------------------------------------
-
-# latex_elements = {
-# The paper size ('letterpaper' or 'a4paper').
-#'papersize': 'letterpaper',
-
-# The font size ('10pt', '11pt' or '12pt').
-#'pointsize': '10pt',
-
-# Additional stuff for the LaTeX preamble.
-#'preamble': '',
-# }
-
-# Grouping the document tree into LaTeX files. List of tuples
-# (source start file, target name, title, author, documentclass 
[howto/manual]).
-
-# The name of an image file (relative to this directory) to place at the top of
-# the title page.
-#latex_logo = None
-
-# For "manual" documents, if this is true, then toplevel headings are parts,
-# not chapters.
-#latex_use_parts = False
-
-# If true, show page references after internal links.
-#latex_show_pagerefs = False
-
-# If true, show URL addresses after external links.
-#latex_show_urls = False
-
-# Documents to append as an appendix to all manuals.
-#latex_appendices = []
-
-# If false, no module index is generated.
-#latex_domain_indices = True
-
-
-# -- Options for manual page output 
--------------------------------------------
-
-# One entry per manual page. List of tuples
-# (source start file, name, description, authors, manual section).
-
-# If true, show URL addresses after external links.
-#man_show_urls = False
-
-
-# -- Options for Texinfo output 
------------------------------------------------
-
-# Grouping the document tree into Texinfo files. List of tuples
-# (source start file, target name, title, author,
-#  dir menu entry, description, category)
-
-# Documents to append as an appendix to all manuals.
-#texinfo_appendices = []
-
-# If false, no module index is generated.
-#texinfo_domain_indices = True
 
-# How to display URL addresses: 'footnote', 'no', or 'inline'.
-#texinfo_show_urls = 'footnote'
+htmlhelp_basename = "lazrdelegatesdoc"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/lazr_delegates-2.1.1/src/lazr/delegates/tests/test_docs.py 
new/lazr_delegates-4.0.0/src/lazr/delegates/tests/test_docs.py
--- old/lazr_delegates-2.1.1/src/lazr/delegates/tests/test_docs.py      
2024-12-04 21:37:08.000000000 +0100
+++ new/lazr_delegates-4.0.0/src/lazr/delegates/tests/test_docs.py      
2026-08-01 20:49:21.000000000 +0200
@@ -18,17 +18,10 @@
 
 __all__ = []
 
-import atexit
 import doctest
+import importlib.util
 import os
-
-from pkg_resources import (
-    resource_filename,
-    resource_exists,
-    resource_listdir,
-    cleanup_resources,
-)
-
+from pathlib import Path
 
 DOCTEST_FLAGS = (
     doctest.ELLIPSIS | doctest.NORMALIZE_WHITESPACE | doctest.REPORT_NDIFF
@@ -38,21 +31,19 @@
 def load_tests(loader, tests, pattern):
     """Load the doc tests (docs/*, if any exist)."""
     doctest_files = []
-    if resource_exists("lazr.delegates", "docs"):
-        for name in resource_listdir("lazr.delegates", "docs"):
-            if name.endswith(".rst"):
-                doctest_files.append(
-                    os.path.abspath(
-                        resource_filename("lazr.delegates", "docs/%s" % name)
-                    )
-                )
-    atexit.register(cleanup_resources)
+    spec = importlib.util.find_spec("lazr.delegates")
+    if spec and spec.submodule_search_locations:
+        docs_path = Path(list(spec.submodule_search_locations)[0]) / "docs"
+        if docs_path.is_dir():
+            for path in sorted(docs_path.iterdir()):
+                if path.name.endswith(".rst"):
+                    doctest_files.append(os.path.abspath(str(path)))
     tests.addTest(
         doctest.DocFileSuite(
             *doctest_files,
             module_relative=False,
             optionflags=DOCTEST_FLAGS,
-            encoding="UTF-8"
+            encoding="UTF-8",
         )
     )
     return tests
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/lazr_delegates-2.1.1/src/lazr/delegates/tests/test_passthrough.py 
new/lazr_delegates-4.0.0/src/lazr/delegates/tests/test_passthrough.py
--- old/lazr_delegates-2.1.1/src/lazr/delegates/tests/test_passthrough.py       
2024-12-05 13:31:31.000000000 +0100
+++ new/lazr_delegates-4.0.0/src/lazr/delegates/tests/test_passthrough.py       
2026-08-01 20:49:21.000000000 +0200
@@ -22,7 +22,7 @@
 
 
 class Base:
-    foo = 'foo from Base'
+    foo = "foo from Base"
 
     @classmethod
     def clsmethod(cls):
@@ -31,8 +31,8 @@
 
 class TestPassthrough(unittest.TestCase):
     def setUp(self):
-        self.p = Passthrough('foo', 'mycontext')
-        self.p2 = Passthrough('clsmethod', 'mycontext')
+        self.p = Passthrough("foo", "mycontext")
+        self.p2 = Passthrough("clsmethod", "mycontext")
 
         self.base = Base()
 
@@ -43,17 +43,16 @@
         self.adapter = Adapter()
 
     def test_get(self):
-        self.assertEqual(self.p.__get__(self.adapter), 'foo from Base')
+        self.assertEqual(self.p.__get__(self.adapter), "foo from Base")
         self.assertTrue(self.p.__get__(None, self.Adapter) is self.p)
-        self.assertEqual(self.p2.__get__(self.adapter)(), 'Base')
+        self.assertEqual(self.p2.__get__(self.adapter)(), "Base")
 
     def test_set(self):
-        self.p.__set__(self.adapter, 'new value')
-        self.assertEqual(self.base.foo, 'new value')
+        self.p.__set__(self.adapter, "new value")
+        self.assertEqual(self.base.foo, "new value")
 
     def test_no_delete(self):
-        self.assertRaises(NotImplementedError,
-                          self.p.__delete__, self.adapter)
+        self.assertRaises(NotImplementedError, self.p.__delete__, self.adapter)
 
     def test_adaptation(self):
         # Passthrough's third argument (adaptation) is optional and, when
@@ -62,6 +61,7 @@
         # before getting/setting the delegated attribute.
         class HasNoFoo:
             _foo = 1
+
         no_foo = HasNoFoo()
         # ... but IHasFooAdapter uses HasNoFoo._foo to provide its own .foo,
         # so it works like an adapter for HasNoFoo into some interface that
@@ -82,7 +82,7 @@
         class Example:
             context = no_foo
 
-        p = Passthrough('foo', 'context', adaptation=IHasFooAdapter)
+        p = Passthrough("foo", "context", adaptation=IHasFooAdapter)
         e = Example()
 
         self.assertEqual(p.__get__(e), 1)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/lazr_delegates-2.1.1/src/lazr.delegates.egg-info/PKG-INFO 
new/lazr_delegates-4.0.0/src/lazr.delegates.egg-info/PKG-INFO
--- old/lazr_delegates-2.1.1/src/lazr.delegates.egg-info/PKG-INFO       
2024-12-05 13:34:46.000000000 +0100
+++ new/lazr_delegates-4.0.0/src/lazr.delegates.egg-info/PKG-INFO       
2026-08-01 20:57:15.000000000 +0200
@@ -1,110 +1,40 @@
-Metadata-Version: 2.1
+Metadata-Version: 2.4
 Name: lazr.delegates
-Version: 2.1.1
+Version: 4.0.0
 Summary: Easily write objects that delegate behavior
-Home-page: https://launchpad.net/lazr.delegates
-Download-URL: https://launchpad.net/lazr.delegates/+download
 Maintainer: LAZR Developers
-Maintainer-email: [email protected]
 License: LGPL v3
+Project-URL: Homepage, https://launchpad.net/lazr.delegates
+Project-URL: Source, https://code.launchpad.net/lazr.delegates
+Project-URL: Issue Tracker, https://bugs.launchpad.net/lazr.delegates
+Project-URL: Documentation, https://lazrdelegates.readthedocs.io/en/latest/
+Project-URL: Download, https://launchpad.net/lazr.delegates/+download
 Classifier: Development Status :: 5 - Production/Stable
 Classifier: Intended Audience :: Developers
 Classifier: License :: OSI Approved :: GNU Library or Lesser General Public 
License (LGPL)
 Classifier: Operating System :: OS Independent
 Classifier: Programming Language :: Python
 Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3 :: Only
 Classifier: Programming Language :: Python :: 3.8
 Classifier: Programming Language :: Python :: 3.9
 Classifier: Programming Language :: Python :: 3.10
 Classifier: Programming Language :: Python :: 3.11
 Classifier: Programming Language :: Python :: 3.12
 Classifier: Programming Language :: Python :: 3.13
+Classifier: Programming Language :: Python :: 3.14
 Requires-Python: >=3.8
 Description-Content-Type: text/x-rst
 License-File: COPYING.txt
-Requires-Dist: setuptools
 Requires-Dist: zope.interface
 Provides-Extra: docs
 Requires-Dist: Sphinx; extra == "docs"
+Provides-Extra: test
+Requires-Dist: zope.testing>=4.6.0; extra == "test"
+Requires-Dist: zope.testrunner>=6.6.1; extra == "test"
+Dynamic: license-file
 
 The ``lazr.delegates`` package makes it easy to write objects that delegate
 behavior to another object. The new object adds some property or behavior on
 to the other object, while still providing the underlying interface, and
 delegating behavior.
-
-=======================
-NEWS for lazr.delegates
-=======================
-
-2.1.1 (2024-12-05)
-==================
-- Add support for Python 3.12 and 3.13.
-- Drop support for Python 3.5, 3.6 and 3.7.
-
-
-2.1.0 (2023-03-20)
-==================
-- Officially add support for Python 3.6, 3.7, 3.8, 3.9, 3.10 and 3.11.
-- Drop support for Python 2, 3.2, 3.3, and 3.4.
-- Test using ``zope.testrunner`` rather than ``nose``.
-- Bring coverage to 100%.
-- Switch to declarative ``setuptools`` configuration.
-- Add linters.
-- Fix the `woke` linter.
-
-
-2.0.4 (2017-10-20)
-==================
-- Adjust versioning strategy to avoid importing pkg_resources, which is slow
-  in large environments.
-
-
-2.0.3 (2015-07-08)
-==================
-- Restore the public import of ``lazr.delegates.Passthrough`` which was
-  inadvertently lost during the port to Python 3.
-- Officially add support for Python 3.5.
-- Drop official Python 2.6 support.
-
-
-2.0.2 (2015-01-05)
-==================
-- Always use old-style namespace package registration in ``lazr/__init__.py``
-  since the mere presence of this file subverts PEP 420 style namespace
-  packages.  (LP: #1407816)
-
-
-2.0.1 (2014-08-21)
-==================
-- Drop the use of `distribute` in favor of `setuptools`.  (LP: #1359927)
-- Run the test suite with `tox`.
-
-
-2.0 (2013-01-10)
-================
-- Port to Python 3, which requires the use of the ``@delegate_to`` class
-  decorator instead of the ``delegates()`` function call.  Officially support
-  Python 2.6, 2.7, 3.2, and 3.3.
-
-
-1.2.0 (2010-07-16)
-==================
-- Extend Passthrough so that it takes an extra (optional) callable argument,
-  used to adapt the context before accessing the delegated attribute.
-
-
-1.1.0 (2009-08-31)
-==================
-- Remove build dependencies on bzr and egg_info
-- remove sys.path hack in setup.py for __version__
-
-
-1.0.1 (2009-03-24)
-==================
-- specify only v3 of LGPL
-- build/developer improvements
-
-
-1.0 (2008-12-19)
-================
-- Initial release
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/lazr_delegates-2.1.1/src/lazr.delegates.egg-info/SOURCES.txt 
new/lazr_delegates-4.0.0/src/lazr.delegates.egg-info/SOURCES.txt
--- old/lazr_delegates-2.1.1/src/lazr.delegates.egg-info/SOURCES.txt    
2024-12-05 13:34:46.000000000 +0100
+++ new/lazr_delegates-4.0.0/src/lazr.delegates.egg-info/SOURCES.txt    
2026-08-01 20:57:15.000000000 +0200
@@ -1,21 +1,18 @@
+.flake8
 .launchpad.yaml
 .pre-commit-config.yaml
 .readthedocs.yaml
-.woke.yaml
 CONTRIBUTING.rst
 COPYING.txt
 MANIFEST.in
 NEWS.rst
 README.rst
-setup.cfg
-setup.py
+SECURITY.md
+pyproject.toml
 tox.ini
-src/lazr/__init__.py
 src/lazr.delegates.egg-info/PKG-INFO
 src/lazr.delegates.egg-info/SOURCES.txt
 src/lazr.delegates.egg-info/dependency_links.txt
-src/lazr.delegates.egg-info/namespace_packages.txt
-src/lazr.delegates.egg-info/not-zip-safe
 src/lazr.delegates.egg-info/requires.txt
 src/lazr.delegates.egg-info/top_level.txt
 src/lazr/delegates/__init__.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/lazr_delegates-2.1.1/src/lazr.delegates.egg-info/namespace_packages.txt 
new/lazr_delegates-4.0.0/src/lazr.delegates.egg-info/namespace_packages.txt
--- old/lazr_delegates-2.1.1/src/lazr.delegates.egg-info/namespace_packages.txt 
2024-12-05 13:34:46.000000000 +0100
+++ new/lazr_delegates-4.0.0/src/lazr.delegates.egg-info/namespace_packages.txt 
1970-01-01 01:00:00.000000000 +0100
@@ -1 +0,0 @@
-lazr
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/lazr_delegates-2.1.1/src/lazr.delegates.egg-info/not-zip-safe 
new/lazr_delegates-4.0.0/src/lazr.delegates.egg-info/not-zip-safe
--- old/lazr_delegates-2.1.1/src/lazr.delegates.egg-info/not-zip-safe   
2024-12-04 21:37:57.000000000 +0100
+++ new/lazr_delegates-4.0.0/src/lazr.delegates.egg-info/not-zip-safe   
1970-01-01 01:00:00.000000000 +0100
@@ -1 +0,0 @@
-
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/lazr_delegates-2.1.1/src/lazr.delegates.egg-info/requires.txt 
new/lazr_delegates-4.0.0/src/lazr.delegates.egg-info/requires.txt
--- old/lazr_delegates-2.1.1/src/lazr.delegates.egg-info/requires.txt   
2024-12-05 13:34:46.000000000 +0100
+++ new/lazr_delegates-4.0.0/src/lazr.delegates.egg-info/requires.txt   
2026-08-01 20:57:15.000000000 +0200
@@ -1,5 +1,8 @@
-setuptools
 zope.interface
 
 [docs]
 Sphinx
+
+[test]
+zope.testing>=4.6.0
+zope.testrunner>=6.6.1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lazr_delegates-2.1.1/tox.ini 
new/lazr_delegates-4.0.0/tox.ini
--- old/lazr_delegates-2.1.1/tox.ini    2024-12-05 13:31:31.000000000 +0100
+++ new/lazr_delegates-4.0.0/tox.ini    2026-08-01 20:49:21.000000000 +0200
@@ -1,58 +1,61 @@
 [tox]
+isolated_build = True
 envlist =
     lint
-    py38
-    py39
-    py310
-    py311
-    py312
-    py313
+    py38,py39,py310,py311,py312,py313,py314
     coverage
     docs
-skip_missing_interpreters =
-    true
+    audit
 
 [testenv]
+# Python 3.8 only: modern virtualenv seeds pip 26 / setuptools 82 into the env,
+# but pip 26 refuses to run on 3.8 and setuptools 82 dropped pkg_resources
+# (which zope.testrunner 6.6.1 -- the last 3.8-compatible release -- imports).
+# Pin the seeded pip and cap setuptools on 3.8 so pkg_resources stays 
available.
+# 3.9+ need neither: pip 26 runs there and zope.testrunner 8.x drops 
pkg_resources.
+# These are no-ops under tox-uv and on CI (focal ships compatible tooling).
+set_env =
+    py38: VIRTUALENV_PIP = 24.3.1
 deps =
+    .[test]
+    py38: setuptools < 81
     zope.testrunner
 commands =
     zope-testrunner --test-path src --tests-pattern ^tests {posargs}
 
 [testenv:lint]
+# align with .launchpad.yaml
 basepython = python3.12
+skip_install = true
 deps =
     pre-commit
-skip_install = true
-commands =
-    pre-commit run -a
-passenv =
-    XDG_CACHE_HOME
-    HOME
-
-[testenv:docs]
-basepython =
-    python3.11
 commands =
-    sphinx-build -b html -d src/lazr/delegates/docs/_build/doctrees 
src/lazr/delegates/docs src/lazr/delegates/docs/_build/html
-deps =
-    .[docs]
+    pre-commit run --all-files
 
 [testenv:coverage]
 basepython = python3.12
 deps =
-    coverage
+    .[test]
     zope.testrunner
+    coverage
 commands =
-    coverage erase
-    coverage run -m zope.testrunner --test-path src --tests-pattern ^tests 
{posargs}
-    coverage html
-    coverage report -m --fail-under=100
+    coverage run --source lazr.delegates -m zope.testrunner \
+        --test-path src --tests-pattern ^tests {posargs}
+    coverage report --show-missing --fail-under=100
 
-[coverage:run]
-source = lazr.delegates
-omit = */docs/conf.py
+[testenv:docs]
+# align with .launchpad.yaml
+basepython = python3.12
+deps =
+    .[docs]
+commands =
+    sphinx-build -b html -d src/lazr/delegates/docs/_build/doctrees 
src/lazr/delegates/docs src/lazr/delegates/docs/_build/html
 
-[coverage:paths]
-source =
-    src
-    .tox/*/site-packages
+[testenv:audit]
+# align with .launchpad.yaml
+basepython = python3.12
+deps =
+    pip>=26.0
+    pip-audit
+commands =
+    pip-audit

Reply via email to