3
3
import os
4
4
import pkgutil
5
5
import sys
6
- from functools import lru_cache
7
6
8
- long_versions = [
7
+ long_versions = {
9
8
"2.6.9" ,
10
9
"2.7.9" ,
11
10
"3.2.6" ,
21
20
"3.12" ,
22
21
"3.13" ,
23
22
"3.14" ,
24
- ]
23
+ }
25
24
26
- short_versions = ["." .join (x .split ("." )[:2 ]) for x in long_versions ]
25
+ short_versions = {"." .join (x .split ("." )[:2 ]) for x in long_versions }
26
+
27
+ _cached_modules : dict [str , frozenset [str ]] = {}
27
28
28
29
29
30
def get_canonical_version (version : str ) -> str :
@@ -35,19 +36,22 @@ def get_canonical_version(version: str) -> str:
35
36
return version
36
37
37
38
38
- def stdlib_list (version : str | None = None ) -> list [str ]:
39
+ def stdlib_modules (version : str | None = None ) -> frozenset [str ]:
39
40
"""
40
- Given a ``version``, return a ``list `` of names of the Python Standard
41
- Libraries for that version.
41
+ Given a ``version``, return a ``frozenset `` of names of the modules in
42
+ the Python Standard Library for that version.
42
43
43
- :param str|None version: The version (as a string) whose list of libraries you want
44
+ :param str|None version:
45
+ The version (as a string) whose list of libraries you want
44
46
(formatted as ``X.Y``, e.g. ``"2.7"`` or ``"3.10"``).
45
47
46
48
If not specified, the current version of Python will be used.
47
49
48
- :return: A list of standard libraries from the specified version of Python
49
- :rtype: list
50
+ :return: The names of standard library modules from the given Python version
51
+ :rtype: frozenset
50
52
"""
53
+ if version in _cached_modules :
54
+ return _cached_modules [version ]
51
55
52
56
version = (
53
57
get_canonical_version (version )
@@ -57,17 +61,29 @@ def stdlib_list(version: str | None = None) -> list[str]:
57
61
58
62
module_list_file = os .path .join ("lists" , f"{ version } .txt" )
59
63
60
- data = pkgutil .get_data ("stdlib_list" , module_list_file ).decode () # type: ignore[union-attr]
64
+ data = pkgutil .get_data ("stdlib_list" , module_list_file )
65
+ lines = data .decode ().splitlines () if data else []
61
66
62
- result = [y for x in data .splitlines () if (y := x .strip ())]
67
+ result = frozenset ({y for x in lines if (y := x .strip ())})
68
+ _cached_modules [version ] = result
63
69
64
70
return result
65
71
66
72
67
- @lru_cache (maxsize = 16 )
68
- def _stdlib_list_with_cache (version : str | None = None ) -> frozenset [str ]:
69
- """Internal cached version of `stdlib_list`"""
70
- return frozenset (stdlib_list (version = version ))
73
+ def stdlib_list (version : str | None = None ) -> list [str ]:
74
+ """
75
+ Given a ``version``, return a ``list`` of names of the Python Standard
76
+ Libraries for that version.
77
+
78
+ :param str|None version: The version (as a string) whose list of libraries you want
79
+ (formatted as ``X.Y``, e.g. ``"2.7"`` or ``"3.10"``).
80
+
81
+ If not specified, the current version of Python will be used.
82
+
83
+ :return: A list of standard libraries from the specified version of Python
84
+ :rtype: list
85
+ """
86
+ return sorted (stdlib_modules (version ))
71
87
72
88
73
89
def in_stdlib (module_name : str , version : str | None = None ) -> bool :
@@ -79,10 +95,6 @@ def in_stdlib(module_name: str, version: str | None = None) -> bool:
79
95
Note that ``True`` will be returned for built-in modules too, since this project
80
96
considers they are part of stdlib. See :issue:21.
81
97
82
- It relies on ``@lru_cache`` to cache the stdlib list and query results for similar
83
- calls. Therefore it is much more efficient than ``module_name in stdlib_list()``
84
- especially if you wish to perform multiple checks.
85
-
86
98
:param str|None module_name: The module name (as a string) to query for.
87
99
:param str|None version: The version (as a string) whose list of libraries you want
88
100
(formatted as ``X.Y``, e.g. ``"2.7"`` or ``"3.10"``).
@@ -91,7 +103,7 @@ def in_stdlib(module_name: str, version: str | None = None) -> bool:
91
103
92
104
:return: A bool indicating if the given module name is part of standard libraries
93
105
for the specified version of Python.
94
- :rtype: list
106
+ :rtype: bool
95
107
"""
96
- ref_list = _stdlib_list_with_cache (version = version )
108
+ ref_list = stdlib_modules (version = version )
97
109
return module_name in ref_list
0 commit comments