Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package supervisor for openSUSE:Factory checked in at 2025-11-12 21:15:34 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/supervisor (Old) and /work/SRC/openSUSE:Factory/.supervisor.new.1980 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "supervisor" Wed Nov 12 21:15:34 2025 rev:8 rq:1317295 version:4.3.0 Changes: -------- --- /work/SRC/openSUSE:Factory/supervisor/supervisor.changes 2023-01-03 15:06:42.262978776 +0100 +++ /work/SRC/openSUSE:Factory/.supervisor.new.1980/supervisor.changes 2025-11-12 21:16:16.486880654 +0100 @@ -1,0 +2,27 @@ +Wed Nov 12 11:54:31 UTC 2025 - Dirk Müller <[email protected]> + +- update to 4.3.0: + * Fixed a bug where the poller would not unregister a closed + file descriptor under some circumstances, which caused + excessive polling, resulting in higher CPU usage. Patch by + aftersnow. + * Fixed a bug where restarting supervisord may have failed with + the message Error: Another program is already listening on a + port that one of our HTTP servers is configured to use. if an + HTTP request was made during restart. Patch by Julien Le + Cléach. + * Fixed a unit test that failed only on Python 3.13. Only test + code was changed; no changes to supervisord itself. Patch by + Colin Watson. + * On Python 3.8 and later, setuptools is no longer a runtime + dependency. Patch by Ofek Lev. + * On Python versions before 3.8, setuptools is still a runtime + dependency (for pkg_resources) but it is no longer declared + in setup.py as such. This is because adding a conditional + dependency with an environment marker (setuptools; + python_version < '3.8') breaks installation in some + scenarios, e.g. setup.py install or older versions of pip. + Ensure that setuptools is installed if using Python before + 3.8. + +------------------------------------------------------------------- Old: ---- supervisor-4.2.5.tar.gz New: ---- supervisor-4.3.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ supervisor.spec ++++++ --- /var/tmp/diff_new_pack.fqfC5f/_old 2025-11-12 21:16:17.346916704 +0100 +++ /var/tmp/diff_new_pack.fqfC5f/_new 2025-11-12 21:16:17.346916704 +0100 @@ -1,7 +1,7 @@ # # spec file for package supervisor # -# Copyright (c) 2023 SUSE LLC +# Copyright (c) 2025 SUSE LLC and contributors # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -17,7 +17,7 @@ Name: supervisor -Version: 4.2.5 +Version: 4.3.0 Release: 0 Summary: A system for controlling process state under UNIX License: SUSE-Repoze @@ -31,7 +31,6 @@ BuildRequires: python3-pytest BuildRequires: python3-rpm-macros BuildRequires: python3-setuptools -Requires: python3-setuptools Suggests: python3-cElementTree >= 1.0.2 BuildArch: noarch %{?systemd_requires} ++++++ supervisor-4.2.5.tar.gz -> supervisor-4.3.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/supervisor-4.2.5/CHANGES.rst new/supervisor-4.3.0/CHANGES.rst --- old/supervisor-4.2.5/CHANGES.rst 2022-12-24 01:25:40.000000000 +0100 +++ new/supervisor-4.3.0/CHANGES.rst 2025-08-23 20:15:55.000000000 +0200 @@ -1,3 +1,29 @@ +4.3.0 (2025-08-23) +------------------ + +- Fixed a bug where the poller would not unregister a closed + file descriptor under some circumstances, which caused excessive + polling, resulting in higher CPU usage. Patch by aftersnow. + +- Fixed a bug where restarting ``supervisord`` may have failed with + the message ``Error: Another program is already listening + on a port that one of our HTTP servers is configured to use.`` + if an HTTP request was made during restart. Patch by Julien Le Cléach. + +- Fixed a unit test that failed only on Python 3.13. Only test code was + changed; no changes to ``supervisord`` itself. Patch by Colin Watson. + +- On Python 3.8 and later, ``setuptools`` is no longer a runtime + dependency. Patch by Ofek Lev. + +- On Python versions before 3.8, ``setuptools`` is still a runtime + dependency (for ``pkg_resources``) but it is no longer declared in + ``setup.py`` as such. This is because adding a conditional dependency + with an environment marker (``setuptools; python_version < '3.8'``) + breaks installation in some scenarios, e.g. ``setup.py install`` or + older versions of ``pip``. Ensure that ``setuptools`` is installed + if using Python before 3.8. + 4.2.5 (2022-12-23) ------------------ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/supervisor-4.2.5/PKG-INFO new/supervisor-4.3.0/PKG-INFO --- old/supervisor-4.2.5/PKG-INFO 2022-12-24 01:52:25.397257600 +0100 +++ new/supervisor-4.3.0/PKG-INFO 2025-08-23 20:16:31.149147700 +0200 @@ -1,11 +1,14 @@ -Metadata-Version: 2.1 +Metadata-Version: 2.2 Name: supervisor -Version: 4.2.5 +Version: 4.3.0 Summary: A system for controlling process state under UNIX Home-page: http://supervisord.org/ Author: Chris McDonough Author-email: [email protected] License: BSD-derived (http://www.repoze.org/LICENSE.txt) +Project-URL: Changelog, http://supervisord.org/changelog +Project-URL: Documentation, http://supervisord.org +Project-URL: Issue Tracker, https://github.com/Supervisor/supervisor Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: No Input/Output (Daemon) Classifier: Intended Audience :: System Administrators @@ -25,8 +28,22 @@ Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 Classifier: Programming Language :: Python :: 3.10 -Provides-Extra: testing +Classifier: Programming Language :: Python :: 3.11 +Classifier: Programming Language :: Python :: 3.12 +Classifier: Programming Language :: Python :: 3.13 License-File: LICENSES.txt +Provides-Extra: test +Requires-Dist: pytest; extra == "test" +Requires-Dist: pytest-cov; extra == "test" +Dynamic: author +Dynamic: author-email +Dynamic: classifier +Dynamic: description +Dynamic: home-page +Dynamic: license +Dynamic: project-url +Dynamic: provides-extra +Dynamic: summary Supervisor ========== @@ -71,6 +88,32 @@ on GitHub. +4.3.0 (2025-08-23) +------------------ + +- Fixed a bug where the poller would not unregister a closed + file descriptor under some circumstances, which caused excessive + polling, resulting in higher CPU usage. Patch by aftersnow. + +- Fixed a bug where restarting ``supervisord`` may have failed with + the message ``Error: Another program is already listening + on a port that one of our HTTP servers is configured to use.`` + if an HTTP request was made during restart. Patch by Julien Le Cléach. + +- Fixed a unit test that failed only on Python 3.13. Only test code was + changed; no changes to ``supervisord`` itself. Patch by Colin Watson. + +- On Python 3.8 and later, ``setuptools`` is no longer a runtime + dependency. Patch by Ofek Lev. + +- On Python versions before 3.8, ``setuptools`` is still a runtime + dependency (for ``pkg_resources``) but it is no longer declared in + ``setup.py`` as such. This is because adding a conditional dependency + with an environment marker (``setuptools; python_version < '3.8'``) + breaks installation in some scenarios, e.g. ``setup.py install`` or + older versions of ``pip``. Ensure that ``setuptools`` is installed + if using Python before 3.8. + 4.2.5 (2022-12-23) ------------------ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/supervisor-4.2.5/docs/api.rst new/supervisor-4.3.0/docs/api.rst --- old/supervisor-4.2.5/docs/api.rst 2022-12-24 01:00:25.000000000 +0100 +++ new/supervisor-4.3.0/docs/api.rst 2025-08-22 20:30:10.000000000 +0200 @@ -297,7 +297,7 @@ .. describe:: stderr_logfile - Absolute path and filename to the STDOUT logfile + Absolute path and filename to the STDERR logfile .. describe:: spawnerr diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/supervisor-4.2.5/docs/configuration.rst new/supervisor-4.3.0/docs/configuration.rst --- old/supervisor-4.2.5/docs/configuration.rst 2022-12-24 01:10:22.000000000 +0100 +++ new/supervisor-4.3.0/docs/configuration.rst 2025-08-23 20:15:21.000000000 +0200 @@ -1480,9 +1480,9 @@ ``result_handler`` - A `pkg_resources entry point string - <http://peak.telecommunity.com/DevCenter/PkgResources>`_ that - resolves to a Python callable. The default value is + An `entry point object reference + <https://packaging.python.org/en/latest/specifications/entry-points/#data-model>`_ + string that resolves to a Python callable. The default value is ``supervisor.dispatchers:default_handler``. Specifying an alternate result handler is a very uncommon thing to need to do, and as a result, how to create one is not documented. @@ -1583,7 +1583,7 @@ ``supervisor.rpcinterface_factory`` - ``pkg_resources`` "entry point" dotted name to your RPC interface's + ``entry point object reference`` dotted name to your RPC interface's factory function. *Default*: N/A diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/supervisor-4.2.5/docs/events.rst new/supervisor-4.3.0/docs/events.rst --- old/supervisor-4.2.5/docs/events.rst 2022-12-24 01:00:25.000000000 +0100 +++ new/supervisor-4.3.0/docs/events.rst 2025-08-22 20:34:27.000000000 +0200 @@ -93,9 +93,9 @@ An advanced feature, specifying an alternate "result handler" for a pool, can be specified via the ``result_handler`` parameter of an - ``[eventlistener:x]`` section in the form of a `pkg_resources - <http://peak.telecommunity.com/DevCenter/PkgResources>`_ "entry - point" string. The default result handler is + ``[eventlistener:x]`` section in the form of an `entry point object reference + <https://packaging.python.org/en/latest/specifications/entry-points/#data-model>`_ + string. The default result handler is ``supervisord.dispatchers:default_handler``. Creating an alternate result handler is not currently documented. @@ -660,7 +660,7 @@ .. code-block:: text - processname:name groupname:name pid:pid + processname:name groupname:name pid:pid channel:stdout data ``PROCESS_LOG_STDERR`` Event Type @@ -680,7 +680,7 @@ .. code-block:: text - processname:name groupname:name pid:pid + processname:name groupname:name pid:pid channel:stderr data ``PROCESS_COMMUNICATION`` Event Type @@ -897,4 +897,3 @@ .. code-block:: text groupname:cat - diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/supervisor-4.2.5/docs/installing.rst new/supervisor-4.3.0/docs/installing.rst --- old/supervisor-4.2.5/docs/installing.rst 2022-11-25 18:42:03.000000000 +0100 +++ new/supervisor-4.3.0/docs/installing.rst 2025-08-23 19:25:32.000000000 +0200 @@ -22,6 +22,12 @@ You can also install supervisor in a virtualenv via ``pip``. +.. note:: + + If installing on a Python version before 3.8, first ensure that the + ``setuptools`` package is installed because it is a runtime + dependency of Supervisor. + Internet-Installing Without Pip ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -39,6 +45,12 @@ need to be the root user to successfully invoke ``python setup.py install``. +.. note:: + + The ``setuptools`` package is required to run ``python setup.py install``. + On Python versions before 3.8, ``setuptools`` is also a runtime + dependency of Supervisor. + Installing To A System Without Internet Access ---------------------------------------------- @@ -48,11 +60,8 @@ install`` depend on internet access to perform downloads of dependent software, neither will work on machines without internet access until dependencies are installed. To install to a machine which is not -internet-connected, obtain the following dependencies on a machine -which is internet-connected: - -- setuptools (latest) from `https://pypi.org/pypi/setuptools/ - <https://pypi.org/pypi/setuptools/>`_. +internet-connected, obtain the dependencies listed in ``setup.py`` +using a machine which is internet-connected. Copy these files to removable media and put them on the target machine. Install each onto the target machine as per its @@ -66,6 +75,12 @@ need to be the root user to invoke ``python setup.py install`` successfully for each package. +.. note:: + + The ``setuptools`` package is required to run ``python setup.py install``. + On Python versions before 3.8, ``setuptools`` is also a runtime + dependency of Supervisor. + Installing a Distribution Package --------------------------------- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/supervisor-4.2.5/docs/introduction.rst new/supervisor-4.3.0/docs/introduction.rst --- old/supervisor-4.2.5/docs/introduction.rst 2022-11-25 18:42:03.000000000 +0100 +++ new/supervisor-4.3.0/docs/introduction.rst 2025-08-22 20:26:29.000000000 +0200 @@ -134,7 +134,7 @@ The command-line client talks to the server across a UNIX domain socket or an internet (TCP) socket. The server can assert that the user of a client should present authentication credentials before it - allows him to perform commands. The client process typically uses + allows them to perform commands. The client process typically uses the same configuration file as the server but any configuration file with a ``[supervisorctl]`` section in it will work. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/supervisor-4.2.5/docs/plugins.rst new/supervisor-4.3.0/docs/plugins.rst --- old/supervisor-4.2.5/docs/plugins.rst 2022-11-25 18:42:03.000000000 +0100 +++ new/supervisor-4.3.0/docs/plugins.rst 2025-08-22 20:32:10.000000000 +0200 @@ -25,6 +25,9 @@ `Supervisord-Monitor <https://github.com/mlazarov/supervisord-monitor>`_ Web-based dashboard written in PHP. +`Supervisord-Monitor 2 <https://github.com/KoNekoD/supervisord-monitor>`_ + Modern and adaptive next gen web-based dashboard written in PHP. + `SupervisorUI <https://github.com/luxbet/supervisorui>`_ Another Web-based dashboard written in PHP. @@ -49,6 +52,11 @@ Web-based dashboard and command line tool written in Python using PostgreSQL with a REST API, event monitoring, and configuration management. +`Polyvisor <https://github.com/poly-laboratory/poly-visor>`_ + Web-based dashboard written in Python using `flask <http://flask.pocoo.org>`_ web server. + Frontend based on `Svelte <https://svelte.dev/>`_ result in lightweighted packages. Communicate via supervisor's event-listener. + Providing system resource management via visualized charts & easy to config processes configs via web interface. + Third Party Plugins and Libraries for Supervisor ------------------------------------------------ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/supervisor-4.2.5/docs/subprocess.rst new/supervisor-4.3.0/docs/subprocess.rst --- old/supervisor-4.2.5/docs/subprocess.rst 2022-12-24 01:00:25.000000000 +0100 +++ new/supervisor-4.3.0/docs/subprocess.rst 2025-08-22 20:31:46.000000000 +0200 @@ -263,7 +263,7 @@ So if you set ``startretries=3``, :program:`supervisord` will wait one, two and then three seconds between each restart attempt, for a total of - 5 seconds. + 6 seconds. When a process is in the ``EXITED`` state, it will automatically restart: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/supervisor-4.2.5/setup.cfg new/supervisor-4.3.0/setup.cfg --- old/supervisor-4.2.5/setup.cfg 2022-12-24 01:52:25.397492200 +0100 +++ new/supervisor-4.3.0/setup.cfg 2025-08-23 20:16:31.149440500 +0200 @@ -1,9 +1,6 @@ [easy_install] zip_ok = false -[aliases] -dev = develop easy_install supervisor[testing] - [bdist_wheel] universal = 1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/supervisor-4.2.5/setup.py new/supervisor-4.3.0/setup.py --- old/supervisor-4.2.5/setup.py 2022-12-23 23:54:41.000000000 +0100 +++ new/supervisor-4.3.0/setup.py 2025-08-23 19:26:19.000000000 +0200 @@ -22,16 +22,19 @@ elif (3, 0) < py_version < (3, 4): raise RuntimeError('On Python 3, Supervisor requires Python 3.4 or later') -# pkg_resource is used in several places -requires = ["setuptools"] -tests_require = [] -if py_version < (3, 3): - tests_require.append('mock<4.0.0.dev0') - -testing_extras = tests_require + [ - 'pytest', - 'pytest-cov', - ] +# setuptools is required as a runtime dependency only on Python < 3.8. +# See the comments in supervisor/compat.py. An environment marker +# like "setuptools; python_version < '3.8'" is not used here because +# it breaks installation via "python setup.py install". See also the +# discussion at: https://github.com/Supervisor/supervisor/issues/1692 +if py_version < (3, 8): + try: + import pkg_resources + except ImportError: + raise RuntimeError( + "On Python < 3.8, Supervisor requires setuptools as a runtime" + " dependency because pkg_resources is used to load plugins" + ) from setuptools import setup, find_packages here = os.path.abspath(os.path.dirname(__file__)) @@ -66,6 +69,9 @@ "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", ] version_txt = os.path.join(here, 'supervisor/version.txt') @@ -77,20 +83,23 @@ version=supervisor_version, license='BSD-derived (http://www.repoze.org/LICENSE.txt)', url='http://supervisord.org/', + project_urls={ + 'Changelog': 'http://supervisord.org/changelog', + 'Documentation': 'http://supervisord.org', + 'Issue Tracker': 'https://github.com/Supervisor/supervisor', + }, description="A system for controlling process state under UNIX", long_description=README + '\n\n' + CHANGES, classifiers=CLASSIFIERS, author="Chris McDonough", author_email="[email protected]", packages=find_packages(), - install_requires=requires, + install_requires=[], extras_require={ - 'testing': testing_extras, - }, - tests_require=tests_require, + 'test': ['pytest', 'pytest-cov'] + }, include_package_data=True, zip_safe=False, - test_suite="supervisor.tests", entry_points={ 'console_scripts': [ 'supervisord = supervisor.supervisord:main', diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/supervisor-4.2.5/supervisor/compat.py new/supervisor-4.3.0/supervisor/compat.py --- old/supervisor-4.2.5/supervisor/compat.py 2022-11-25 18:42:03.000000000 +0100 +++ new/supervisor-4.3.0/supervisor/compat.py 2025-08-22 20:26:50.000000000 +0200 @@ -149,3 +149,52 @@ from html.parser import HTMLParser except ImportError: # pragma: no cover from HTMLParser import HTMLParser + +# Begin importlib/setuptools compatibility code + +# Supervisor used pkg_resources (a part of setuptools) to load package +# resources for 15 years, until setuptools 67.5.0 (2023-03-05) deprecated +# the use of pkg_resources. On Python 3.8 or later, Supervisor now uses +# importlib (part of Python 3 stdlib). Unfortunately, on Python < 3.8, +# Supervisor needs to use pkg_resources despite its deprecation. The PyPI +# backport packages "importlib-resources" and "importlib-metadata" couldn't +# be added as dependencies to Supervisor because they require even more +# dependencies that would likely cause some Supervisor installs to fail. +from warnings import filterwarnings as _fw +_fw("ignore", message="pkg_resources is deprecated as an API") + +try: # pragma: no cover + from importlib.metadata import EntryPoint as _EntryPoint + + def import_spec(spec): + return _EntryPoint(None, spec, None).load() + +except ImportError: # pragma: no cover + from pkg_resources import EntryPoint as _EntryPoint + + def import_spec(spec): + ep = _EntryPoint.parse("x=" + spec) + if hasattr(ep, 'resolve'): + # this is available on setuptools >= 10.2 + return ep.resolve() + else: + # this causes a DeprecationWarning on setuptools >= 11.3 + return ep.load(False) + +try: # pragma: no cover + import importlib.resources as _importlib_resources + + if hasattr(_importlib_resources, "files"): + def resource_filename(package, path): + return str(_importlib_resources.files(package).joinpath(path)) + + else: + # fall back to deprecated .path if .files is not available + def resource_filename(package, path): + with _importlib_resources.path(package, '__init__.py') as p: + return str(p.parent.joinpath(path)) + +except ImportError: # pragma: no cover + from pkg_resources import resource_filename + +# End importlib/setuptools compatibility code diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/supervisor-4.2.5/supervisor/confecho.py new/supervisor-4.3.0/supervisor/confecho.py --- old/supervisor-4.2.5/supervisor/confecho.py 2022-11-25 18:42:03.000000000 +0100 +++ new/supervisor-4.3.0/supervisor/confecho.py 2025-08-22 20:26:50.000000000 +0200 @@ -1,7 +1,8 @@ -import pkg_resources import sys from supervisor.compat import as_string +from supervisor.compat import resource_filename + def main(out=sys.stdout): - config = pkg_resources.resource_string(__name__, 'skel/sample.conf') - out.write(as_string(config)) + with open(resource_filename(__package__, 'skel/sample.conf'), 'r') as f: + out.write(as_string(f.read())) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/supervisor-4.2.5/supervisor/http_client.py new/supervisor-4.3.0/supervisor/http_client.py --- old/supervisor-4.2.5/supervisor/http_client.py 2022-11-25 18:42:03.000000000 +0100 +++ new/supervisor-4.3.0/supervisor/http_client.py 2025-08-22 20:27:35.000000000 +0200 @@ -1,4 +1,4 @@ -# this code based on Daniel Krech's RDFLib HTTP client code (see rdflib.net) +# this code based on Daniel Krech's RDFLib HTTP client code (see rdflib.dev) import sys import socket diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/supervisor-4.2.5/supervisor/medusa/asyncore_25.py new/supervisor-4.3.0/supervisor/medusa/asyncore_25.py --- old/supervisor-4.2.5/supervisor/medusa/asyncore_25.py 2022-11-25 18:42:03.000000000 +0100 +++ new/supervisor-4.3.0/supervisor/medusa/asyncore_25.py 2025-08-22 20:32:01.000000000 +0200 @@ -358,7 +358,16 @@ def close(self): self.del_channel() - self.socket.close() + + try: + self.socket.shutdown(socket.SHUT_RDWR) + except socket.error: + # must swallow exception from already-closed socket + # (at least with Python 3.11.7 on macOS 14.2.1) + pass + + # does not raise if called on already-closed socket + self.socket.close() # cheap inheritance, used to pass all other attribute # references to the underlying socket object. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/supervisor-4.2.5/supervisor/options.py new/supervisor-4.3.0/supervisor/options.py --- old/supervisor-4.2.5/supervisor/options.py 2022-12-24 01:10:22.000000000 +0100 +++ new/supervisor-4.3.0/supervisor/options.py 2025-08-23 20:15:21.000000000 +0200 @@ -10,7 +10,6 @@ import grp import resource import stat -import pkg_resources import glob import platform import warnings @@ -22,6 +21,7 @@ from supervisor.compat import xmlrpclib from supervisor.compat import StringIO from supervisor.compat import basestring +from supervisor.compat import import_spec from supervisor.medusa import asyncore_25 as asyncore @@ -374,7 +374,7 @@ (section, factory_key)) try: factory = self.import_spec(factory_spec) - except ImportError: + except (AttributeError, ImportError): raise ValueError('%s cannot be resolved within [%s]' % ( factory_spec, section)) @@ -387,13 +387,8 @@ return factories def import_spec(self, spec): - ep = pkg_resources.EntryPoint.parse("x=" + spec) - if hasattr(ep, 'resolve'): - # this is available on setuptools >= 10.2 - return ep.resolve() - else: - # this causes a DeprecationWarning on setuptools >= 11.3 - return ep.load(False) + """On failure, raises either AttributeError or ImportError""" + return import_spec(spec) class ServerOptions(Options): @@ -748,7 +743,7 @@ 'supervisor.dispatchers:default_handler') try: result_handler = self.import_spec(result_handler) - except ImportError: + except (AttributeError, ImportError): raise ValueError('%s cannot be resolved within [%s]' % ( result_handler, section)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/supervisor-4.2.5/supervisor/supervisord.py new/supervisor-4.3.0/supervisor/supervisord.py --- old/supervisor-4.2.5/supervisor/supervisord.py 2022-12-24 01:00:25.000000000 +0100 +++ new/supervisor-4.3.0/supervisor/supervisord.py 2025-08-22 20:33:34.000000000 +0200 @@ -222,6 +222,14 @@ raise except: combined_map[fd].handle_error() + else: + # if the fd is not in combined_map, we should unregister it. otherwise, + # it will be polled every time, which may cause 100% cpu usage + self.options.logger.blather('unexpected read event from fd %r' % fd) + try: + self.options.poller.unregister_readable(fd) + except: + pass for fd in w: if fd in combined_map: @@ -237,6 +245,12 @@ raise except: combined_map[fd].handle_error() + else: + self.options.logger.blather('unexpected write event from fd %r' % fd) + try: + self.options.poller.unregister_writable(fd) + except: + pass for group in pgroups: group.transition() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/supervisor-4.2.5/supervisor/tests/fixtures/issue-1596.conf new/supervisor-4.3.0/supervisor/tests/fixtures/issue-1596.conf --- old/supervisor-4.2.5/supervisor/tests/fixtures/issue-1596.conf 1970-01-01 01:00:00.000000000 +0100 +++ new/supervisor-4.3.0/supervisor/tests/fixtures/issue-1596.conf 2025-08-22 20:32:01.000000000 +0200 @@ -0,0 +1,12 @@ +[supervisord] +loglevel=info ; log level; default info; others: debug,warn,trace +logfile=/tmp/issue-1596.log ; main log file; default $CWD/supervisord.log +pidfile=/tmp/issue-1596.pid ; supervisord pidfile; default supervisord.pid +nodaemon=true ; start in foreground if true; default false +identifier=from_config_file + +[rpcinterface:supervisor] +supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface + +[unix_http_server] +file=/tmp/issue-1596.sock ; the path to the socket file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/supervisor-4.2.5/supervisor/tests/test_childutils.py new/supervisor-4.3.0/supervisor/tests/test_childutils.py --- old/supervisor-4.2.5/supervisor/tests/test_childutils.py 2022-11-25 18:42:03.000000000 +0100 +++ new/supervisor-4.3.0/supervisor/tests/test_childutils.py 2025-08-22 20:19:42.000000000 +0200 @@ -132,10 +132,3 @@ listener.send(msg, stdout) expected = '%s%s\n%s' % (begin, len(msg), msg) self.assertEqual(stdout.getvalue(), expected) - - -def test_suite(): - return unittest.findTestCases(sys.modules[__name__]) - -if __name__ == '__main__': - unittest.main(defaultTest='test_suite') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/supervisor-4.2.5/supervisor/tests/test_confecho.py new/supervisor-4.3.0/supervisor/tests/test_confecho.py --- old/supervisor-4.2.5/supervisor/tests/test_confecho.py 2022-11-25 18:42:03.000000000 +0100 +++ new/supervisor-4.3.0/supervisor/tests/test_confecho.py 2025-08-22 20:21:55.000000000 +0200 @@ -1,6 +1,5 @@ """Test suite for supervisor.confecho""" -import sys import unittest from supervisor.compat import StringIO from supervisor import confecho @@ -12,10 +11,3 @@ output = sio.getvalue() self.assertTrue("[supervisord]" in output) - - -def test_suite(): - return unittest.findTestCases(sys.modules[__name__]) - -if __name__ == '__main__': - unittest.main(defaultTest='test_suite') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/supervisor-4.2.5/supervisor/tests/test_dispatchers.py new/supervisor-4.3.0/supervisor/tests/test_dispatchers.py --- old/supervisor-4.2.5/supervisor/tests/test_dispatchers.py 2022-11-25 18:42:03.000000000 +0100 +++ new/supervisor-4.3.0/supervisor/tests/test_dispatchers.py 2025-08-22 20:21:55.000000000 +0200 @@ -1,6 +1,5 @@ import unittest import os -import sys from supervisor.compat import as_bytes @@ -1227,9 +1226,3 @@ def test_noansi(self): noansi = b'Hello world... this is longer than a token!' self.assertEqual(self._callFUT(noansi), noansi) - -def test_suite(): - return unittest.findTestCases(sys.modules[__name__]) - -if __name__ == '__main__': - unittest.main(defaultTest='test_suite') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/supervisor-4.2.5/supervisor/tests/test_end_to_end.py new/supervisor-4.3.0/supervisor/tests/test_end_to_end.py --- old/supervisor-4.2.5/supervisor/tests/test_end_to_end.py 2022-11-25 18:42:03.000000000 +0100 +++ new/supervisor-4.3.0/supervisor/tests/test_end_to_end.py 2025-08-22 20:32:01.000000000 +0200 @@ -5,11 +5,10 @@ import signal import sys import unittest -import pkg_resources +from supervisor.compat import resource_filename from supervisor.compat import xmlrpclib from supervisor.xmlrpc import SupervisorTransport - # end-to-test tests are slow so only run them when asked if 'END_TO_END' in os.environ: import pexpect @@ -26,7 +25,7 @@ passed to the child without the percent sign being mangled.""" key = "SUPERVISOR_TEST_1441B" val = "foo_%s_%_%%_%%%_%2_bar" - filename = pkg_resources.resource_filename(__name__, 'fixtures/issue-291a.conf') + filename = resource_filename(__package__, 'fixtures/issue-291a.conf') args = ['-m', 'supervisor.supervisord', '-c', filename] try: os.environ[key] = val @@ -39,7 +38,7 @@ def test_issue_550(self): """When an environment variable is set in the [supervisord] section, it should be put into the environment of the subprocess.""" - filename = pkg_resources.resource_filename(__name__, 'fixtures/issue-550.conf') + filename = resource_filename(__package__, 'fixtures/issue-550.conf') args = ['-m', 'supervisor.supervisord', '-c', filename] supervisord = pexpect.spawn(sys.executable, args, encoding='utf-8') self.addCleanup(supervisord.kill, signal.SIGINT) @@ -55,7 +54,7 @@ def test_issue_565(self): """When a log file has Unicode characters in it, 'supervisorctl tail -f name' should still work.""" - filename = pkg_resources.resource_filename(__name__, 'fixtures/issue-565.conf') + filename = resource_filename(__package__, 'fixtures/issue-565.conf') args = ['-m', 'supervisor.supervisord', '-c', filename] supervisord = pexpect.spawn(sys.executable, args, encoding='utf-8') self.addCleanup(supervisord.kill, signal.SIGINT) @@ -72,7 +71,7 @@ def test_issue_638(self): """When a process outputs something on its stdout or stderr file descriptor that is not valid UTF-8, supervisord should not crash.""" - filename = pkg_resources.resource_filename(__name__, 'fixtures/issue-638.conf') + filename = resource_filename(__package__, 'fixtures/issue-638.conf') args = ['-m', 'supervisor.supervisord', '-c', filename] supervisord = pexpect.spawn(sys.executable, args, encoding='utf-8') self.addCleanup(supervisord.kill, signal.SIGINT) @@ -91,7 +90,7 @@ def test_issue_663(self): """When Supervisor is run on Python 3, the eventlistener protocol should work.""" - filename = pkg_resources.resource_filename(__name__, 'fixtures/issue-663.conf') + filename = resource_filename(__package__, 'fixtures/issue-663.conf') args = ['-m', 'supervisor.supervisord', '-c', filename] supervisord = pexpect.spawn(sys.executable, args, encoding='utf-8') self.addCleanup(supervisord.kill, signal.SIGINT) @@ -103,7 +102,7 @@ """When a subprocess name has Unicode characters, 'supervisord' should not send incomplete XML-RPC responses and 'supervisorctl status' should work.""" - filename = pkg_resources.resource_filename(__name__, 'fixtures/issue-664.conf') + filename = resource_filename(__package__, 'fixtures/issue-664.conf') args = ['-m', 'supervisor.supervisord', '-c', filename] supervisord = pexpect.spawn(sys.executable, args, encoding='utf-8') self.addCleanup(supervisord.kill, signal.SIGINT) @@ -122,7 +121,7 @@ def test_issue_733(self): """When a subprocess enters the FATAL state, a one-line eventlistener can be used to signal supervisord to shut down.""" - filename = pkg_resources.resource_filename(__name__, 'fixtures/issue-733.conf') + filename = resource_filename(__package__, 'fixtures/issue-733.conf') args = ['-m', 'supervisor.supervisord', '-c', filename] supervisord = pexpect.spawn(sys.executable, args, encoding='utf-8') self.addCleanup(supervisord.kill, signal.SIGINT) @@ -131,7 +130,7 @@ supervisord.expect(pexpect.EOF) def test_issue_835(self): - filename = pkg_resources.resource_filename(__name__, 'fixtures/issue-835.conf') + filename = resource_filename(__package__, 'fixtures/issue-835.conf') args = ['-m', 'supervisor.supervisord', '-c', filename] supervisord = pexpect.spawn(sys.executable, args, encoding='utf-8') self.addCleanup(supervisord.kill, signal.SIGINT) @@ -147,7 +146,7 @@ transport.connection.close() def test_issue_836(self): - filename = pkg_resources.resource_filename(__name__, 'fixtures/issue-836.conf') + filename = resource_filename(__package__, 'fixtures/issue-836.conf') args = ['-m', 'supervisor.supervisord', '-c', filename] supervisord = pexpect.spawn(sys.executable, args, encoding='utf-8') self.addCleanup(supervisord.kill, signal.SIGINT) @@ -170,7 +169,7 @@ def test_issue_986_command_string_with_double_percent(self): """A percent sign can be used in a command= string without being expanded if it is escaped by a second percent sign.""" - filename = pkg_resources.resource_filename(__name__, 'fixtures/issue-986.conf') + filename = resource_filename(__package__, 'fixtures/issue-986.conf') args = ['-m', 'supervisor.supervisord', '-c', filename] supervisord = pexpect.spawn(sys.executable, args, encoding='utf-8') self.addCleanup(supervisord.kill, signal.SIGINT) @@ -179,7 +178,7 @@ def test_issue_1054(self): """When run on Python 3, the 'supervisorctl avail' command should work.""" - filename = pkg_resources.resource_filename(__name__, 'fixtures/issue-1054.conf') + filename = resource_filename(__package__, 'fixtures/issue-1054.conf') args = ['-m', 'supervisor.supervisord', '-c', filename] supervisord = pexpect.spawn(sys.executable, args, encoding='utf-8') self.addCleanup(supervisord.kill, signal.SIGINT) @@ -197,7 +196,7 @@ """When the [supervisord] section has a variable defined in environment=, that variable should be able to be used in an %(ENV_x) expansion in a [program] section.""" - filename = pkg_resources.resource_filename(__name__, 'fixtures/issue-1170a.conf') + filename = resource_filename(__package__, 'fixtures/issue-1170a.conf') args = ['-m', 'supervisor.supervisord', '-c', filename] supervisord = pexpect.spawn(sys.executable, args, encoding='utf-8') self.addCleanup(supervisord.kill, signal.SIGINT) @@ -208,7 +207,7 @@ environment=, and a variable by the same name is defined in enviroment= of a [program] section, the one in the [program] section should be used.""" - filename = pkg_resources.resource_filename(__name__, 'fixtures/issue-1170b.conf') + filename = resource_filename(__package__, 'fixtures/issue-1170b.conf') args = ['-m', 'supervisor.supervisord', '-c', filename] supervisord = pexpect.spawn(sys.executable, args, encoding='utf-8') self.addCleanup(supervisord.kill, signal.SIGINT) @@ -219,7 +218,7 @@ environment=, and a variable by the same name is defined in enviroment= of an [eventlistener] section, the one in the [eventlistener] section should be used.""" - filename = pkg_resources.resource_filename(__name__, 'fixtures/issue-1170c.conf') + filename = resource_filename(__package__, 'fixtures/issue-1170c.conf') args = ['-m', 'supervisor.supervisord', '-c', filename] supervisord = pexpect.spawn(sys.executable, args, encoding='utf-8') self.addCleanup(supervisord.kill, signal.SIGINT) @@ -230,7 +229,7 @@ then the non-rotating logger will be used to avoid an IllegalSeekError in the case that the user has configured a non-seekable file like /dev/stdout.""" - filename = pkg_resources.resource_filename(__name__, 'fixtures/issue-1224.conf') + filename = resource_filename(__package__, 'fixtures/issue-1224.conf') args = ['-m', 'supervisor.supervisord', '-c', filename] supervisord = pexpect.spawn(sys.executable, args, encoding='utf-8') self.addCleanup(supervisord.kill, signal.SIGINT) @@ -239,7 +238,7 @@ def test_issue_1231a(self): """When 'supervisorctl tail -f name' is run and the log contains unicode, it should not fail.""" - filename = pkg_resources.resource_filename(__name__, 'fixtures/issue-1231a.conf') + filename = resource_filename(__package__, 'fixtures/issue-1231a.conf') args = ['-m', 'supervisor.supervisord', '-c', filename] supervisord = pexpect.spawn(sys.executable, args, encoding='utf-8') self.addCleanup(supervisord.kill, signal.SIGINT) @@ -256,7 +255,7 @@ def test_issue_1231b(self): """When 'supervisorctl tail -f name' is run and the log contains unicode, it should not fail.""" - filename = pkg_resources.resource_filename(__name__, 'fixtures/issue-1231b.conf') + filename = resource_filename(__package__, 'fixtures/issue-1231b.conf') args = ['-m', 'supervisor.supervisord', '-c', filename] supervisord = pexpect.spawn(sys.executable, args, encoding='utf-8') self.addCleanup(supervisord.kill, signal.SIGINT) @@ -290,7 +289,7 @@ def test_issue_1231c(self): """When 'supervisorctl tail -f name' is run and the log contains unicode, it should not fail.""" - filename = pkg_resources.resource_filename(__name__, 'fixtures/issue-1231c.conf') + filename = resource_filename(__package__, 'fixtures/issue-1231c.conf') args = ['-m', 'supervisor.supervisord', '-c', filename] supervisord = pexpect.spawn(sys.executable, args, encoding='utf-8') self.addCleanup(supervisord.kill, signal.SIGINT) @@ -332,7 +331,7 @@ """When the output of 'supervisorctl tail -f worker' is piped such as 'supervisor tail -f worker | grep something', 'supervisorctl' should not crash.""" - filename = pkg_resources.resource_filename(__name__, 'fixtures/issue-1298.conf') + filename = resource_filename(__package__, 'fixtures/issue-1298.conf') args = ['-m', 'supervisor.supervisord', '-c', filename] supervisord = pexpect.spawn(sys.executable, args, encoding='utf-8') self.addCleanup(supervisord.kill, signal.SIGINT) @@ -366,7 +365,7 @@ def test_issue_1483a_identifier_default(self): """When no identifier is supplied on the command line or in the config file, the default is used.""" - filename = pkg_resources.resource_filename(__name__, 'fixtures/issue-1483a.conf') + filename = resource_filename(__package__, 'fixtures/issue-1483a.conf') args = ['-m', 'supervisor.supervisord', '-c', filename] supervisord = pexpect.spawn(sys.executable, args, encoding='utf-8') self.addCleanup(supervisord.kill, signal.SIGINT) @@ -385,7 +384,7 @@ def test_issue_1483b_identifier_from_config_file(self): """When the identifier is supplied in the config file only, that identifier is used instead of the default.""" - filename = pkg_resources.resource_filename(__name__, 'fixtures/issue-1483b.conf') + filename = resource_filename(__package__, 'fixtures/issue-1483b.conf') args = ['-m', 'supervisor.supervisord', '-c', filename] supervisord = pexpect.spawn(sys.executable, args, encoding='utf-8') self.addCleanup(supervisord.kill, signal.SIGINT) @@ -404,7 +403,7 @@ def test_issue_1483c_identifier_from_command_line(self): """When an identifier is supplied in both the config file and on the command line, the one from the command line is used.""" - filename = pkg_resources.resource_filename(__name__, 'fixtures/issue-1483c.conf') + filename = resource_filename(__package__, 'fixtures/issue-1483c.conf') args = ['-m', 'supervisor.supervisord', '-c', filename, '-i', 'from_command_line'] supervisord = pexpect.spawn(sys.executable, args, encoding='utf-8') self.addCleanup(supervisord.kill, signal.SIGINT) @@ -420,8 +419,39 @@ transport.close() self.assertEqual(ident, "from_command_line") -def test_suite(): - return unittest.findTestCases(sys.modules[__name__]) + def test_pull_request_1578_echo_supervisord_conf(self): + """The command echo_supervisord_conf, whose implementation depends on + importlib.resources to work, should print the example config.""" + args = ['-c', 'from supervisor import confecho; confecho.main()'] + echo_supervisord_conf = pexpect.spawn(sys.executable, args, encoding='utf-8') + self.addCleanup(echo_supervisord_conf.kill, signal.SIGKILL) + echo_supervisord_conf.expect_exact('Sample supervisor config file') + + def test_issue_1596_asyncore_close_does_not_crash(self): + """If the socket is already closed when socket.shutdown(socket.SHUT_RDWR) + is called in the close() method of an asyncore dispatcher, an exception + will be raised (at least with Python 3.11.7 on macOS 14.2.1). If it is + not caught in that method, supervisord will crash.""" + filename = resource_filename(__package__, 'fixtures/issue-1596.conf') + args = ['-m', 'supervisor.supervisord', '-c', filename] + supervisord = pexpect.spawn(sys.executable, args, encoding='utf-8') + self.addCleanup(supervisord.kill, signal.SIGINT) + supervisord.expect_exact('supervisord started with pid') + + from supervisor.compat import xmlrpclib + from supervisor.xmlrpc import SupervisorTransport + + socket_url = 'unix:///tmp/issue-1596.sock' + dummy_url = 'http://transport.ignores.host/RPC2' -if __name__ == '__main__': - unittest.main(defaultTest='test_suite') + # supervisord will crash after close() if it has the bug + t1 = SupervisorTransport('', '', socket_url) + s1 = xmlrpclib.ServerProxy(dummy_url, t1) + s1.system.listMethods() + t1.close() + + # this call will only succeed if supervisord did not crash + t2 = SupervisorTransport('', '', socket_url) + s2 = xmlrpclib.ServerProxy(dummy_url, t2) + s2.system.listMethods() + t2.close() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/supervisor-4.2.5/supervisor/tests/test_events.py new/supervisor-4.3.0/supervisor/tests/test_events.py --- old/supervisor-4.2.5/supervisor/tests/test_events.py 2022-12-24 01:00:25.000000000 +0100 +++ new/supervisor-4.3.0/supervisor/tests/test_events.py 2025-08-22 20:21:55.000000000 +0200 @@ -1,4 +1,3 @@ -import sys import unittest from supervisor.tests.base import DummyOptions @@ -508,10 +507,3 @@ self.assertTrue(events.EventTypes.FOO is FooEvent) finally: del events.EventTypes.FOO - -def test_suite(): - return unittest.findTestCases(sys.modules[__name__]) - -if __name__ == '__main__': - unittest.main(defaultTest='test_suite') - diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/supervisor-4.2.5/supervisor/tests/test_http.py new/supervisor-4.3.0/supervisor/tests/test_http.py --- old/supervisor-4.2.5/supervisor/tests/test_http.py 2022-12-24 01:10:43.000000000 +0100 +++ new/supervisor-4.3.0/supervisor/tests/test_http.py 2025-08-22 20:21:55.000000000 +0200 @@ -1,7 +1,6 @@ import base64 import os import stat -import sys import socket import tempfile import unittest @@ -684,9 +683,3 @@ return self.data.pop(0) else: return b'' - -def test_suite(): - return unittest.findTestCases(sys.modules[__name__]) - -if __name__ == '__main__': - unittest.main(defaultTest='test_suite') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/supervisor-4.2.5/supervisor/tests/test_loggers.py new/supervisor-4.3.0/supervisor/tests/test_loggers.py --- old/supervisor-4.2.5/supervisor/tests/test_loggers.py 2022-11-25 18:42:03.000000000 +0100 +++ new/supervisor-4.3.0/supervisor/tests/test_loggers.py 2025-08-22 20:19:42.000000000 +0200 @@ -599,9 +599,3 @@ self.records.append(record) def close(self): self.closed = True - -def test_suite(): - return unittest.findTestCases(sys.modules[__name__]) - -if __name__ == '__main__': - unittest.main(defaultTest='test_suite') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/supervisor-4.2.5/supervisor/tests/test_options.py new/supervisor-4.3.0/supervisor/tests/test_options.py --- old/supervisor-4.2.5/supervisor/tests/test_options.py 2022-12-24 01:10:43.000000000 +0100 +++ new/supervisor-4.3.0/supervisor/tests/test_options.py 2025-08-23 20:15:21.000000000 +0200 @@ -2606,7 +2606,26 @@ gconfig1 = gconfigs[0] self.assertEqual(gconfig1.result_handler, dummy_handler) - def test_event_listener_pool_result_handler_unimportable(self): + def test_event_listener_pool_result_handler_unimportable_ImportError(self): + text = lstrip("""\ + [eventlistener:cat] + events=PROCESS_COMMUNICATION + command = /bin/cat + result_handler = thisishopefullynotanimportablepackage:nonexistent + """) + from supervisor.options import UnhosedConfigParser + config = UnhosedConfigParser() + config.read_string(text) + instance = self._makeOne() + try: + instance.process_groups_from_parser(config) + self.fail('nothing raised') + except ValueError as exc: + self.assertEqual(exc.args[0], + 'thisishopefullynotanimportablepackage:nonexistent cannot be ' + 'resolved within [eventlistener:cat]') + + def test_event_listener_pool_result_handler_unimportable_AttributeError(self): text = lstrip("""\ [eventlistener:cat] events=PROCESS_COMMUNICATION @@ -3804,10 +3823,3 @@ self.assertEqual(s('process'), ('process', 'process')) self.assertEqual(s('group:'), ('group', None)) self.assertEqual(s('group:*'), ('group', None)) - -def test_suite(): - return unittest.findTestCases(sys.modules[__name__]) - -if __name__ == '__main__': - unittest.main(defaultTest='test_suite') - diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/supervisor-4.2.5/supervisor/tests/test_poller.py new/supervisor-4.3.0/supervisor/tests/test_poller.py --- old/supervisor-4.2.5/supervisor/tests/test_poller.py 2022-11-25 18:42:03.000000000 +0100 +++ new/supervisor-4.3.0/supervisor/tests/test_poller.py 2025-08-22 20:21:55.000000000 +0200 @@ -1,4 +1,3 @@ -import sys import unittest import errno import select @@ -437,10 +436,3 @@ def __init__(self, ident, filter): self.ident = ident self.filter = filter - - -def test_suite(): - return unittest.findTestCases(sys.modules[__name__]) - -if __name__ == '__main__': - unittest.main(defaultTest='test_suite') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/supervisor-4.2.5/supervisor/tests/test_process.py new/supervisor-4.3.0/supervisor/tests/test_process.py --- old/supervisor-4.2.5/supervisor/tests/test_process.py 2022-12-24 01:00:25.000000000 +0100 +++ new/supervisor-4.3.0/supervisor/tests/test_process.py 2025-08-22 20:34:55.000000000 +0200 @@ -39,7 +39,7 @@ from supervisor.states import ProcessStates from supervisor.process import getProcessStateDescription for statename, code in ProcessStates.__dict__.items(): - if isinstance(code, int): + if not statename.startswith("__"): self.assertEqual(getProcessStateDescription(code), statename) def test_ctor(self): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/supervisor-4.2.5/supervisor/tests/test_rpcinterfaces.py new/supervisor-4.3.0/supervisor/tests/test_rpcinterfaces.py --- old/supervisor-4.2.5/supervisor/tests/test_rpcinterfaces.py 2022-12-23 23:54:41.000000000 +0100 +++ new/supervisor-4.3.0/supervisor/tests/test_rpcinterfaces.py 2025-08-22 20:21:55.000000000 +0200 @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- import unittest -import sys import operator import os import time @@ -2392,14 +2391,6 @@ ) - class DummyRPCInterface: def hello(self): return 'Hello!' - -def test_suite(): - return unittest.findTestCases(sys.modules[__name__]) - -if __name__ == '__main__': - unittest.main(defaultTest='test_suite') - diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/supervisor-4.2.5/supervisor/tests/test_socket_manager.py new/supervisor-4.3.0/supervisor/tests/test_socket_manager.py --- old/supervisor-4.2.5/supervisor/tests/test_socket_manager.py 2022-11-25 18:42:03.000000000 +0100 +++ new/supervisor-4.3.0/supervisor/tests/test_socket_manager.py 2025-08-22 20:35:49.000000000 +0200 @@ -1,7 +1,6 @@ """Test suite for supervisor.socket_manager""" import gc -import sys import os import unittest import socket @@ -248,9 +247,3 @@ gc.collect() gc.collect() gc.collect() - -def test_suite(): - return unittest.findTestCases(sys.modules[__name__]) - -if __name__ == '__main__': - unittest.main(defaultTest='test_suite') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/supervisor-4.2.5/supervisor/tests/test_states.py new/supervisor-4.3.0/supervisor/tests/test_states.py --- old/supervisor-4.2.5/supervisor/tests/test_states.py 2022-11-25 18:42:03.000000000 +0100 +++ new/supervisor-4.3.0/supervisor/tests/test_states.py 2025-08-22 20:21:55.000000000 +0200 @@ -1,6 +1,5 @@ """Test suite for supervisor.states""" -import sys import unittest from supervisor import states @@ -50,10 +49,3 @@ def test_getEventListenerStateDescription_returns_None_when_not_found(self): self.assertEqual(states.getEventListenerStateDescription(3.14159), None) - - -def test_suite(): - return unittest.findTestCases(sys.modules[__name__]) - -if __name__ == '__main__': - unittest.main(defaultTest='test_suite') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/supervisor-4.2.5/supervisor/tests/test_supervisorctl.py new/supervisor-4.3.0/supervisor/tests/test_supervisorctl.py --- old/supervisor-4.2.5/supervisor/tests/test_supervisorctl.py 2022-12-24 01:00:25.000000000 +0100 +++ new/supervisor-4.3.0/supervisor/tests/test_supervisorctl.py 2025-08-22 20:21:55.000000000 +0200 @@ -1,4 +1,3 @@ -import sys import unittest from supervisor import xmlrpc from supervisor.compat import StringIO @@ -2067,10 +2066,3 @@ def do_help(self, arg): self.helped = True - -def test_suite(): - return unittest.findTestCases(sys.modules[__name__]) - -if __name__ == '__main__': - unittest.main(defaultTest='test_suite') - diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/supervisor-4.2.5/supervisor/tests/test_supervisord.py new/supervisor-4.3.0/supervisor/tests/test_supervisord.py --- old/supervisor-4.2.5/supervisor/tests/test_supervisord.py 2022-11-25 18:42:03.000000000 +0100 +++ new/supervisor-4.3.0/supervisor/tests/test_supervisord.py 2025-08-22 20:19:42.000000000 +0200 @@ -834,10 +834,3 @@ self.assertEqual(supervisord.ticks[3600], 3600) self.assertEqual(len(L), 6) self.assertEqual(L[-1].__class__, events.Tick3600Event) - -def test_suite(): - return unittest.findTestCases(sys.modules[__name__]) - -if __name__ == '__main__': - unittest.main(defaultTest='test_suite') - diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/supervisor-4.2.5/supervisor/tests/test_templating.py new/supervisor-4.3.0/supervisor/tests/test_templating.py --- old/supervisor-4.2.5/supervisor/tests/test_templating.py 2022-11-25 18:42:03.000000000 +0100 +++ new/supervisor-4.3.0/supervisor/tests/test_templating.py 2025-08-22 20:21:55.000000000 +0200 @@ -6,7 +6,6 @@ import unittest import re -import sys _SIMPLE_XML = r"""<?xml version="1.0"?> <root xmlns:meld="https://github.com/Supervisor/supervisor"> @@ -1785,12 +1784,3 @@ s = re.sub(r"(?s)\s+<", "<", s) s = re.sub(r"(?s)>\s+", ">", s) return s - -def test_suite(): - return unittest.findTestCases(sys.modules[__name__]) - -def main(): - unittest.main(defaultTest='test_suite') - -if __name__ == '__main__': - main() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/supervisor-4.2.5/supervisor/tests/test_web.py new/supervisor-4.3.0/supervisor/tests/test_web.py --- old/supervisor-4.2.5/supervisor/tests/test_web.py 2022-11-25 18:42:03.000000000 +0100 +++ new/supervisor-4.3.0/supervisor/tests/test_web.py 2025-08-22 20:21:55.000000000 +0200 @@ -1,4 +1,3 @@ -import sys import unittest from supervisor.tests.base import DummySupervisor @@ -177,9 +176,3 @@ class DummyContext: pass - -def test_suite(): - return unittest.findTestCases(sys.modules[__name__]) - -if __name__ == '__main__': - unittest.main(defaultTest='test_suite') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/supervisor-4.2.5/supervisor/tests/test_xmlrpc.py new/supervisor-4.3.0/supervisor/tests/test_xmlrpc.py --- old/supervisor-4.2.5/supervisor/tests/test_xmlrpc.py 2022-11-25 18:42:03.000000000 +0100 +++ new/supervisor-4.3.0/supervisor/tests/test_xmlrpc.py 2025-08-22 20:19:42.000000000 +0200 @@ -917,4 +917,3 @@ def close(self): self.closed = True - diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/supervisor-4.2.5/supervisor/version.txt new/supervisor-4.3.0/supervisor/version.txt --- old/supervisor-4.2.5/supervisor/version.txt 2022-12-24 01:26:13.000000000 +0100 +++ new/supervisor-4.3.0/supervisor/version.txt 2025-08-23 20:16:03.000000000 +0200 @@ -1 +1 @@ -4.2.5 +4.3.0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/supervisor-4.2.5/supervisor.egg-info/PKG-INFO new/supervisor-4.3.0/supervisor.egg-info/PKG-INFO --- old/supervisor-4.2.5/supervisor.egg-info/PKG-INFO 2022-12-24 01:52:25.000000000 +0100 +++ new/supervisor-4.3.0/supervisor.egg-info/PKG-INFO 2025-08-23 20:16:31.000000000 +0200 @@ -1,11 +1,14 @@ -Metadata-Version: 2.1 +Metadata-Version: 2.2 Name: supervisor -Version: 4.2.5 +Version: 4.3.0 Summary: A system for controlling process state under UNIX Home-page: http://supervisord.org/ Author: Chris McDonough Author-email: [email protected] License: BSD-derived (http://www.repoze.org/LICENSE.txt) +Project-URL: Changelog, http://supervisord.org/changelog +Project-URL: Documentation, http://supervisord.org +Project-URL: Issue Tracker, https://github.com/Supervisor/supervisor Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: No Input/Output (Daemon) Classifier: Intended Audience :: System Administrators @@ -25,8 +28,22 @@ Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 Classifier: Programming Language :: Python :: 3.10 -Provides-Extra: testing +Classifier: Programming Language :: Python :: 3.11 +Classifier: Programming Language :: Python :: 3.12 +Classifier: Programming Language :: Python :: 3.13 License-File: LICENSES.txt +Provides-Extra: test +Requires-Dist: pytest; extra == "test" +Requires-Dist: pytest-cov; extra == "test" +Dynamic: author +Dynamic: author-email +Dynamic: classifier +Dynamic: description +Dynamic: home-page +Dynamic: license +Dynamic: project-url +Dynamic: provides-extra +Dynamic: summary Supervisor ========== @@ -71,6 +88,32 @@ on GitHub. +4.3.0 (2025-08-23) +------------------ + +- Fixed a bug where the poller would not unregister a closed + file descriptor under some circumstances, which caused excessive + polling, resulting in higher CPU usage. Patch by aftersnow. + +- Fixed a bug where restarting ``supervisord`` may have failed with + the message ``Error: Another program is already listening + on a port that one of our HTTP servers is configured to use.`` + if an HTTP request was made during restart. Patch by Julien Le Cléach. + +- Fixed a unit test that failed only on Python 3.13. Only test code was + changed; no changes to ``supervisord`` itself. Patch by Colin Watson. + +- On Python 3.8 and later, ``setuptools`` is no longer a runtime + dependency. Patch by Ofek Lev. + +- On Python versions before 3.8, ``setuptools`` is still a runtime + dependency (for ``pkg_resources``) but it is no longer declared in + ``setup.py`` as such. This is because adding a conditional dependency + with an environment marker (``setuptools; python_version < '3.8'``) + breaks installation in some scenarios, e.g. ``setup.py install`` or + older versions of ``pip``. Ensure that ``setuptools`` is installed + if using Python before 3.8. + 4.2.5 (2022-12-23) ------------------ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/supervisor-4.2.5/supervisor.egg-info/SOURCES.txt new/supervisor-4.3.0/supervisor.egg-info/SOURCES.txt --- old/supervisor-4.2.5/supervisor.egg-info/SOURCES.txt 2022-12-24 01:52:25.000000000 +0100 +++ new/supervisor-4.3.0/supervisor.egg-info/SOURCES.txt 2025-08-23 20:16:31.000000000 +0200 @@ -112,6 +112,7 @@ supervisor/tests/fixtures/issue-1483a.conf supervisor/tests/fixtures/issue-1483b.conf supervisor/tests/fixtures/issue-1483c.conf +supervisor/tests/fixtures/issue-1596.conf supervisor/tests/fixtures/issue-291a.conf supervisor/tests/fixtures/issue-550.conf supervisor/tests/fixtures/issue-565.conf diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/supervisor-4.2.5/supervisor.egg-info/requires.txt new/supervisor-4.3.0/supervisor.egg-info/requires.txt --- old/supervisor-4.2.5/supervisor.egg-info/requires.txt 2022-12-24 01:52:25.000000000 +0100 +++ new/supervisor-4.3.0/supervisor.egg-info/requires.txt 2025-08-23 20:16:31.000000000 +0200 @@ -1,5 +1,4 @@ -setuptools -[testing] +[test] pytest pytest-cov diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/supervisor-4.2.5/tox.ini new/supervisor-4.3.0/tox.ini --- old/supervisor-4.2.5/tox.ini 2022-12-24 01:00:25.000000000 +0100 +++ new/supervisor-4.3.0/tox.ini 2025-08-22 20:35:30.000000000 +0200 @@ -1,6 +1,6 @@ [tox] envlist = - cover,cover3,docs,py27,py34,py35,py36,py37,py38,py39,py310 + cover,cover3,docs,py27,py34,py35,py36,py37,py38,py39,py310,py311,py312,py313 [testenv] deps = @@ -10,7 +10,7 @@ mock >= 0.5.0 passenv = END_TO_END commands = - pytest {posargs} + pytest --capture=no {posargs} [testenv:py27-configparser] ;see https://github.com/Supervisor/supervisor/issues/1230 @@ -24,20 +24,21 @@ [testenv:cover] basepython = python2.7 commands = - pytest --cov=supervisor --cov-report=term-missing --cov-report=xml {posargs} + pytest --capture=no --cov=supervisor --cov-report=term-missing --cov-report=xml {posargs} deps = {[testenv]deps} pytest-cov [testenv:cover3] -basepython = python3.7 +basepython = python3.8 commands = - pytest --cov=supervisor --cov-report=term-missing --cov-report=xml {posargs} + pytest --capture=no --cov=supervisor --cov-report=term-missing --cov-report=xml {posargs} deps = {[testenv:cover]deps} [testenv:docs] deps = + pygments >= 2.19.1 # Sphinx build fails on 2.19.0 when highlighting ini block Sphinx readme setuptools >= 18.5
