@@ -75,24 +75,29 @@ class Version:
75
75
76
76
STATUSES = {"EOL" , "security-fixes" , "stable" , "pre-release" , "in development" }
77
77
78
+ # Those synonyms map branch status vocabulary found in the devguide
79
+ # with our vocabulary.
80
+ SYNONYMS = {
81
+ "feature" : "in development" ,
82
+ "bugfix" : "stable" ,
83
+ "security" : "security-fixes" ,
84
+ "end-of-life" : "EOL" ,
85
+ }
86
+
78
87
def __init__ (
79
88
self ,
80
89
name ,
81
90
* ,
82
91
status ,
83
- branch = None ,
84
- tag = None ,
92
+ branch_or_tag = None ,
85
93
):
94
+ status = self .SYNONYMS .get (status , status )
86
95
if status not in self .STATUSES :
87
96
raise ValueError (
88
- f"Version status expected to be in { ', ' .join (self .STATUSES ) } "
97
+ f"Version status expected to be one of: { ', ' .join (self .STATUSES | set ( self . SYNONYMS . keys ())) } , got { status !r } . "
89
98
)
90
99
self .name = name
91
- if branch is not None and tag is not None :
92
- raise ValueError ("Please build a version from either a branch or a tag." )
93
- if branch is None and tag is None :
94
- raise ValueError ("Please build a version with at least a branch or a tag." )
95
- self .branch_or_tag = branch or tag
100
+ self .branch_or_tag = branch_or_tag
96
101
self .status = status
97
102
98
103
def __repr__ (self ):
@@ -190,6 +195,10 @@ def setup_indexsidebar(self, versions, dest_path):
190
195
)
191
196
)
192
197
198
+ @classmethod
199
+ def from_json (cls , name , values ):
200
+ return cls (name , status = values ["status" ], branch_or_tag = values ["branch" ])
201
+
193
202
def __eq__ (self , other ):
194
203
return self .name == other .name
195
204
@@ -206,6 +215,15 @@ class Language:
206
215
sphinxopts : tuple
207
216
html_only : bool = False
208
217
218
+ @staticmethod
219
+ def filter (languages , language_tags = None ):
220
+ if language_tags :
221
+ languages_dict = {language .tag : language for language in languages }
222
+ return [languages_dict [tag ] for tag in language_tags ]
223
+ return languages
224
+
225
+
226
+
209
227
210
228
XELATEX_DEFAULT = (
211
229
"-D latex_engine=xelatex" ,
@@ -572,8 +590,7 @@ def parse_args():
572
590
parser .add_argument (
573
591
"-b" ,
574
592
"--branch" ,
575
- choices = dict .fromkeys (chain (* ((v .branch_or_tag , v .name ) for v in VERSIONS ))),
576
- metavar = Version .current_dev ().name ,
593
+ metavar = "3.7" ,
577
594
help = "Version to build (defaults to all maintained branches)." ,
578
595
)
579
596
parser .add_argument (
@@ -609,7 +626,6 @@ def parse_args():
609
626
parser .add_argument (
610
627
"--languages" ,
611
628
nargs = "*" ,
612
- default = "all" ,
613
629
help = "Language translation, as a PEP 545 language tag like" " 'fr' or 'pt-br'. "
614
630
"Use 'all' to build all of them (it's the default behavior)." ,
615
631
metavar = "fr" ,
@@ -1037,44 +1053,42 @@ def purge_path(www_root: Path, path: Path):
1037
1053
run (["curl" , "-XPURGE" , f"https://docs.python.org/{{{ ',' .join (to_purge )} }}" ])
1038
1054
1039
1055
1040
- def parse_config ():
1056
+ def parse_versions_from_devguide ():
1057
+ releases = requests .get (
1058
+ "https://raw.githubusercontent.com/python/devguide/main/include/release-cycle.json"
1059
+ ).json ()
1060
+ return [Version .from_json (name , release ) for name , release in releases .items ()]
1061
+
1062
+
1063
+ def parse_languages_from_config ():
1041
1064
config = configparser .ConfigParser ()
1042
1065
config .read (HERE / "config.ini" )
1043
1066
versions , languages = [], []
1044
1067
for name , section in config .items ():
1045
- if section .get ("status" ): # It's a version
1046
- versions .append (
1047
- Version (
1048
- name ,
1049
- status = section ["status" ],
1050
- branch = section .get ("branch" ),
1051
- tag = section .get ("tag" ),
1052
- )
1053
- )
1054
- if section .get ("name" ): # It's a language
1055
- languages .append (
1056
- Language (
1057
- name ,
1058
- section .get ("iso639_tag" , name ),
1059
- section ["name" ],
1060
- section .getboolean ("in_prod" , True ),
1061
- sphinxopts = globals ()[section .get ("sphinxopts" , "XELATEX_DEFAULT" )],
1062
- html_only = section .get ("html_only" , False ),
1063
- )
1068
+ if name == "DEFAULT" :
1069
+ continue
1070
+ languages .append (
1071
+ Language (
1072
+ name ,
1073
+ section .get ("iso639_tag" , name ),
1074
+ section ["name" ],
1075
+ section .getboolean ("in_prod" , True ),
1076
+ sphinxopts = globals ()[section .get ("sphinxopts" , "XELATEX_DEFAULT" )],
1077
+ html_only = section .get ("html_only" , False ),
1064
1078
)
1065
- return versions , languages
1079
+ )
1080
+ return languages
1066
1081
1067
1082
1068
1083
def build_docs (args ) -> bool :
1069
1084
"""Build all docs (each languages and each versions)."""
1070
- versions , languages = parse_config ()
1071
- languages_dict = {language .tag : language for language in languages }
1072
- todo = list (
1073
- product (
1074
- Version .filter (versions , args .branch ),
1075
- [languages_dict [tag ] for tag in args .languages ],
1076
- )
1077
- )
1085
+ versions = parse_versions_from_devguide ()
1086
+ languages = parse_languages_from_config ()
1087
+ todo = [
1088
+ (version , language )
1089
+ for version in Version .filter (versions , args .branch )
1090
+ for language in Language .filter (languages , args .languages )
1091
+ ]
1078
1092
del args .branch
1079
1093
del args .languages
1080
1094
all_built_successfully = True
0 commit comments