22
22
23
23
from __future__ import annotations
24
24
25
+ import argparse
26
+ import dataclasses
27
+ import datetime as dt
25
28
import filecmp
26
29
import json
27
30
import logging
28
31
import logging .handlers
32
+ import os
29
33
import re
30
34
import shlex
31
35
import shutil
32
36
import subprocess
33
37
import sys
34
- from argparse import ArgumentParser , Namespace
35
38
from bisect import bisect_left as bisect
36
39
from contextlib import contextmanager , suppress
37
- from dataclasses import dataclass
38
- from datetime import datetime as dt , timezone
39
40
from functools import total_ordering
40
- from os import getenv , readlink
41
41
from pathlib import Path
42
42
from string import Template
43
43
from time import perf_counter , sleep
68
68
HERE = Path (__file__ ).resolve ().parent
69
69
70
70
71
- @dataclass (frozen = True , slots = True )
71
+ @dataclasses . dataclass (frozen = True , slots = True )
72
72
class Versions :
73
73
_seq : Sequence [Version ]
74
74
@@ -213,7 +213,7 @@ def picker_label(self):
213
213
return self .name
214
214
215
215
216
- @dataclass (frozen = True , slots = True )
216
+ @dataclasses . dataclass (frozen = True , slots = True )
217
217
class Languages :
218
218
_seq : Sequence [Language ]
219
219
@@ -250,7 +250,7 @@ def filter(self, language_tags: Sequence[str] = ()) -> Sequence[Language]:
250
250
return list (self )
251
251
252
252
253
- @dataclass (order = True , frozen = True , kw_only = True )
253
+ @dataclasses . dataclass (order = True , frozen = True , kw_only = True )
254
254
class Language :
255
255
iso639_tag : str
256
256
name : str
@@ -337,7 +337,7 @@ def traverse(dircmp_result):
337
337
return changed
338
338
339
339
340
- @dataclass
340
+ @dataclasses . dataclass
341
341
class Repository :
342
342
"""Git repository abstraction for our specific needs."""
343
343
@@ -505,7 +505,7 @@ def version_info():
505
505
)
506
506
507
507
508
- @dataclass
508
+ @dataclasses . dataclass
509
509
class DocBuilder :
510
510
"""Builder for a CPython version and a language."""
511
511
@@ -539,7 +539,7 @@ def includes_html(self):
539
539
def run (self , http : urllib3 .PoolManager ) -> bool :
540
540
"""Build and publish a Python doc, for a language, and a version."""
541
541
start_time = perf_counter ()
542
- start_timestamp = dt .now (tz = timezone . utc ).replace (microsecond = 0 )
542
+ start_timestamp = dt .datetime . now (tz = dt . UTC ).replace (microsecond = 0 )
543
543
logging .info ("Running." )
544
544
try :
545
545
if self .language .html_only and not self .includes_html :
@@ -861,7 +861,7 @@ def load_state(self) -> dict:
861
861
except (KeyError , FileNotFoundError ):
862
862
return {}
863
863
864
- def save_state (self , build_start : dt , build_duration : float , trigger : str ):
864
+ def save_state (self , build_start : dt . datetime , build_duration : float , trigger : str ):
865
865
"""Save current CPython sha1 and current translation sha1.
866
866
867
867
Using this we can deduce if a rebuild is needed or not.
@@ -932,8 +932,9 @@ def main():
932
932
def parse_args ():
933
933
"""Parse command-line arguments."""
934
934
935
- parser = ArgumentParser (
936
- description = "Runs a build of the Python docs for various branches."
935
+ parser = argparse .ArgumentParser (
936
+ description = "Runs a build of the Python docs for various branches." ,
937
+ allow_abbrev = False ,
937
938
)
938
939
parser .add_argument (
939
940
"--select-output" ,
@@ -1032,7 +1033,7 @@ def setup_logging(log_directory: Path, select_output: str | None):
1032
1033
logging .getLogger ().setLevel (logging .DEBUG )
1033
1034
1034
1035
1035
- def build_docs_with_lock (args : Namespace , lockfile_name : str ) -> int :
1036
+ def build_docs_with_lock (args : argparse . Namespace , lockfile_name : str ) -> int :
1036
1037
try :
1037
1038
lock = zc .lockfile .LockFile (HERE / lockfile_name )
1038
1039
except zc .lockfile .LockError :
@@ -1045,7 +1046,7 @@ def build_docs_with_lock(args: Namespace, lockfile_name: str) -> int:
1045
1046
lock .close ()
1046
1047
1047
1048
1048
- def build_docs (args ) -> bool :
1049
+ def build_docs (args : argparse . Namespace ) -> bool :
1049
1050
"""Build all docs (each language and each version)."""
1050
1051
logging .info ("Full build start." )
1051
1052
start_time = perf_counter ()
@@ -1259,7 +1260,7 @@ def symlink(
1259
1260
if not directory_path .exists ():
1260
1261
return # No touching link, dest doc not built yet.
1261
1262
1262
- if not link .exists () or readlink (link ) != directory :
1263
+ if not link .exists () or os . readlink (link ) != directory :
1263
1264
# Link does not exist or points to the wrong target.
1264
1265
link .unlink (missing_ok = True )
1265
1266
link .symlink_to (directory )
@@ -1318,8 +1319,8 @@ def purge_surrogate_key(http: urllib3.PoolManager, surrogate_key: str) -> None:
1318
1319
1319
1320
https://www.fastly.com/documentation/reference/api/purging/#purge-tag
1320
1321
"""
1321
- service_id = getenv ("FASTLY_SERVICE_ID" , "__UNSET__" )
1322
- fastly_key = getenv ("FASTLY_TOKEN" , "__UNSET__" )
1322
+ service_id = os . environ . get ("FASTLY_SERVICE_ID" , "__UNSET__" )
1323
+ fastly_key = os . environ . get ("FASTLY_TOKEN" , "__UNSET__" )
1323
1324
1324
1325
logging .info ("Purging Surrogate-Key '%s' from CDN" , surrogate_key )
1325
1326
http .request (
0 commit comments