Skip to content

Commit ca8f80e

Browse files
authored
Fix tests, run tests in CI (#64)
* tests: fix version calculation This was incorrect on 3.10+ * workflows: ci * travis: remove old travis CI config * tests: disable some broken tests These are seemingly intentionally incompatible with pytest. * [WIP] experiment with CI * [WIP] listgen: fix path * [WIP] more experimenting * [WIP] listgen: syntax * [WIP] listgen: disable 2.7 temporarily * [WIP] disable 3.2 * [WIP]: 3.6+ only * [WIP] listgen: tweak runner * [WIP]: 3.7 and newer only * [WIP] handle accelerator mods * [WIP] do recursive step correctly * [WIP] dedupe correctly * [WIP]: use pkgutil * [WIP] hackety hack * [WIP] hackety hack * [WIP] builtin_module_names * [WIP] newer python support * [WIP] fix path * listgen: auto-PRs for 3.10+ * listgen: fix base branch * walk-modules: be slightly smarter * listgen: temporarily disable PR creation * rewrite tests * Makefile: enforce 100% coverage * README: mention the new `sys` APIs * listgen: run for old Pythons, drop pull_request trigger * ci: enable caching * ci: test on 3.10 and 3.11 * base: update docstrings * test_base: add another consistency test * tests: test long_versions as well for consistency * listgen: every tuesday
1 parent fb92bfd commit ca8f80e

File tree

14 files changed

+317
-317
lines changed

14 files changed

+317
-317
lines changed

.github/workflows/ci.yml

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
pull_request:
8+
workflow_dispatch:
9+
10+
jobs:
11+
test:
12+
strategy:
13+
matrix:
14+
python:
15+
- "3.7"
16+
- "3.8"
17+
- "3.9"
18+
- "3.10"
19+
- "3.11"
20+
runs-on: ubuntu-latest
21+
steps:
22+
- uses: actions/checkout@v3
23+
24+
- uses: actions/setup-python@v4
25+
with:
26+
python-version: ${{ matrix.python }}
27+
cache: pip
28+
29+
- name: test
30+
run: make test INSTALL_EXTRA=test
31+
32+
# lint:
33+
# runs-on: ubuntu-latest
34+
# steps:
35+
# - uses: actions/checkout@v3
36+
# - uses: actions/setup-python@v4
37+
# with:
38+
# python-version: "3.10"
39+
# - name: lint
40+
# run: make lint INSTALL_EXTRA=lint

.github/workflows/listgen.yml

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
name: Generate stdlib lists
2+
3+
on:
4+
workflow_dispatch:
5+
schedule:
6+
- cron: "0 0 * * 2"
7+
8+
jobs:
9+
pre-list-legacy:
10+
strategy:
11+
matrix:
12+
python:
13+
- "3.7"
14+
- "3.8"
15+
- "3.9"
16+
17+
runs-on: ubuntu-latest
18+
19+
steps:
20+
- uses: actions/checkout@v3
21+
- uses: actions/setup-python@v4
22+
with:
23+
# NOTE: matrix.python is intentionally not used here.
24+
python-version: "3.x"
25+
- name: support deps
26+
run: make dev INSTALL_EXTRA=support
27+
- name: build pre-list
28+
env:
29+
LISTGEN_PYTHON_VERSION: "${{ matrix.python }}"
30+
run: |
31+
./env/bin/python ./support/fetch-sphinx.py "${LISTGEN_PYTHON_VERSION}" > pre-list.txt
32+
- name: upload pre-list
33+
uses: actions/upload-artifact@v3
34+
with:
35+
name: pre-list-${{ matrix.python }}
36+
path: pre-list.txt
37+
38+
expand-list-legacy:
39+
needs: pre-list-legacy
40+
strategy:
41+
matrix:
42+
python:
43+
- "3.7"
44+
- "3.8"
45+
- "3.9"
46+
47+
runs-on: ubuntu-latest
48+
49+
steps:
50+
- uses: actions/checkout@v3
51+
- uses: actions/setup-python@v4
52+
with:
53+
python-version: ${{ matrix.python }}
54+
- uses: actions/download-artifact@v3
55+
with:
56+
name: pre-list-${{ matrix.python }}
57+
- name: walk modules
58+
run: |
59+
python -V
60+
python ./support/walk-modules.py "${LISTGEN_PYTHON_VERSION}.txt" < pre-list.txt
61+
rm pre-list.txt
62+
sort -o "${LISTGEN_PYTHON_VERSION}.txt" "${LISTGEN_PYTHON_VERSION}.txt"
63+
mv "${LISTGEN_PYTHON_VERSION}.txt" ./stdlib_list/lists/
64+
- name: create PR
65+
uses: peter-evans/create-pull-request@v5
66+
with:
67+
commit-message: "[BOT] update list for ${{ matrix.python }}"
68+
branch: update-stdlib-list-${{ matrix.python }}
69+
base: main
70+
branch-suffix: timestamp
71+
title: "[BOT] update list for ${{ matrix.python }}"
72+
body: |
73+
This is an automated pull request, updating `${{ matrix.python }}.txt` after a detected change.
74+
75+
Please review manually before merging.
76+
assignees: "woodruffw"
77+
reviewers: "woodruffw"
78+
79+
expand-list:
80+
strategy:
81+
matrix:
82+
python:
83+
- "3.10"
84+
- "3.11"
85+
86+
runs-on: ubuntu-latest
87+
88+
steps:
89+
- uses: actions/checkout@v3
90+
- uses: actions/setup-python@v4
91+
with:
92+
python-version: ${{ matrix.python }}
93+
- name: walk modules
94+
env:
95+
LISTGEN_PYTHON_VERSION: ${{ matrix.python }}
96+
run: |
97+
python -V
98+
python ./support/walk-modules.py "${LISTGEN_PYTHON_VERSION}.txt"
99+
sort -o "${LISTGEN_PYTHON_VERSION}.txt" "${LISTGEN_PYTHON_VERSION}.txt"
100+
mv "${LISTGEN_PYTHON_VERSION}.txt" ./stdlib_list/lists/
101+
102+
- name: create PR
103+
uses: peter-evans/create-pull-request@v5
104+
with:
105+
commit-message: "[BOT] update list for ${{ matrix.python }}"
106+
branch: update-stdlib-list-${{ matrix.python }}
107+
base: main
108+
branch-suffix: timestamp
109+
title: "[BOT] update list for ${{ matrix.python }}"
110+
body: |
111+
This is an automated pull request, updating `${{ matrix.python }}.txt` after a detected change.
112+
113+
Please review manually before merging.
114+
assignees: "woodruffw"
115+
reviewers: "woodruffw"

.travis.yml

Lines changed: 0 additions & 31 deletions
This file was deleted.

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ reformat:
7070
test tests: $(VENV)/pyvenv.cfg
7171
. $(VENV_BIN)/activate && \
7272
pytest --cov=$(PY_MODULE) $(T) $(TEST_ARGS) && \
73-
python -m coverage report -m $(COV_ARGS)
73+
python -m coverage report -m $(COV_ARGS) --fail-under 100
7474

7575
.PHONY: doc
7676
doc: $(VENV)/pyvenv.cfg

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ This package includes lists of all of the standard libraries for Python 2.6,
44
2.7, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7, 3.8, and 3.9 along with the code for
55
scraping the official Python docs to get said lists.
66

7+
**IMPORTANT**: If you're on Python 3.10 or newer, you **probably don't need this library**.
8+
See [`sys.stdlib_module_names`](https://docs.python.org/3/library/sys.html#sys.stdlib_module_names)
9+
and [`sys.builtin_module_names`](https://docs.python.org/3/library/sys.html#sys.builtin_module_names)
10+
for similar functionality.
11+
712
## Installation
813

914
`stdlib-list` is available on PyPI:

pyproject.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ test = ["pytest", "pytest-cov", "coverage[toml]"]
3232
lint = ["black", "mypy", "ruff"]
3333
doc = ["sphinx", "sphinx_rtd_theme"]
3434
dev = ["build", "stdlib-list[test,lint,doc]"]
35+
# CI only: used for list generation for Python versions < 3.10.
36+
support = ["sphobjinv"]
37+
3538

3639
[tool.black]
3740
line-length = 100

stdlib_list/__init__.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,11 @@
88
short_versions,
99
long_versions,
1010
)
11+
12+
__all__ = [
13+
"stdlib_list",
14+
"in_stdlib",
15+
"get_canonical_version",
16+
"short_versions",
17+
"long_versions",
18+
]

stdlib_list/base.py

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,20 @@
66

77
from functools import lru_cache
88

9-
long_versions = ["2.6.9", "2.7.9", "3.2.6", "3.3.6", "3.4.3", "3.5", "3.6", "3.7", "3.8", "3.9"]
9+
long_versions = [
10+
"2.6.9",
11+
"2.7.9",
12+
"3.2.6",
13+
"3.3.6",
14+
"3.4.3",
15+
"3.5",
16+
"3.6",
17+
"3.7",
18+
"3.8",
19+
"3.9",
20+
"3.10",
21+
"3.11",
22+
]
1023

1124
short_versions = [".".join(x.split(".")[:2]) for x in long_versions]
1225

@@ -23,11 +36,10 @@ def get_canonical_version(version):
2336
def stdlib_list(version=None):
2437
"""
2538
Given a ``version``, return a ``list`` of names of the Python Standard
26-
Libraries for that version. These names are obtained from the Sphinx inventory
27-
file (used in :py:mod:`sphinx.ext.intersphinx`).
39+
Libraries for that version.
2840
2941
:param str|None version: The version (as a string) whose list of libraries you want
30-
(one of ``"2.6"``, ``"2.7"``, ``"3.2"``, ``"3.3"``, ``"3.4"``, or ``"3.5"``).
42+
(formatted as ``X.Y``, e.g. ``"2.7"`` or ``"3.10"``).
3143
3244
If not specified, the current version of Python will be used.
3345
@@ -72,7 +84,7 @@ def in_stdlib(module_name, version=None):
7284
7385
:param str|None module_name: The module name (as a string) to query for.
7486
:param str|None version: The version (as a string) whose list of libraries you want
75-
(one of ``"2.6"``, ``"2.7"``, ``"3.2"``, ``"3.3"``, ``"3.4"``, or ``"3.5"``).
87+
(formatted as ``X.Y``, e.g. ``"2.7"`` or ``"3.10"``).
7688
7789
If not specified, the current version of Python will be used.
7890

support/fetch-sphinx.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#!/usr/bin/env python
2+
3+
# fetch-sphinx.py: retrieve a particular Python version's stdlib list
4+
# using its hosted Sphinx inventory.
5+
6+
import sys
7+
import sphobjinv as soi
8+
9+
if __name__ == "__main__":
10+
vers = sys.argv[1]
11+
inv = soi.Inventory(url=f"https://docs.python.org/{vers}/objects.inv")
12+
modules = list(sorted(obj.name for obj in inv.objects if obj.role == "module"))
13+
print("\n".join(modules))

support/walk-modules.py

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
#!/usr/bin/env python
2+
3+
import inspect
4+
import pkgutil
5+
import sys
6+
7+
SEEN_MODS = set()
8+
9+
10+
def walk_pkgutil(mod_name, mod, io):
11+
for pkg in pkgutil.walk_packages(mod.__path__, mod_name + "."):
12+
if pkg.name in SEEN_MODS:
13+
continue
14+
else:
15+
# We don't recurse here because `walk_packages` takes care of
16+
# it for us.
17+
SEEN_MODS.add(pkg.name)
18+
print(pkg.name, file=io)
19+
20+
21+
def walk_naive(mod_name, mod, io):
22+
for attr in dir(mod):
23+
attr_obj = getattr(mod, attr, None)
24+
# Shouldn't happen, but who knows.
25+
if attr_obj is None:
26+
continue
27+
28+
# If this member isn't a module, skip it.
29+
if not inspect.ismodule(attr_obj):
30+
continue
31+
32+
# To filter "real" submodules from re-exports, we try
33+
# and import the submodule by its qualified name.
34+
# If the import fails, we know it's a re-exported module.
35+
try:
36+
submod_name = mod_name + "." + attr
37+
__import__(submod_name)
38+
walk(submod_name, io)
39+
except ImportError:
40+
# ...but sometimes we do want to include re-exports, since
41+
# they might be things like "accelerator" modules that don't
42+
# appear anywhere else.
43+
# For example, `_bz2` might appear as a re-export.
44+
try:
45+
# Again, try and import to avoid module-looking object
46+
# that don't actually appear on disk. Experimentally,
47+
# there are a few of these (like "TK").
48+
__import__(attr)
49+
walk(attr, io)
50+
except ImportError:
51+
continue
52+
53+
54+
def walk(mod_name, io):
55+
if mod_name in SEEN_MODS:
56+
return
57+
else:
58+
SEEN_MODS.add(mod_name)
59+
print(mod_name, file=io)
60+
61+
# Try and import it.
62+
try:
63+
mod = __import__(mod_name)
64+
65+
if hasattr(mod, "__path__"):
66+
walk_pkgutil(mod_name, mod, io)
67+
else:
68+
walk_naive(mod_name, mod, io)
69+
70+
except ImportError:
71+
pass
72+
73+
74+
if __name__ == "__main__":
75+
output = sys.argv[1]
76+
77+
with open(output, mode="w") as io:
78+
for mod_name in sys.builtin_module_names:
79+
walk(mod_name, io)
80+
81+
if hasattr(sys, "stdlib_module_names"):
82+
for mod_name in sys.stdlib_module_names:
83+
walk(mod_name, io)
84+
else:
85+
for mod_name in sys.stdin:
86+
walk(mod_name.rstrip("\n"), io)

0 commit comments

Comments
 (0)