Skip to content

Commit f9ec77e

Browse files
authored
Port list and mock_package into PackageManager (#118)
* feat: port list() * feat: add mock_package to package manager * fix: import
1 parent 8b39458 commit f9ec77e

File tree

4 files changed

+95
-62
lines changed

4 files changed

+95
-62
lines changed

micropip/_commands/list.py

Lines changed: 4 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,7 @@
1-
import importlib.metadata
2-
3-
from .._compat import REPODATA_PACKAGES, loadedPackages
4-
from ..package import PackageDict, PackageMetadata
1+
from .._compat import REPODATA_PACKAGES
2+
from ..list import list_installed_packages
3+
from ..package import PackageDict
54

65

76
def _list() -> PackageDict:
8-
"""Get the dictionary of installed packages.
9-
10-
Returns
11-
-------
12-
``PackageDict``
13-
A dictionary of installed packages.
14-
15-
>>> import micropip
16-
>>> await micropip.install('regex') # doctest: +SKIP
17-
>>> package_list = micropip.list()
18-
>>> print(package_list) # doctest: +SKIP
19-
Name | Version | Source
20-
----------------- | -------- | -------
21-
regex | 2021.7.6 | pyodide
22-
>>> "regex" in package_list # doctest: +SKIP
23-
True
24-
"""
25-
26-
# Add packages that are loaded through pyodide.loadPackage
27-
packages = PackageDict()
28-
for dist in importlib.metadata.distributions():
29-
name = dist.name
30-
version = dist.version
31-
source = dist.read_text("PYODIDE_SOURCE")
32-
if source is None:
33-
# source is None if PYODIDE_SOURCE does not exist. In this case the
34-
# wheel was installed manually, not via `pyodide.loadPackage` or
35-
# `micropip`.
36-
continue
37-
packages[name] = PackageMetadata(
38-
name=name,
39-
version=version,
40-
source=source,
41-
)
42-
43-
for name, pkg_source in loadedPackages.to_py().items():
44-
if name in packages:
45-
continue
46-
47-
if name in REPODATA_PACKAGES:
48-
version = REPODATA_PACKAGES[name]["version"]
49-
source_ = "pyodide"
50-
if pkg_source != "default channel":
51-
# Pyodide package loaded from a custom URL
52-
source_ = pkg_source
53-
else:
54-
# TODO: calculate version from wheel metadata
55-
version = "unknown"
56-
source_ = pkg_source
57-
packages[name] = PackageMetadata(name=name, version=version, source=source_)
58-
return packages
7+
return list_installed_packages(REPODATA_PACKAGES)

micropip/list.py

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import importlib.metadata
2+
from typing import Any
3+
4+
from ._compat import loadedPackages
5+
from .package import PackageDict, PackageMetadata
6+
7+
8+
def list_installed_packages(
9+
lockfile_packages: dict[str, dict[str, Any]]
10+
) -> PackageDict:
11+
"""Get the dictionary of installed packages.
12+
13+
Returns
14+
-------
15+
``PackageDict``
16+
A dictionary of installed packages.
17+
18+
>>> import micropip
19+
>>> await micropip.install('regex') # doctest: +SKIP
20+
>>> package_list = micropip.list()
21+
>>> print(package_list) # doctest: +SKIP
22+
Name | Version | Source
23+
----------------- | -------- | -------
24+
regex | 2021.7.6 | pyodide
25+
>>> "regex" in package_list # doctest: +SKIP
26+
True
27+
"""
28+
29+
# Add packages that are loaded through pyodide.loadPackage
30+
packages = PackageDict()
31+
for dist in importlib.metadata.distributions():
32+
name = dist.name
33+
version = dist.version
34+
source = dist.read_text("PYODIDE_SOURCE")
35+
if source is None:
36+
# source is None if PYODIDE_SOURCE does not exist. In this case the
37+
# wheel was installed manually, not via `pyodide.loadPackage` or
38+
# `micropip`.
39+
continue
40+
packages[name] = PackageMetadata(
41+
name=name,
42+
version=version,
43+
source=source,
44+
)
45+
46+
for name, pkg_source in loadedPackages.to_py().items():
47+
if name in packages:
48+
continue
49+
50+
if name in lockfile_packages:
51+
version = lockfile_packages[name]["version"]
52+
source_ = "pyodide"
53+
if pkg_source != "default channel":
54+
# Pyodide package loaded from a custom URL
55+
source_ = pkg_source
56+
else:
57+
# TODO: calculate version from wheel metadata
58+
version = "unknown"
59+
source_ = pkg_source
60+
packages[name] = PackageMetadata(name=name, version=version, source=source_)
61+
return packages

micropip/package_manager.py

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@
44
)
55

66
from micropip import package_index
7+
from micropip._commands import mock_package
78
from micropip.freeze import freeze_lockfile
9+
from micropip.list import list_installed_packages
10+
from micropip.package import PackageDict
811

912

1013
class PackageManager:
@@ -29,20 +32,29 @@ def __init__(self) -> None:
2932
def install(self):
3033
raise NotImplementedError()
3134

32-
def list(self):
33-
raise NotImplementedError()
35+
def list(self) -> PackageDict:
36+
return list_installed_packages(self.repodata_packages)
3437

3538
def freeze(self) -> str:
3639
return freeze_lockfile(self.repodata_packages, self.repodata_info)
3740

38-
def add_mock_package(self):
39-
raise NotImplementedError()
41+
def add_mock_package(
42+
self,
43+
name: str,
44+
version: str,
45+
*,
46+
modules: dict[str, str | None] | None = None,
47+
persistent: bool = False,
48+
):
49+
return mock_package.add_mock_package(
50+
name, version, modules=modules, persistent=persistent
51+
)
4052

4153
def list_mock_packages(self):
42-
raise NotImplementedError()
54+
return mock_package.list_mock_packages()
4355

44-
def remove_mock_package(self):
45-
raise NotImplementedError()
56+
def remove_mock_package(self, name: str):
57+
return mock_package.remove_mock_package(name)
4658

4759
def uninstall(self):
4860
raise NotImplementedError()

tests/test_package_manager.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import json
22

3+
import pytest
4+
35
import micropip.package_index as package_index
46
from micropip.package_manager import PackageManager
57

@@ -57,3 +59,12 @@ def test_freeze():
5759
"info": test_repodata_info,
5860
"packages": test_repodata_packages,
5961
}
62+
63+
64+
@pytest.mark.skip(reason="Not implemented")
65+
def test_list():
66+
manager = get_test_package_manager()
67+
68+
_package_dict = manager.list()
69+
70+
# TODO: implement test after implementing manager.install()

0 commit comments

Comments
 (0)