emcd-projects 1.23a0__tar.gz → 1.24__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {emcd_projects-1.23a0 → emcd_projects-1.24}/.gitignore +3 -0
- {emcd_projects-1.23a0 → emcd_projects-1.24}/PKG-INFO +1 -1
- emcd_projects-1.24/data/templates/website.html.jinja +103 -0
- {emcd_projects-1.23a0 → emcd_projects-1.24}/pyproject.toml +0 -2
- {emcd_projects-1.23a0 → emcd_projects-1.24}/sources/emcdproj/__/imports.py +2 -3
- {emcd_projects-1.23a0 → emcd_projects-1.24}/sources/emcdproj/__init__.py +1 -1
- {emcd_projects-1.23a0 → emcd_projects-1.24}/sources/emcdproj/cli.py +0 -2
- {emcd_projects-1.23a0 → emcd_projects-1.24}/sources/emcdproj/website.py +251 -28
- emcd_projects-1.23a0/data/templates/website.html.jinja +0 -58
- {emcd_projects-1.23a0 → emcd_projects-1.24}/LICENSE.txt +0 -0
- {emcd_projects-1.23a0 → emcd_projects-1.24}/data/.gitignore +0 -0
- {emcd_projects-1.23a0 → emcd_projects-1.24}/data/copier/answers-default.yaml +0 -0
- {emcd_projects-1.23a0 → emcd_projects-1.24}/data/copier/answers-maximum.yaml +0 -0
- {emcd_projects-1.23a0 → emcd_projects-1.24}/data/templates/coverage.svg.jinja +0 -0
- {emcd_projects-1.23a0 → emcd_projects-1.24}/sources/emcdproj/README.rst +0 -0
- {emcd_projects-1.23a0 → emcd_projects-1.24}/sources/emcdproj/__/__init__.py +0 -0
- {emcd_projects-1.23a0 → emcd_projects-1.24}/sources/emcdproj/__/application.py +0 -0
- {emcd_projects-1.23a0 → emcd_projects-1.24}/sources/emcdproj/__/distribution.py +0 -0
- {emcd_projects-1.23a0 → emcd_projects-1.24}/sources/emcdproj/__/nomina.py +0 -0
- {emcd_projects-1.23a0 → emcd_projects-1.24}/sources/emcdproj/__/preparation.py +0 -0
- {emcd_projects-1.23a0 → emcd_projects-1.24}/sources/emcdproj/__/state.py +0 -0
- {emcd_projects-1.23a0 → emcd_projects-1.24}/sources/emcdproj/__main__.py +0 -0
- {emcd_projects-1.23a0 → emcd_projects-1.24}/sources/emcdproj/_typedecls/__builtins__.pyi +0 -0
- {emcd_projects-1.23a0 → emcd_projects-1.24}/sources/emcdproj/exceptions.py +0 -0
- {emcd_projects-1.23a0 → emcd_projects-1.24}/sources/emcdproj/filesystem.py +0 -0
- {emcd_projects-1.23a0 → emcd_projects-1.24}/sources/emcdproj/interfaces.py +0 -0
- {emcd_projects-1.23a0 → emcd_projects-1.24}/sources/emcdproj/py.typed +0 -0
- {emcd_projects-1.23a0 → emcd_projects-1.24}/sources/emcdproj/template.py +0 -0
@@ -0,0 +1,103 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html lang="en">
|
3
|
+
<head>
|
4
|
+
<meta charset="UTF-8">
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
6
|
+
<title>Available Releases</title>
|
7
|
+
<style>
|
8
|
+
table {
|
9
|
+
width: 100%;
|
10
|
+
border-collapse: collapse;
|
11
|
+
}
|
12
|
+
th, td {
|
13
|
+
padding: 8px;
|
14
|
+
text-align: left;
|
15
|
+
border-bottom: 1px solid #ddd;
|
16
|
+
}
|
17
|
+
th {
|
18
|
+
background-color: #f2f2f2;
|
19
|
+
}
|
20
|
+
tr:hover {
|
21
|
+
background-color: #f5f5f5;
|
22
|
+
}
|
23
|
+
</style>
|
24
|
+
</head>
|
25
|
+
<body>
|
26
|
+
<h1>Available Releases</h1>
|
27
|
+
|
28
|
+
{% if stable_dev_versions %}
|
29
|
+
<h2>Current Releases</h2>
|
30
|
+
<table>
|
31
|
+
<thead>
|
32
|
+
<tr>
|
33
|
+
<th>Version</th>
|
34
|
+
<th>Documentation</th>
|
35
|
+
<th>Coverage</th>
|
36
|
+
</tr>
|
37
|
+
</thead>
|
38
|
+
<tbody>
|
39
|
+
{% for version_label, attributes in stable_dev_versions.items() %}
|
40
|
+
<tr>
|
41
|
+
<td>{{ version_label }}</td>
|
42
|
+
<td>
|
43
|
+
{% if 'sphinx-html' in attributes %}
|
44
|
+
{% if version_label.startswith('stable') %}
|
45
|
+
<a href="stable/sphinx-html/index.html">Docs</a>
|
46
|
+
{% elif version_label.startswith('development') %}
|
47
|
+
<a href="development/sphinx-html/index.html">Docs</a>
|
48
|
+
{% endif %}
|
49
|
+
{% else %}
|
50
|
+
N/A
|
51
|
+
{% endif %}
|
52
|
+
</td>
|
53
|
+
<td>
|
54
|
+
{% if 'coverage-pytest' in attributes %}
|
55
|
+
{% if version_label.startswith('stable') %}
|
56
|
+
<a href="stable/coverage-pytest/index.html">Coverage</a>
|
57
|
+
{% elif version_label.startswith('development') %}
|
58
|
+
<a href="development/coverage-pytest/index.html">Coverage</a>
|
59
|
+
{% endif %}
|
60
|
+
{% else %}
|
61
|
+
N/A
|
62
|
+
{% endif %}
|
63
|
+
</td>
|
64
|
+
</tr>
|
65
|
+
{% endfor %}
|
66
|
+
</tbody>
|
67
|
+
</table>
|
68
|
+
|
69
|
+
<h2>All Releases</h2>
|
70
|
+
{% endif %}
|
71
|
+
|
72
|
+
<table>
|
73
|
+
<thead>
|
74
|
+
<tr>
|
75
|
+
<th>Version</th>
|
76
|
+
<th>Documentation</th>
|
77
|
+
<th>Coverage</th>
|
78
|
+
</tr>
|
79
|
+
</thead>
|
80
|
+
<tbody>
|
81
|
+
{% for version, attributes in versions.items() %}
|
82
|
+
<tr>
|
83
|
+
<td>{{ version }}</td>
|
84
|
+
<td>
|
85
|
+
{% if 'sphinx-html' in attributes %}
|
86
|
+
<a href="{{ version }}/sphinx-html/index.html">Docs</a>
|
87
|
+
{% else %}
|
88
|
+
N/A
|
89
|
+
{% endif %}
|
90
|
+
</td>
|
91
|
+
<td>
|
92
|
+
{% if 'coverage-pytest' in attributes %}
|
93
|
+
<a href="{{ version }}/coverage-pytest/index.html">Coverage</a>
|
94
|
+
{% else %}
|
95
|
+
N/A
|
96
|
+
{% endif %}
|
97
|
+
</td>
|
98
|
+
</tr>
|
99
|
+
{% endfor %}
|
100
|
+
</tbody>
|
101
|
+
</table>
|
102
|
+
</body>
|
103
|
+
</html>
|
@@ -18,13 +18,11 @@
|
|
18
18
|
#============================================================================#
|
19
19
|
|
20
20
|
|
21
|
-
''' Common imports
|
21
|
+
''' Common imports used throughout the package. '''
|
22
22
|
|
23
23
|
# ruff: noqa: F401
|
24
24
|
|
25
25
|
|
26
|
-
from __future__ import annotations
|
27
|
-
|
28
26
|
import abc
|
29
27
|
import collections.abc as cabc
|
30
28
|
import contextlib as ctxl
|
@@ -33,6 +31,7 @@ import io
|
|
33
31
|
import json
|
34
32
|
import math
|
35
33
|
import os
|
34
|
+
import subprocess
|
36
35
|
import shutil
|
37
36
|
import sys
|
38
37
|
import tempfile
|
@@ -19,8 +19,6 @@
|
|
19
19
|
|
20
20
|
|
21
21
|
''' Static website maintenance utilities for projects. '''
|
22
|
-
# TODO: Support separate section for current documentation: stable, latest.
|
23
|
-
# TODO? Separate coverage SVG files for each release.
|
24
22
|
|
25
23
|
|
26
24
|
from __future__ import annotations
|
@@ -60,11 +58,15 @@ class SurveyCommand(
|
|
60
58
|
):
|
61
59
|
''' Surveys release versions published in static website. '''
|
62
60
|
|
61
|
+
use_extant: __.typx.Annotated[
|
62
|
+
bool,
|
63
|
+
__.typx.Doc( ''' Fetch publication branch and use tarball. ''' ),
|
64
|
+
] = False
|
65
|
+
|
63
66
|
async def __call__(
|
64
67
|
self, auxdata: __.Globals, display: _interfaces.ConsoleDisplay
|
65
68
|
) -> None:
|
66
|
-
|
67
|
-
pass
|
69
|
+
survey( auxdata, use_extant = self.use_extant )
|
68
70
|
|
69
71
|
|
70
72
|
class UpdateCommand(
|
@@ -78,10 +80,24 @@ class UpdateCommand(
|
|
78
80
|
__.tyro.conf.Positional,
|
79
81
|
]
|
80
82
|
|
83
|
+
use_extant: __.typx.Annotated[
|
84
|
+
bool,
|
85
|
+
__.typx.Doc( ''' Fetch publication branch and use tarball. ''' ),
|
86
|
+
] = False
|
87
|
+
|
88
|
+
production: __.typx.Annotated[
|
89
|
+
bool,
|
90
|
+
__.typx.Doc( ''' Update publication branch with new tarball.
|
91
|
+
Implies --use-extant to prevent data loss. ''' ),
|
92
|
+
] = False
|
93
|
+
|
81
94
|
async def __call__(
|
82
95
|
self, auxdata: __.Globals, display: _interfaces.ConsoleDisplay
|
83
96
|
) -> None:
|
84
|
-
update(
|
97
|
+
update(
|
98
|
+
auxdata, self.version,
|
99
|
+
use_extant = self.use_extant,
|
100
|
+
production = self.production )
|
85
101
|
|
86
102
|
|
87
103
|
class Locations( metaclass = __.ImmutableDataclass ):
|
@@ -129,11 +145,57 @@ class Locations( metaclass = __.ImmutableDataclass ):
|
|
129
145
|
templates = templates )
|
130
146
|
|
131
147
|
|
148
|
+
def survey(
|
149
|
+
auxdata: __.Globals, *,
|
150
|
+
project_anchor: __.Absential[ __.Path ] = __.absent,
|
151
|
+
use_extant: bool = False
|
152
|
+
) -> None:
|
153
|
+
''' Surveys release versions published in static website.
|
154
|
+
|
155
|
+
Lists all versions from the versions manifest, showing their
|
156
|
+
available documentation types and highlighting the latest version.
|
157
|
+
'''
|
158
|
+
locations = Locations.from_project_anchor( auxdata, project_anchor )
|
159
|
+
|
160
|
+
# Handle --use-extant flag: fetch publication branch and checkout tarball
|
161
|
+
if use_extant:
|
162
|
+
_fetch_publication_branch_and_tarball( locations )
|
163
|
+
# Extract the fetched tarball to view published versions
|
164
|
+
if locations.archive.is_file( ):
|
165
|
+
from tarfile import open as tarfile_open
|
166
|
+
if locations.website.is_dir( ):
|
167
|
+
__.shutil.rmtree( locations.website )
|
168
|
+
locations.website.mkdir( exist_ok = True, parents = True )
|
169
|
+
with tarfile_open( locations.archive, 'r:xz' ) as archive:
|
170
|
+
archive.extractall( path = locations.website ) # noqa: S202
|
171
|
+
|
172
|
+
if not locations.versions.is_file( ):
|
173
|
+
context = "published" if use_extant else "local"
|
174
|
+
print( f"No versions manifest found for {context} website. "
|
175
|
+
f"Run 'website update' first." )
|
176
|
+
return
|
177
|
+
with locations.versions.open( 'r' ) as file:
|
178
|
+
data = __.json.load( file )
|
179
|
+
versions = data.get( 'versions', { } )
|
180
|
+
latest = data.get( 'latest_version' )
|
181
|
+
if not versions:
|
182
|
+
context = "published" if use_extant else "local"
|
183
|
+
print( f"No versions found in {context} manifest." )
|
184
|
+
return
|
185
|
+
context = "Published" if use_extant else "Local"
|
186
|
+
print( f"{context} versions:" )
|
187
|
+
for version, species in versions.items( ):
|
188
|
+
marker = " (latest)" if version == latest else ""
|
189
|
+
species_list = ', '.join( species ) if species else "none"
|
190
|
+
print( f" {version}{marker}: {species_list}" )
|
191
|
+
|
132
192
|
|
133
193
|
def update(
|
134
194
|
auxdata: __.Globals,
|
135
195
|
version: str, *,
|
136
|
-
project_anchor: __.Absential[ __.Path ] = __.absent
|
196
|
+
project_anchor: __.Absential[ __.Path ] = __.absent,
|
197
|
+
use_extant: bool = False,
|
198
|
+
production: bool = False
|
137
199
|
) -> None:
|
138
200
|
''' Updates project website with latest documentation and coverage.
|
139
201
|
|
@@ -145,6 +207,9 @@ def update(
|
|
145
207
|
from tarfile import open as tarfile_open
|
146
208
|
locations = Locations.from_project_anchor( auxdata, project_anchor )
|
147
209
|
locations.publications.mkdir( exist_ok = True, parents = True )
|
210
|
+
# --production implies --use-extant to prevent clobbering existing versions
|
211
|
+
if use_extant or production:
|
212
|
+
_fetch_publication_branch_and_tarball( locations )
|
148
213
|
if locations.website.is_dir( ): __.shutil.rmtree( locations.website )
|
149
214
|
locations.website.mkdir( exist_ok = True, parents = True )
|
150
215
|
if locations.archive.is_file( ):
|
@@ -155,14 +220,86 @@ def update(
|
|
155
220
|
loader = _jinja2.FileSystemLoader( locations.templates ),
|
156
221
|
autoescape = True )
|
157
222
|
index_data = _update_versions_json( locations, version, available_species )
|
223
|
+
_enhance_index_data_with_stable_dev( index_data )
|
224
|
+
_create_stable_dev_directories( locations, index_data )
|
158
225
|
_update_index_html( locations, j2context, index_data )
|
159
226
|
if ( locations.artifacts / 'coverage-pytest' ).is_dir( ):
|
160
227
|
_update_coverage_badge( locations, j2context )
|
228
|
+
_update_version_coverage_badge( locations, j2context, version )
|
161
229
|
( locations.website / '.nojekyll' ).touch( )
|
162
230
|
from .filesystem import chdir
|
163
231
|
with chdir( locations.website ): # noqa: SIM117
|
164
232
|
with tarfile_open( locations.archive, 'w:xz' ) as archive:
|
165
233
|
archive.add( '.' )
|
234
|
+
if production: _update_publication_branch( locations, version )
|
235
|
+
|
236
|
+
|
237
|
+
def _create_stable_dev_directories(
|
238
|
+
locations: Locations, data: dict[ __.typx.Any, __.typx.Any ]
|
239
|
+
) -> None:
|
240
|
+
''' Creates stable/ and development/ directories with current releases.
|
241
|
+
|
242
|
+
Copies the content from the identified stable and development versions
|
243
|
+
to stable/ and development/ directories to provide persistent URLs
|
244
|
+
that don't change when new versions are released.
|
245
|
+
'''
|
246
|
+
stable_version = data.get( 'stable_version' )
|
247
|
+
development_version = data.get( 'development_version' )
|
248
|
+
if stable_version:
|
249
|
+
stable_source = locations.website / stable_version
|
250
|
+
stable_dest = locations.website / 'stable'
|
251
|
+
if stable_dest.is_dir( ):
|
252
|
+
__.shutil.rmtree( stable_dest )
|
253
|
+
if stable_source.is_dir( ):
|
254
|
+
__.shutil.copytree( stable_source, stable_dest )
|
255
|
+
if development_version:
|
256
|
+
dev_source = locations.website / development_version
|
257
|
+
dev_dest = locations.website / 'development'
|
258
|
+
if dev_dest.is_dir( ):
|
259
|
+
__.shutil.rmtree( dev_dest )
|
260
|
+
if dev_source.is_dir( ):
|
261
|
+
__.shutil.copytree( dev_source, dev_dest )
|
262
|
+
|
263
|
+
|
264
|
+
def _enhance_index_data_with_stable_dev(
|
265
|
+
data: dict[ __.typx.Any, __.typx.Any ]
|
266
|
+
) -> None:
|
267
|
+
''' Enhances index data with stable/development version information.
|
268
|
+
|
269
|
+
Identifies the latest stable release and latest development version
|
270
|
+
from the versions data and adds them as separate entries for the
|
271
|
+
stable/development table.
|
272
|
+
'''
|
273
|
+
from packaging.version import Version
|
274
|
+
versions = data.get( 'versions', { } )
|
275
|
+
if not versions:
|
276
|
+
data[ 'stable_dev_versions' ] = { }
|
277
|
+
return
|
278
|
+
stable_version = None
|
279
|
+
development_version = None
|
280
|
+
# Sort versions by packaging.version.Version for proper comparison
|
281
|
+
sorted_versions = sorted(
|
282
|
+
versions.items( ),
|
283
|
+
key = lambda entry: Version( entry[ 0 ] ),
|
284
|
+
reverse = True )
|
285
|
+
# Find latest stable (non-prerelease) and development (prerelease) versions
|
286
|
+
for version_string, species in sorted_versions:
|
287
|
+
version_obj = Version( version_string )
|
288
|
+
if not version_obj.is_prerelease and stable_version is None:
|
289
|
+
stable_version = ( version_string, species )
|
290
|
+
if version_obj.is_prerelease and development_version is None:
|
291
|
+
development_version = ( version_string, species )
|
292
|
+
if stable_version and development_version:
|
293
|
+
break
|
294
|
+
stable_dev_versions: dict[ str, tuple[ str, ... ] ] = { }
|
295
|
+
if stable_version:
|
296
|
+
stable_dev_versions[ 'stable (current)' ] = stable_version[ 1 ]
|
297
|
+
data[ 'stable_version' ] = stable_version[ 0 ]
|
298
|
+
if development_version:
|
299
|
+
stable_dev_versions[ 'development (current)' ] = (
|
300
|
+
development_version[ 1 ] )
|
301
|
+
data[ 'development_version' ] = development_version[ 0 ]
|
302
|
+
data[ 'stable_dev_versions' ] = stable_dev_versions
|
166
303
|
|
167
304
|
|
168
305
|
def _extract_coverage( locations: Locations ) -> int:
|
@@ -184,6 +321,58 @@ def _extract_coverage( locations: Locations ) -> int:
|
|
184
321
|
return __.math.floor( float( line_rate ) * 100 )
|
185
322
|
|
186
323
|
|
324
|
+
def _fetch_publication_branch_and_tarball( locations: Locations ) -> None:
|
325
|
+
''' Fetches publication branch and checks out existing tarball.
|
326
|
+
|
327
|
+
Attempts to fetch the publication branch from origin and checkout
|
328
|
+
the website tarball. Ignores failures if branch or tarball don't exist.
|
329
|
+
'''
|
330
|
+
with __.ctxl.suppress( Exception ):
|
331
|
+
__.subprocess.run(
|
332
|
+
[ 'git', 'fetch', 'origin', 'publication:publication' ],
|
333
|
+
cwd = locations.project,
|
334
|
+
check = False,
|
335
|
+
capture_output = True )
|
336
|
+
with __.ctxl.suppress( Exception ):
|
337
|
+
__.subprocess.run(
|
338
|
+
[ 'git', 'checkout', 'publication', '--',
|
339
|
+
str( locations.archive ) ],
|
340
|
+
cwd = locations.project,
|
341
|
+
check = False,
|
342
|
+
capture_output = True )
|
343
|
+
|
344
|
+
|
345
|
+
def _generate_coverage_badge_svg(
|
346
|
+
locations: Locations, j2context: _jinja2.Environment
|
347
|
+
) -> str:
|
348
|
+
''' Generates coverage badge SVG content.
|
349
|
+
|
350
|
+
Returns the rendered SVG content for a coverage badge based on the
|
351
|
+
current coverage percentage. Colors indicate coverage quality:
|
352
|
+
- red: < 50%
|
353
|
+
- yellow: 50-79%
|
354
|
+
- green: >= 80%
|
355
|
+
'''
|
356
|
+
coverage = _extract_coverage( locations )
|
357
|
+
color = (
|
358
|
+
'red' if coverage < 50 else ( # noqa: PLR2004
|
359
|
+
'yellow' if coverage < 80 else 'green' ) ) # noqa: PLR2004
|
360
|
+
label_text = 'coverage'
|
361
|
+
value_text = f"{coverage}%"
|
362
|
+
label_width = len( label_text ) * 6 + 10
|
363
|
+
value_width = len( value_text ) * 6 + 15
|
364
|
+
total_width = label_width + value_width
|
365
|
+
template = j2context.get_template( 'coverage.svg.jinja' )
|
366
|
+
# TODO: Add error handling for template rendering failures.
|
367
|
+
return template.render(
|
368
|
+
color = color,
|
369
|
+
total_width = total_width,
|
370
|
+
label_text = label_text,
|
371
|
+
value_text = value_text,
|
372
|
+
label_width = label_width,
|
373
|
+
value_width = value_width )
|
374
|
+
|
375
|
+
|
187
376
|
def _update_available_species(
|
188
377
|
locations: Locations, version: str
|
189
378
|
) -> tuple[ str, ... ]:
|
@@ -204,30 +393,49 @@ def _update_coverage_badge(
|
|
204
393
|
''' Updates coverage badge SVG.
|
205
394
|
|
206
395
|
Generates a color-coded coverage badge based on the current coverage
|
207
|
-
percentage
|
208
|
-
- red: < 50%
|
209
|
-
- yellow: 50-79%
|
210
|
-
- green: >= 80%
|
396
|
+
percentage and writes it to the main coverage.svg location.
|
211
397
|
'''
|
212
|
-
|
213
|
-
color = (
|
214
|
-
'red' if coverage < 50 else ( # noqa: PLR2004
|
215
|
-
'yellow' if coverage < 80 else 'green' ) ) # noqa: PLR2004
|
216
|
-
label_text = 'coverage'
|
217
|
-
value_text = f"{coverage}%"
|
218
|
-
label_width = len( label_text ) * 6 + 10
|
219
|
-
value_width = len( value_text ) * 6 + 15
|
220
|
-
total_width = label_width + value_width
|
221
|
-
template = j2context.get_template( 'coverage.svg.jinja' )
|
222
|
-
# TODO: Add error handling for template rendering failures.
|
398
|
+
svg_content = _generate_coverage_badge_svg( locations, j2context )
|
223
399
|
with locations.coverage.open( 'w' ) as file:
|
224
|
-
file.write(
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
400
|
+
file.write( svg_content )
|
401
|
+
|
402
|
+
|
403
|
+
def _update_publication_branch( locations: Locations, version: str ) -> None:
|
404
|
+
''' Updates publication branch with new tarball.
|
405
|
+
|
406
|
+
Adds the tarball to git, commits to the publication branch, and pushes
|
407
|
+
to origin. Uses the same approach as the GitHub workflow.
|
408
|
+
'''
|
409
|
+
__.subprocess.run(
|
410
|
+
[ 'git', 'add', str( locations.archive ) ],
|
411
|
+
cwd = locations.project,
|
412
|
+
check = True )
|
413
|
+
# Commit to publication branch without checkout
|
414
|
+
# Get current tree hash
|
415
|
+
tree_result = __.subprocess.run(
|
416
|
+
[ 'git', 'write-tree' ],
|
417
|
+
cwd = locations.project,
|
418
|
+
check = True,
|
419
|
+
capture_output = True,
|
420
|
+
text = True )
|
421
|
+
tree_hash = tree_result.stdout.strip( )
|
422
|
+
# Create commit with publication branch as parent
|
423
|
+
commit_result = __.subprocess.run(
|
424
|
+
[ 'git', 'commit-tree', tree_hash, '-p', 'publication',
|
425
|
+
'-m', f"Update documents for publication. ({version})" ],
|
426
|
+
cwd = locations.project,
|
427
|
+
check = True,
|
428
|
+
capture_output = True,
|
429
|
+
text = True )
|
430
|
+
commit_hash = commit_result.stdout.strip( )
|
431
|
+
__.subprocess.run(
|
432
|
+
[ 'git', 'branch', '--force', 'publication', commit_hash ],
|
433
|
+
cwd = locations.project,
|
434
|
+
check = True )
|
435
|
+
__.subprocess.run(
|
436
|
+
[ 'git', 'push', 'origin', 'publication:publication' ],
|
437
|
+
cwd = locations.project,
|
438
|
+
check = True )
|
231
439
|
|
232
440
|
|
233
441
|
def _update_index_html(
|
@@ -246,6 +454,21 @@ def _update_index_html(
|
|
246
454
|
file.write( template.render( **data ) )
|
247
455
|
|
248
456
|
|
457
|
+
def _update_version_coverage_badge(
|
458
|
+
locations: Locations, j2context: _jinja2.Environment, version: str
|
459
|
+
) -> None:
|
460
|
+
''' Updates version-specific coverage badge SVG.
|
461
|
+
|
462
|
+
Generates a coverage badge for the specific version and places it
|
463
|
+
in the version's subtree. This allows each version to have its own
|
464
|
+
coverage badge accessible at version/coverage.svg.
|
465
|
+
'''
|
466
|
+
svg_content = _generate_coverage_badge_svg( locations, j2context )
|
467
|
+
version_coverage_path = locations.website / version / 'coverage.svg'
|
468
|
+
with version_coverage_path.open( 'w' ) as file:
|
469
|
+
file.write( svg_content )
|
470
|
+
|
471
|
+
|
249
472
|
def _update_versions_json(
|
250
473
|
locations: Locations,
|
251
474
|
version: str,
|
@@ -1,58 +0,0 @@
|
|
1
|
-
<!DOCTYPE html>
|
2
|
-
<html lang="en">
|
3
|
-
<head>
|
4
|
-
<meta charset="UTF-8">
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
6
|
-
<title>Available Releases</title>
|
7
|
-
<style>
|
8
|
-
table {
|
9
|
-
width: 100%;
|
10
|
-
border-collapse: collapse;
|
11
|
-
}
|
12
|
-
th, td {
|
13
|
-
padding: 8px;
|
14
|
-
text-align: left;
|
15
|
-
border-bottom: 1px solid #ddd;
|
16
|
-
}
|
17
|
-
th {
|
18
|
-
background-color: #f2f2f2;
|
19
|
-
}
|
20
|
-
tr:hover {
|
21
|
-
background-color: #f5f5f5;
|
22
|
-
}
|
23
|
-
</style>
|
24
|
-
</head>
|
25
|
-
<body>
|
26
|
-
<h1>Available Releases</h1>
|
27
|
-
<table>
|
28
|
-
<thead>
|
29
|
-
<tr>
|
30
|
-
<th>Version</th>
|
31
|
-
<th>Documentation</th>
|
32
|
-
<th>Coverage</th>
|
33
|
-
</tr>
|
34
|
-
</thead>
|
35
|
-
<tbody>
|
36
|
-
{% for version, attributes in versions.items() %}
|
37
|
-
<tr>
|
38
|
-
<td>{{ version }}</td>
|
39
|
-
<td>
|
40
|
-
{% if 'sphinx-html' in attributes %}
|
41
|
-
<a href="{{ version }}/sphinx-html/index.html">Docs</a>
|
42
|
-
{% else %}
|
43
|
-
N/A
|
44
|
-
{% endif %}
|
45
|
-
</td>
|
46
|
-
<td>
|
47
|
-
{% if 'coverage-pytest' in attributes %}
|
48
|
-
<a href="{{ version }}/coverage-pytest/index.html">Coverage</a>
|
49
|
-
{% else %}
|
50
|
-
N/A
|
51
|
-
{% endif %}
|
52
|
-
</td>
|
53
|
-
</tr>
|
54
|
-
{% endfor %}
|
55
|
-
</tbody>
|
56
|
-
</table>
|
57
|
-
</body>
|
58
|
-
</html>
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|