Skip to content

Commit 8391c6a

Browse files
committed
Merge remote-tracking branch 'upstream/main' into index_condense
* upstream/main: DOCS: Add gallery carousel to docs homepage (SciTools#6884) SPEC0 - support Python 3.12 to 3.14 (SciTools#6816)
2 parents 2eb875b + fe7a4d7 commit 8391c6a

File tree

21 files changed

+632
-130
lines changed

21 files changed

+632
-130
lines changed

.github/workflows/ci-tests.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,18 +35,18 @@ jobs:
3535
fail-fast: false
3636
matrix:
3737
os: ["ubuntu-latest"]
38-
python-version: ["3.13"]
38+
python-version: ["3.14"]
3939
session: ["doctest", "gallery"]
4040
include:
4141
- os: "ubuntu-latest"
42-
python-version: "3.13"
42+
python-version: "3.14"
4343
session: "tests"
4444
coverage: "--coverage"
4545
- os: "ubuntu-latest"
46-
python-version: "3.12"
46+
python-version: "3.13"
4747
session: "tests"
4848
- os: "ubuntu-latest"
49-
python-version: "3.11"
49+
python-version: "3.12"
5050
session: "tests"
5151

5252
env:

.github/workflows/ci-wheels.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ jobs:
5252
strategy:
5353
fail-fast: false
5454
matrix:
55-
python-version: ["3.11", "3.12", "3.13"]
55+
python-version: ["3.12", "3.13", "3.14"]
5656
session: ["wheel"]
5757
env:
5858
ENV_NAME: "ci-wheels"

benchmarks/bm_runner.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ def _check_requirements(package: str) -> None:
6767

6868
def _prep_data_gen_env() -> None:
6969
"""Create or access a separate, unchanging environment for generating test data."""
70-
python_version = "3.13"
70+
python_version = "3.14"
7171
data_gen_var = "DATA_GEN_PYTHON"
7272
if data_gen_var in environ:
7373
echo("Using existing data generation environment.")

docs/src/_static/theme_override.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,8 @@ ul.squarelist {
5050
.custom-body {
5151
text-align: left;
5252
margin-left: max(45px, 15%);
53+
}
54+
55+
.center {
56+
text-align: center;
5357
}

docs/src/conf.py

Lines changed: 152 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@
1919

2020
"""Config for sphinx."""
2121

22+
import ast
23+
import contextlib
2224
import datetime
25+
import importlib
2326
from importlib.metadata import version as get_version
2427
from inspect import getsource
2528
import ntpath
@@ -29,6 +32,7 @@
2932
from subprocess import run
3033
import sys
3134
from tempfile import gettempdir
35+
import textwrap
3236
from urllib.parse import quote
3337
import warnings
3438

@@ -219,6 +223,11 @@ def _dotv(version):
219223
autoclass_content = "both"
220224
modindex_common_prefix = ["iris"]
221225

226+
# if geovista is not installed we need to mock the imports so the autodoc build works:
227+
if importlib.util.find_spec("geovista") is None:
228+
autodoc_mock_imports = ["geovista", "pyvista"]
229+
230+
222231
# -- apidoc extension ---------------------------------------------------------
223232
# See https://github.com/sphinx-contrib/apidoc
224233
source_code_root = (Path(__file__).parents[2]).absolute()
@@ -283,7 +292,15 @@ def _dotv(version):
283292

284293
# -- Doctest ("make doctest")--------------------------------------------------
285294

286-
doctest_global_setup = "import iris"
295+
doctest_global_setup = """
296+
import iris
297+
298+
# To handle conditional doctest skipping if geovista is not installed:
299+
try:
300+
import geovista as gv
301+
except ImportError:
302+
gv = None
303+
"""
287304

288305
# -- Options for HTML output --------------------------------------------------
289306

@@ -412,12 +429,14 @@ def reset_modules(gallery_conf, fname):
412429
)
413430
sys.path.insert(0, str(reset_modules_dir))
414431

432+
GALLERY_CODE: str = "../gallery_code"
433+
GALLERY_DIRS: str = "generated/gallery"
415434

416435
sphinx_gallery_conf = {
417436
# path to your example scripts
418-
"examples_dirs": ["../gallery_code"],
437+
"examples_dirs": GALLERY_CODE,
419438
# path to where to save gallery generated output
420-
"gallery_dirs": ["generated/gallery"],
439+
"gallery_dirs": GALLERY_DIRS,
421440
# filename pattern for the files in the gallery
422441
"filename_pattern": "/plot_",
423442
# filename pattern to ignore in the gallery
@@ -441,3 +460,133 @@ def reset_modules(gallery_conf, fname):
441460
"section": "Section %s",
442461
"table": "Table %s",
443462
}
463+
464+
# ============================================================================
465+
# | Copyright GeoVista |
466+
# | Code from this point unto the termination banner is copyright GeoVista. |
467+
# | Minimal code changes made to make it generic. |
468+
# | |
469+
# | License details can be found at: |
470+
# | https://github.com/bjlittle/geovista/blob/main/LICENSE |
471+
# ============================================================================
472+
473+
# Source: https://github.com/bjlittle/geovista/blob/main/docs/src/conf.py
474+
475+
476+
def _bool_eval(*, arg: str | bool) -> bool:
477+
"""Sanitise to a boolean only configuration."""
478+
if isinstance(arg, str):
479+
with contextlib.suppress(TypeError):
480+
arg = ast.literal_eval(arg.capitalize())
481+
482+
return bool(arg)
483+
484+
485+
def generate_carousel(
486+
app: Sphinx,
487+
fname: Path,
488+
ncards: int | None = None,
489+
margin: int | None = None,
490+
width: int | None = None,
491+
) -> None:
492+
"""Generate and write the gallery carousel RST file."""
493+
if ncards is None:
494+
ncards = 3
495+
496+
if margin is None:
497+
margin = 4
498+
499+
if width is None:
500+
width = "25%"
501+
502+
base = Path(app.srcdir, *GALLERY_DIRS.split("/"))
503+
cards_by_link = {}
504+
505+
card = r""".. card::
506+
:img-background: {image}
507+
:link: {link}
508+
:link-type: ref
509+
:width: {width}
510+
:margin: {margin}
511+
:class-card: align-self-center
512+
"""
513+
514+
# TODO @bjlittle: use Path.walk when python >=3.12
515+
for root, _, files in os.walk(str(base)):
516+
root = Path(root) # noqa: PLW2901
517+
if root.name == "images":
518+
root_relative = root.relative_to(app.srcdir)
519+
link_relative = root.parent.relative_to(app.srcdir)
520+
521+
for file in files:
522+
path = Path(file)
523+
if path.suffix == ".png":
524+
# generate the card "img-background" filename
525+
image = root_relative / path
526+
527+
# generate the card "link" reference
528+
# remove numeric gallery image index e.g., "001"
529+
parts = path.stem.split("_")[:-1]
530+
link = parts[:2] + list(link_relative.parts) + parts[2:]
531+
link = f"{'_'.join(link)}.py"
532+
533+
# needed in case a gallery filename has mixed case
534+
link = link.lower()
535+
536+
kwargs = {
537+
"image": image,
538+
"link": link,
539+
"width": width,
540+
"margin": margin,
541+
}
542+
543+
cards_by_link[link] = card.format(**kwargs)
544+
545+
# sort the cards by their link
546+
cards = [cards_by_link[link] for link in sorted(cards_by_link.keys())]
547+
cards = textwrap.indent("\n".join(cards), prefix=" " * 4)
548+
549+
# now, create the card carousel
550+
carousel = f""".. card-carousel:: {ncards}
551+
552+
{cards}
553+
554+
.. rst-class:: center
555+
556+
:fa:`images` Gallery Carousel
557+
558+
"""
559+
560+
# finally, write the rst for the gallery carousel
561+
Path(app.srcdir, fname).write_text(carousel)
562+
563+
564+
def gallery_carousel(
565+
app: Sphinx,
566+
env: BuildEnvironment, # noqa: ARG001
567+
docnames: list[str], # noqa: ARG001
568+
) -> None:
569+
"""Create the gallery carousel."""
570+
# create empty or truncate existing file
571+
fname = Path(app.srcdir, "gallery_carousel.txt")
572+
573+
with fname.open("w"):
574+
pass
575+
576+
if _bool_eval(arg=app.builder.config.plot_gallery):
577+
# only generate the carousel if we have a gallery
578+
generate_carousel(app, fname)
579+
580+
581+
# ============================================================================
582+
# | END GeoVista copyright |
583+
# ============================================================================
584+
585+
586+
def setup(app: Sphinx) -> None:
587+
"""Configure sphinx application."""
588+
# we require the output of this extension
589+
app.setup_extension("sphinx_gallery.gen_gallery")
590+
591+
# register callback to generate gallery carousel
592+
app.connect("env-before-read-docs", gallery_carousel)

docs/src/further_topics/ugrid/operations.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -583,6 +583,7 @@ below:
583583
:icon: code
584584
585585
.. doctest:: ugrid_operations
586+
:skipif: gv is None
586587
587588
>>> from geovista.geodesic import BBox
588589
>>> from iris import load_cube, sample_data_path

docs/src/index.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ representations become unwieldy and inefficient.
1515

1616
For more information see :ref:`why_iris`.
1717

18+
<<<<<<< HEAD
19+
=======
20+
21+
.. grid:: 3
22+
>>>>>>> upstream/main
1823

1924
.. grid:: 1 1 2 2
2025
:gutter: 2
@@ -88,6 +93,9 @@ For more information see :ref:`why_iris`.
8893
Icons made by FreePik from `Flaticon <https://www.flaticon.com/>`_
8994

9095

96+
.. include:: gallery_carousel.txt
97+
98+
9199
.. _iris_support:
92100

93101
Support

docs/src/whatsnew/latest.rst

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,12 @@ This document explains the changes made to Iris for this release
8181
📚 Documentation
8282
================
8383

84+
<<<<<<< HEAD
8485
#. `@tkknight`_ reduced the space used on the documentation homepage by the quick
8586
link cards to allow for easier reading. (:pull:`6886`)
87+
=======
88+
#. `@tkknight`_ added a gallery carousel to the documentation homepage. (:pull:`6884`)
89+
>>>>>>> upstream/main
8690

8791

8892
💼 Internal
@@ -99,13 +103,19 @@ This document explains the changes made to Iris for this release
99103

100104
#. `@tkknight`_ removed flake8, we have ruff now instead. (:pull:`6889`)
101105

106+
#. `@trexfeathers`_ and `@ukmo-ccbunney`_ updated CI to support Python 3.14
107+
inline with `SPEC0 Minimum Supported Dependencies`_. Note: `pyvista` (and
108+
hence `geovista`) is not yet compatible with Python 3.14, so
109+
`:module:~iris.experimental.geovista` is currently only available for
110+
Python \<3.14. (:pull:`6816`, :issue:`6775`)
111+
102112
.. comment
103113
Whatsnew author names (@github name) in alphabetical order. Note that,
104114
core dev names are automatically included by the common_links.inc:
105115
106116
.. _@hdyson: https://github.com/hdyson
107117

108-
118+
.. _SPEC0 Minimum Supported Dependencies: https://scientific-python.org/specs/spec-0000/
109119

110120
.. comment
111121
Whatsnew resources in alphabetical order:

0 commit comments

Comments
 (0)