Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

Three defects in `sphinx-alt-text-validator`

Open Beginner friendly
#5,693 1 comment 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

@kesavan272006 is already working on this.

Since Sep 24, 2026.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
75/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
python

Research direction

The issue points to three specific defects in sphinx-alt-text-validator. Start by examining the scripts/image-tester directory and the sphinx_alt_text_validator/verify_images.py module. Look for the is_image function, the validate_images loop logic, and the main() function's glob pattern. The fixes involve adding '.. figure::' to the directive check, handling end-of-file validation, and extending the file extension glob. Test changes by running the validator on sample RST and Python files with and without alt text.

Written by the indexing model from the issue text.

Description

content 📄 infra 🏗️

While adding an alt-text check to qiskit-fermions' own CI (see https://github.com/Qiskit/qiskit-fermions/pull/358), I tried to adopt scripts/image-tester rather than write another copy — the tool exists precisely so the nine API repos don't each maintain one (#2445: "instead of duplicating the same script 9 times").

I couldn't use it, for three independent reasons. Each is reproducible against the code at main, and two of them also affect Qiskit's vendored ancestor tools/verify_images.py.

Reporting them together because their combined effect is worse than any one alone: on a repository like ours the tool exits 0 having validated nothing, which is indistinguishable from a clean pass.

1. .. figure:: is not recognised

is_image() matches only .. image:: and .. plot:::

def is_image(line: str) -> bool:
    """Determine if a line is an image"""
    return line.strip().startswith((".. image::", ".. plot::"))

.. figure:: is an image directive that takes :alt: exactly like .. image::, so a figure without alt text passes silently:

>>> from sphinx_alt_text_validator.verify_images import validate_images
>>> validate_images(".. figure:: images/overview.svg\n\n   A caption.\n")
[]

This is not hypothetical. qiskit-fermions was asked by the platform linter to add alt text to one image, and the fix (Qiskit/qiskit-fermions#349) converted that .. image:: to a .. figure:: with :alt: — because a figure is the right directive when the image has a caption. The result is that the tool intended to catch this class no longer sees our only non-plot image at all. After that change our tree contains 116 .. plot:: + 1 .. figure:: + 0 .. image::, so the blind spot covers 100% of the images that aren't plots.

Suggested fix, matching the existing style:

return line.strip().startswith((".. image::", ".. figure::", ".. plot::"))

is_valid_image needs no change: :nofigs: is plot-only, and a figure with :alt: already passes.

2. A directive at end of file is never checked

validate_images decides whether a directive was valid on a later loop iteration — when it encounters a line that is not an option. If the directive's option block runs to the end of the file, that iteration never happens and the directive is dropped:

>>> validate_images(".. image:: a.png\n")          # nothing after it
[]
>>> validate_images(".. image:: a.png\n\ntext\n")  # something after it
['- Error in line 1: .. image:: a.png']

Same input, same defect, different verdict depending only on whether the file happens to end there. A docstring whose last line is a .. plot:: — or an .rst file ending in an image — is exempt by accident.

The fix is to run the same validity check once more after the loop, when image_found is still set.

3. main() only globs **/*.py, and the glob isn't overridable

files = glob.glob(f"{args.folder}/**/*.py", recursive=True)

The CLI exposes --folder and --skip, so there is no way to reach any other file type.

For repositories whose docs are reStructuredText this means the tool cannot be pointed at them at all. In qiskit-fermions the 117 image directives live in .rst (113), .rs (2, PyO3 docstrings) and .pyi (2, generated stubs) — and zero in .py. Run as documented, sphinx-alt-text-validator -f docs scans conf.py and conftest.py, finds no directives, and prints ✅ All images have alt text.

The underlying validate_file is fine on other extensions — I verified it returns correct results on our .rst and .rs files. Only the entry point's glob is the problem.

Suggested fix: an --extensions option defaulting to py to preserve current behaviour, or glob a set covering py, pyi, rst and rs. Adding rs would also let this cover Rust-based projects, which is where Qiskit's own C API docstrings now live.

Why this matters beyond one repo

Defects 1 and 3 are inherited rather than introduced here — Qiskit/qiskit/tools/verify_images.py has the identical *.py glob and the identical missing figure, and Qiskit still runs that copy rather than this package. So the shared tool currently has no adopter that would have caught these, and the duplication #2445 set out to remove is still in place.

Separately, scripts/js/commands/checkMarkdown.ts reasons about exactly this division of labour:

"If it happens, it would probably be a backport from latest or dev, and the linter in the API repo should catch it. If an image is missed by the API repo's linter, it will still have an alt text defined, although it won't be very useful. That's because Sphinx auto-generates alt text."

That assumption holds only if the API-repo linter actually sees the repo's images. For an .rst-based project today, it doesn't.

What we did meanwhile

We implemented the check in qiskit-fermions (tools/lint_docs.py, wired into tox -e lint), covering image/figure/plot across .rst, .rs, .py and .pyi, with :alt: required and :nofigs: accepted for plots — the same policy as here.

Happy to open a PR for any or all of the three fixes if that's useful; defects 1 and 2 are a few lines each. We'd rather converge on the shared tool than keep a parallel implementation, so if the glob becomes configurable we would look at switching to it.

Dominant language
Jupyter Notebook
Stars
108
Forks
236
Avg merge
2d 11h
Merged PRs (30d)
73

Getting set up

This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from Qiskit/documentation

All issues in Qiskit/documentation

Similar issues

More DevOps issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.