1
+ import json
1
2
import pathlib
2
- import sys
3
+ import re
4
+ import subprocess
3
5
from typing import Any
6
+ from urllib .request import urlopen
4
7
5
8
from docutils import nodes
6
9
from docutils .parsers .rst import Directive
10
+ from pyodide_lock import PackageSpec , PyodideLockSpec
7
11
from sphinx import addnodes
8
12
9
13
base_dir = pathlib .Path (__file__ ).resolve ().parents [3 ]
10
- sys .path .append (str (base_dir / "pyodide-build" ))
11
-
12
- from pyodide_build .io import MetaConfig
13
-
14
- PYODIDE_TESTONLY = "pyodide.test"
15
14
16
15
17
16
def get_packages_summary_directive (app ):
@@ -21,56 +20,64 @@ class PyodidePackagesSummary(Directive):
21
20
required_arguments = 1
22
21
23
22
def run (self ):
24
- packages_root = base_dir / self .arguments [0 ]
25
- packages_list = self .get_package_metadata_list (packages_root )
23
+ url = self .parse_lockfile_url ()
24
+ resp = urlopen (url )
25
+ lockfile_json = resp .read ().decode ("utf-8" )
26
+
27
+ lockfile = PyodideLockSpec (** json .loads (lockfile_json ))
28
+ lockfile_packages = lockfile .packages
26
29
27
- packages = {}
28
- for package in packages_list :
30
+ python_packages = {}
31
+ for package in lockfile_packages . values () :
29
32
try :
30
- name , version , is_package , tag , disabled = self .parse_package_info (
31
- package
32
- )
33
+ name , version , is_package = self .parse_package_info (package )
33
34
except Exception :
34
35
print (f"Warning: failed to parse package config for { package } " )
35
36
36
- # skip libraries (e.g. libxml, libyaml, ...) and test only packages
37
- if not is_package or PYODIDE_TESTONLY in tag or disabled :
37
+ if not is_package or name .endswith ("-tests" ):
38
38
continue
39
39
40
- packages [name ] = {
40
+ python_packages [name ] = {
41
41
"name" : name ,
42
42
"version" : version ,
43
43
}
44
44
45
45
result = []
46
46
columns = ("name" , "version" )
47
- table_markup = self .format_packages_table (packages , columns )
47
+ table_markup = self .format_packages_table (python_packages , columns )
48
48
result .extend (table_markup )
49
49
50
50
return result
51
51
52
- def parse_package_info (
53
- self , config : pathlib .Path
54
- ) -> tuple [str , str , bool , list [str ], bool ]:
55
- yaml_data = MetaConfig .from_yaml (config )
56
-
57
- name = yaml_data .package .name
58
- version = yaml_data .package .version
59
- tag = yaml_data .package .tag
60
- is_package = yaml_data .build .package_type == "package"
61
- disabled = yaml_data .package .disabled
62
-
63
- return name , version , is_package , tag , disabled
64
-
65
- def get_package_metadata_list (
66
- self , directory : pathlib .Path
67
- ) -> list [pathlib .Path ]:
68
- """Return metadata files of packages in alphabetical order (case insensitive)"""
69
- return sorted (
70
- directory .glob ("**/meta.yaml" ),
71
- key = lambda path : path .parent .name .lower (),
52
+ def parse_lockfile_url (self ) -> str :
53
+ envs = subprocess .run (
54
+ ["make" , "-f" , str (base_dir / "Makefile.envs" ), ".output_vars" ],
55
+ capture_output = True ,
56
+ text = True ,
57
+ env = {"PYODIDE_ROOT" : str (base_dir )},
58
+ check = False ,
72
59
)
73
60
61
+ if envs .returncode != 0 :
62
+ raise RuntimeError ("Failed to parse Makefile.envs" )
63
+
64
+ pattern = re .search (r"PYODIDE_PREBUILT_PACKAGES_LOCKFILE=(.*)" , envs .stdout )
65
+ if not pattern :
66
+ raise RuntimeError ("Failed to find lockfile URL in Makefile.envs" )
67
+
68
+ url = pattern .group (1 )
69
+ return url
70
+
71
+ def parse_package_info (
72
+ self ,
73
+ package : PackageSpec ,
74
+ ) -> tuple [str , str , bool ]:
75
+ name = package .name
76
+ version = package .version
77
+ is_package = package .package_type == "package"
78
+
79
+ return name , version , is_package
80
+
74
81
def format_packages_table (
75
82
self , packages : dict [str , Any ], columns : tuple [str , ...]
76
83
) -> list [Any ]:
0 commit comments