55Extracts API documentation for multiple versions of PathSim packages by checking out
66historical git tags and running the extraction script.
77
8+ Version strategy:
9+ - Historical versions: Only vX.Y.0 tags (first patch of each minor version)
10+ - Latest version: Always the actual most recent tag (e.g., v0.16.4)
11+
812Smart extraction mode (default):
9- - Only extracts versions that are missing from cache
10- - Always re-extracts the latest version
13+ - Only extracts missing vX.Y.0 versions from cache
14+ - Always re-extracts the latest version (actual latest tag)
1115- Respects minimum supported version per package
1216
1317Usage:
1418 python scripts/extract-versions.py # Smart extract (missing + latest)
15- python scripts/extract-versions.py --all # Force extract all versions
19+ python scripts/extract-versions.py --all # Force extract all vX.Y.0 versions + latest
1620 python scripts/extract-versions.py --package pathsim # Single package
1721 python scripts/extract-versions.py --dry-run # Preview without extraction
1822"""
@@ -110,19 +114,27 @@ def get_cached_versions(package_id: str) -> set[str]:
110114 return cached
111115
112116
113- def group_by_minor_version (tags : list [str ]) -> dict [str , str ]:
114- """Group tags by minor version, keeping the latest patch for each ."""
115- versions : dict [str , tuple [ str , tuple [ int , int , int ]] ] = {}
117+ def get_minor_zero_tags (tags : list [str ]) -> dict [str , str ]:
118+ """Get vX.Y.0 tags for each minor version ( for historical caching) ."""
119+ versions : dict [str , str ] = {}
116120
117121 for tag in tags :
118- minor = get_minor_version (tag )
119- version_tuple = parse_version (tag )
122+ major , minor , patch = parse_version (tag )
123+ if patch == 0 : # Only vX.Y.0 tags
124+ minor_str = f"{ major } .{ minor } "
125+ versions [minor_str ] = tag
126+
127+ return versions
128+
120129
121- if minor not in versions or version_tuple > versions [minor ][1 ]:
122- versions [minor ] = (tag , version_tuple )
130+ def get_latest_tag (tags : list [str ]) -> tuple [str , str ] | None :
131+ """Get the actual latest tag (highest version number)."""
132+ if not tags :
133+ return None
123134
124- # Return dict of minor_version -> tag
125- return {minor : tag for minor , (tag , _ ) in versions .items ()}
135+ latest_tag = max (tags , key = parse_version )
136+ minor = get_minor_version (latest_tag )
137+ return (minor , latest_tag )
126138
127139
128140def git_checkout (repo_path : Path , ref : str ) -> bool :
@@ -183,8 +195,12 @@ def extract_package_versions(
183195) -> list [dict [str , str ]]:
184196 """Extract versions for a single package.
185197
186- Smart mode (default): Only extracts missing versions + always re-extracts latest.
187- All mode: Extracts all versions from minimum supported version.
198+ Version strategy:
199+ - Historical versions: Only vX.Y.0 tags (first patch of each minor)
200+ - Latest version: Always the actual most recent tag (e.g., v0.16.4)
201+
202+ Smart mode (default): Only extracts missing historical versions + always re-extracts latest.
203+ All mode: Extracts all vX.Y.0 versions from minimum supported version + latest.
188204 """
189205 repo_path = PACKAGE_REPOS .get (package_id )
190206 if not repo_path or not repo_path .exists ():
@@ -207,58 +223,63 @@ def extract_package_versions(
207223
208224 print (f" Found { len (all_tags )} tags" )
209225
210- # Group by minor version
211- minor_versions = group_by_minor_version (all_tags )
226+ # Get vX.Y.0 tags for historical versions
227+ minor_zero_versions = get_minor_zero_tags (all_tags )
212228
213229 # Filter to supported versions only
214- supported_versions = {
215- v : tag for v , tag in minor_versions .items ()
230+ supported_historical = {
231+ v : tag for v , tag in minor_zero_versions .items ()
216232 if version_gte (v , min_version )
217233 }
218234
219- if not supported_versions :
220- print (f" No versions >= { min_version } found" )
235+ # Get the actual latest tag (could be vX.Y.Z where Z > 0)
236+ latest_info = get_latest_tag (all_tags )
237+ if not latest_info :
238+ print (f" No valid tags found" )
221239 return []
222240
223- print (f" { len (supported_versions )} supported versions: { sorted (supported_versions .keys (), key = parse_minor_version , reverse = True )} " )
224-
225- # Sort by version (newest first)
226- sorted_versions = sorted (
227- supported_versions .items (),
228- key = lambda x : parse_minor_version (x [0 ]),
229- reverse = True ,
230- )
241+ latest_minor , latest_tag = latest_info
242+ print (f" Latest tag: { latest_tag } (minor: { latest_minor } )" )
243+ print (f" Historical vX.Y.0 versions: { sorted (supported_historical .keys (), key = parse_minor_version , reverse = True )} " )
231244
232245 # Determine which versions to extract
233246 cached = get_cached_versions (package_id )
234- latest_version = sorted_versions [0 ][0 ] if sorted_versions else None
247+
248+ # Build extraction list
249+ versions_to_extract = []
235250
236251 if extract_all :
237- versions_to_extract = sorted_versions
238- print (f" Mode: Extract ALL ({ len (versions_to_extract )} versions)" )
252+ # Extract all historical vX.Y.0 versions
253+ for minor_version , tag in sorted (supported_historical .items (), key = lambda x : parse_minor_version (x [0 ]), reverse = True ):
254+ # Skip if this is the latest minor (we'll add the actual latest tag separately)
255+ if minor_version != latest_minor :
256+ versions_to_extract .append ((minor_version , tag ))
257+ print (f" Mode: Extract ALL historical ({ len (versions_to_extract )} versions) + latest" )
239258 else :
240- # Smart mode: only missing + latest
241- versions_to_extract = []
242- for minor_version , tag in sorted_versions :
243- is_latest = minor_version == latest_version
244- is_cached = minor_version in cached
245-
246- if is_latest or not is_cached :
259+ # Smart mode: only missing historical + latest
260+ for minor_version , tag in sorted (supported_historical .items (), key = lambda x : parse_minor_version (x [0 ]), reverse = True ):
261+ # Skip if this is the latest minor (we'll add the actual latest tag separately)
262+ if minor_version == latest_minor :
263+ continue
264+ if minor_version not in cached :
247265 versions_to_extract .append ((minor_version , tag ))
248266
249- missing_count = len ([ v for v , _ in versions_to_extract if v != latest_version and v not in cached ] )
267+ missing_count = len (versions_to_extract )
250268 print (f" Mode: Smart extraction" )
251269 print (f" Cached: { len (cached )} versions" )
252- print (f" Missing: { missing_count } versions" )
253- print (f" Latest ({ latest_version } ): will { 're-' if latest_version in cached else '' } extract" )
254- print (f" Total to extract: { len (versions_to_extract )} versions" )
270+ print (f" Missing historical: { missing_count } versions" )
271+
272+ # Always add the latest tag (uses actual latest, not necessarily vX.Y.0)
273+ versions_to_extract .append ((latest_minor , latest_tag ))
274+ print (f" Latest ({ latest_tag } ): will { 're-' if latest_minor in cached else '' } extract" )
275+ print (f" Total to extract: { len (versions_to_extract )} versions" )
255276
256277 extracted = []
257278 output_dir = VERSIONS_DIR / package_id
258279 output_dir .mkdir (parents = True , exist_ok = True )
259280
260281 for minor_version , tag in versions_to_extract :
261- is_latest = minor_version == latest_version
282+ is_latest = minor_version == latest_minor
262283 is_cached = minor_version in cached
263284 status = "LATEST" if is_latest else ("NEW" if not is_cached else "cached" )
264285
@@ -322,8 +343,12 @@ def main():
322343 chem: %(chem)s
323344 vehicle: %(vehicle)s
324345
346+ Version strategy:
347+ - Historical: Only vX.Y.0 tags (first patch of each minor)
348+ - Latest: Actual most recent tag (e.g., v0.16.4)
349+
325350By default, uses smart extraction:
326- - Only extracts versions that are missing from cache
351+ - Only extracts missing vX.Y.0 versions from cache
327352 - Always re-extracts the latest version
328353 - Respects minimum supported versions
329354 """ % MIN_SUPPORTED_VERSIONS
@@ -337,7 +362,7 @@ def main():
337362 "--all" , "-a" ,
338363 action = "store_true" ,
339364 dest = "extract_all" ,
340- help = "Force extract all versions (ignore cache)"
365+ help = "Force extract all vX.Y.0 versions + latest (ignore cache)"
341366 )
342367 parser .add_argument (
343368 "--dry-run" , "-n" ,
0 commit comments