diff --git a/.gitignore b/.gitignore
index 0d1c931c..2eafad14 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,3 +11,7 @@ public
.*.swp
.DS_Store
+
+__pycache__
+__pycache__/
+*.py[cod]
diff --git a/.gitmodules b/.gitmodules
deleted file mode 100644
index 50395675..00000000
--- a/.gitmodules
+++ /dev/null
@@ -1,3 +0,0 @@
-[submodule "themes/hugo-atom-feed"]
- path = themes/hugo-atom-feed
- url = https://github.com/kaushalmodi/hugo-atom-feed
diff --git a/config.yaml b/config.yaml
index 1bd5f09e..78765892 100644
--- a/config.yaml
+++ b/config.yaml
@@ -1,7 +1,5 @@
disableKinds:
- taxonomy
-theme:
- - scientific-python-hugo-theme/themes/hugo-atom-feed
params:
colorScheme: auto # can be auto (browser setting), light, or dark
images:
@@ -11,3 +9,14 @@ params:
plausible:
dataDomain: null
javaScript: "https://views.scientific-python.org/js/script.js"
+
+mediaTypes:
+ application/atom+xml:
+ suffixes:
+ - xml
+
+outputFormats:
+ atom:
+ baseName: atom
+ mediaType: application/atom+xml
+ noUgly: true
diff --git a/layouts/_default/baseof.html b/layouts/_default/baseof.html
index 074fefcc..d248ae09 100644
--- a/layouts/_default/baseof.html
+++ b/layouts/_default/baseof.html
@@ -6,6 +6,9 @@
{{ with .Params.canonicalURL -}}
{{- end }}
+ {{- range .AlternativeOutputFormats }}
+
+ {{- end }}
{{ block "title" . }}{{ .Site.Title }}{{ if not (eq .Site.Title .Title) }} - {{ .Title }}{{end}}{{ end }}
diff --git a/layouts/list.atom.xml b/layouts/list.atom.xml
new file mode 100644
index 00000000..4769affa
--- /dev/null
+++ b/layouts/list.atom.xml
@@ -0,0 +1,47 @@
+{{ printf `` | safeHTML }}
+
+ Hugo
+ {{ .Title }}
+ {{- with site.Params.description }}
+ {{ . }}
+ {{- end }}
+ {{ .Permalink }}
+ {{- $entries := .RegularPagesRecursive.ByDate.Reverse -}}
+ {{- $limit := site.Config.Services.RSS.Limit -}}
+ {{- if ge $limit 1 -}}
+ {{- $entries = first $limit $entries -}}
+ {{- end -}}
+ {{- $updated := .Lastmod -}}
+ {{- with $entries.ByLastmod.Reverse -}}
+ {{- $updated = (index . 0).Lastmod -}}
+ {{- end }}
+ {{ $updated.Format "2006-01-02T15:04:05Z07:00" }}
+
+ {{ site.Params.author.name | default site.Title }}
+ {{- with site.Params.author.email }}
+ {{ . }}
+ {{- end }}
+
+ {{- with .OutputFormats.Get "atom" }}
+
+ {{- end }}
+ {{- with .OutputFormats.Get "html" }}
+
+ {{- end }}
+
+ {{- range $entries }}
+
+ {{ .Title }}
+ {{ .Permalink }}
+ {{ .Lastmod.Format "2006-01-02T15:04:05Z07:00" }}
+ {{ .Date.Format "2006-01-02T15:04:05Z07:00" }}
+ {{- with .OutputFormats.Get "html" }}
+
+ {{- end }}
+ {{ printf "%s" .Content }}
+ {{- range .GetTerms "tags" }}
+
+ {{- end }}
+
+ {{- end }}
+
diff --git a/pixi.lock b/pixi.lock
new file mode 100644
index 00000000..f60a4f05
--- /dev/null
+++ b/pixi.lock
@@ -0,0 +1,970 @@
+version: 7
+platforms:
+- name: linux-64
+- name: osx-64
+- name: osx-arm64
+environments:
+ default:
+ channels:
+ - url: https://conda.anaconda.org/conda-forge/
+ packages:
+ linux-64:
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_10.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/dart-sass-1.101.3-hfc2019e_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/hugo-0.164.0-hc83c272_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-h54a6638_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.46.1-default_hbd61a6d_102.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.8.1-hecca717_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.7.0-h3435931_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-16.1.0-ha9f2e26_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-16.1.0-he0feb66_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-hb03c661_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb03c661_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.53.4-hf4e2dac_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-16.1.0-h934c35e_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42.2-h5347b49_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_3.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.6-hdb14827_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.3-h35e630c_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.14.6-h242f9ac_102_cp314.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_hd70dff1_3.conda
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-hbd8a1cb_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.3-pyhc364b38_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-9.1.1-pyhc364b38_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.16.0-pyhcf101f3_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda
+ osx-64:
+ - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-hbd8a1cb_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.3-pyhc364b38_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-9.1.1-pyhc364b38_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.16.0-pyhcf101f3_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-64/bzip2-1.0.8-h374f1ed_10.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-64/dart-sass-1.101.3-h8822bef_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-64/hugo-0.164.0-h0938e48_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-64/libcxx-22.1.8-h19cb2f5_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-64/libexpat-2.8.1-hcc62823_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-64/libffi-3.7.0-h8c408c4_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-64/liblzma-5.8.3-hbb4bfdb_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-64/libmpdec-4.0.0-hf3981d6_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.53.4-h77d7759_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.3.2-hbb4bfdb_3.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.6-hcc0dc9a_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-64/openssl-3.6.3-hc881268_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.14.6-hb933c43_102_cp314.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-64/readline-8.3-h68b038d_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-hb794df6_3.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.7-h3eecb57_6.conda
+ osx-arm64:
+ - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-hbd8a1cb_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.3-pyhc364b38_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-9.1.1-pyhc364b38_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.16.0-pyhcf101f3_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-h4e30115_10.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/dart-sass-1.101.3-h820172f_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/hugo-0.164.0-ha4d9615_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.3-hc7cc350_2.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-22.1.8-h55c6f16_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.8.1-hf6b4638_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.7.0-hcf2aa1b_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.3-h8088a28_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmpdec-4.0.0-h84a0fba_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.53.4-h1ae2325_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.2-h8088a28_3.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.6-he64c551_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.3-hd24854e_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.14.6-hf4d206d_102_cp314.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-hd3d0363_3.conda
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda
+packages:
+- conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda
+ build_number: 20
+ sha256: 1dd3fffd892081df9726d7eb7e0dea6198962ba775bd88842135a4ddb4deb3c9
+ md5: a9f577daf3de00bca7c3c76c0ecbd1de
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgomp >=7.5.0
+ constrains:
+ - openmp_impl <0.0a0
+ license: BSD-3-Clause
+ license_family: BSD
+ run_exports:
+ strong:
+ - _openmp_mutex >=4.5
+ size: 28948
+ timestamp: 1770939786096
+- conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_10.conda
+ sha256: 1a0d382c515ebf55f8ee1f38c8b81bc95af5c2acc42ad53b66bc5df932032f96
+ md5: e675fabcf81499adc7edf58124fb1e01
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=14
+ license: bzip2-1.0.6
+ license_family: BSD
+ run_exports:
+ weak:
+ - bzip2 >=1.0.8,<2.0a0
+ size: 257808
+ timestamp: 1785906269155
+- conda: https://conda.anaconda.org/conda-forge/linux-64/dart-sass-1.101.3-hfc2019e_0.conda
+ sha256: 69536500f63f975797c5d5783e39c44a10d6df18a618e439794025607bfef5c6
+ md5: 25aa9feec8bc49793e99f2309b0498c9
+ license: MIT
+ license_family: MIT
+ run_exports: {}
+ size: 4102233
+ timestamp: 1784613983631
+- conda: https://conda.anaconda.org/conda-forge/linux-64/hugo-0.164.0-hc83c272_0.conda
+ sha256: 3c6c4a6e11e726a62a4c714d3280d455e80e76f2417fa3875c24ce718a2aff30
+ md5: f2046a91afc72270485d553ccdd10c3a
+ depends:
+ - __glibc >=2.17
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=14
+ - libstdcxx >=14
+ license: Apache-2.0
+ license_family: APACHE
+ run_exports: {}
+ size: 20275039
+ timestamp: 1783400884917
+- conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-h54a6638_2.conda
+ sha256: d7c260b7e1cf22ce04d6ba8a86eabf4e6c50bc96a5c27fe2ecb32298af3e88eb
+ md5: 4ef4b977bb216a3001a3334696a80850
+ depends:
+ - libstdcxx >=14
+ - libgcc >=14
+ - __glibc >=2.17,<3.0.a0
+ license: MIT
+ license_family: MIT
+ run_exports:
+ weak:
+ - icu >=78.3,<79.0a0
+ size: 14455340
+ timestamp: 1784916378180
+- conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.46.1-default_hbd61a6d_102.conda
+ sha256: 27d83f1188cd19bcb7754a078b3fa7f4cfb8527f8eb2fde54dd01fc529d1adec
+ md5: 449500f2c089da11c40f5c21312e3e07
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - zstd >=1.5.7,<1.6.0a0
+ constrains:
+ - binutils_impl_linux-64 2.46.1
+ license: GPL-3.0-only
+ license_family: GPL
+ run_exports: {}
+ size: 745303
+ timestamp: 1784214507189
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.8.1-hecca717_1.conda
+ sha256: 16feffd9ddbbe5b718515d38ee376c685ba95491cd901244e24671d20b952a77
+ md5: b24d3c612f71e7aa74158d92106318b2
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=14
+ constrains:
+ - expat 2.8.1.*
+ license: MIT
+ license_family: MIT
+ run_exports: {}
+ size: 77856
+ timestamp: 1781203599810
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.7.0-h3435931_0.conda
+ sha256: ac38603008bf1e99b8ed379b1a656a67a70e2841f2b6a069c630cdf6316012d2
+ md5: 0abe40a9880086ca4d2e5daf09dceff9
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=14
+ license: MIT
+ license_family: MIT
+ run_exports:
+ weak:
+ - libffi >=3.7.0,<3.8.0a0
+ size: 67576
+ timestamp: 1783520858222
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-16.1.0-ha9f2e26_1.conda
+ sha256: d5cb8475131c31680f8fd30512c418f373064e272e452063276a8fb14c9fa42f
+ md5: 5a7d954665c707c93311657cd779c705
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - _openmp_mutex >=4.5
+ constrains:
+ - libgomp 16.1.0 he0feb66_1
+ - libgcc-ng ==16.1.0=*_1
+ license: GPL-3.0-only WITH GCC-exception-3.1
+ license_family: GPL
+ run_exports: {}
+ size: 1057877
+ timestamp: 1785375436766
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-16.1.0-he0feb66_1.conda
+ sha256: 62cb599ad0539d99386515326d9d5e8f51f75a60c69c2131b21df76edf35bd89
+ md5: 88f2d91cb1533194c323534253094d23
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ license: GPL-3.0-only WITH GCC-exception-3.1
+ license_family: GPL
+ run_exports:
+ strong:
+ - _openmp_mutex >=4.5
+ size: 640415
+ timestamp: 1785375373755
+- conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-hb03c661_1.conda
+ sha256: 9787df8c22a59c9a70d3e5a10db9ad663485e75e9ccc3f09bd092cb7b95e0dab
+ md5: 1390b7c5ac0b1d8e447bc5efa6d3c8c2
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=14
+ constrains:
+ - xz 5.8.3.*
+ license: 0BSD
+ run_exports:
+ weak:
+ - liblzma >=5.8.3,<6.0a0
+ size: 112995
+ timestamp: 1786348617826
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb03c661_1.conda
+ sha256: fe171ed5cf5959993d43ff72de7596e8ac2853e9021dec0344e583734f1e0843
+ md5: 2c21e66f50753a083cbe6b80f38268fa
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=14
+ license: BSD-2-Clause
+ license_family: BSD
+ run_exports: {}
+ size: 92400
+ timestamp: 1769482286018
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.53.4-hf4e2dac_0.conda
+ sha256: 72023efc207fe681e26b65fc9d668062cf0b4f0eacf3431e6eb099b95c1f2efd
+ md5: df088a279cd5e6fd2790b4c196434da1
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - icu >=78.3,<79.0a0
+ - libgcc >=14
+ - libzlib >=1.3.2,<2.0a0
+ license: blessing
+ run_exports:
+ weak:
+ - libsqlite >=3.53.4,<4.0a0
+ size: 964200
+ timestamp: 1785016112246
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-16.1.0-h934c35e_1.conda
+ sha256: 79721dd08aeb0ab9e773f1f9ef41cf4e6c17477e3d72319147619045bce05a09
+ md5: aed6cf89adc1e9b846e4367ac538e434
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc 16.1.0 ha9f2e26_1
+ constrains:
+ - libstdcxx-ng ==16.1.0=*_1
+ license: GPL-3.0-only WITH GCC-exception-3.1
+ license_family: GPL
+ run_exports: {}
+ size: 6631744
+ timestamp: 1785375462643
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42.2-h5347b49_0.conda
+ sha256: 9b1bdce27a7e31f7d241aeecff67a1f3101d52a2b1e33ccc2cdf2613072bf81f
+ md5: 01bb81d12c957de066ea7362007df642
+ depends:
+ - libgcc >=14
+ - __glibc >=2.17,<3.0.a0
+ license: BSD-3-Clause
+ license_family: BSD
+ run_exports:
+ weak:
+ - libuuid >=2.42.2,<3.0a0
+ size: 40017
+ timestamp: 1781625522462
+- conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_3.conda
+ sha256: eb8a0db0aa570124f7d2a93d7c7f596e3390df5e047818d873baad32985fc736
+ md5: 0de0122d9570a8ab637c6b73db268389
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ constrains:
+ - zlib 1.3.2 *_3
+ license: Zlib
+ license_family: Other
+ run_exports:
+ weak:
+ - libzlib >=1.3.2,<2.0a0
+ size: 63713
+ timestamp: 1785362952714
+- conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.6-hdb14827_1.conda
+ sha256: 5d46557214ed184381dafe835b7c94a474a1c3b307a08a250b1ea4779b44ffb3
+ md5: ee6c0cd80a60961a1f48aa3e0b91f986
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=14
+ license: X11 AND BSD-3-Clause
+ run_exports:
+ weak:
+ - ncurses >=6.6,<7.0a0
+ size: 911196
+ timestamp: 1786355078102
+- conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.3-h35e630c_1.conda
+ sha256: 012096056b97abf1f68c46b7146bd2cbd68c1be762340b4f5dad4fbbe99177bc
+ md5: c5955c27917ff2234def47f075e71e02
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - ca-certificates
+ - libgcc >=14
+ license: Apache-2.0
+ license_family: Apache
+ run_exports:
+ weak:
+ - openssl >=3.6.3,<4.0a0
+ size: 3182423
+ timestamp: 1785913583650
+- conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.14.6-h242f9ac_102_cp314.conda
+ build_number: 102
+ sha256: f5ff5c1fac471dfed4fc4288856a63eb9d771e6042d9f70420d75b9f488400d8
+ md5: 9b6c336ef7195fbee1c10c09bfcf901b
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - bzip2 >=1.0.8,<2.0a0
+ - ld_impl_linux-64 >=2.36.1
+ - libexpat >=2.8.1,<3.0a0
+ - libffi >=3.7.0,<3.8.0a0
+ - libgcc >=14
+ - liblzma >=5.8.3,<6.0a0
+ - libmpdec >=4.0.0,<5.0a0
+ - libsqlite >=3.53.4,<4.0a0
+ - libuuid >=2.42.2,<3.0a0
+ - libzlib >=1.3.2,<2.0a0
+ - ncurses >=6.6,<7.0a0
+ - openssl >=3.5.7,<4.0a0
+ - python_abi 3.14.* *_cp314
+ - readline >=8.3,<9.0a0
+ - tk >=8.6.13,<8.7.0a0
+ - tzdata
+ - zstd >=1.5.7,<1.6.0a0
+ license: Python-2.0
+ run_exports:
+ weak:
+ - python_abi 3.14.* *_cp314
+ noarch:
+ - python
+ size: 36866750
+ timestamp: 1786444737142
+ python_site_packages_path: lib/python3.14/site-packages
+- conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda
+ sha256: 12ffde5a6f958e285aa22c191ca01bbd3d6e710aa852e00618fa6ddc59149002
+ md5: d7d95fc8287ea7bf33e0e7116d2b95ec
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=14
+ - ncurses >=6.5,<7.0a0
+ license: GPL-3.0-only
+ license_family: GPL
+ run_exports:
+ weak:
+ - readline >=8.3,<9.0a0
+ size: 345073
+ timestamp: 1765813471974
+- conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_hd70dff1_3.conda
+ build_number: 103
+ sha256: 43624eab22f5f29df7d6ffe914cf442f28fd559b55b290906255492826e636e8
+ md5: 48a1049e710857572fc2a832aa394d9f
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libgcc >=14
+ - libzlib >=1.3.2,<2.0a0
+ constrains:
+ - xorg-libx11 >=1.8.13,<2.0a0
+ license: TCL
+ run_exports:
+ weak:
+ - tk >=8.6.13,<8.7.0a0
+ size: 3550916
+ timestamp: 1784229071544
+- conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda
+ sha256: 68f0206ca6e98fea941e5717cec780ed2873ffabc0e1ed34428c061e2c6268c7
+ md5: 4a13eeac0b5c8e5b8ab496e6c4ddd829
+ depends:
+ - __glibc >=2.17,<3.0.a0
+ - libzlib >=1.3.1,<2.0a0
+ license: BSD-3-Clause
+ license_family: BSD
+ run_exports:
+ weak:
+ - zstd >=1.5.7,<1.6.0a0
+ size: 601375
+ timestamp: 1764777111296
+- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-hbd8a1cb_0.conda
+ sha256: 0a0544cf95f64394fe4959286f5c71f5444ad58feb0602e53becb27448d24da6
+ md5: 0f51e2391ade309db462a55611263e9c
+ depends:
+ - __unix
+ license: ISC
+ run_exports: {}
+ size: 131780
+ timestamp: 1784754889428
+- conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda
+ sha256: ab29d57dc70786c1269633ba3dff20288b81664d3ff8d21af995742e2bb03287
+ md5: 962b9857ee8e7018c22f2776ffa0b2d7
+ depends:
+ - python >=3.9
+ license: BSD-3-Clause
+ license_family: BSD
+ run_exports: {}
+ size: 27011
+ timestamp: 1733218222191
+- conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda
+ sha256: ee6cf346d017d954255bbcbdb424cddea4d14e4ed7e9813e429db1d795d01144
+ md5: 8e662bd460bda79b1ea39194e3c4c9ab
+ depends:
+ - python >=3.10
+ - typing_extensions >=4.6.0
+ license: MIT and PSF-2.0
+ run_exports: {}
+ size: 21333
+ timestamp: 1763918099466
+- conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.3.0-pyhd8ed1ab_0.conda
+ sha256: e1a9e3b1c8fe62dc3932a616c284b5d8cbe3124bbfbedcf4ce5c828cb166ee19
+ md5: 9614359868482abba1bd15ce465e3c42
+ depends:
+ - python >=3.10
+ license: MIT
+ license_family: MIT
+ run_exports: {}
+ size: 13387
+ timestamp: 1760831448842
+- conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.3-pyhc364b38_0.conda
+ sha256: c432626b16768b8dab228bfb706f7060c2d462a21c516d240f68f2f902b5a044
+ md5: 936687ed80f295a1f5dbcf8bd34c252c
+ depends:
+ - python >=3.9
+ - python
+ license: Apache-2.0
+ license_family: APACHE
+ run_exports: {}
+ size: 116363
+ timestamp: 1785888127370
+- conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda
+ sha256: e14aafa63efa0528ca99ba568eaf506eb55a0371d12e6250aaaa61718d2eb62e
+ md5: d7585b6550ad04c8c5e21097ada2888e
+ depends:
+ - python >=3.9
+ - python
+ license: MIT
+ license_family: MIT
+ run_exports: {}
+ size: 25877
+ timestamp: 1764896838868
+- conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda
+ sha256: cf70b2f5ad9ae472b71235e5c8a736c9316df3705746de419b59d442e8348e86
+ md5: 16c18772b340887160c79a6acc022db0
+ depends:
+ - python >=3.10
+ license: BSD-2-Clause
+ license_family: BSD
+ run_exports: {}
+ size: 893031
+ timestamp: 1774796815820
+- conda: https://conda.anaconda.org/conda-forge/noarch/pytest-9.1.1-pyhc364b38_2.conda
+ sha256: 430051d80765207a7d782b2b188230ba1489d35c6e75fd9903f76cb9fda4af16
+ md5: 64c98a12c4e23eb238bf66bbecafdf3c
+ depends:
+ - colorama
+ - pygments >=2.7.2
+ - python >=3.10
+ - iniconfig >=1.0.1
+ - packaging >=22
+ - pluggy >=1.5,<2
+ - tomli >=1
+ - exceptiongroup >=1
+ - python
+ constrains:
+ - pytest-faulthandler >=2
+ license: MIT
+ license_family: MIT
+ run_exports: {}
+ size: 306724
+ timestamp: 1782127176429
+- conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda
+ build_number: 8
+ sha256: ad6d2e9ac39751cc0529dd1566a26751a0bf2542adb0c232533d32e176e21db5
+ md5: 0539938c55b6b1a59b560e843ad864a4
+ constrains:
+ - python 3.14.* *_cp314
+ license: BSD-3-Clause
+ license_family: BSD
+ run_exports: {}
+ size: 6989
+ timestamp: 1752805904792
+- conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda
+ sha256: 91cafdb64268e43e0e10d30bd1bef5af392e69f00edd34dfaf909f69ab2da6bd
+ md5: b5325cf06a000c5b14970462ff5e4d58
+ depends:
+ - python >=3.10
+ - python
+ license: MIT
+ license_family: MIT
+ run_exports: {}
+ size: 21561
+ timestamp: 1774492402955
+- conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.16.0-pyhcf101f3_0.conda
+ sha256: 2d888f90af0686044882c74193ec80a90ec1943145d94a7b1b048958acda1848
+ md5: c70ad746c22219b9700931707482992c
+ depends:
+ - python >=3.10
+ - python
+ license: PSF-2.0
+ license_family: PSF
+ run_exports: {}
+ size: 52631
+ timestamp: 1783002732887
+- conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda
+ sha256: b928c30ddcb0e3f544c6eade8352737e6e610e263276b90232db6a578ef899d8
+ md5: fcb489df604d100968b737f2cb6076c6
+ license: LicenseRef-Public-Domain
+ run_exports: {}
+ size: 118849
+ timestamp: 1784250406640
+- conda: https://conda.anaconda.org/conda-forge/osx-64/bzip2-1.0.8-h374f1ed_10.conda
+ sha256: 4ed83961876dc8844a6f0df49c07b408efbaea275ffb0b37133e24c006990b3a
+ md5: 9d9a39212a876e4bb751c1cc3927b678
+ depends:
+ - __osx >=11.0
+ license: bzip2-1.0.6
+ license_family: BSD
+ run_exports:
+ weak:
+ - bzip2 >=1.0.8,<2.0a0
+ size: 133271
+ timestamp: 1785906721507
+- conda: https://conda.anaconda.org/conda-forge/osx-64/dart-sass-1.101.3-h8822bef_0.conda
+ sha256: e3da7b731922b61f494ba2d74b3aa05587ea234d96758f9e63fa37a384f370ed
+ md5: 5517d1f3cb90262b5f1b0ea243cc5391
+ license: MIT
+ license_family: MIT
+ run_exports: {}
+ size: 3965373
+ timestamp: 1784614030450
+- conda: https://conda.anaconda.org/conda-forge/osx-64/hugo-0.164.0-h0938e48_0.conda
+ sha256: a31720ba10988efa337f4bb6d88f68815a17c7549bb69e3279f13d4a5a9828ec
+ md5: c7ecd42ed449c36a576ee839d905f2da
+ depends:
+ - __osx >=12.3
+ - libcxx >=19
+ constrains:
+ - __osx>=10.12
+ license: Apache-2.0
+ license_family: APACHE
+ run_exports: {}
+ size: 19024394
+ timestamp: 1783401338521
+- conda: https://conda.anaconda.org/conda-forge/osx-64/libcxx-22.1.8-h19cb2f5_0.conda
+ sha256: 57ee997f1f800cf38abc743c0f0a9ddfe6a101c697c35510452ce6f4ddf96361
+ md5: 0f600157f28fc7bc9549ecafdfa5bc12
+ depends:
+ - __osx >=11.0
+ license: Apache-2.0 WITH LLVM-exception
+ license_family: Apache
+ run_exports: {}
+ size: 566717
+ timestamp: 1781672189697
+- conda: https://conda.anaconda.org/conda-forge/osx-64/libexpat-2.8.1-hcc62823_1.conda
+ sha256: 9c96cc05e056e1bba5b545cbbd57b6e01db622dc2c82934caaaa25cfb22fe666
+ md5: dcfdea7b7013beef0a4d744d776ea38f
+ depends:
+ - __osx >=11.0
+ constrains:
+ - expat 2.8.1.*
+ license: MIT
+ license_family: MIT
+ run_exports: {}
+ size: 76020
+ timestamp: 1781204303305
+- conda: https://conda.anaconda.org/conda-forge/osx-64/libffi-3.7.0-h8c408c4_0.conda
+ sha256: 525e9b574d6a62b73ccd4cb616495fccd11e80c7e6f4fd7e97a9dd5804bf4c0e
+ md5: b85d1868b8d9af5306443978da2961d6
+ depends:
+ - __osx >=11.0
+ license: MIT
+ license_family: MIT
+ run_exports:
+ weak:
+ - libffi >=3.7.0,<3.8.0a0
+ size: 61307
+ timestamp: 1783521470318
+- conda: https://conda.anaconda.org/conda-forge/osx-64/liblzma-5.8.3-hbb4bfdb_1.conda
+ sha256: 7915dac7c71c208e40e716e2f6d3eff41a8d5584e0e7c2d46f9bf9bd5f9aa739
+ md5: daf49067580fbfeae3ac7f9535400494
+ depends:
+ - __osx >=11.0
+ constrains:
+ - xz 5.8.3.*
+ license: 0BSD
+ run_exports:
+ weak:
+ - liblzma >=5.8.3,<6.0a0
+ size: 104919
+ timestamp: 1786349094608
+- conda: https://conda.anaconda.org/conda-forge/osx-64/libmpdec-4.0.0-hf3981d6_1.conda
+ sha256: 1096c740109386607938ab9f09a7e9bca06d86770a284777586d6c378b8fb3fd
+ md5: ec88ba8a245855935b871a7324373105
+ depends:
+ - __osx >=10.13
+ license: BSD-2-Clause
+ license_family: BSD
+ run_exports: {}
+ size: 79899
+ timestamp: 1769482558610
+- conda: https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.53.4-h77d7759_0.conda
+ sha256: 5725d44a17d196adba9798a5fd9f692b7039a827cd6145556a072a80e1931c49
+ md5: 993009426e1d3aa90eed155171bd59d8
+ depends:
+ - __osx >=11.0
+ - libzlib >=1.3.2,<2.0a0
+ license: blessing
+ run_exports:
+ weak:
+ - libsqlite >=3.53.4,<4.0a0
+ size: 1008531
+ timestamp: 1785016345740
+- conda: https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.3.2-hbb4bfdb_3.conda
+ sha256: b2dba286dd6632292b12296e761193b5ef9fb0eaeecaa481f5ba9af72c0c18e1
+ md5: 7d3fa28263bb7f8ea32db11f570a5bb6
+ depends:
+ - __osx >=11.0
+ constrains:
+ - zlib 1.3.2 *_3
+ license: Zlib
+ license_family: Other
+ run_exports:
+ weak:
+ - libzlib >=1.3.2,<2.0a0
+ size: 58993
+ timestamp: 1785276808631
+- conda: https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.6-hcc0dc9a_1.conda
+ sha256: 12c1d676b9a0e8109b576672519312c5428308f3f3d7706f8717e2f536d5d9e7
+ md5: 88a79390f87c8f3334b9999a892e78d4
+ depends:
+ - __osx >=11.0
+ license: X11 AND BSD-3-Clause
+ run_exports:
+ weak:
+ - ncurses >=6.6,<7.0a0
+ size: 834865
+ timestamp: 1786356957789
+- conda: https://conda.anaconda.org/conda-forge/osx-64/openssl-3.6.3-hc881268_1.conda
+ sha256: d43abd09a455847108fc821e81cf4e36dba31755263a1313b6f1b538ac218998
+ md5: da403ed66c373b5fb25266b4be662327
+ depends:
+ - __osx >=11.0
+ - ca-certificates
+ license: Apache-2.0
+ license_family: Apache
+ run_exports:
+ weak:
+ - openssl >=3.6.3,<4.0a0
+ size: 2773506
+ timestamp: 1785915436200
+- conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.14.6-hb933c43_102_cp314.conda
+ build_number: 102
+ sha256: 19e3a84df66b88348387113e2ffa5c5a5d244e15064dc02f805add29815934e2
+ md5: 8c2a3f8e3e9aaca5d8336deca3ba483b
+ depends:
+ - __osx >=11.0
+ - bzip2 >=1.0.8,<2.0a0
+ - libexpat >=2.8.1,<3.0a0
+ - libffi >=3.7.0,<3.8.0a0
+ - liblzma >=5.8.3,<6.0a0
+ - libmpdec >=4.0.0,<5.0a0
+ - libsqlite >=3.53.4,<4.0a0
+ - libzlib >=1.3.2,<2.0a0
+ - ncurses >=6.6,<7.0a0
+ - openssl >=3.5.7,<4.0a0
+ - python_abi 3.14.* *_cp314
+ - readline >=8.3,<9.0a0
+ - tk >=8.6.13,<8.7.0a0
+ - tzdata
+ - zstd >=1.5.7,<1.6.0a0
+ license: Python-2.0
+ run_exports:
+ weak:
+ - python_abi 3.14.* *_cp314
+ noarch:
+ - python
+ size: 14503943
+ timestamp: 1786445946056
+ python_site_packages_path: lib/python3.14/site-packages
+- conda: https://conda.anaconda.org/conda-forge/osx-64/readline-8.3-h68b038d_0.conda
+ sha256: 4614af680aa0920e82b953fece85a03007e0719c3399f13d7de64176874b80d5
+ md5: eefd65452dfe7cce476a519bece46704
+ depends:
+ - __osx >=10.13
+ - ncurses >=6.5,<7.0a0
+ license: GPL-3.0-only
+ license_family: GPL
+ run_exports:
+ weak:
+ - readline >=8.3,<9.0a0
+ size: 317819
+ timestamp: 1765813692798
+- conda: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-hb794df6_3.conda
+ sha256: 670a364b8285887e5738880bb026f721af2662cfefe9ef64aa9e93eff1981535
+ md5: bc699b366e49399bf8e5c6de99bb8cfb
+ depends:
+ - __osx >=11.0
+ - libzlib >=1.3.2,<2.0a0
+ license: TCL
+ run_exports:
+ weak:
+ - tk >=8.6.13,<8.7.0a0
+ size: 3516600
+ timestamp: 1784229134070
+- conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.7-h3eecb57_6.conda
+ sha256: 47101a4055a70a4876ffc87b750ab2287b67eca793f21c8224be5e1ee6394d3f
+ md5: 727109b184d680772e3122f40136d5ca
+ depends:
+ - __osx >=10.13
+ - libzlib >=1.3.1,<2.0a0
+ license: BSD-3-Clause
+ license_family: BSD
+ run_exports:
+ weak:
+ - zstd >=1.5.7,<1.6.0a0
+ size: 528148
+ timestamp: 1764777156963
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-h4e30115_10.conda
+ sha256: 8ec22f0ba25cbfc2e64d70cf29459eccd7ffdf6436f6a6ff15bbfef799f7d4f6
+ md5: b50612e7d190b8061ab4e7dc119cf4d5
+ depends:
+ - __osx >=11.0
+ license: bzip2-1.0.6
+ license_family: BSD
+ run_exports:
+ weak:
+ - bzip2 >=1.0.8,<2.0a0
+ size: 124965
+ timestamp: 1785906749812
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/dart-sass-1.101.3-h820172f_0.conda
+ sha256: fe3c652bd917df379887a6dcd4433e7d59da1f666350ec681f37335ae79c9f89
+ md5: 3e77cec4663f3011fc510d44b0be0967
+ license: MIT
+ license_family: MIT
+ run_exports: {}
+ size: 3764220
+ timestamp: 1784613997813
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/hugo-0.164.0-ha4d9615_0.conda
+ sha256: aab0f97f766a8d80b5d31ed1c123905874dfae88b8b242980dab277d577a1db9
+ md5: c66298dc742f3a1d50767e09d0c3a530
+ depends:
+ - __osx >=12.3
+ - libcxx >=19
+ license: Apache-2.0
+ license_family: APACHE
+ run_exports: {}
+ size: 17935717
+ timestamp: 1783402039253
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.3-hc7cc350_2.conda
+ sha256: f0b22bc30e4cc29e29ba3234cb38497fe8def2c2aae4b775d42fe5b378a018c9
+ md5: 6133ddbb17ba2b50700dd88e9303ce27
+ depends:
+ - __osx >=11.0
+ license: MIT
+ license_family: MIT
+ run_exports:
+ weak:
+ - icu >=78.3,<79.0a0
+ size: 14070698
+ timestamp: 1784916459058
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-22.1.8-h55c6f16_0.conda
+ sha256: a2e7abab5add9750fab064c024394de48e49f97631c605ad5db5c8ac3fc769ef
+ md5: 89f76a2a21a3ec3ec983b5eb237c4113
+ depends:
+ - __osx >=11.0
+ license: Apache-2.0 WITH LLVM-exception
+ license_family: Apache
+ run_exports: {}
+ size: 569349
+ timestamp: 1781670209146
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.8.1-hf6b4638_1.conda
+ sha256: 5af74261101e3c777399c6294b2b5d290e508153268eb2e9ff99c4d69834612f
+ md5: a915151d5d3c5bf039f5ccc8402a436f
+ depends:
+ - __osx >=11.0
+ constrains:
+ - expat 2.8.1.*
+ license: MIT
+ license_family: MIT
+ run_exports: {}
+ size: 69362
+ timestamp: 1781203631990
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.7.0-hcf2aa1b_0.conda
+ sha256: 2c6ac9a6cd65af89b2bd448518bb1e13b44a2e48c0d469398e37bcfc0092e832
+ md5: 92e8690d170d46d768c32553458c0105
+ depends:
+ - __osx >=11.0
+ license: MIT
+ license_family: MIT
+ run_exports:
+ weak:
+ - libffi >=3.7.0,<3.8.0a0
+ size: 43734
+ timestamp: 1783521647536
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.3-h8088a28_1.conda
+ sha256: 23d0630046a3e8b164d8f80f2b74ed2605af2e7050ab9913018056402fae4311
+ md5: 8ab10323068b107661a4b9a4af84f3b5
+ depends:
+ - __osx >=11.0
+ constrains:
+ - xz 5.8.3.*
+ license: 0BSD
+ run_exports:
+ weak:
+ - liblzma >=5.8.3,<6.0a0
+ size: 91720
+ timestamp: 1786348695846
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmpdec-4.0.0-h84a0fba_1.conda
+ sha256: 1089c7f15d5b62c622625ec6700732ece83be8b705da8c6607f4dabb0c4bd6d2
+ md5: 57c4be259f5e0b99a5983799a228ae55
+ depends:
+ - __osx >=11.0
+ license: BSD-2-Clause
+ license_family: BSD
+ run_exports: {}
+ size: 73690
+ timestamp: 1769482560514
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.53.4-h1ae2325_0.conda
+ sha256: 745662565e103f290e9dc4263bbd88285082f8cf699854fe2d5f1e35a4a0d326
+ md5: 0e3477c0c3e718dcf2eb74ccc8f68570
+ depends:
+ - __osx >=11.0
+ - icu >=78.3,<79.0a0
+ - libzlib >=1.3.2,<2.0a0
+ license: blessing
+ run_exports:
+ weak:
+ - libsqlite >=3.53.4,<4.0a0
+ size: 929203
+ timestamp: 1785016131414
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.2-h8088a28_3.conda
+ sha256: a18fa5d5bac452401459f966cf0d872224e8080c4ff93c77e168d43ab42ef9d7
+ md5: f39288f0ea63ae962e1a2e4f355a0d75
+ depends:
+ - __osx >=11.0
+ constrains:
+ - zlib 1.3.2 *_3
+ license: Zlib
+ license_family: Other
+ run_exports:
+ weak:
+ - libzlib >=1.3.2,<2.0a0
+ size: 47822
+ timestamp: 1785277049190
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.6-he64c551_1.conda
+ sha256: 7024a48c8c0d0114ed4ab53c76bf9275d50e91ba7cea367a9aead638d3c29c68
+ md5: 3dfa0d0316dc246cd44937a557de4501
+ depends:
+ - __osx >=11.0
+ license: X11 AND BSD-3-Clause
+ run_exports:
+ weak:
+ - ncurses >=6.6,<7.0a0
+ size: 804298
+ timestamp: 1786355189145
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.3-hd24854e_1.conda
+ sha256: 66be2283b5b37dcda1332b5e74c1782a8cb14fd2e62e0d38017c2d35bf73c119
+ md5: 65d1906712b85d1679263c518d011b5b
+ depends:
+ - __osx >=11.0
+ - ca-certificates
+ license: Apache-2.0
+ license_family: Apache
+ run_exports:
+ weak:
+ - openssl >=3.6.3,<4.0a0
+ size: 3109132
+ timestamp: 1785913735357
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.14.6-hf4d206d_102_cp314.conda
+ build_number: 102
+ sha256: 9767b5eee5cef50716708787bb3b4225d2a974bcd50653e856f9db5910a4b17e
+ md5: 8da4ea285021110e2617f7538c386afc
+ depends:
+ - __osx >=11.0
+ - bzip2 >=1.0.8,<2.0a0
+ - libexpat >=2.8.1,<3.0a0
+ - libffi >=3.7.0,<3.8.0a0
+ - liblzma >=5.8.3,<6.0a0
+ - libmpdec >=4.0.0,<5.0a0
+ - libsqlite >=3.53.4,<4.0a0
+ - libzlib >=1.3.2,<2.0a0
+ - ncurses >=6.6,<7.0a0
+ - openssl >=3.5.7,<4.0a0
+ - python_abi 3.14.* *_cp314
+ - readline >=8.3,<9.0a0
+ - tk >=8.6.13,<8.7.0a0
+ - tzdata
+ - zstd >=1.5.7,<1.6.0a0
+ license: Python-2.0
+ run_exports:
+ weak:
+ - python_abi 3.14.* *_cp314
+ noarch:
+ - python
+ size: 13960847
+ timestamp: 1786444540722
+ python_site_packages_path: lib/python3.14/site-packages
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda
+ sha256: a77010528efb4b548ac2a4484eaf7e1c3907f2aec86123ed9c5212ae44502477
+ md5: f8381319127120ce51e081dce4865cf4
+ depends:
+ - __osx >=11.0
+ - ncurses >=6.5,<7.0a0
+ license: GPL-3.0-only
+ license_family: GPL
+ run_exports:
+ weak:
+ - readline >=8.3,<9.0a0
+ size: 313930
+ timestamp: 1765813902568
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-hd3d0363_3.conda
+ sha256: 47186bc7ab8d7e8bee86bbd1a917196f8c21cf63f081fc33cd6d1221af087580
+ md5: 8e3cf0e455e6b54519f0b1c72c61780a
+ depends:
+ - __osx >=11.0
+ - libzlib >=1.3.2,<2.0a0
+ license: TCL
+ run_exports:
+ weak:
+ - tk >=8.6.13,<8.7.0a0
+ size: 3338712
+ timestamp: 1784229090530
+- conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda
+ sha256: 9485ba49e8f47d2b597dd399e88f4802e100851b27c21d7525625b0b4025a5d9
+ md5: ab136e4c34e97f34fb621d2592a393d8
+ depends:
+ - __osx >=11.0
+ - libzlib >=1.3.1,<2.0a0
+ license: BSD-3-Clause
+ license_family: BSD
+ run_exports:
+ weak:
+ - zstd >=1.5.7,<1.6.0a0
+ size: 433413
+ timestamp: 1764777166076
diff --git a/pixi.toml b/pixi.toml
new file mode 100644
index 00000000..7fc42634
--- /dev/null
+++ b/pixi.toml
@@ -0,0 +1,14 @@
+[workspace]
+name = "scientific-python-hugo-theme"
+channels = ["conda-forge"]
+platforms = ["linux-64", "osx-64", "osx-arm64"]
+
+[dependencies]
+python = ">=3.11"
+pytest = ">=8"
+hugo = "==0.164.0"
+dart-sass = "==1.101.3"
+
+[tasks]
+test = "python -m pytest"
+test-atom = "python -m pytest tests/test_atom.py -v"
diff --git a/tests/Makefile b/tests/Makefile
new file mode 100644
index 00000000..522562ad
--- /dev/null
+++ b/tests/Makefile
@@ -0,0 +1,9 @@
+.PHONY: help test
+
+.DEFAULT_GOAL := help
+
+help:
+ @grep ": ##" Makefile | grep -v grep | tr -d '#'
+
+test: ## Run the test suite
+ cd .. && python -m pytest tests
diff --git a/tests/fixtures/atom/config.yaml b/tests/fixtures/atom/config.yaml
new file mode 100644
index 00000000..c0962998
--- /dev/null
+++ b/tests/fixtures/atom/config.yaml
@@ -0,0 +1,22 @@
+baseURL: "https://example.org/"
+languageCode: "en-GB"
+title: "Atom Test Site"
+theme: scientific-python-hugo-theme
+
+params:
+ author:
+ name: "Example Team"
+ email: "team@example.org"
+ description: "A test feed"
+
+outputs:
+ home:
+ - HTML
+ - ATOM
+ section:
+ - HTML
+ - ATOM
+
+services:
+ rss:
+ limit: 2
diff --git a/tests/fixtures/atom/content/_index.md b/tests/fixtures/atom/content/_index.md
new file mode 100644
index 00000000..7cd893af
--- /dev/null
+++ b/tests/fixtures/atom/content/_index.md
@@ -0,0 +1,4 @@
+---
+title: "Atom Test Site"
+description: "The home feed used by the Atom test fixture."
+---
diff --git a/tests/fixtures/atom/content/empty/_index.md b/tests/fixtures/atom/content/empty/_index.md
new file mode 100644
index 00000000..3589ee58
--- /dev/null
+++ b/tests/fixtures/atom/content/empty/_index.md
@@ -0,0 +1,5 @@
+---
+title: "Empty section"
+date: 2026-01-07T09:00:00Z
+lastmod: 2026-01-07T09:00:00Z
+---
\ No newline at end of file
diff --git a/tests/fixtures/atom/content/posts/_index.md b/tests/fixtures/atom/content/posts/_index.md
new file mode 100644
index 00000000..1822ae79
--- /dev/null
+++ b/tests/fixtures/atom/content/posts/_index.md
@@ -0,0 +1,4 @@
+---
+title: "Test Posts"
+description: "The section feed used by the Atom test fixture."
+---
diff --git a/tests/fixtures/atom/content/posts/excluded_older.md b/tests/fixtures/atom/content/posts/excluded_older.md
new file mode 100644
index 00000000..a4b42a78
--- /dev/null
+++ b/tests/fixtures/atom/content/posts/excluded_older.md
@@ -0,0 +1,7 @@
+---
+title: "Excluded older post"
+date: 2025-12-01T10:00:00Z
+lastmod: 2025-12-01T10:00:00Z
+---
+
+This post should not appear in the limited feed.
diff --git a/tests/fixtures/atom/content/posts/newer.md b/tests/fixtures/atom/content/posts/newer.md
new file mode 100644
index 00000000..32e73a1e
--- /dev/null
+++ b/tests/fixtures/atom/content/posts/newer.md
@@ -0,0 +1,11 @@
+---
+title: "Newer post"
+date: 2026-01-03T11:00:00Z
+tags:
+ - Python
+ - Scientific computing
+---
+
+This entry was published second.
+
+It contains **formatted text** and an [ordinary link](https://example.org/documentation/).
diff --git a/tests/fixtures/atom/content/posts/older.md b/tests/fixtures/atom/content/posts/older.md
new file mode 100644
index 00000000..07aa9076
--- /dev/null
+++ b/tests/fixtures/atom/content/posts/older.md
@@ -0,0 +1,16 @@
+---
+title: "Older post with & characters"
+date: 2026-01-01T10:00:00Z
+lastmod: 2026-01-05T12:00:00Z
+tags:
+ - Python
+ - Scientific computing
+---
+
+This entry was published first but updated most recently.
+
+It contains an ampersand: Smith & Jones.
+
+It also contains Unicode: λ, café, and naïve.
+
+A link with query parameters
diff --git a/tests/test_atom.py b/tests/test_atom.py
new file mode 100644
index 00000000..f330dbd7
--- /dev/null
+++ b/tests/test_atom.py
@@ -0,0 +1,477 @@
+from __future__ import annotations
+
+import subprocess
+import xml.etree.ElementTree as ET
+from pathlib import Path
+
+import pytest
+import re
+from html.parser import HTMLParser
+
+
+PROJECT_ROOT = Path(__file__).resolve().parents[1]
+FIXTURE_ROOT = PROJECT_ROOT / "tests" / "fixtures" / "atom"
+THEMES_DIR = PROJECT_ROOT.parent
+
+ATOM_NAMESPACE = "http://www.w3.org/2005/Atom"
+ATOM = f"{{{ATOM_NAMESPACE}}}"
+
+XML_NAMESPACE = "http://www.w3.org/XML/1998/namespace"
+XML_LANG = f"{{{XML_NAMESPACE}}}lang"
+
+
+class LinkParser(HTMLParser):
+ def __init__(self) -> None:
+ super().__init__()
+ self.links: list[dict[str, str | None]] = []
+
+ def handle_starttag(
+ self,
+ tag: str,
+ attrs: list[tuple[str, str | None]],
+ ) -> None:
+ if tag == "link":
+ self.links.append(dict(attrs))
+
+
+def parse_html_links(path: Path) -> list[dict[str, str | None]]:
+ parser = LinkParser()
+ parser.feed(path.read_text(encoding="utf-8"))
+ return parser.links
+
+
+@pytest.fixture(scope="module")
+def built_site(tmp_path_factory: pytest.TempPathFactory) -> Path:
+ output_dir = tmp_path_factory.mktemp("atom-site") / "public"
+
+ result = subprocess.run(
+ [
+ "hugo",
+ "--source",
+ str(FIXTURE_ROOT),
+ "--themesDir",
+ str(THEMES_DIR),
+ "--destination",
+ str(output_dir),
+ ],
+ capture_output=True,
+ text=True,
+ check=False,
+ )
+
+ assert result.returncode == 0, (
+ "Hugo failed to build the Atom fixture.\n\n"
+ f"stdout:\n{result.stdout}\n\n"
+ f"stderr:\n{result.stderr}"
+ )
+
+ return output_dir
+
+
+@pytest.fixture(scope="module")
+def atom_feed(built_site: Path) -> ET.Element:
+ atom_path = built_site / "atom.xml"
+
+ assert atom_path.is_file(), "Hugo did not generate atom.xml"
+
+ source = atom_path.read_text(encoding="utf-8")
+
+ try:
+ return ET.fromstring(source)
+ except ET.ParseError as error:
+ numbered_source = "\n".join(
+ f"{line_number:4}: {line}"
+ for line_number, line in enumerate(
+ source.splitlines(),
+ start=1,
+ )
+ )
+ pytest.fail(
+ f"Generated Atom feed is not valid XML: {error}\n\n{numbered_source}"
+ )
+
+
+# RFC 4287: https://www.rfc-editor.org/info/rfc4287/#section-4
+
+
+def test_atom_feed_uses_atom_namespace(atom_feed: ET.Element) -> None:
+ assert atom_feed.tag == f"{ATOM}feed"
+
+
+@pytest.mark.parametrize("element_name", ["title", "id", "updated"])
+def test_atom_feed_contains_required_metadata(
+ atom_feed: ET.Element,
+ element_name: str,
+) -> None:
+ elements = atom_feed.findall(f"{ATOM}{element_name}")
+
+ assert len(elements) == 1
+ assert elements[0].text
+
+
+def test_atom_feed_title(atom_feed: ET.Element) -> None:
+ assert atom_feed.findtext(f"{ATOM}title") == "Atom Test Site"
+
+
+def test_atom_feed_id_is_canonical_home_url(atom_feed: ET.Element) -> None:
+ assert atom_feed.findtext(f"{ATOM}id") == "https://example.org/"
+
+
+def test_atom_feed_updated_uses_latest_entry_update(
+ atom_feed: ET.Element,
+) -> None:
+ assert atom_feed.findtext(f"{ATOM}updated") == "2026-01-05T12:00:00Z"
+
+
+def test_atom_feed_contains_author(atom_feed: ET.Element) -> None:
+ authors = atom_feed.findall(f"{ATOM}author")
+
+ assert len(authors) == 1
+
+
+def test_atom_feed_author_has_name(atom_feed: ET.Element) -> None:
+ author = atom_feed.find(f"{ATOM}author")
+
+ assert author is not None
+ assert author.findtext(f"{ATOM}name") == "Example Team"
+
+
+def test_atom_feed_author_includes_configured_email(
+ atom_feed: ET.Element,
+) -> None:
+ author = atom_feed.find(f"{ATOM}author")
+
+ assert author is not None
+ assert author.findtext(f"{ATOM}email") == "team@example.org"
+
+
+def find_link(atom_feed: ET.Element, rel: str) -> ET.Element:
+ links = [
+ link for link in atom_feed.findall(f"{ATOM}link") if link.get("rel") == rel
+ ]
+
+ assert len(links) == 1
+ return links[0]
+
+
+def test_atom_feed_has_self_link(atom_feed: ET.Element) -> None:
+ link = find_link(atom_feed, "self")
+
+ assert link.get("href") == "https://example.org/atom.xml"
+ assert link.get("type") == "application/atom+xml"
+
+
+def test_atom_feed_has_alternate_html_link(
+ atom_feed: ET.Element,
+) -> None:
+ link = find_link(atom_feed, "alternate")
+
+ assert link.get("href") == "https://example.org/"
+ assert link.get("type") == "text/html"
+
+
+@pytest.fixture(scope="module")
+def atom_entries(atom_feed: ET.Element) -> list[ET.Element]:
+ return atom_feed.findall(f"{ATOM}entry")
+
+
+def test_atom_feed_contains_entries(
+ atom_entries: list[ET.Element],
+) -> None:
+ assert len(atom_entries) == 2
+
+
+def test_atom_entries_are_ordered_by_publication_date(
+ atom_entries: list[ET.Element],
+) -> None:
+ titles = [entry.findtext(f"{ATOM}title") for entry in atom_entries]
+
+ assert titles == [
+ "Newer post",
+ "Older post with & characters",
+ ]
+
+
+@pytest.mark.parametrize("element_name", ["title", "id", "updated"])
+def test_atom_entries_contain_required_metadata(
+ atom_entries: list[ET.Element],
+ element_name: str,
+) -> None:
+ for entry in atom_entries:
+ elements = entry.findall(f"{ATOM}{element_name}")
+
+ assert len(elements) == 1
+ assert elements[0].text
+
+
+def test_atom_entry_ids_are_canonical_urls(
+ atom_entries: list[ET.Element],
+) -> None:
+ ids = [entry.findtext(f"{ATOM}id") for entry in atom_entries]
+
+ assert ids == [
+ "https://example.org/posts/newer/",
+ "https://example.org/posts/older/",
+ ]
+
+
+def test_atom_entry_dates(atom_entries: list[ET.Element]) -> None:
+ assert [entry.findtext(f"{ATOM}published") for entry in atom_entries] == [
+ "2026-01-03T11:00:00Z",
+ "2026-01-01T10:00:00Z",
+ ]
+
+ assert [entry.findtext(f"{ATOM}updated") for entry in atom_entries] == [
+ "2026-01-03T11:00:00Z",
+ "2026-01-05T12:00:00Z",
+ ]
+
+
+def test_atom_entries_have_alternate_html_links(
+ atom_entries: list[ET.Element],
+) -> None:
+ expected_urls = [
+ "https://example.org/posts/newer/",
+ "https://example.org/posts/older/",
+ ]
+
+ for entry, expected_url in zip(
+ atom_entries,
+ expected_urls,
+ strict=True,
+ ):
+ links = [
+ link
+ for link in entry.findall(f"{ATOM}link")
+ if link.get("rel") == "alternate"
+ ]
+
+ assert len(links) == 1
+ assert links[0].get("href") == expected_url
+ assert links[0].get("type") == "text/html"
+
+
+def test_atom_entries_contain_html_content(
+ atom_entries: list[ET.Element],
+) -> None:
+ for entry in atom_entries:
+ contents = entry.findall(f"{ATOM}content")
+
+ assert len(contents) == 1
+ assert contents[0].get("type") == "html"
+ assert contents[0].text
+
+
+def test_atom_entry_content_is_encoded_html(
+ atom_entries: list[ET.Element],
+) -> None:
+ for entry in atom_entries:
+ content = entry.find(f"{ATOM}content")
+
+ assert content is not None
+ assert len(content) == 0
+ assert "" in (content.text or "")
+
+
+def test_atom_entry_content_preserves_html(
+ atom_entries: list[ET.Element],
+) -> None:
+ content = atom_entries[1].findtext(f"{ATOM}content")
+
+ assert content is not None
+ assert "
" in content
+ assert "
" in content
+
+
+def entry_by_title(
+ atom_entries: list[ET.Element],
+ title: str,
+) -> ET.Element:
+ matches = [
+ entry for entry in atom_entries if entry.findtext(f"{ATOM}title") == title
+ ]
+
+ assert len(matches) == 1
+ return matches[0]
+
+
+def test_atom_entry_categories(
+ atom_entries: list[ET.Element],
+) -> None:
+ entry = entry_by_title(atom_entries, "Newer post")
+
+ categories = entry.findall(f"{ATOM}category")
+
+ assert [
+ (
+ category.get("term"),
+ category.get("scheme"),
+ category.get("label"),
+ )
+ for category in categories
+ ] == [
+ (
+ "Python",
+ "https://example.org/tags/",
+ "Python",
+ ),
+ (
+ "Scientific Computing",
+ "https://example.org/tags/",
+ "Scientific Computing",
+ ),
+ ]
+
+
+@pytest.fixture(scope="module")
+def posts_atom_feed(built_site: Path) -> ET.Element:
+ atom_path = built_site / "posts" / "atom.xml"
+
+ assert atom_path.is_file(), "Hugo did not generate posts/atom.xml"
+
+ source = atom_path.read_text(encoding="utf-8")
+
+ try:
+ return ET.fromstring(source)
+ except ET.ParseError as error:
+ pytest.fail(f"Generated posts/atom.xml is not valid XML: {error}\n\n{source}")
+
+
+def test_posts_atom_feed_metadata(
+ posts_atom_feed: ET.Element,
+) -> None:
+ assert posts_atom_feed.tag == f"{ATOM}feed"
+ assert posts_atom_feed.findtext(f"{ATOM}title") == "Test Posts"
+ assert posts_atom_feed.findtext(f"{ATOM}id") == "https://example.org/posts/"
+
+ self_link = find_link(posts_atom_feed, "self")
+ assert self_link.get("href") == "https://example.org/posts/atom.xml"
+ assert self_link.get("type") == "application/atom+xml"
+
+ alternate_link = find_link(posts_atom_feed, "alternate")
+ assert alternate_link.get("href") == "https://example.org/posts/"
+ assert alternate_link.get("type") == "text/html"
+
+
+def test_posts_atom_feed_contains_section_entries(
+ posts_atom_feed: ET.Element,
+) -> None:
+ entries = posts_atom_feed.findall(f"{ATOM}entry")
+
+ assert [entry.findtext(f"{ATOM}title") for entry in entries] == [
+ "Newer post",
+ "Older post with & characters",
+ ]
+
+
+@pytest.fixture(scope="module")
+def empty_atom_feed(built_site: Path) -> ET.Element:
+ atom_path = built_site / "empty" / "atom.xml"
+
+ assert atom_path.is_file(), "Hugo did not generate empty/atom.xml"
+
+ source = atom_path.read_text(encoding="utf-8")
+
+ try:
+ return ET.fromstring(source)
+ except ET.ParseError as error:
+ pytest.fail(f"Generated empty/atom.xml is not valid XML: {error}\n\n{source}")
+
+
+def test_empty_atom_feed_has_required_metadata(
+ empty_atom_feed: ET.Element,
+) -> None:
+ assert empty_atom_feed.findtext(f"{ATOM}title") == "Empty section"
+ assert empty_atom_feed.findtext(f"{ATOM}id") == "https://example.org/empty/"
+ assert empty_atom_feed.findtext(f"{ATOM}updated") == "2026-01-07T09:00:00Z"
+
+
+def test_empty_atom_feed_contains_no_entries(
+ empty_atom_feed: ET.Element,
+) -> None:
+ assert empty_atom_feed.findall(f"{ATOM}entry") == []
+
+
+def test_atom_feed_identifies_hugo_generator(
+ atom_feed: ET.Element,
+) -> None:
+ generators = atom_feed.findall(f"{ATOM}generator")
+
+ assert len(generators) == 1
+
+ generator = generators[0]
+
+ assert generator.text == "Hugo"
+ assert generator.get("uri") == "https://gohugo.io/"
+ version = generator.get("version")
+
+ assert version is not None
+ assert re.fullmatch(r"\d+\.\d+\.\d+", version), (
+ f"Unexpected Hugo version format: {version!r}"
+ )
+
+
+def test_atom_feed_declares_language(atom_feed: ET.Element) -> None:
+ # locale differs depending on the environment, so just check that it exists
+ assert atom_feed.get(XML_LANG)
+
+
+def test_atom_feed_contains_description(
+ atom_feed: ET.Element,
+) -> None:
+ assert atom_feed.findtext(f"{ATOM}subtitle") == "A test feed"
+
+
+def test_atom_entry_content_uses_entry_as_base_url(
+ atom_entries: list[ET.Element],
+) -> None:
+ for entry in atom_entries:
+ content = entry.find(f"{ATOM}content")
+
+ assert content is not None
+ assert content.get(
+ "{http://www.w3.org/XML/1998/namespace}base"
+ ) == entry.findtext(f"{ATOM}id")
+
+
+def test_atom_feed_respects_configured_item_limit(
+ built_site: Path,
+ atom_entries: list[ET.Element],
+) -> None:
+ assert (built_site / "posts" / "excluded_older" / "index.html").is_file()
+
+ assert [entry.findtext(f"{ATOM}title") for entry in atom_entries] == [
+ "Newer post",
+ "Older post with & characters",
+ ]
+
+
+@pytest.mark.parametrize(
+ ("html_path", "expected_feed_url"),
+ [
+ ("index.html", "https://example.org/atom.xml"),
+ (
+ "posts/index.html",
+ "https://example.org/posts/atom.xml",
+ ),
+ (
+ "empty/index.html",
+ "https://example.org/empty/atom.xml",
+ ),
+ ],
+)
+def test_html_pages_advertise_atom_feed(
+ built_site: Path,
+ html_path: str,
+ expected_feed_url: str,
+) -> None:
+ links = parse_html_links(built_site / html_path)
+
+ atom_links = [
+ link
+ for link in links
+ if link.get("rel") == "alternate" and link.get("type") == "application/atom+xml"
+ ]
+
+ assert len(atom_links) == 1
+ assert atom_links[0].get("href") == expected_feed_url
diff --git a/themes/hugo-atom-feed b/themes/hugo-atom-feed
deleted file mode 160000
index d545effe..00000000
--- a/themes/hugo-atom-feed
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit d545effed9949bf834eaed09ad423ec3e030794f