Skip to content

Commit 8d9f755

Browse files
authored
Merge branch 'main' into for_use_python-package-guide_continuous-integrationpot_ja.po
2 parents 6fee2c2 + 5c9a867 commit 8d9f755

File tree

8 files changed

+200
-13
lines changed

8 files changed

+200
-13
lines changed

README.md

+22
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,28 @@ To build live documentation that updates when you update local files, run the fo
6060
$ nox -s docs-live
6161
```
6262

63+
### Building for release
64+
65+
When building for release, the docs are built multiple times for each translation,
66+
but translations are only included in the production version of the guide after some completion threshold.
67+
68+
The sphinx build environment is controlled by an environment variable `SPHINX_ENV`
69+
70+
- when `SPHINX_ENV=development` (default), sphinx assumes all languages are built,
71+
and includes them in the language selector
72+
- when `SPHINX_ENV=production`, only those languages in `release_languages` (set in `conf.py`)
73+
are built and included in the language selector.
74+
75+
Most of the time you should not need to set `SPHINX_ENV`,
76+
as it is forced by the primary nox sessions intended to be used for release or development:
77+
78+
`SPHINX_ENV=development`
79+
- `docs-live` - autobuild english
80+
- `docs-live-lang` - autobuild a single language
81+
- `docs-live-langs` - autobuild all languages
82+
83+
`SPHINX_ENV=production`
84+
- `build-test` - build all languages for production
6385

6486
## Contributing to this guide
6587

_static/language_select.js

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
document.addEventListener("DOMContentLoaded", () => {
2+
let selectors = document.querySelectorAll("#language-selector");
3+
selectors.forEach((selector) => {
4+
selector.addEventListener("change", (event) => {
5+
let target = event.target.value;
6+
if (target.startsWith("https")) {
7+
window.location.href = target;
8+
} else {
9+
window.location.pathname = target;
10+
}
11+
});
12+
});
13+
});

_static/pyos.css

+8
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ body {
4646
margin-right: auto !important;
4747
}
4848

49+
.navbar-persistent--mobile {
50+
margin-left: unset !important;
51+
}
52+
4953
/* custom fonts */
5054

5155
html,
@@ -414,3 +418,7 @@ th {
414418
border: 1px solid #ccc; /* Light gray border */
415419
padding: 8px; /* Add some padding for better readability */
416420
}
421+
422+
/* ----------------- */
423+
/* Language Selector */
424+
/* ----------------- */

_templates/language-selector.html

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{%- macro langlink(lang, selected=False) -%} {%- if lang == "en" %}
2+
<option
3+
value="{{ baseurl }}{{ pagename }}{{ file_suffix }}"
4+
{%
5+
if
6+
selected
7+
%}selected{%
8+
endif
9+
%}
10+
>
11+
{{ lang }}
12+
</option>
13+
{%- else %}
14+
<option
15+
value="{{ baseurl }}{{ lang }}/{{ pagename }}{{ file_suffix }}"
16+
{%
17+
if
18+
selected
19+
%}selected{%
20+
endif
21+
%}
22+
>
23+
{{ lang }}
24+
</option>
25+
{%- endif -%} {%- endmacro -%}
26+
<select class="dropdown" id="language-selector" aria-label="Choose a language">
27+
{{ langlink(language, selected=True) }} {%- for a_language in languages -%}
28+
{%- if a_language != language -%} {{ langlink(a_language) }} {%- endif -%} {%-
29+
endfor %}
30+
</select>

conf.py

+34-3
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,40 @@
1515
# sys.path.insert(0, os.path.abspath('.'))
1616
from datetime import datetime
1717
import subprocess
18+
import os
1819

1920
current_year = datetime.now().year
2021
organization_name = "pyOpenSci"
2122

23+
# env vars
24+
sphinx_env = os.environ.get("SPHINX_ENV", "development")
25+
language_env = os.environ.get("SPHINX_LANG", "en")
26+
2227

2328
# -- Project information -----------------------------------------------------
2429

2530
project = "pyOpenSci Python Package Guide"
2631
copyright = f"{current_year}, {organization_name}"
2732
author = "pyOpenSci Community"
2833

34+
# Language of the current build
35+
# language can later be overridden (eg with the -D flag)
36+
# but we need it set here so it can make it into the html_context
37+
language = language_env
38+
# all languages that have .po files generated for them
39+
# (excluding english)
40+
languages = ["es", "ja"]
41+
# the languages that will be included in a production build
42+
# (also excluding english)
43+
release_languages = ["ja"]
44+
45+
# languages that will be included in the language dropdown
46+
# (ie. all that are being built in this nox build session)
47+
if sphinx_env == "production":
48+
build_languages = ["en"] + release_languages
49+
else:
50+
build_languages = ["en"] + languages
51+
2952
# Get the latest Git tag - there might be a prettier way to do this but...
3053
try:
3154
release_value = (
@@ -72,7 +95,11 @@
7295
{"href": "https://www.pyopensci.org/images/favicon.ico"},
7396
]
7497

75-
# Link to our repo for easy PR/ editing
98+
html_baseurl = "https://www.pyopensci.org/python-package-guide/"
99+
if not sphinx_env == "production":
100+
# for links in language selector when developing locally
101+
html_baseurl = "/"
102+
76103
html_theme_options = {
77104
"announcement": "<p><a href='https://www.pyopensci.org/about-peer-review/index.html'>We run peer review of scientific Python software. Learn more.</a></p>",
78105
# "navbar_center": ["nav"], this can be a way to override the default navigation structure
@@ -112,12 +139,16 @@
112139
"github_url": "https://github.com/pyopensci/python-package-guide",
113140
"footer_start": ["code_of_conduct", "copyright"],
114141
"footer_end": [],
142+
"navbar_persistent": ["language-selector", "search-button"]
115143
}
116144

117145
html_context = {
118146
"github_user": "pyopensci",
119147
"github_repo": "python-package-guide",
120148
"github_version": "main",
149+
"language": language,
150+
"languages": build_languages,
151+
"baseurl": html_baseurl,
121152
}
122153

123154
# Add any paths that contain templates here, relative to this directory.
@@ -141,7 +172,7 @@
141172
]
142173

143174
# For sitemap generation
144-
html_baseurl = "https://www.pyopensci.org/python-package-guide/"
175+
145176
sitemap_url_scheme = "{link}"
146177

147178
# -- Options for HTML output -------------------------------------------------
@@ -153,7 +184,7 @@
153184
html_static_path = ["_static"]
154185
html_css_files = ["pyos.css"]
155186
html_title = "Python Packaging Guide"
156-
html_js_files = ["matomo.js"]
187+
html_js_files = ["matomo.js", "language_select.js"]
157188

158189

159190
# Social cards

index.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ The first round of our community-developed, how to create a Python package tutor
7070
:class-card: left-aligned
7171

7272
* [What is a Python package?](/tutorials/intro)
73-
* [Make your code installable](/tutorials/installable-code)
73+
* [Create a Python package](/tutorials/installable-code)
7474
* [Publish your package to (test) PyPI](/tutorials/publish-pypi)
7575
* [Publish your package to conda-forge](/tutorials/publish-conda-forge)
7676

noxfile.py

+91-8
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22
import pathlib
33
import shutil
44
import nox
5+
import sys
6+
import subprocess
7+
8+
# for some reason necessary to correctly import conf from cwd
9+
sys.path.insert(0, str(pathlib.Path(__file__).parent.absolute()))
10+
import conf
511

612

713
## Sphinx related options
@@ -23,7 +29,7 @@
2329
BUILD_PARAMETERS = ["-b", "html"]
2430

2531
# Sphinx parameters used to test the build of the guide
26-
TEST_PARAMETERS = ['-W', '--keep-going', '-E', '-a']
32+
TEST_PARAMETERS = ['--keep-going', '-E', '-a']
2733

2834
# Sphinx parameters to generate translation templates
2935
TRANSLATION_TEMPLATE_PARAMETERS = ["-b", "gettext"]
@@ -42,16 +48,19 @@
4248
## Localization options (translations)
4349

4450
# List of languages for which locales will be generated in (/locales/<lang>)
45-
LANGUAGES = ["es", "ja"]
51+
LANGUAGES = conf.languages
4652

4753
# List of languages that should be built when releasing the guide (docs or docs-test sessions)
48-
RELEASE_LANGUAGES = []
54+
RELEASE_LANGUAGES = conf.release_languages
4955

56+
# allowable values of `SPHINX_ENV`
57+
SPHINX_ENVS = ('production', 'development')
5058

5159
@nox.session
5260
def docs(session):
5361
"""Build the packaging guide."""
5462
session.install("-e", ".")
63+
sphinx_env = _sphinx_env(session)
5564
session.run(SPHINX_BUILD, *BUILD_PARAMETERS, SOURCE_DIR, OUTPUT_DIR, *session.posargs)
5665
# When building the guide, also build the translations in RELEASE_LANGUAGES
5766
session.notify("build-release-languages", session.posargs)
@@ -65,11 +74,18 @@ def docs_test(session):
6574
Note: this is the session used in CI/CD to release the guide.
6675
"""
6776
session.install("-e", ".")
68-
session.run(SPHINX_BUILD, *BUILD_PARAMETERS, *TEST_PARAMETERS, SOURCE_DIR, OUTPUT_DIR, *session.posargs)
77+
session.run(SPHINX_BUILD, *BUILD_PARAMETERS, *TEST_PARAMETERS, SOURCE_DIR, OUTPUT_DIR, *session.posargs,
78+
env={'SPHINX_ENV': 'production'})
6979
# When building the guide with additional parameters, also build the translations in RELEASE_LANGUAGES
7080
# with those same parameters.
7181
session.notify("build-release-languages", [*TEST_PARAMETERS, *session.posargs])
7282

83+
def _autobuild_cmd(posargs: list[str], output_dir = OUTPUT_DIR) -> list[str]:
84+
cmd = [SPHINX_AUTO_BUILD, *BUILD_PARAMETERS, str(SOURCE_DIR), str(output_dir), *posargs]
85+
for folder in AUTOBUILD_IGNORE:
86+
cmd.extend(["--ignore", f"*/{folder}/*"])
87+
return cmd
88+
7389

7490
@nox.session(name="docs-live")
7591
def docs_live(session):
@@ -87,13 +103,11 @@ def docs_live(session):
87103
so they don't need to remember the specific sphinx-build parameters to build a different language.
88104
"""
89105
session.install("-e", ".")
90-
cmd = [SPHINX_AUTO_BUILD, *BUILD_PARAMETERS, SOURCE_DIR, OUTPUT_DIR, *session.posargs]
91-
for folder in AUTOBUILD_IGNORE:
92-
cmd.extend(["--ignore", f"*/{folder}/*"])
106+
cmd = _autobuild_cmd(session.posargs)
93107
# This part was commented in the previous version of the nox file, keeping the same here
94108
# for folder in AUTOBUILD_INCLUDE:
95109
# cmd.extend(["--watch", folder])
96-
session.run(*cmd)
110+
session.run(*cmd, env={'SPHINX_ENV': "development"})
97111

98112

99113
@nox.session(name="docs-live-lang")
@@ -127,6 +141,37 @@ def docs_live_lang(session):
127141
f"where LANG is one of: {LANGUAGES}"
128142
)
129143

144+
@nox.session(name="docs-live-langs")
145+
def docs_live_langs(session):
146+
"""
147+
Like docs-live but build all languages simultaneously
148+
149+
Requires concurrently to run (npm install -g concurrently)
150+
"""
151+
try:
152+
subprocess.check_call(['concurrently'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
153+
except subprocess.CalledProcessError:
154+
# handle errors in the called executable
155+
# (aka, was found)
156+
pass
157+
except OSError:
158+
session.error('docs-live-langs requires concurrently (npm install -g concurrently)')
159+
160+
session.install("-e", ".")
161+
162+
cmds = ['"' + " ".join(["SPHINX_ENV=development"] + _autobuild_cmd(session.posargs) + ['--open-browser']) + '"']
163+
for language in LANGUAGES:
164+
cmds.append(
165+
'"' + " ".join(
166+
[f"SPHINX_LANG={language}", "SPHINX_ENV=development"] +
167+
_autobuild_cmd(
168+
session.posargs + ["-D", f"language={language}"],
169+
output_dir=OUTPUT_DIR / language
170+
) + ["--port=0"]
171+
) + '"'
172+
)
173+
cmd = ['concurrently', '--kill-others', '-n', ','.join(["en"] + LANGUAGES), '-c', 'auto', *cmds]
174+
session.run(*cmd)
130175

131176
@nox.session(name="docs-clean")
132177
def clean_dir(session):
@@ -187,6 +232,13 @@ def update_language(session):
187232
"nox -s update-language -- LANG\n\n "
188233
f" where LANG is one of: {LANGUAGES}"
189234
)
235+
if not session.posargs:
236+
session.error("Please provide the list of languages to build the translation for")
237+
238+
sphinx_env = _sphinx_env(session)
239+
240+
languages_to_build = session.posargs.pop(0)
241+
190242

191243
@nox.session(name="build-language")
192244
def build_language(session):
@@ -215,13 +267,20 @@ def build_release_languages(session):
215267
"""
216268
Build the translations of the guide for the languages in RELEASE_LANGUAGES.
217269
"""
270+
sphinx_env = _sphinx_env(session)
218271
if not RELEASE_LANGUAGES:
219272
session.warn("No release languages defined in RELEASE_LANGUAGES")
220273
return
221274
session.install("-e", ".")
222275
for lang in RELEASE_LANGUAGES:
223276
session.log(f"Building [{lang}] guide")
224277
session.run(SPHINX_BUILD, *BUILD_PARAMETERS, "-D", f"language={lang}", ".", OUTPUT_DIR / lang, *session.posargs)
278+
if lang == 'en':
279+
out_dir = OUTPUT_DIR
280+
else:
281+
out_dir = OUTPUT_DIR / lang
282+
session.run(SPHINX_BUILD, *BUILD_PARAMETERS, "-D", f"language={lang}", ".", out_dir, *session.posargs,
283+
env={"SPHINX_LANG": lang, "SPHINX_ENV": sphinx_env})
225284
session.log(f"Translations built for {RELEASE_LANGUAGES}")
226285

227286
@nox.session(name="build-all-languages")
@@ -237,6 +296,19 @@ def build_all_languages(session):
237296
session.log(f"Building [{lang}] guide")
238297
session.run(SPHINX_BUILD, *BUILD_PARAMETERS, "-D", f"language={lang}", ".", OUTPUT_DIR / lang, *session.posargs)
239298
session.log(f"Translations built for {LANGUAGES}")
299+
sphinx_env = _sphinx_env(session)
300+
301+
# if running from the docs or docs-test sessions, build only release languages
302+
BUILD_LANGUAGES = RELEASE_LANGUAGES if sphinx_env == "production" else LANGUAGES
303+
# only build languages that have a locale folder
304+
BUILD_LANGUAGES = [lang for lang in BUILD_LANGUAGES if (TRANSLATION_LOCALES_DIR / lang).exists()]
305+
session.log(f"Declared languages: {LANGUAGES}")
306+
session.log(f"Release languages: {RELEASE_LANGUAGES}")
307+
session.log(f"Building languages{' for release' if sphinx_env == 'production' else ''}: {BUILD_LANGUAGES}")
308+
if not BUILD_LANGUAGES:
309+
session.warn("No translations to build")
310+
else:
311+
session.notify("build-languages", [sphinx_env, BUILD_LANGUAGES, *session.posargs])
240312

241313

242314
@nox.session(name="build-all-languages-test")
@@ -248,3 +320,14 @@ def build_all_languages_test(session):
248320
in the same way docs-test does for the English version.
249321
"""
250322
session.notify("build-all-languages", [*TEST_PARAMETERS])
323+
324+
325+
def _sphinx_env(session) -> str:
326+
"""
327+
Get the sphinx env, from the first positional argument if present or from the
328+
``SPHINX_ENV`` environment variable, defaulting to "development"
329+
"""
330+
if session.posargs and session.posargs[0] in SPHINX_ENVS:
331+
return session.posargs.pop(0)
332+
else:
333+
return os.environ.get('SPHINX_ENV', 'development')

tutorials/intro.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ Get to know Hatch <get-to-know-hatch>
3737
:caption: Create and publish a Python Package
3838

3939
What is a Python package? <self>
40-
Make your code installable <installable-code>
40+
Create a Python package <installable-code>
4141
Publish to PyPI <publish-pypi>
4242
Publish to conda-forge <publish-conda-forge>
4343
:::

0 commit comments

Comments
 (0)