[Debian-astro-maintainers] Bug#1084277: imexam: FTBFS against python 3.15rc2

Maximiliano Curia maxy at debian.org
Sat Sep 12 21:24:19 BST 2026


user debian-python at lists.debian.org
usertags 1084277 python3.15
tags 1084277 patch
thanks

Hi!

While rebuilding the python related packages against the Python 3.15rc2
version I ran into this FTBFS [1]. 

To get it back into a buildable state I needed to apply numerous fixes:
- Upstream patch 3f991f9 Update setup.py
- Upstream patch d7f82ac, 9a4e7a4, a4f3cbf Update setup.cfg
- Upstream patch 1ac361b Update __init__
- Upstream patch 60839f9 Update astropy_init
- Drop patch to remove astropy test runner
- Add patch to fix test failures with NumPy 2.x
- Add patch to support photutils >= 2.0 and handle optional import
   errors
- Replace patch Don-t-use-doctest-extension-in-sphinx.patch with
   backport of cee4c15 / 29b6511
- Add missing python3-pytest autopkgtest dependency

I've applied these fixes in the sandbox [2] to verify that it builds
successfully, these should be applied in Debian to get the package back
to a healthy state.

Happy hacking,

[1]: https://debusine.debian.net/debian/r-python-python3.15/artifact/4645860/
[2]: https://debusine.debian.net/debian/r-python-python3.15/

-- 
"Can you imagine what I would do if I could do all I can?" -- Sun Tzu
Saludos /\/\ /\ >< `/
-------------- next part --------------
diff -Nru imexam-0.9.1/debian/changelog imexam-0.9.1/debian/changelog
--- imexam-0.9.1/debian/changelog	2023-11-28 10:08:03.000000000 +0100
+++ imexam-0.9.1/debian/changelog	2026-09-11 20:25:28.000000000 +0200
@@ -1,3 +1,20 @@
+imexam (0.9.1-6.1) UNRELEASED; urgency=medium
+
+  * Team upload.
+  * Upstream patch 3f991f9 Update setup.py
+  * Upstream patch d7f82ac, 9a4e7a4, a4f3cbf Update setup.cfg
+  * Upstream patch 1ac361b Update __init__
+  * Upstream patch 60839f9 Update astropy_init
+  * Drop patch to remove astropy test runner
+  * Add patch to fix test failures with NumPy 2.x
+  * Add patch to support photutils >= 2.0 and handle optional import
+    errors
+  * Replace patch Don-t-use-doctest-extension-in-sphinx.patch with
+    backport of cee4c15 / 29b6511
+  * Add missing python3-pytest autopkgtest dependency
+
+ -- Maximiliano Curia <maxy at debian.org>  Fri, 11 Sep 2026 20:25:28 +0200
+
 imexam (0.9.1-6) unstable; urgency=medium
 
   * Remove unused astropy config code (Astropy 6.0)
diff -Nru imexam-0.9.1/debian/patches/Add-tests-subdir-to-copy.patch imexam-0.9.1/debian/patches/Add-tests-subdir-to-copy.patch
--- imexam-0.9.1/debian/patches/Add-tests-subdir-to-copy.patch	2023-11-28 10:07:55.000000000 +0100
+++ imexam-0.9.1/debian/patches/Add-tests-subdir-to-copy.patch	1970-01-01 01:00:00.000000000 +0100
@@ -1,20 +0,0 @@
-From: Ole Streicher <olebole at debian.org>
-Date: Thu, 16 Apr 2020 13:24:10 +0200
-Subject: Add tests subdir to copy
-
----
- setup.cfg | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/setup.cfg b/setup.cfg
-index 9a22f76..b6aed77 100644
---- a/setup.cfg
-+++ b/setup.cfg
-@@ -27,6 +27,7 @@ setup_requires =
- 	setuptools >= 30.3.0
- packages = 
- 	imexam
-+	imexam/tests
- install_requires = 
- 	numpy>=1.14
- 	scipy>=0.18
diff -Nru imexam-0.9.1/debian/patches/Don-t-use-doctest-extension-in-sphinx.patch imexam-0.9.1/debian/patches/Don-t-use-doctest-extension-in-sphinx.patch
--- imexam-0.9.1/debian/patches/Don-t-use-doctest-extension-in-sphinx.patch	2023-11-28 10:07:55.000000000 +0100
+++ imexam-0.9.1/debian/patches/Don-t-use-doctest-extension-in-sphinx.patch	1970-01-01 01:00:00.000000000 +0100
@@ -1,20 +0,0 @@
-From: Ole Streicher <ole at aip.de>
-Date: Mon, 25 Oct 2021 08:43:43 +0200
-Subject: Don't use doctest extension in sphinx
-
----
- docs/conf.py | 1 -
- 1 file changed, 1 deletion(-)
-
-diff --git a/docs/conf.py b/docs/conf.py
-index 72a4b06..086bb39 100644
---- a/docs/conf.py
-+++ b/docs/conf.py
-@@ -130,7 +130,6 @@ extensions = [
-     'sphinx_automodapi.automodsumm',
-     'sphinx_automodapi.autodoc_enhancements',
-     'sphinx_automodapi.smart_resolver',
--    'sphinx_astropy.ext.doctest',
-     ]
- 
- 
diff -Nru imexam-0.9.1/debian/patches/numpy-2.patch imexam-0.9.1/debian/patches/numpy-2.patch
--- imexam-0.9.1/debian/patches/numpy-2.patch	1970-01-01 01:00:00.000000000 +0100
+++ imexam-0.9.1/debian/patches/numpy-2.patch	2026-09-11 20:25:28.000000000 +0200
@@ -0,0 +1,27 @@
+Description: Fix test failures with NumPy 2.x
+ NumPy 2.x no longer allows converting 1D single-element arrays to Python
+ scalars. Extract scalar integers from the result of np.where in radial
+ profile tests.
+
+Index: imexam/imexam/tests/test_imexamine.py
+===================================================================
+--- imexam.orig/imexam/tests/test_imexamine.py
++++ imexam/imexam/tests/test_imexamine.py
+@@ -146,6 +146,8 @@ def test_radial_profile():
+     data = Gaussian2DKernel(1.5, x_size=25, y_size=25)
+     xx, yy = np.meshgrid(np.arange(25), np.arange(25))
+     x0, y0 = np.where(data.array == data.array.max())
++    x0 = int(x0[0])
++    y0 = int(y0[0])
+ 
+     rad_in = np.sqrt((xx - x0)**2 + (yy - y0)**2)
+     rad_in = rad_in.ravel()
+@@ -186,6 +188,8 @@ def test_radial_profile_cumulative():
+     data = Gaussian2DKernel(1.5, x_size=ksize, y_size=ksize)
+     xx, yy = np.meshgrid(np.arange(ksize), np.arange(ksize))
+     x0, y0 = np.where(data.array == data.array.max())
++    x0 = int(x0[0])
++    y0 = int(y0[0])
+     rad_in = np.sqrt((xx - x0)**2 + (yy - y0)**2)
+ 
+     rad_in = rad_in.ravel()
diff -Nru imexam-0.9.1/debian/patches/photutils-aperture.patch imexam-0.9.1/debian/patches/photutils-aperture.patch
--- imexam-0.9.1/debian/patches/photutils-aperture.patch	1970-01-01 01:00:00.000000000 +0100
+++ imexam-0.9.1/debian/patches/photutils-aperture.patch	2026-09-11 20:25:28.000000000 +0200
@@ -0,0 +1,129 @@
+Description: Support photutils >= 2.0 and handle optional import errors
+ CircularAperture, CircularAnnulus, and aperture_photometry were moved to
+ photutils.aperture in photutils 2.0. Also catch generic Exception on photutils
+ import when optional metadata is unavailable.
+
+Index: imexam/imexam/imexamine.py
+===================================================================
+--- imexam.orig/imexam/imexamine.py
++++ imexam/imexam/imexamine.py
+@@ -61,12 +61,20 @@ except ImportError:
+ 
+ try:
+     import photutils
++    try:
++        from photutils.aperture import (CircularAperture,
++                                        CircularAnnulus,
++                                        aperture_photometry)
++    except (ImportError, AttributeError):
++        from photutils import (CircularAperture,
++                               CircularAnnulus,
++                               aperture_photometry)
+     photutils_installed = True
+     from photutils.centroids import centroid_com
+     # account for API change
+     from packaging import version
+     photutils_version = version.parse(photutils.__version__)
+-except ImportError:
++except Exception:
+     print("photutils not installed, photometry functionality "
+           "in imexam() not available")
+     photutils_installed = False
+@@ -589,8 +597,8 @@ class Imexamine:
+ 
+             outer = inner + width
+ 
+-            apertures = photutils.CircularAperture((xx, yy), radius)
+-            rawflux_table = photutils.aperture_photometry(
++            apertures = CircularAperture((xx, yy), radius)
++            rawflux_table = aperture_photometry(
+                 data,
+                 apertures,
+                 subpixels=1,
+@@ -600,9 +608,9 @@ class Imexamine:
+             sky_per_pix = 0.
+             annulus_apertures = None
+             if subsky:
+-                annulus_apertures = photutils.CircularAnnulus(
++                annulus_apertures = CircularAnnulus(
+                     (xx, yy), r_in=inner, r_out=outer)
+-                bkgflux_table = photutils.aperture_photometry(
++                bkgflux_table = aperture_photometry(
+                     data,
+                     annulus_apertures)
+ 
+@@ -1138,11 +1146,11 @@ class Imexamine:
+         if subtract_background:
+             inner = pars["skyrad"][0]
+             width = pars["width"][0]
+-            annulus_apertures = photutils.CircularAnnulus((centerx, centery),
+-                                                          r_in=inner,
+-                                                          r_out=inner+width)
+-            bkgflux_table = photutils.aperture_photometry(data,
+-                                                          annulus_apertures)
++            annulus_apertures = CircularAnnulus((centerx, centery),
++                                                  r_in=inner,
++                                                  r_out=inner+width)
++            bkgflux_table = aperture_photometry(data,
++                                                annulus_apertures)
+ 
+             # to calculate the mean local background, divide the circular
+             # annulus aperture sums by the area of the circular annulus.
+@@ -1401,17 +1409,17 @@ class Imexamine:
+             if data is None:
+                 data = self._data
+ 
+-            apertures = photutils.CircularAperture((x, y), radsize)
+-            rawflux_table = photutils.aperture_photometry(
++            apertures = CircularAperture((x, y), radsize)
++            rawflux_table = aperture_photometry(
+                 data,
+                 apertures,
+                 subpixels=1,
+                 method="center")
+ 
+             outer = sky_inner + skywidth
+-            annulus_apertures = photutils.CircularAnnulus(
++            annulus_apertures = CircularAnnulus(
+                 (x, y), r_in=sky_inner, r_out=outer)
+-            bkgflux_table = photutils.aperture_photometry(
++            bkgflux_table = aperture_photometry(
+                 data,
+                 annulus_apertures)
+ 
+Index: imexam/imexam/tests/test_imexamine.py
+===================================================================
+--- imexam.orig/imexam/tests/test_imexamine.py
++++ imexam/imexam/tests/test_imexamine.py
+@@ -15,10 +15,14 @@ except ImportError:
+ 
+ try:
+     import photutils
++    try:
++        from photutils.aperture import CircularAperture, aperture_photometry
++    except (ImportError, AttributeError):
++        from photutils import CircularAperture, aperture_photometry
+     HAS_PHOTUTILS = True
+     from packaging import version
+     photutils_version = version.parse(photutils.__version__)
+-except ImportError:
++except Exception:
+     HAS_PHOTUTILS = False
+ 
+ 
+@@ -56,13 +60,13 @@ def test_line_plot():
+ def test_aper_phot(capsys):
+     """Check that apertures are as expected from photutils"""
+     radius = 5
+-    apertures = photutils.CircularAperture((50, 50), radius)
++    apertures = CircularAperture((50, 50), radius)
+     if photutils_version >= version.parse('0.7'):
+         aperture_area = apertures.area
+     else:
+         aperture_area = apertures.area()
+     assert_equal(aperture_area, np.pi * radius**2)
+-    rawflux_table = photutils.aperture_photometry(
++    rawflux_table = aperture_photometry(
+         test_data,
+         apertures,
+         subpixels=1,
diff -Nru imexam-0.9.1/debian/patches/Remove-astropy-test-runner.patch imexam-0.9.1/debian/patches/Remove-astropy-test-runner.patch
--- imexam-0.9.1/debian/patches/Remove-astropy-test-runner.patch	1970-01-01 01:00:00.000000000 +0100
+++ imexam-0.9.1/debian/patches/Remove-astropy-test-runner.patch	2026-09-11 20:25:28.000000000 +0200
@@ -0,0 +1,24 @@
+From: P. L. Lim <2090236+pllim at users.noreply.github.com>
+Date: Mon, 3 Mar 2025 18:03:50 -0500
+Subject: Remove astropy test runner
+
+Index: imexam/imexam/_astropy_init.py
+===================================================================
+--- imexam.orig/imexam/_astropy_init.py
++++ imexam/imexam/_astropy_init.py
+@@ -1,14 +1,8 @@
+ # Licensed under a 3-clause BSD style license - see LICENSE.rst
+ 
+-import os
+-
+-__all__ = ['__version__', 'test']
++__all__ = ['__version__']
+ 
+ try:
+     from .version import version as __version__
+ except ImportError:
+     __version__ = ''
+-
+-# Create the test function for self test
+-from astropy.tests.runner import TestRunner
+-test = TestRunner.make_test_runner_in(os.path.dirname(__file__))
diff -Nru imexam-0.9.1/debian/patches/series imexam-0.9.1/debian/patches/series
--- imexam-0.9.1/debian/patches/series	2023-11-28 10:07:55.000000000 +0100
+++ imexam-0.9.1/debian/patches/series	2026-09-11 20:25:28.000000000 +0200
@@ -1,7 +1,13 @@
 Use-external-xpa.patch
-Add-tests-subdir-to-copy.patch
 Fix-failing-test.patch
-Don-t-use-doctest-extension-in-sphinx.patch
+Update-docs-conf.patch
 Mark-test-failing-with-astropy-5.2-as-xfail.patch
 numpy-1.24.patch
 Remove-unused-astropy-config-code.patch
+Update-setup.py.patch
+Update-setup.cfg.patch
+Update-__init__.patch
+Update-astropy_init.patch
+Remove-astropy-test-runner.patch
+photutils-aperture.patch
+numpy-2.patch
diff -Nru imexam-0.9.1/debian/patches/Update-astropy_init.patch imexam-0.9.1/debian/patches/Update-astropy_init.patch
--- imexam-0.9.1/debian/patches/Update-astropy_init.patch	1970-01-01 01:00:00.000000000 +0100
+++ imexam-0.9.1/debian/patches/Update-astropy_init.patch	2026-09-11 20:25:28.000000000 +0200
@@ -0,0 +1,47 @@
+From: Larry Bradley <larry.bradley at gmail.com>
+Date: Tue, 12 Oct 2021 12:42:43 -0400
+Subject: Update astropy_init
+
+Index: imexam/imexam/_astropy_init.py
+===================================================================
+--- imexam.orig/imexam/_astropy_init.py
++++ imexam/imexam/_astropy_init.py
+@@ -1,33 +1,14 @@
+ # Licensed under a 3-clause BSD style license - see LICENSE.rst
+ 
+-__all__ = ['__version__', '__githash__']
++import os
+ 
+-# this indicates whether or not we are in the package's setup.py
+-try:
+-    _ASTROPY_SETUP_
+-except NameError:
+-    from sys import version_info
+-    if version_info[0] >= 3:
+-        import builtins
+-    else:
+-        import __builtin__ as builtins
+-    builtins._ASTROPY_SETUP_ = False
++__all__ = ['__version__', 'test']
+ 
+ try:
+     from .version import version as __version__
+ except ImportError:
+     __version__ = ''
+-try:
+-    from .version import githash as __githash__
+-except ImportError:
+-    __githash__ = ''
+-
+-
+-if not _ASTROPY_SETUP_:  # noqa
+-    import os
+ 
+-    # Create the test function for self test
+-    from astropy.tests.runner import TestRunner
+-    test = TestRunner.make_test_runner_in(os.path.dirname(__file__))
+-    test.__test__ = False
+-    __all__ += ['test']
++# Create the test function for self test
++from astropy.tests.runner import TestRunner
++test = TestRunner.make_test_runner_in(os.path.dirname(__file__))
diff -Nru imexam-0.9.1/debian/patches/Update-docs-conf.patch imexam-0.9.1/debian/patches/Update-docs-conf.patch
--- imexam-0.9.1/debian/patches/Update-docs-conf.patch	1970-01-01 01:00:00.000000000 +0100
+++ imexam-0.9.1/debian/patches/Update-docs-conf.patch	2026-09-11 20:25:28.000000000 +0200
@@ -0,0 +1,412 @@
+From: Larry Bradley <larry.bradley at gmail.com>
+Date: Tue, 12 Oct 2021 12:47:29 -0400
+Subject: Update docs conf
+
+Applied-Upstream: https://github.com/spacetelescope/imexam/commit/cee4c1541a4f87ceee169b379127ed090f1f6004
+---
+diff --git a/docs/conf.py b/docs/conf.py
+index 72a4b06..14dbc55 100644
+--- a/docs/conf.py
++++ b/docs/conf.py
+@@ -1,290 +1,181 @@
+ # -*- coding: utf-8 -*-
+ # Licensed under a 3-clause BSD style license - see LICENSE.rst
+ #
+-# Astropy documentation build configuration file.
++# Documentation build configuration file.
+ #
+-# This file is execfile()d with the current directory set to its containing dir
++# This file is execfile()d with the current directory set to its
++# containing dir.
+ #
+-# Note that not all possible configuration values are present in this file.
++# Note that not all possible configuration values are present in this
++# file.
+ #
+ # All configuration values have a default. Some values are defined in
+-# the global Astropy configuration which is loaded here before anything else.
+-# See astropy.sphinx.conf for which values are set there.
+-import datetime
++# the global Astropy configuration which is loaded here before anything
++# else. See astropy.sphinx.conf for which values are set there.
++
++from configparser import ConfigParser
++from datetime import datetime
+ import os
+ import sys
+-import importlib
+-import sphinx
+-import sphinx.environment
+-from docutils.utils import get_source_line
+-# from pkg_resources import get_distribution
+-from distutils.version import LooseVersion
+-
+-try:
+-    from ConfigParser import ConfigParser
+-except ImportError:
+-    from configparser import ConfigParser
+-conf = ConfigParser()
+-conf.read([os.path.join(os.path.dirname(__file__), '..', 'setup.cfg')])
+-setup_cfg = dict(conf.items('metadata'))
+ 
+ try:
+-    import imexam
+-    release = imexam.__version__
++    from sphinx_astropy.conf.v1 import *  # noqa
+ except ImportError:
+-    from pkg_resources import get_distribution
+-    release = get_distribution(setup_cfg['package_name']).version
+-
+-# for example take major/minor
+-version = '.'.join(release.split('.')[:4])
+-
+-# 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('../'))
+-
+-sys.path.insert(0, os.path.abspath('../'))
+-sys.path.insert(0, os.path.abspath('imexam/'))
+-
+-# IMPORTANT: the above commented section was generated by sphinx-quickstart,but
+-# is *NOT* appropriate for astropy or Astropy affiliated packages. It is left
+-# commented out with this explanation to make it clear why this should not be
+-# done. If the sys.path entry above is added, when the astropy.sphinx.conf
+-# import occurs, it will import the *source* version of astropy instead of the
+-# version installed (if invoked as "make html" or directly with sphinx), or the
+-# version in the build directory (if "python setup.py build_sphinx" is used).
+-# Thus, any C-extensions that are needed to build the documentation will *not*
+-# be accessible, and the documentation will not build correctly.
+-
++    print('ERROR: the documentation requires the sphinx-astropy package to '
++          'be installed')
++    sys.exit(1)
+ 
+ # Get configuration information from setup.cfg
+-try:
+-    from ConfigParser import ConfigParser
+-except ImportError:
+-    from configparser import ConfigParser
+ conf = ConfigParser()
+ conf.read([os.path.join(os.path.dirname(__file__), '..', 'setup.cfg')])
+ setup_cfg = dict(conf.items('metadata'))
+ 
+ 
+-def check_sphinx_version(expected_version):
+-    sphinx_version = LooseVersion(sphinx.__version__)
+-    expected_version = LooseVersion(expected_version)
+-    if sphinx_version < expected_version:
+-        raise RuntimeError(
+-            "At least Sphinx version {0} is required to build this "
+-            "documentation.  Found {1}.".format(
+-                expected_version, sphinx_version))
+-
+-# Monkey patch to suppress "nonlocal image URI found" warnings
+-# http://stackoverflow.com/questions/12772927/specifying-an-online-image-in-sphinx-restructuredtext-format
+-
+-
+-def _warn_node(self, msg, node, **kwargs):
+-    if not msg.startswith('nonlocal image URI found:'):
+-        self._warnfunc(msg, '%s:%s' % get_source_line(node), **kwargs)
+-
+-sphinx.environment.BuildEnvironment.warn_node = _warn_node
+-
+ # -- General configuration ----------------------------------------------------
+-on_rtd = os.environ.get('READTHEDOCS', None) == 'True'
+-
+-# Configuration for intersphinx: refer to the Python standard library.
+-intersphinx_mapping = {
+-    'python': ('https://docs.python.org/3/', None),
+-    'numpy': ('https://docs.scipy.org/doc/numpy/', None),
+-    'scipy': ('https://docs.scipy.org/doc/scipy/reference/', None),
+-    'matplotlib': ('http://matplotlib.org/', None),
+-    'ginga': ('http://ginga.readthedocs.io/en/latest/', None),
+-    }
+-
+-if sys.version_info[0] == 2:
+-    intersphinx_mapping['python'] = ('http://docs.python.org/2/', None)
+-    intersphinx_mapping['pythonloc'] = (
+-        'http://docs.python.org/',
+-        os.path.abspath(os.path.join(os.path.dirname(__file__),
+-                                     'local/python2_local_links.inv')))
+-
+-
+-# suppress  epub errors for static file formats (.ico) on rtd
+-suppress_warnings = ['epub.unknown_project_files']
+-
+-# Add any Sphinx extension module names here, as strings. They can be
+-# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
+-# ones.
+-# Add any Sphinx extension module names here, as strings. They can be
+-# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
+-# ones.
+-extensions = [
+-    'sphinx.ext.mathjax',
+-    'sphinx.ext.ifconfig',
+-    'sphinx.ext.autodoc',
+-    'sphinx.ext.intersphinx',
+-    'sphinx.ext.todo',
+-    'sphinx.ext.coverage',
+-    'sphinx.ext.inheritance_diagram',
+-    'sphinx.ext.viewcode',
+-    'sphinx.ext.autosummary',
+-    'sphinx.ext.napoleon',
+-    'sphinx_automodapi.automodapi',
+-    'sphinx_automodapi.automodsumm',
+-    'sphinx_automodapi.autodoc_enhancements',
+-    'sphinx_automodapi.smart_resolver',
+-    'sphinx_astropy.ext.doctest',
+-    ]
+-
+-
+-if on_rtd:
+-    extensions.append('sphinx.ext.mathjax')
+-
+-elif LooseVersion(sphinx.__version__) < LooseVersion('1.4'):
+-    extensions.append('sphinx.ext.pngmath')
+-else:
+-    extensions.append('sphinx.ext.imgmath')
+-
++# By default, highlight as Python 3.
++# highlight_language = 'python3'
+ 
+ # If your documentation needs a minimal Sphinx version, state it here.
+-needs_sphinx = '2.0'
++needs_sphinx = '1.7'
++
++# Extend astropy intersphinx_mapping with packages we use here
++intersphinx_mapping['ginga'] = ('http://ginga.readthedocs.io/en/latest/', None)
+ 
++# Exclude astropy intersphinx_mapping for unused packages
++intersphinx_mapping.pop('h5py', None)
+ 
+ # List of patterns, relative to source directory, that match files and
+ # directories to ignore when looking for source files.
+-exclude_patterns = ['_templates', '_build']
++exclude_patterns.append('_templates')  # noqa
+ 
+-
+-# This is added to the end of RST files - a good place to put substitutions to
+-# be used globally.
++# This is added to the end of RST files - a good place to put
++# substitutions to be used globally.
+ rst_epilog = """.. _imexam: high-level_API.html"""
+ 
+-# The reST default role (used for this markup: `text`) to use for all
+-# documents.
+-default_role = 'obj'
+-
+-# Don't show summaries of the members in each class along with the
+-# class' docstring
+-numpydoc_show_class_members = False
+-
+-autosummary_generate = True
+-
+-automodapi_toctreedirnm = 'api'
+-
+-# Class documentation should contain *both* the class docstring and
+-# the __init__ docstring
+-autoclass_content = "both"
+-
+ # Render inheritance diagrams in SVG
+-graphviz_output_format = "svg"
+-
+-graphviz_dot_args = [
+-    '-Nfontsize=10',
+-    '-Nfontname=Helvetica Neue, Helvetica, Arial, sans-serif',
+-    '-Efontsize=10',
+-    '-Efontname=Helvetica Neue, Helvetica, Arial, sans-serif',
+-    '-Gfontsize=10',
+-    '-Gfontname=Helvetica Neue, Helvetica, Arial, sans-serif'
+-]
++#graphviz_output_format = "svg"
++#
++#graphviz_dot_args = [
++#    '-Nfontsize=10',
++#    '-Nfontname=Helvetica Neue, Helvetica, Arial, sans-serif',
++#    '-Efontsize=10',
++#    '-Efontname=Helvetica Neue, Helvetica, Arial, sans-serif',
++#    '-Gfontsize=10',
++#    '-Gfontname=Helvetica Neue, Helvetica, Arial, sans-serif'
++#]
+ # -- Project information ------------------------------------------------------
+ 
+ # This does not *have* to match the package name, but typically does
+-project = setup_cfg['package_name']
++project = setup_cfg['name']
+ author = setup_cfg['author']
+-copyright = '{0}, {1}'.format(datetime.datetime.now().year, author)
+-
+-# 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.
++copyright = f'2011-{datetime.utcnow().year}, {author}'
+ 
+ # 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.
+-
+-importlib.import_module(setup_cfg['package_name'])
+-package = sys.modules[setup_cfg['package_name']]
++__import__(project)
++package = sys.modules[project]
+ 
+ # The short X.Y version.
+-version = package.__version__.split('-', 1)[0]
+-# The full version, including alpha/beta/rc tags.
++version = package.__version__.split('-', 1)[0]                                  # The full version, including alpha/beta/rc tags.
+ release = package.__version__
+ 
+-# -- Options for HTML output ------------------------------------------------
+-
+-# A NOTE ON HTML THEMES
+-# The global astropy configuration uses a custom theme, 'bootstrap-astropy',
+-# which is installed along with astropy. A different theme can be used or
+-# the options for this theme can be modified by overriding some of the
+-# variables set in the global configuration. The variables set in the
+-# global configuration are listed below, commented out.
+ 
+-# The theme to use for HTML and HTML Help pages.  See the documentation for
+-# a list of builtin themes. To override the custom theme, set this to the
+-# name of a builtin theme or the name of a custom theme in html_theme_path.
+-html_theme = 'bootstrap-astropy'
++# -- Options for HTML output ------------------------------------------------
++# The global astropy configuration uses a custom theme,
++# 'bootstrap-astropy', which is installed along with astropy. A different
++# theme can be used or the options for this theme can be modified by
++# overriding some of the variables set in the global configuration. The
++# variables set in the global configuration are listed below, commented
++# out.
++
++# Add any paths that contain custom themes here, relative to this
++# directory.
++# html_theme_path = []                                                                                                                                          # The theme to use for HTML and HTML Help pages. See the documentation
++# for a list of builtin themes. To override the custom theme, set this
++# to the name of a builtin theme or the name of a custom theme in
++# html_theme_path.
++# html_theme = Noneo
+ 
+ html_theme_options = {
+-    'logotext1': 'im',      # white, semi-bold
+-    'logotext2': 'exam',    # orange, light
+-    'logotext3': ':docs'    # white, light
++    'logotext1': 'im',  # white, semi-bold
++    'logotext2': 'exam',  # orange, light
++    'logotext3': ':docs'  # white, light
+ }
+ 
+-# Add any paths that contain custom themes here, relative to this directory.
+-# To use a different custom theme, add the directory containing the theme.
+-# html_theme_path = []
+-
+ # Custom sidebar templates, maps document names to template names.
+ # html_sidebars = {}
+ 
+-# 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.
+-from os.path import join
+-html_favicon = join('_static', 'imexam.ico')
++# The name of an image file (relative to this directory) to place at the
++# top of the sidebar.
++html_logo = '_static/imexam_logo_trans.png'
++
++# 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 = os.path.join('_static', 'imexam.ico')
+ 
+-# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+-# using the given strftime format.
+-# html_last_updated_fmt = ''
++# A "Last built" timestamp is inserted at every page bottom, using the
++# given strftime format. Set to '' to omit this timestamp.
++# html_last_updated_fmt = '%d %b %Y'
+ 
+-# The name for this set of Sphinx documents.  If None, it defaults to
+-# "<project> v<release> documentation".
+-html_title = '{0} v{1}'.format(project, version)
++# The name for this set of Sphinx documents. If None, it defaults to
++# "<project> v<release>".
++html_title = f'{project} {release}'
+ 
+ # Output file base name for HTML help builder.
+ htmlhelp_basename = project + 'doc'
+ 
+-html_logo = '_static/imexam_logo_trans.png'
+-
+ # Static files to copy after template files
+ html_static_path = ['_static']
+ html_style = 'imexam.css'
+ 
+ 
+-# -- Options for LaTeX output ------------------------------------------------
+-
+-# Grouping the document tree into LaTeX files. List of tuples
+-# (source start file, target name, title, author, documentclass [howto/manual])
+-latex_documents = [('index', project + '.tex', project + u' Documentation',
+-                    author, 'manual')]
+-
++# -- Options for LaTeX output -------------------------------------------------
++# Grouping the document tree into LaTeX files. List of tuples (source
++# start file, target name, title, author, documentclass [howto/manual]).
++latex_documents = [('index', project + '.tex', project + u' Documentation',                         author, 'manual')]
+ latex_logo = '_static/imexam_logo.pdf'
+ 
+-# -- Options for manual page output ------------------------------------------
+-
+-# One entry per manual page. List of tuples
+-# (source start file, name, description, authors, manual section).
++                                                                                # -- Options for manual page output ------------------------------------------- # One entry per manual page. List of tuples (source start file, name,
++# description, authors, manual section).
+ man_pages = [('index', project.lower(), project + u' Documentation',
+               [author], 1)]
+ 
+ 
+-#  -- Options for the edit_on_github extension --------------------------------
++# -- Resolving issue number to links in changelog -----------------------------
++github_project = setup_cfg['github_project']
++github_issues_url = f'https://github.com/{github_project}/issues/'
+ 
+-if eval(setup_cfg.get('edit_on_github')):
+-    extensions += ['astropy.sphinx.ext.edit_on_github']
+ 
+-    versionmod = __import__(setup_cfg['package_name'] + '.version')
+-    edit_on_github_project = setup_cfg['github_project']
+-    if versionmod.release:
+-        edit_on_github_branch = "v" + versionmod.version
+-    else:
+-        edit_on_github_branch = "master"
++# -- Turn on nitpicky mode for sphinx (to warn about references not found) ----
++nitpicky = False
++nitpick_ignore = []
+ 
+-    edit_on_github_source_root = ""
+-    edit_on_github_doc_root = "docs"
++# Some warnings are impossible to suppress, and you can list specific
++# references that should be ignored in a nitpick-exceptions file which
++# should be inside the docs/ directory. The format of the file should be:
++#
++# <type> <class>
++#
++# for example:                                                                  #
++# py:class astropy.io.votable.tree.Element
++# py:class astropy.io.votable.tree.SimpleElement
++# py:class astropy.io.votable.tree.SimpleElementWithContent                     #                                                                               # Uncomment the following lines to enable the exceptions:
++nitpick_filename = 'nitpick-exceptions.txt'
++if os.path.isfile(nitpick_filename):
++    for line in open(nitpick_filename):
++        if line.strip() == "" or line.startswith("#"):
++            continue
++        dtype, target = line.split(None, 1)
++        target = target.strip()
++        nitpick_ignore.append((dtype, target))
++
++
++# -- Options for linkcheck output ---------------------------------------------
++linkcheck_retry = 5
++linkcheck_ignore = ['http://data.astropy.org',
++                    r'https://iraf.net/*',
++                    r'https://github\.com/astropy/photutils/(?:issues|pull)/\d+']
++linkcheck_timeout = 180
++linkcheck_anchors = False
diff -Nru imexam-0.9.1/debian/patches/Update-__init__.patch imexam-0.9.1/debian/patches/Update-__init__.patch
--- imexam-0.9.1/debian/patches/Update-__init__.patch	1970-01-01 01:00:00.000000000 +0100
+++ imexam-0.9.1/debian/patches/Update-__init__.patch	2026-09-11 20:25:28.000000000 +0200
@@ -0,0 +1,59 @@
+From: Larry Bradley <larry.bradley at gmail.com>
+Date: Tue, 12 Oct 2021 00:20:58 -0400
+Subject: Update __init__
+
+Index: imexam/imexam/__init__.py
+===================================================================
+--- imexam.orig/imexam/__init__.py
++++ imexam/imexam/__init__.py
+@@ -7,40 +7,20 @@ viewing tool, like DS9
+ # Affiliated packages may add whatever they like to this file, but
+ # should keep this content at the top.
+ # ----------------------------------------------------------------------------
+-from ._astropy_init import *
++from ._astropy_init import *  # noqa
+ # ----------------------------------------------------------------------------
+-from pkg_resources import get_distribution, DistributionNotFound
+-
+-__all__ = ['__version__', '__githash__']
+-
+-
+ 
+ try:
+-    from . import imexamxpa
++    from . import imexamxpa  # noqa
+     _have_xpa = True
+ except ImportError:
+     _have_xpa = False
+ 
+-if not _ASTROPY_SETUP_:
+-    # import high level functions into the imexam namespace
+-    if _have_xpa:
+-        from .util import list_active_ds9, find_path
+-        from .util import display_help, display_xpa_help
+-
+-    from .util import set_logging
+-    from . import connect as _connect
+-    connect = _connect.Connect
+-
+-    try:
+-        import astropy
+-    except ImportError:
+-        raise ImportError("astropy required but not found")
+-
+-
+-try:
+-    release = get_distribution('imexam').version
+-    __version__ = '.'.join(release.split('.')[:4])
+-except DistributionNotFound:
+-    # package is not installed
+-    __version__ = 'unknown'
+-    __githash__ = ''
++# import high level functions into the imexam namespace
++if _have_xpa:
++    from .util import list_active_ds9, find_path  # noqa
++    from .util import display_help, display_xpa_help  # noqa
++
++from .util import set_logging  # noqa
++from . import connect as _connect
++connect = _connect.Connect
diff -Nru imexam-0.9.1/debian/patches/Update-setup.cfg.patch imexam-0.9.1/debian/patches/Update-setup.cfg.patch
--- imexam-0.9.1/debian/patches/Update-setup.cfg.patch	1970-01-01 01:00:00.000000000 +0100
+++ imexam-0.9.1/debian/patches/Update-setup.cfg.patch	2026-09-11 20:25:28.000000000 +0200
@@ -0,0 +1,161 @@
+From: Larry Bradley <larry.bradley at gmail.com>
+Date: Tue, 12 Oct 2021 17:39:01 -0400
+Subject: Update setup.cfg
+
+Index: imexam/setup.cfg
+===================================================================
+--- imexam.orig/setup.cfg
++++ imexam/setup.cfg
+@@ -1,75 +1,88 @@
+ [metadata]
+-package_name = imexam
+-description = Astropy affiliated package
+-long_description = A package to help perform command-line image examination and plotting
+-author = Megan Sosey
+-author_email = help at stsci.edu
+-license = BSD
+-edit_on_github = False
++name = imexam
++author = Imexam Developers
++license = BSD 3-Clause
++license_file = licenses/LICENSE.rst
++url = https://github.com/spacetelescope/imexam
+ github_project = spacetelescope/imexam
+-description-file = README.rst
+-url = http://imexam.readthedocs.io/
+-homepage = http://imexam.readthedocs.io/
+-classifiers = 
+-	License :: OSI Approved :: BSD License
+-	Development Status :: 4 - Beta
+-	Programming Language :: Python
+-	Programming Language :: C
+-	Programming Language :: Python :: 3
+-	Programming Language :: Python :: Implementation :: CPython
+-	Topic :: Scientific/Engineering :: Astronomy
+-	Topic :: Software Development :: Libraries :: Python Modules
++edit_on_github = False
++description = A package to help perform command-line image examination and plotting
++long_description = file: README.rst
++long_description_content_type = text/x-rst
++classifiers =
++    Intended Audience :: Science/Research
++    License :: OSI Approved :: BSD License
++    Development Status :: 4 - Beta
++    Programming Language :: Python
++    Programming Language :: C
++    Programming Language :: Python :: 3
++    Programming Language :: Python :: Implementation :: CPython
++    Topic :: Scientific/Engineering :: Astronomy
+ 
+ [options]
+-python_requires > = 3.6
+-setup_requires = 
+-	setuptools_scm
+-	setuptools >= 30.3.0
+-packages = 
+-	imexam
+-install_requires = 
+-	numpy>=1.14
+-	scipy>=0.18
+-	astropy>=3.0
+-	matplotlib
+-zip_safe = false
+-
+-[easy_install]
+-zip_ok = False
++zip_safe = False
++packages = find:
++python_requires = >= 3.6
++install_requires =
++    numpy>=1.14
++    scipy>=0.18
++    astropy>=3.0
++    matplotlib
+ 
+ [options.extras_require]
+-docs = 
+-	sphinx
+-	sphinx-automodapi
+-	sphinx-astropy
+-	graphviz
+-tests = 
+-	pytest
+-photometry = 
+-	photutils
+-
+-[build-system]
+-requires = ["cython"]
+-
+-[build_sphinx]
+-source-dir = docs
+-build-dir = docs/_build
+-all_files = 1
+-
+-[upload_docs]
+-upload-dir = docs/_build/html
+-show-response = 1
++all =
++    photutils
++test =
++    pytest-astropy
++docs =
++    sphinx
++    sphinx-automodapi
++    sphinx-astropy
++    graphviz
+ 
+ [tool:pytest]
+-minversion = 2.2
+-norecursedirs = build docs/_build wrappers cextern
+-pep8ignore = E501 W391
++testpaths = "imexam" "docs"
++norecursedirs =
++    "docs[\/]_build"
++    "docs[\/]generated"
++    "imexam[\/]extern"
++    wrappers
++astropy_header = true
++# doctest_plus = enabled
++text_file_format = rst
++
++[coverage:run]
++omit =
++    imexam/_astropy_init*
++    imexam/conftest.py
++    imexam/*setup_package*
++    imexam/tests/*
++    imexam/*/tests/*
++    imexam/extern/*
++    imexam/version*
++    */imexam/_astropy_init*
++    */imexam/conftest.py
++    */imexam/*setup_package*
++    */imexam/tests/*
++    */imexam/*/tests/*
++    */imexam/extern/*
++    */imexam/version*
++
++[coverage:report]
++exclude_lines =
++    # Have to re-enable the standard pragma
++    pragma: no cover
++    # Don't complain about packages we have installed
++    except ImportError
++    # Don't complain if tests don't hit assertions
++    raise AssertionError
++    raise NotImplementedError
++    # Don't complain about script hooks
++    def main\(.*\):
++    # Ignore branches that don't pertain to this version of Python
++    pragma: py{ignore_python_version}
++    # Don't complain about IPython completion helper
++    def _ipython_key_completions_
+ 
+ [flake8]
+ exclude = extern
+-select = E101 W191 W291 W292 W293 W391 E11 E502 E722 E901 E902
+-
+-[egg_info]
+-tag_build = 
+-tag_date = 0
+-
diff -Nru imexam-0.9.1/debian/patches/Update-setup.py.patch imexam-0.9.1/debian/patches/Update-setup.py.patch
--- imexam-0.9.1/debian/patches/Update-setup.py.patch	1970-01-01 01:00:00.000000000 +0100
+++ imexam-0.9.1/debian/patches/Update-setup.py.patch	2026-09-11 20:25:28.000000000 +0200
@@ -0,0 +1,226 @@
+From: Larry Bradley <larry.bradley at gmail.com>
+Date: Tue, 12 Oct 2021 17:39:16 -0400
+Subject: Update setup.py
+
+Index: imexam/setup.py
+===================================================================
+--- imexam.orig/setup.py
++++ imexam/setup.py
+@@ -1,94 +1,68 @@
+-#!/usr/bin/env python
+-# Licensed under a 3-clause BSD style license - see LICENSE.rst
++# NOTE: The configuration for the package, including the name, version, and
++# other information are set in the setup.cfg file.
+ 
+ import sys
+-import os
+-import importlib
+-from distutils.command.clean import clean
+-from setuptools.command.install import install
+-from setuptools.command.build_py import build_py
+-from setuptools import setup, Command, Extension
+-from setuptools.command.test import test as TestCommand
+-from subprocess import check_call, CalledProcessError
+ 
++# First provide helpful messages if contributors try and run legacy commands
++# for tests or docs.
+ 
+-if sys.version_info < (3, 5):
+-    error = """ERROR: imexam requires python >= 3.5."""
+-    sys.exit(error)
+-
+-
+-class PyTest(TestCommand):
+-    user_options = []
+-
+-    def initialize_options(self):
+-        TestCommand.initialize_options(self)
+-        self.pytest_args = ["--cov", PACKAGENAME]
+-
+-    def finalize_options(self):
+-        TestCommand.finalize_options(self)
+-        self.test_args = []
+-        self.test_suite = True
+-
+-    def run_tests(self):
+-        try:
+-            import pytest
+-        except ImportError:
+-            print('Unable to run tests...')
+-            print('To continue, please install "pytest":')
+-            print('    pip install pytest')
+-            exit(1)
++TEST_HELP = """
++Note: running tests is no longer done using 'python setup.py test'. Instead
++you will need to run:
+ 
+-        errno = pytest.main(self.pytest_args)
+-        sys.exit(errno)
++    tox -e test
+ 
++If you don't already have tox installed, you can install it with:
+ 
+-try:
+-    from sphinx.cmd.build import build_main
+-    from sphinx.setup_command import BuildDoc
++    pip install tox
+ 
+-    class BuildSphinx(BuildDoc):
+-        """Build Sphinx documentation after compiling C source files"""
++If you only want to run part of the test suite, you can also use pytest
++directly with::
+ 
+-        description = 'Build Sphinx documentation'
+-        user_options = BuildDoc.user_options[:]
+-        user_options.append(
+-            ('keep-going', 'k',
+-             'Parses the sphinx output and sets the return code to 1 if there '
+-             'are any warnings. Note that this will cause the sphinx log to '
+-             'only update when it completes, rather than continuously as is '
+-             'normally the case.'))
+-
+-
+-        def initialize_options(self):
+-            BuildDoc.initialize_options(self)
+-
+-        def finalize_options(self):
+-            BuildDoc.finalize_options(self)
+-
+-        def run(self):
+-            try:
+-                import imexam
+-            except ImportError as e:
+-                build_cmd = self.reinitialize_command('build_ext')
+-                build_cmd.inplace = 1
+-            retcode = build_main(['-W', '--keep-going', '-b', 'html', './docs', './docs/_build/html'])
+-            if retcode != 0:
+-                sys.exit(retcode)
++    pip install -e .[test]
++    pytest
+ 
+-except ImportError:
+-    print("Sphinx is not installed, can't build documents!!\n")
+-    class BuildSphinx(Command):
+-        user_options = []
++For more information, see:
++
++  http://docs.astropy.org/en/latest/development/testguide.html#running-tests
++"""
++
++if 'test' in sys.argv:
++    print(TEST_HELP)
++    sys.exit(1)
++
++DOCS_HELP = """
++Note: building the documentation is no longer done using
++'python setup.py build_docs'. Instead you will need to run:
++
++    tox -e build_docs
++
++If you don't already have tox installed, you can install it with:
++
++    pip install tox
++
++You can also build the documentation with Sphinx directly using::
+ 
+-        def initialize_options(self):
+-            pass
++    pip install -e .[docs]
++    cd docs
++    make html
+ 
+-        def finalize_options(self):
+-            pass
++For more information, see:
+ 
+-        def run(self):
+-            pass
++  http://docs.astropy.org/en/latest/install.html#builddocs
++"""
+ 
++if 'build_docs' in sys.argv or 'build_sphinx' in sys.argv:
++    print(DOCS_HELP)
++    sys.exit(1)
++
++
++import os
++import importlib
++from distutils.command.clean import clean
++from setuptools.command.install import install
++from setuptools import setup, Command, Extension
++from subprocess import check_call, CalledProcessError
+ 
+ try:
+     from ConfigParser import ConfigParser
+@@ -100,25 +74,11 @@ conf.read(['setup.cfg'])
+ 
+ # Get some values from the setup.cfg
+ metadata = dict(conf.items('metadata'))
+-PACKAGENAME = metadata.get('package_name', 'imexam')
+-DESCRIPTION = metadata.get('description', 'Astropy affiliated package')
+-LONG_DESCRIPTION = metadata.get('long_description', 'A package to help perform \
+-                                image examination and plotting')
+-AUTHOR = metadata.get('author', 'STScI')
+-AUTHOR_EMAIL = metadata.get('author_email', 'help at stsci.edu')
+-LICENSE = metadata.get('license', 'BSD-3-Clause')
+-URL = metadata.get('url', 'http://astropy.org')
+-HOMEPAGE = metadata.get('homepage', '')
+-
+-
+-
+-
++PACKAGENAME = metadata.get('name', 'imexam')
+ package_data = {PACKAGENAME: []}
+-ext = []
+ 
+-cmdclass = {'test': PyTest,
+-            'build_sphinx': BuildSphinx,
+-            }
++ext = []
++cmdclass = {}
+ 
+ 
+ if not sys.platform.startswith('win'):
+@@ -258,20 +218,25 @@ if not sys.platform.startswith('win'):
+         ext = [xpa_module]
+ 
+ 
+-setup(
+-    name=PACKAGENAME,
+-    description=DESCRIPTION,
+-    setup_requires=['setuptools_scm'],
+-    provides=[PACKAGENAME],
+-    author=AUTHOR,
+-    author_email=AUTHOR_EMAIL,
+-    license=LICENSE,
+-    long_description=LONG_DESCRIPTION,
+-    use_2to3=False,
+-    use_scm_version=True,
+-    zip_safe=False,
+-    cmdclass=cmdclass,
+-    package_data=package_data,
+-    package_dir={'imexam': 'imexam'},
+-    ext_modules=ext,
+-)
++VERSION_TEMPLATE = """
++# Note that we need to fall back to the hard-coded version if either
++# setuptools_scm can't be imported or setuptools_scm can't determine the
++# version, so we catch the generic 'Exception'.
++try:
++    from setuptools_scm import get_version
++    version = get_version(root='..', relative_to=__file__)
++except Exception:
++    version = '{version}'
++""".lstrip()
++
++
++# Import these after the above checks to ensure they are printed even if
++# extensions_helpers is not installed
++from setuptools import setup  # noqa
++
++
++setup(use_scm_version={'write_to': os.path.join('imexam', 'version.py'),
++                       'write_to_template': VERSION_TEMPLATE},
++      cmdclass=cmdclass,
++      package_data=package_data,
++      ext_modules=ext)
diff -Nru imexam-0.9.1/debian/tests/control imexam-0.9.1/debian/tests/control
--- imexam-0.9.1/debian/tests/control	2020-04-08 17:18:11.000000000 +0200
+++ imexam-0.9.1/debian/tests/control	2026-09-11 20:25:28.000000000 +0200
@@ -1,3 +1,3 @@
 Test-Command: cd $AUTOPKGTEST_TMP && MPLBACKEND=Agg python3 -m pytest --pyargs imexam
-Depends: python3-imexam, python3-scipy, python3-matplotlib, ipython3
+Depends: python3-pytest, python3-imexam, python3-scipy, python3-matplotlib, ipython3
 Restrictions: allow-stderr


More information about the Debian-astro-maintainers mailing list