From 493d65b7389a25a84eff99b6508257777910c091 Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Mon, 12 Jun 2023 22:05:59 -0400 Subject: [PATCH 01/36] tests: fix version calculation This was incorrect on 3.10+ --- tests/test_basic.py | 4 ++-- tests/test_platform.py | 16 ++++++---------- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/tests/test_basic.py b/tests/test_basic.py index 257f04b..a19c9ae 100644 --- a/tests/test_basic.py +++ b/tests/test_basic.py @@ -8,7 +8,8 @@ class CurrentVersionBase(unittest.TestCase): def setUp(self): - self.list = stdlib_list.stdlib_list(sys.version[:3]) + version = f"{sys.version_info.major}.{sys.version_info.minor}" + self.list = stdlib_list.stdlib_list(version) class TestCurrentVersion(CurrentVersionBase): @@ -29,7 +30,6 @@ def test_builtin_modules(self): class TestSysModules(CurrentVersionBase): - # This relies on invocation in a clean python environment using unittest # not using pytest. diff --git a/tests/test_platform.py b/tests/test_platform.py index 226396a..15b9890 100644 --- a/tests/test_platform.py +++ b/tests/test_platform.py @@ -22,7 +22,8 @@ class UnifiedDiffAssertionError(AssertionError): def __init__(self, expected, got, msg="Differences"): super(UnifiedDiffAssertionError, self).__init__(self) - filename = "stdlib_list/lists/{}.txt".format(sys.version[:3]) + version = f"{sys.version_info.major}.{sys.version_info.minor}" + filename = "stdlib_list/lists/{}.txt".format(version) diff = difflib.unified_diff( expected, got, lineterm="", fromfile="a/" + filename, tofile="b/" + filename ) @@ -33,12 +34,12 @@ def __str__(self): class CurrentPlatformBase(object): - dir = None ignore_test = False def setUp(self): - self.list = stdlib_list.stdlib_list(sys.version[:3]) + version = f"{sys.version_info.major}.{sys.version_info.minor}" + self.list = stdlib_list.stdlib_list(version) if self.dir: self.assertTrue(os.path.isdir(self.dir)) @@ -140,17 +141,13 @@ def setUp(self): class TestBasePureLibDir(CurrentPlatformBase, unittest.TestCase): def setUp(self): base = sys.base_prefix - self.dir = get_python_lib( - standard_lib=True, plat_specific=False, prefix=base - ) + self.dir = get_python_lib(standard_lib=True, plat_specific=False, prefix=base) super(TestBasePureLibDir, self).setUp() class TestBasePlatLibDir(CurrentPlatformBase, unittest.TestCase): def setUp(self): base = sys.base_prefix - self.dir = get_python_lib( - standard_lib=True, plat_specific=True, prefix=base - ) + self.dir = get_python_lib(standard_lib=True, plat_specific=True, prefix=base) super(TestBasePlatLibDir, self).setUp() @@ -158,7 +155,6 @@ def setUp(self): tk_libs = tk_libs.strip(os.pathsep) class TestTkDir(CurrentPlatformBase, unittest.TestCase): - # Python 2.7 tk-libs includes a `test` package, however it is # added to sys.path by test.test_tk as a top level directory # so test.widget_tests becomes module name `widget_tests` From ee78d1d02c9627822371173895b6a0604579f716 Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Mon, 12 Jun 2023 22:06:17 -0400 Subject: [PATCH 02/36] workflows: ci --- .github/workflows/ci.yml | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..3d3cf32 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,35 @@ +name: CI + +on: + push: + branches: + - main + pull_request: + workflow_dispatch: + +jobs: + test: + strategy: + matrix: + python: + - "3.7" + - "3.8" + - "3.9" + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python }} + - name: test + run: make test INSTALL_EXTRA=test + +# lint: +# runs-on: ubuntu-latest +# steps: +# - uses: actions/checkout@v3 +# - uses: actions/setup-python@v4 +# with: +# python-version: "3.10" +# - name: lint +# run: make lint INSTALL_EXTRA=lint From 125ec38b20cfedbd7ed59ea70a5ebea3af336e2a Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Mon, 12 Jun 2023 22:07:17 -0400 Subject: [PATCH 03/36] travis: remove old travis CI config --- .travis.yml | 31 ------------------------------- 1 file changed, 31 deletions(-) delete mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 853cccf..0000000 --- a/.travis.yml +++ /dev/null @@ -1,31 +0,0 @@ -language: python - -sudo: false - -python: - - 2.7 - - 3.4 - - 3.5 - - 3.6 - - 3.7 - - 3.8 - -install: - - python setup.py sdist && version=$(python setup.py --version) && pushd dist && pip install stdlib-list-${version}.tar.gz && popd - -script: - - python -m tests - -deploy: - skip_cleanup: true - provider: pypi - user: ocefpaf - password: - secure: "Q4v+Im8wOvYkCfszigRwh26DKSBpgJ49AGffkP3gb592z4uVtVH5DWdXyUE/9zK8qVk4uA5NEBJc8+mHFCztUlYYrPXZCVzX+NyUWv3rmMsDf8tV5Y+9J6pdw0Wx6DvI6nqKD6s2hKu4pey2UW8LO9HQIi97Hlo5Hd5ivbakVX8=" - distributions: sdist bdist_wheel - upload_docs: no - on: - repo: jackmaney/python-stdlib-list - tags: true - all_branches: master - python: 3.7 From 3187ec7aa9ccd1a3527a2f262a04b90dd9d4e0d1 Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Mon, 12 Jun 2023 22:11:28 -0400 Subject: [PATCH 04/36] tests: disable some broken tests These are seemingly intentionally incompatible with pytest. --- tests/test_basic.py | 96 ++++++++++++++++++++++----------------------- 1 file changed, 48 insertions(+), 48 deletions(-) diff --git a/tests/test_basic.py b/tests/test_basic.py index a19c9ae..471fefc 100644 --- a/tests/test_basic.py +++ b/tests/test_basic.py @@ -29,70 +29,70 @@ def test_builtin_modules(self): self.assertFalse(sorted(unknown_builtins)) -class TestSysModules(CurrentVersionBase): - # This relies on invocation in a clean python environment using unittest - # not using pytest. +# class TestSysModules(CurrentVersionBase): +# # This relies on invocation in a clean python environment using unittest +# # not using pytest. - ignore_list = ["stdlib_list", "functools32", "tests", "_virtualenv_distutils"] +# ignore_list = ["stdlib_list", "functools32", "tests", "_virtualenv_distutils"] - def setUp(self): - super(TestSysModules, self).setUp() - self.maxDiff = None +# def setUp(self): +# super(TestSysModules, self).setUp() +# self.maxDiff = None - def test_preloaded_packages(self): - """Check all top level stdlib packages are recognised.""" - not_stdlib = set() - for module_name in sys.modules: - pkg, _, module = module_name.partition(".") +# def test_preloaded_packages(self): +# """Check all top level stdlib packages are recognised.""" +# not_stdlib = set() +# for module_name in sys.modules: +# pkg, _, module = module_name.partition(".") - # https://github.com/jackmaney/python-stdlib-list/issues/29 - if pkg.startswith("_sysconfigdata_"): - continue +# # https://github.com/jackmaney/python-stdlib-list/issues/29 +# if pkg.startswith("_sysconfigdata_"): +# continue - if pkg in self.ignore_list: - continue +# if pkg in self.ignore_list: +# continue - # Avoid duplicating errors covered by other tests - if pkg in sys.builtin_module_names: - continue +# # Avoid duplicating errors covered by other tests +# if pkg in sys.builtin_module_names: +# continue - if pkg not in self.list: - not_stdlib.add(pkg) +# if pkg not in self.list: +# not_stdlib.add(pkg) - self.assertFalse(sorted(not_stdlib)) +# self.assertFalse(sorted(not_stdlib)) - def test_preloaded_modules(self): - """Check all stdlib modules are recognised.""" - not_stdlib = set() - for module_name in sys.modules: - pkg, _, module = module_name.partition(".") +# def test_preloaded_modules(self): +# """Check all stdlib modules are recognised.""" +# not_stdlib = set() +# for module_name in sys.modules: +# pkg, _, module = module_name.partition(".") - # https://github.com/jackmaney/python-stdlib-list/issues/29 - if pkg.startswith("_sysconfigdata_"): - continue +# # https://github.com/jackmaney/python-stdlib-list/issues/29 +# if pkg.startswith("_sysconfigdata_"): +# continue - if pkg in self.ignore_list: - continue +# if pkg in self.ignore_list: +# continue - # Avoid duplicating errors covered by other tests - if module_name in sys.builtin_module_names: - continue +# # Avoid duplicating errors covered by other tests +# if module_name in sys.builtin_module_names: +# continue - if PY2: - # Python 2.7 creates sub-modules for imports - if pkg in self.list and module in self.list: - continue +# if PY2: +# # Python 2.7 creates sub-modules for imports +# if pkg in self.list and module in self.list: +# continue - # Python 2.7 deprecation solution for old names - if pkg == "email": - mod = sys.modules[module_name] - if mod.__class__.__name__ == "LazyImporter": - continue +# # Python 2.7 deprecation solution for old names +# if pkg == "email": +# mod = sys.modules[module_name] +# if mod.__class__.__name__ == "LazyImporter": +# continue - if module_name not in self.list: - not_stdlib.add(module_name) +# if module_name not in self.list: +# not_stdlib.add(module_name) - self.assertFalse(sorted(not_stdlib)) +# self.assertFalse(sorted(not_stdlib)) if __name__ == "__main__": From e85109dca8dd6e3b5acfe4e0414de07e3154d24e Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Tue, 13 Jun 2023 23:19:51 -0400 Subject: [PATCH 05/36] [WIP] experiment with CI --- .github/workflows/listgen.yml | 36 +++++++++++++++++++++++++++++++++++ pyproject.toml | 3 +++ support/fetch-sphinx.py | 13 +++++++++++++ 3 files changed, 52 insertions(+) create mode 100644 .github/workflows/listgen.yml create mode 100755 support/fetch-sphinx.py diff --git a/.github/workflows/listgen.yml b/.github/workflows/listgen.yml new file mode 100644 index 0000000..65add44 --- /dev/null +++ b/.github/workflows/listgen.yml @@ -0,0 +1,36 @@ +name: Generate stdlib lists + +on: + pull_request: + workflow_dispatch: + +jobs: + pre-list-legacy: + strategy: + matrix: + python: + - "2.7" + - "3.2" + - "3.3" + - "3.4" + - "3.5" + - "3.6" + - "3.7" + - "3.8" + - "3.9" + + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v4 + with: + python-version: "3.x" + - name: support deps + run: make dev INSTALL_EXTRA=support + - name: build pre-list + env: + PRE_LIST_VERSION: "${{ matrix.python }}" + run: | + ./env/bin/python ./support/fetch-sphinx "${PRE_LIST_VERSION}" + + diff --git a/pyproject.toml b/pyproject.toml index 821e077..fb49c61 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -32,6 +32,9 @@ test = ["pytest", "pytest-cov", "coverage[toml]"] lint = ["black", "mypy", "ruff"] doc = ["sphinx", "sphinx_rtd_theme"] dev = ["build", "stdlib-list[test,lint,doc]"] +# CI only: used for list generation for Python versions < 3.10. +support = ["sphobjinv"] + [tool.black] line-length = 100 diff --git a/support/fetch-sphinx.py b/support/fetch-sphinx.py new file mode 100755 index 0000000..7398c18 --- /dev/null +++ b/support/fetch-sphinx.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python + +# fetch-sphinx.py: retrieve a particular Python version's stdlib list +# using its hosted Sphinx inventory. + +import sys +import sphobjinv as soi + +if __name__ == "__main__": + vers = sys.argv[1] + inv = soi.Inventory(url=f"https://docs.python.org/{vers}/objects.inv") + modules = list(sorted(obj.name for obj in inv.objects if obj.role == "module")) + print("\n".join(modules)) From e6430b02facd874a9f82ed73befa99644dca44cf Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Tue, 13 Jun 2023 23:21:04 -0400 Subject: [PATCH 06/36] [WIP] listgen: fix path --- .github/workflows/listgen.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/listgen.yml b/.github/workflows/listgen.yml index 65add44..4a190da 100644 --- a/.github/workflows/listgen.yml +++ b/.github/workflows/listgen.yml @@ -31,6 +31,6 @@ jobs: env: PRE_LIST_VERSION: "${{ matrix.python }}" run: | - ./env/bin/python ./support/fetch-sphinx "${PRE_LIST_VERSION}" + ./env/bin/python ./support/fetch-sphinx.py "${PRE_LIST_VERSION}" From 235c31ea2db7abf39559fcc33a73c8a1169ce04c Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Wed, 14 Jun 2023 00:27:28 -0400 Subject: [PATCH 07/36] [WIP] more experimenting --- .github/workflows/listgen.yml | 37 ++++++++++++++++++++++++++++++++- support/walk-modules.py | 39 +++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 1 deletion(-) create mode 100755 support/walk-modules.py diff --git a/.github/workflows/listgen.yml b/.github/workflows/listgen.yml index 4a190da..f55af36 100644 --- a/.github/workflows/listgen.yml +++ b/.github/workflows/listgen.yml @@ -20,10 +20,12 @@ jobs: - "3.9" runs-on: ubuntu-latest + steps: - uses: actions/checkout@v3 - uses: actions/setup-python@v4 with: + # NOTE: matrix.python is intentionally not used here. python-version: "3.x" - name: support deps run: make dev INSTALL_EXTRA=support @@ -31,6 +33,39 @@ jobs: env: PRE_LIST_VERSION: "${{ matrix.python }}" run: | - ./env/bin/python ./support/fetch-sphinx.py "${PRE_LIST_VERSION}" + ./env/bin/python ./support/fetch-sphinx.py "${PRE_LIST_VERSION}" > modules.txt + - name: upload pre-list + uses: actions/upload-artifact@v3 + with: + name: pre-list-${{ matrix.python }} + path: modules.txt + expand-list-legacy: + needs: pre-list-legacy + strategy: + matrix: + python: + - "2.7" + - "3.2" + - "3.3" + - "3.4" + - "3.5" + - "3.6" + - "3.7" + - "3.8" + - "3.9" + + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python }} + - uses: actions/download-artifact@v3 + with: + name: pre-list-${{ matrix.python }} + - name: walk pre-list modules + run: + python -V + python ./support/walk-modules.py < modules.txt diff --git a/support/walk-modules.py b/support/walk-modules.py new file mode 100755 index 0000000..0c50c8a --- /dev/null +++ b/support/walk-modules.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python + +import inspect +import sys + + +def walk(mod_name): + # Print the module itself. + print(mod_name) + + # Try and import it. + try: + mod = __import__(mod_name) + for attr in dir(mod): + attr_obj = getattr(mod, attr, None) + # Shouldn't happen, but who knows. + if attr_obj is None: + continue + + # If this member isn't a module, skip it. + if not inspect.ismodule(attr_obj): + continue + + # To filter "real" submodules from re-exports, we try + # and import the submodule by its qualified name. + # If the import fails, we know it's a re-exported module. + try: + submod_name = mod_name + "." + attr + __import__(submod_name) + walk(submod_name) + except ImportError: + continue + except ImportError: + pass + + +if __name__ == "__main__": + for mod_name in sys.stdin: + walk(mod_name.rstrip("\n")) From 3aaac6dcaf102116a53fb6ddda6e5d82cace161c Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Wed, 14 Jun 2023 00:29:15 -0400 Subject: [PATCH 08/36] [WIP] listgen: syntax --- .github/workflows/listgen.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/listgen.yml b/.github/workflows/listgen.yml index f55af36..26df089 100644 --- a/.github/workflows/listgen.yml +++ b/.github/workflows/listgen.yml @@ -66,6 +66,6 @@ jobs: with: name: pre-list-${{ matrix.python }} - name: walk pre-list modules - run: + run: | python -V python ./support/walk-modules.py < modules.txt From 63770a85ec1234eb31616486ae9b7d26406a9919 Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Wed, 14 Jun 2023 00:31:46 -0400 Subject: [PATCH 09/36] [WIP] listgen: disable 2.7 temporarily --- .github/workflows/listgen.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/listgen.yml b/.github/workflows/listgen.yml index 26df089..13b4c09 100644 --- a/.github/workflows/listgen.yml +++ b/.github/workflows/listgen.yml @@ -9,7 +9,7 @@ jobs: strategy: matrix: python: - - "2.7" + # - "2.7" - "3.2" - "3.3" - "3.4" @@ -45,7 +45,7 @@ jobs: strategy: matrix: python: - - "2.7" + # - "2.7" - "3.2" - "3.3" - "3.4" From a429b8026e453e588fad7d23c2bab6bec7f06d8d Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Wed, 14 Jun 2023 00:33:39 -0400 Subject: [PATCH 10/36] [WIP] disable 3.2 --- .github/workflows/listgen.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/listgen.yml b/.github/workflows/listgen.yml index 13b4c09..e59808e 100644 --- a/.github/workflows/listgen.yml +++ b/.github/workflows/listgen.yml @@ -10,7 +10,7 @@ jobs: matrix: python: # - "2.7" - - "3.2" + # - "3.2" - "3.3" - "3.4" - "3.5" @@ -46,7 +46,7 @@ jobs: matrix: python: # - "2.7" - - "3.2" + # - "3.2" - "3.3" - "3.4" - "3.5" From 892e30e08d889c9210f2ab66fad3894248a3250d Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Wed, 14 Jun 2023 00:35:27 -0400 Subject: [PATCH 11/36] [WIP]: 3.6+ only --- .github/workflows/listgen.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/listgen.yml b/.github/workflows/listgen.yml index e59808e..5594975 100644 --- a/.github/workflows/listgen.yml +++ b/.github/workflows/listgen.yml @@ -11,9 +11,9 @@ jobs: python: # - "2.7" # - "3.2" - - "3.3" - - "3.4" - - "3.5" + # - "3.3" + # - "3.4" + # - "3.5" - "3.6" - "3.7" - "3.8" @@ -47,9 +47,9 @@ jobs: python: # - "2.7" # - "3.2" - - "3.3" - - "3.4" - - "3.5" + # - "3.3" + # - "3.4" + # - "3.5" - "3.6" - "3.7" - "3.8" From 635b079731657dcf8722949b13ed72e9d0530883 Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Wed, 14 Jun 2023 00:38:16 -0400 Subject: [PATCH 12/36] [WIP] listgen: tweak runner --- .github/workflows/listgen.yml | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/.github/workflows/listgen.yml b/.github/workflows/listgen.yml index 5594975..931544d 100644 --- a/.github/workflows/listgen.yml +++ b/.github/workflows/listgen.yml @@ -11,9 +11,9 @@ jobs: python: # - "2.7" # - "3.2" - # - "3.3" - # - "3.4" - # - "3.5" + - "3.3" + - "3.4" + - "3.5" - "3.6" - "3.7" - "3.8" @@ -47,15 +47,18 @@ jobs: python: # - "2.7" # - "3.2" - # - "3.3" - # - "3.4" - # - "3.5" + - "3.3" + - "3.4" + - "3.5" - "3.6" - "3.7" - "3.8" - "3.9" - runs-on: ubuntu-latest + # NOTE: Intentionally runs on an ancient Ubuntu to get access to older + # Python versions in setup-python. + # See: https://raw.githubusercontent.com/actions/python-versions/main/versions-manifest.json + runs-on: ubuntu-18.04 steps: - uses: actions/checkout@v3 From 07e95a583e9fb1a4633dc46a2551ff502b055e0c Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Wed, 14 Jun 2023 00:40:30 -0400 Subject: [PATCH 13/36] [WIP]: 3.7 and newer only --- .github/workflows/listgen.yml | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/.github/workflows/listgen.yml b/.github/workflows/listgen.yml index 931544d..de8bb59 100644 --- a/.github/workflows/listgen.yml +++ b/.github/workflows/listgen.yml @@ -11,10 +11,10 @@ jobs: python: # - "2.7" # - "3.2" - - "3.3" - - "3.4" - - "3.5" - - "3.6" + # - "3.3" + # - "3.4" + # - "3.5" + # - "3.6" - "3.7" - "3.8" - "3.9" @@ -47,18 +47,15 @@ jobs: python: # - "2.7" # - "3.2" - - "3.3" - - "3.4" - - "3.5" - - "3.6" + # - "3.3" + # - "3.4" + # - "3.5" + # - "3.6" - "3.7" - "3.8" - "3.9" - # NOTE: Intentionally runs on an ancient Ubuntu to get access to older - # Python versions in setup-python. - # See: https://raw.githubusercontent.com/actions/python-versions/main/versions-manifest.json - runs-on: ubuntu-18.04 + runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 From 7eabc103be45fd7c7999d9ae2af84ae8b933a5b8 Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Wed, 14 Jun 2023 00:51:54 -0400 Subject: [PATCH 14/36] [WIP] handle accelerator mods --- .github/workflows/listgen.yml | 3 ++- support/walk-modules.py | 10 +++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/.github/workflows/listgen.yml b/.github/workflows/listgen.yml index de8bb59..df63ec7 100644 --- a/.github/workflows/listgen.yml +++ b/.github/workflows/listgen.yml @@ -68,4 +68,5 @@ jobs: - name: walk pre-list modules run: | python -V - python ./support/walk-modules.py < modules.txt + python ./support/walk-modules.py < modules.txt > all-modules.txt + sort all-modules.txt diff --git a/support/walk-modules.py b/support/walk-modules.py index 0c50c8a..d28c059 100755 --- a/support/walk-modules.py +++ b/support/walk-modules.py @@ -3,10 +3,13 @@ import inspect import sys +SEEN_MODS = set() + def walk(mod_name): # Print the module itself. print(mod_name) + SEEN_MODS.add(mod_name) # Try and import it. try: @@ -29,7 +32,12 @@ def walk(mod_name): __import__(submod_name) walk(submod_name) except ImportError: - continue + # ...but sometimes we do want to include re-exports, since + # they might be things like "accelerator" modules that don't + # appear anywhere else. + # For example, `_bz2` might appear as a re-export. + if attr not in SEEN_MODS: + print(attr) except ImportError: pass From 4b6a4ea7d975011115564673a570000aa6b05a3c Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Wed, 14 Jun 2023 00:53:44 -0400 Subject: [PATCH 15/36] [WIP] do recursive step correctly --- support/walk-modules.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/support/walk-modules.py b/support/walk-modules.py index d28c059..9c4c6fe 100755 --- a/support/walk-modules.py +++ b/support/walk-modules.py @@ -37,7 +37,7 @@ def walk(mod_name): # appear anywhere else. # For example, `_bz2` might appear as a re-export. if attr not in SEEN_MODS: - print(attr) + walk(attr) except ImportError: pass From 206519a2b5c621a9903237c3c5524f49ea80cf23 Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Wed, 14 Jun 2023 01:03:01 -0400 Subject: [PATCH 16/36] [WIP] dedupe correctly --- support/walk-modules.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/support/walk-modules.py b/support/walk-modules.py index 9c4c6fe..3c5f659 100755 --- a/support/walk-modules.py +++ b/support/walk-modules.py @@ -7,9 +7,11 @@ def walk(mod_name): - # Print the module itself. - print(mod_name) - SEEN_MODS.add(mod_name) + if mod_name in SEEN_MODS: + return + else: + SEEN_MODS.add(mod_name) + print(mod_name) # Try and import it. try: @@ -36,8 +38,7 @@ def walk(mod_name): # they might be things like "accelerator" modules that don't # appear anywhere else. # For example, `_bz2` might appear as a re-export. - if attr not in SEEN_MODS: - walk(attr) + walk(attr) except ImportError: pass From 84598f97ca9eb98fc0963ac3e303fda28efce45e Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Wed, 14 Jun 2023 01:13:36 -0400 Subject: [PATCH 17/36] [WIP]: use pkgutil --- support/walk-modules.py | 61 +++++++++++++++++++++++++---------------- 1 file changed, 38 insertions(+), 23 deletions(-) diff --git a/support/walk-modules.py b/support/walk-modules.py index 3c5f659..fce4b79 100755 --- a/support/walk-modules.py +++ b/support/walk-modules.py @@ -1,11 +1,43 @@ #!/usr/bin/env python import inspect +import pkgutil import sys SEEN_MODS = set() +def walk_pkgutil(mod_name, mod): + for pkg in pkgutil.walk_packages(mod.__path__, mod_name + "."): + walk(pkg.name) + + +def walk_naive(mod_name, mod): + for attr in dir(mod): + attr_obj = getattr(mod, attr, None) + # Shouldn't happen, but who knows. + if attr_obj is None: + continue + + # If this member isn't a module, skip it. + if not inspect.ismodule(attr_obj): + continue + + # To filter "real" submodules from re-exports, we try + # and import the submodule by its qualified name. + # If the import fails, we know it's a re-exported module. + try: + submod_name = mod_name + "." + attr + __import__(submod_name) + walk(submod_name) + except ImportError: + # ...but sometimes we do want to include re-exports, since + # they might be things like "accelerator" modules that don't + # appear anywhere else. + # For example, `_bz2` might appear as a re-export. + walk(attr) + + def walk(mod_name): if mod_name in SEEN_MODS: return @@ -16,29 +48,12 @@ def walk(mod_name): # Try and import it. try: mod = __import__(mod_name) - for attr in dir(mod): - attr_obj = getattr(mod, attr, None) - # Shouldn't happen, but who knows. - if attr_obj is None: - continue - - # If this member isn't a module, skip it. - if not inspect.ismodule(attr_obj): - continue - - # To filter "real" submodules from re-exports, we try - # and import the submodule by its qualified name. - # If the import fails, we know it's a re-exported module. - try: - submod_name = mod_name + "." + attr - __import__(submod_name) - walk(submod_name) - except ImportError: - # ...but sometimes we do want to include re-exports, since - # they might be things like "accelerator" modules that don't - # appear anywhere else. - # For example, `_bz2` might appear as a re-export. - walk(attr) + + if hasattr(mod, "__path__"): + walk_pkgutil(mod_name, mod) + else: + walk_naive(mod_name, mod) + except ImportError: pass From 747b2fc45348716dd44998ee1d2471ec6eccc352 Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Wed, 14 Jun 2023 01:20:59 -0400 Subject: [PATCH 18/36] [WIP] hackety hack --- support/walk-modules.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/support/walk-modules.py b/support/walk-modules.py index fce4b79..425f515 100755 --- a/support/walk-modules.py +++ b/support/walk-modules.py @@ -9,7 +9,13 @@ def walk_pkgutil(mod_name, mod): for pkg in pkgutil.walk_packages(mod.__path__, mod_name + "."): - walk(pkg.name) + # pkgutil can produce false positives due to re-exports; + # we filter them out by attempting to import them. + try: + __import__(pkg.name) + walk(pkg.name) + except: + pass def walk_naive(mod_name, mod): From 300689cf5be44ed4c1b4c04408a1a7a47a44819d Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Wed, 14 Jun 2023 01:26:48 -0400 Subject: [PATCH 19/36] [WIP] hackety hack --- support/walk-modules.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/support/walk-modules.py b/support/walk-modules.py index 425f515..ef0407c 100755 --- a/support/walk-modules.py +++ b/support/walk-modules.py @@ -9,13 +9,13 @@ def walk_pkgutil(mod_name, mod): for pkg in pkgutil.walk_packages(mod.__path__, mod_name + "."): - # pkgutil can produce false positives due to re-exports; - # we filter them out by attempting to import them. - try: - __import__(pkg.name) - walk(pkg.name) - except: - pass + if pkg.name in SEEN_MODS: + continue + else: + # We don't recurse here because `walk_packages` takes care of + # it for us. + SEEN_MODS.add(pkg.name) + print(pkg.name) def walk_naive(mod_name, mod): From b4216549a46f0be78104e732e74307916eba80c4 Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Wed, 14 Jun 2023 01:41:39 -0400 Subject: [PATCH 20/36] [WIP] builtin_module_names --- support/walk-modules.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/support/walk-modules.py b/support/walk-modules.py index ef0407c..55dfa7a 100755 --- a/support/walk-modules.py +++ b/support/walk-modules.py @@ -67,3 +67,6 @@ def walk(mod_name): if __name__ == "__main__": for mod_name in sys.stdin: walk(mod_name.rstrip("\n")) + + for mod_name in sys.builtin_module_names: + walk(mod_name) From 8ae1b6cebb2fefc3fa70b6403b47f34f300d3bd1 Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Wed, 14 Jun 2023 20:26:18 -0400 Subject: [PATCH 21/36] [WIP] newer python support --- .github/workflows/listgen.yml | 34 +++++++++++++++++++++------------- support/walk-modules.py | 33 ++++++++++++++++++++------------- 2 files changed, 41 insertions(+), 26 deletions(-) diff --git a/.github/workflows/listgen.yml b/.github/workflows/listgen.yml index df63ec7..5db28c2 100644 --- a/.github/workflows/listgen.yml +++ b/.github/workflows/listgen.yml @@ -9,12 +9,6 @@ jobs: strategy: matrix: python: - # - "2.7" - # - "3.2" - # - "3.3" - # - "3.4" - # - "3.5" - # - "3.6" - "3.7" - "3.8" - "3.9" @@ -45,12 +39,6 @@ jobs: strategy: matrix: python: - # - "2.7" - # - "3.2" - # - "3.3" - # - "3.4" - # - "3.5" - # - "3.6" - "3.7" - "3.8" - "3.9" @@ -68,5 +56,25 @@ jobs: - name: walk pre-list modules run: | python -V - python ./support/walk-modules.py < modules.txt > all-modules.txt + python ./support/walk-modules-legacy.py all-modules.txt < modules.txt + sort all-modules.txt + + expand-list: + strategy: + matrix: + python: + - "3.10" + - "3.11" + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python }} + - name: walk pre-list modules + run: | + python -V + python ./support/walk-modules-legacy.py all-modules.txt sort all-modules.txt diff --git a/support/walk-modules.py b/support/walk-modules.py index 55dfa7a..9f3f3b7 100755 --- a/support/walk-modules.py +++ b/support/walk-modules.py @@ -7,7 +7,7 @@ SEEN_MODS = set() -def walk_pkgutil(mod_name, mod): +def walk_pkgutil(mod_name, mod, io): for pkg in pkgutil.walk_packages(mod.__path__, mod_name + "."): if pkg.name in SEEN_MODS: continue @@ -15,10 +15,10 @@ def walk_pkgutil(mod_name, mod): # We don't recurse here because `walk_packages` takes care of # it for us. SEEN_MODS.add(pkg.name) - print(pkg.name) + print(pkg.name, file=io) -def walk_naive(mod_name, mod): +def walk_naive(mod_name, mod, io): for attr in dir(mod): attr_obj = getattr(mod, attr, None) # Shouldn't happen, but who knows. @@ -35,38 +35,45 @@ def walk_naive(mod_name, mod): try: submod_name = mod_name + "." + attr __import__(submod_name) - walk(submod_name) + walk(submod_name, io) except ImportError: # ...but sometimes we do want to include re-exports, since # they might be things like "accelerator" modules that don't # appear anywhere else. # For example, `_bz2` might appear as a re-export. - walk(attr) + walk(attr, io) -def walk(mod_name): +def walk(mod_name, io): if mod_name in SEEN_MODS: return else: SEEN_MODS.add(mod_name) - print(mod_name) + print(mod_name, file=io) # Try and import it. try: mod = __import__(mod_name) if hasattr(mod, "__path__"): - walk_pkgutil(mod_name, mod) + walk_pkgutil(mod_name, mod, io) else: - walk_naive(mod_name, mod) + walk_naive(mod_name, mod, io) except ImportError: pass if __name__ == "__main__": - for mod_name in sys.stdin: - walk(mod_name.rstrip("\n")) + output = sys.argv[1] - for mod_name in sys.builtin_module_names: - walk(mod_name) + with open(output, mode="w") as io: + for mod_name in sys.builtin_module_names: + walk(mod_name, io) + + if hasattr(sys, "stdlib_module_names"): + for mod_name in sys.stdlib_module_names: + walk(mod_name, io) + else: + for mod_name in sys.stdin: + walk(mod_name.rstrip("\n"), io) From c69a61e11e7448cd97d775f6ce69cbc30cee60ce Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Wed, 14 Jun 2023 20:27:23 -0400 Subject: [PATCH 22/36] [WIP] fix path --- .github/workflows/listgen.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/listgen.yml b/.github/workflows/listgen.yml index 5db28c2..08df957 100644 --- a/.github/workflows/listgen.yml +++ b/.github/workflows/listgen.yml @@ -56,7 +56,7 @@ jobs: - name: walk pre-list modules run: | python -V - python ./support/walk-modules-legacy.py all-modules.txt < modules.txt + python ./support/walk-modules.py all-modules.txt < modules.txt sort all-modules.txt expand-list: @@ -76,5 +76,5 @@ jobs: - name: walk pre-list modules run: | python -V - python ./support/walk-modules-legacy.py all-modules.txt + python ./support/walk-modules.py all-modules.txt sort all-modules.txt From eb8253400e5143cfc4659ffc86c3aeccc9c66748 Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Wed, 14 Jun 2023 20:39:09 -0400 Subject: [PATCH 23/36] listgen: auto-PRs for 3.10+ --- .github/workflows/listgen.yml | 37 ++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/.github/workflows/listgen.yml b/.github/workflows/listgen.yml index 08df957..2475f8f 100644 --- a/.github/workflows/listgen.yml +++ b/.github/workflows/listgen.yml @@ -25,14 +25,14 @@ jobs: run: make dev INSTALL_EXTRA=support - name: build pre-list env: - PRE_LIST_VERSION: "${{ matrix.python }}" + LISTGEN_PYTHON_VERSION: "${{ matrix.python }}" run: | - ./env/bin/python ./support/fetch-sphinx.py "${PRE_LIST_VERSION}" > modules.txt + ./env/bin/python ./support/fetch-sphinx.py "${LISTGEN_PYTHON_VERSION}" > pre-list.txt - name: upload pre-list uses: actions/upload-artifact@v3 with: name: pre-list-${{ matrix.python }} - path: modules.txt + path: pre-list.txt expand-list-legacy: needs: pre-list-legacy @@ -53,11 +53,13 @@ jobs: - uses: actions/download-artifact@v3 with: name: pre-list-${{ matrix.python }} - - name: walk pre-list modules + - name: walk modules run: | python -V - python ./support/walk-modules.py all-modules.txt < modules.txt - sort all-modules.txt + python ./support/walk-modules.py "${LISTGEN_PYTHON_VERSION}.txt" < pre-list.txt + rm pre-list.txt + sort -o "${LISTGEN_PYTHON_VERSION}.txt" "${LISTGEN_PYTHON_VERSION}.txt" + mv "${LISTGEN_PYTHON_VERSION}.txt" ./stdlib_list/lists/ expand-list: strategy: @@ -73,8 +75,25 @@ jobs: - uses: actions/setup-python@v4 with: python-version: ${{ matrix.python }} - - name: walk pre-list modules + - name: walk modules + env: + LISTGEN_PYTHON_VERSION: ${{ matrix.python }} run: | python -V - python ./support/walk-modules.py all-modules.txt - sort all-modules.txt + python ./support/walk-modules.py "${LISTGEN_PYTHON_VERSION}.txt" + sort -o "${LISTGEN_PYTHON_VERSION}.txt" "${LISTGEN_PYTHON_VERSION}.txt" + mv "${LISTGEN_PYTHON_VERSION}.txt" ./stdlib_list/lists/ + + - name: create PR + uses: peter-evans/create-pull-request@v5 + with: + commit-message: "[BOT] update list for ${{ matrix.python }}" + branch: update-stdlib-list-${{ matrix.python }} + branch-suffix: timestamp + title: "[BOT] update list for ${{ matrix.python }}" + body: | + This is an automated pull request, updating `${{ matrix.python }}.txt` after a detected change. + + Please review manually before merging. + assignees: "woodruffw" + reviewers: "woodruffw" From bd49ee15126ec578d7a380bd195bf485044e8a29 Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Wed, 14 Jun 2023 20:40:58 -0400 Subject: [PATCH 24/36] listgen: fix base branch --- .github/workflows/listgen.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/listgen.yml b/.github/workflows/listgen.yml index 2475f8f..db1cbd7 100644 --- a/.github/workflows/listgen.yml +++ b/.github/workflows/listgen.yml @@ -89,6 +89,7 @@ jobs: with: commit-message: "[BOT] update list for ${{ matrix.python }}" branch: update-stdlib-list-${{ matrix.python }} + base: main branch-suffix: timestamp title: "[BOT] update list for ${{ matrix.python }}" body: | From ab25cc8f0b83974256dd3b7468e8b0bcbf209b4a Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Wed, 14 Jun 2023 20:54:42 -0400 Subject: [PATCH 25/36] walk-modules: be slightly smarter --- support/walk-modules.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/support/walk-modules.py b/support/walk-modules.py index 9f3f3b7..8713939 100755 --- a/support/walk-modules.py +++ b/support/walk-modules.py @@ -41,7 +41,14 @@ def walk_naive(mod_name, mod, io): # they might be things like "accelerator" modules that don't # appear anywhere else. # For example, `_bz2` might appear as a re-export. - walk(attr, io) + try: + # Again, try and import to avoid module-looking object + # that don't actually appear on disk. Experimentally, + # there are a few of these (like "TK"). + __import__(attr) + walk(attr, io) + except ImportError: + continue def walk(mod_name, io): From 37f9ffb5af036a021b4841c197f5ef1731930bd1 Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Thu, 15 Jun 2023 21:10:45 -0400 Subject: [PATCH 26/36] listgen: temporarily disable PR creation --- .github/workflows/listgen.yml | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/listgen.yml b/.github/workflows/listgen.yml index db1cbd7..301fea3 100644 --- a/.github/workflows/listgen.yml +++ b/.github/workflows/listgen.yml @@ -84,17 +84,17 @@ jobs: sort -o "${LISTGEN_PYTHON_VERSION}.txt" "${LISTGEN_PYTHON_VERSION}.txt" mv "${LISTGEN_PYTHON_VERSION}.txt" ./stdlib_list/lists/ - - name: create PR - uses: peter-evans/create-pull-request@v5 - with: - commit-message: "[BOT] update list for ${{ matrix.python }}" - branch: update-stdlib-list-${{ matrix.python }} - base: main - branch-suffix: timestamp - title: "[BOT] update list for ${{ matrix.python }}" - body: | - This is an automated pull request, updating `${{ matrix.python }}.txt` after a detected change. + # - name: create PR + # uses: peter-evans/create-pull-request@v5 + # with: + # commit-message: "[BOT] update list for ${{ matrix.python }}" + # branch: update-stdlib-list-${{ matrix.python }} + # base: main + # branch-suffix: timestamp + # title: "[BOT] update list for ${{ matrix.python }}" + # body: | + # This is an automated pull request, updating `${{ matrix.python }}.txt` after a detected change. - Please review manually before merging. - assignees: "woodruffw" - reviewers: "woodruffw" + # Please review manually before merging. + # assignees: "woodruffw" + # reviewers: "woodruffw" From 04df9c79cc2b36a315d612d8a5e136da04d14cb2 Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Thu, 15 Jun 2023 21:26:19 -0400 Subject: [PATCH 27/36] rewrite tests --- stdlib_list/__init__.py | 8 ++ stdlib_list/base.py | 18 ++++- tests/__main__.py | 7 -- tests/test_base.py | 27 +++++++ tests/test_basic.py | 99 ----------------------- tests/test_platform.py | 170 ---------------------------------------- 6 files changed, 50 insertions(+), 279 deletions(-) delete mode 100644 tests/__main__.py create mode 100644 tests/test_base.py delete mode 100644 tests/test_basic.py delete mode 100644 tests/test_platform.py diff --git a/stdlib_list/__init__.py b/stdlib_list/__init__.py index 95e9050..ab610d9 100644 --- a/stdlib_list/__init__.py +++ b/stdlib_list/__init__.py @@ -8,3 +8,11 @@ short_versions, long_versions, ) + +__all__ = [ + "stdlib_list", + "in_stdlib", + "get_canonical_version", + "short_versions", + "long_versions", +] diff --git a/stdlib_list/base.py b/stdlib_list/base.py index 496fc16..cd6f15f 100644 --- a/stdlib_list/base.py +++ b/stdlib_list/base.py @@ -6,7 +6,20 @@ from functools import lru_cache -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"] +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", + "3.10", + "3.11", +] short_versions = [".".join(x.split(".")[:2]) for x in long_versions] @@ -23,8 +36,7 @@ def get_canonical_version(version): def stdlib_list(version=None): """ Given a ``version``, return a ``list`` of names of the Python Standard - Libraries for that version. These names are obtained from the Sphinx inventory - file (used in :py:mod:`sphinx.ext.intersphinx`). + Libraries for that version. :param str|None version: The version (as a string) whose list of libraries you want (one of ``"2.6"``, ``"2.7"``, ``"3.2"``, ``"3.3"``, ``"3.4"``, or ``"3.5"``). diff --git a/tests/__main__.py b/tests/__main__.py deleted file mode 100644 index 9fea50d..0000000 --- a/tests/__main__.py +++ /dev/null @@ -1,7 +0,0 @@ -import unittest - -from tests.test_basic import * -from tests.test_platform import * - -if __name__ == "__main__": - unittest.main() diff --git a/tests/test_base.py b/tests/test_base.py new file mode 100644 index 0000000..19c40b4 --- /dev/null +++ b/tests/test_base.py @@ -0,0 +1,27 @@ +import pkgutil +import pytest + +import stdlib_list + + +@pytest.mark.parametrize( + ("version", "canonicalized"), + [("2.7", "2.7"), ("3.10", "3.10")], +) +def test_get_canonical_version(version, canonicalized): + assert stdlib_list.get_canonical_version(version) == canonicalized + + +@pytest.mark.parametrize("version", ["nonsense", "1.2.3", "3.1000"]) +def test_get_canonical_version_raises(version): + with pytest.raises(ValueError, match=rf"No such version: {version}"): + stdlib_list.get_canonical_version(version) + + +@pytest.mark.parametrize("version", stdlib_list.short_versions) +def test_self_consistent(version): + list_path = f"lists/{version}.txt" + modules = pkgutil.get_data("stdlib_list", list_path).decode().splitlines() + + for mod_name in modules: + assert stdlib_list.in_stdlib(mod_name, version) diff --git a/tests/test_basic.py b/tests/test_basic.py deleted file mode 100644 index 471fefc..0000000 --- a/tests/test_basic.py +++ /dev/null @@ -1,99 +0,0 @@ -import sys -import unittest - -import stdlib_list - -PY2 = sys.version_info[0] == 2 - - -class CurrentVersionBase(unittest.TestCase): - def setUp(self): - version = f"{sys.version_info.major}.{sys.version_info.minor}" - self.list = stdlib_list.stdlib_list(version) - - -class TestCurrentVersion(CurrentVersionBase): - def test_string(self): - self.assertIn("string", self.list) - - def test_list_is_sorted(self): - self.assertEqual(sorted(self.list), self.list) - - def test_builtin_modules(self): - """Check all top level stdlib packages are recognised.""" - unknown_builtins = set() - for module_name in sys.builtin_module_names: - if module_name not in self.list: - unknown_builtins.add(module_name) - - self.assertFalse(sorted(unknown_builtins)) - - -# class TestSysModules(CurrentVersionBase): -# # This relies on invocation in a clean python environment using unittest -# # not using pytest. - -# ignore_list = ["stdlib_list", "functools32", "tests", "_virtualenv_distutils"] - -# def setUp(self): -# super(TestSysModules, self).setUp() -# self.maxDiff = None - -# def test_preloaded_packages(self): -# """Check all top level stdlib packages are recognised.""" -# not_stdlib = set() -# for module_name in sys.modules: -# pkg, _, module = module_name.partition(".") - -# # https://github.com/jackmaney/python-stdlib-list/issues/29 -# if pkg.startswith("_sysconfigdata_"): -# continue - -# if pkg in self.ignore_list: -# continue - -# # Avoid duplicating errors covered by other tests -# if pkg in sys.builtin_module_names: -# continue - -# if pkg not in self.list: -# not_stdlib.add(pkg) - -# self.assertFalse(sorted(not_stdlib)) - -# def test_preloaded_modules(self): -# """Check all stdlib modules are recognised.""" -# not_stdlib = set() -# for module_name in sys.modules: -# pkg, _, module = module_name.partition(".") - -# # https://github.com/jackmaney/python-stdlib-list/issues/29 -# if pkg.startswith("_sysconfigdata_"): -# continue - -# if pkg in self.ignore_list: -# continue - -# # Avoid duplicating errors covered by other tests -# if module_name in sys.builtin_module_names: -# continue - -# if PY2: -# # Python 2.7 creates sub-modules for imports -# if pkg in self.list and module in self.list: -# continue - -# # Python 2.7 deprecation solution for old names -# if pkg == "email": -# mod = sys.modules[module_name] -# if mod.__class__.__name__ == "LazyImporter": -# continue - -# if module_name not in self.list: -# not_stdlib.add(module_name) - -# self.assertFalse(sorted(not_stdlib)) - - -if __name__ == "__main__": - unittest.main() diff --git a/tests/test_platform.py b/tests/test_platform.py deleted file mode 100644 index 15b9890..0000000 --- a/tests/test_platform.py +++ /dev/null @@ -1,170 +0,0 @@ -import difflib -import os -import os.path -import sys -import unittest -from distutils.sysconfig import get_python_lib -from sysconfig import get_config_var - -import stdlib_list - -try: - sys.base_prefix - has_base_prefix = sys.base_prefix != sys.prefix -except AttributeError: - has_base_prefix = False - -shlib_ext = get_config_var("SHLIB_SUFFIX") or get_config_var("SO") - -tk_libs = get_config_var("TKPATH") - - -class UnifiedDiffAssertionError(AssertionError): - def __init__(self, expected, got, msg="Differences"): - super(UnifiedDiffAssertionError, self).__init__(self) - version = f"{sys.version_info.major}.{sys.version_info.minor}" - filename = "stdlib_list/lists/{}.txt".format(version) - diff = difflib.unified_diff( - expected, got, lineterm="", fromfile="a/" + filename, tofile="b/" + filename - ) - self.description = "{name}\n{diff}".format(name=msg, diff="\n".join(diff)) - - def __str__(self): - return self.description - - -class CurrentPlatformBase(object): - dir = None - ignore_test = False - - def setUp(self): - version = f"{sys.version_info.major}.{sys.version_info.minor}" - self.list = stdlib_list.stdlib_list(version) - if self.dir: - self.assertTrue(os.path.isdir(self.dir)) - - def _collect_shared(self, name): - # stdlib extensions are not in subdirectories - if "/" in name: - return None - - return name.split(".", 1)[0] - - def _collect_file(self, name): - if name.endswith(shlib_ext): - return self._collect_shared(name) - - if not name.endswith(".py"): - return None - - # This excludes `_sysconfigdata_m_linux_x86_64-linux-gnu` - # https://github.com/jackmaney/python-stdlib-list/issues/29 - if "-" in name: - return None - - # Ignore this oddball stdlib test.test_frozen helper - if name == "__phello__.foo.py": - return None - - if name.endswith("/__init__.py"): - return name[:-12].replace("/", ".") - - # Strip .py and replace '/' - return name[:-3].replace("/", ".") - - def _collect_all(self, base): - base = base + "/" if not base.endswith("/") else base - base_len = len(base) - modules = [] - - for root, dirs, files in os.walk(base): - for filename in files: - relative_base = root[base_len:] - relative_path = os.path.join(relative_base, filename) - module_name = self._collect_file(relative_path) - if module_name: - modules.append(module_name) - - # In-place filtering of traversal, removing invalid module names - # and cache directories - for dir in dirs: - if "-" in dir: - dirs.remove(dir) - if "__pycache__" in dirs: - dirs.remove("__pycache__") - - if self.ignore_test and "test" in dirs: - dirs.remove("test") - - # openSUSE custom module added to stdlib directory - if "_import_failed" in dirs: - dirs.remove("_import_failed") - - return modules - - def assertNoDiff(self, base, new): - if base == new: - self.assertEqual(base, new) - else: - raise UnifiedDiffAssertionError(got=sorted(new), expected=sorted(base)) - - def test_dir(self): - needed = set(self.list) - items = self._collect_all(self.dir) - for item in items: - if item not in self.list: - needed.add(item) - - self.assertNoDiff(set(self.list), needed) - - -class TestPureLibDir(CurrentPlatformBase, unittest.TestCase): - def setUp(self): - self.dir = get_python_lib(standard_lib=True, plat_specific=False) - super(TestPureLibDir, self).setUp() - - -class TestPlatLibDir(CurrentPlatformBase, unittest.TestCase): - def setUp(self): - self.dir = get_python_lib(standard_lib=True, plat_specific=True) - super(TestPlatLibDir, self).setUp() - - -class TestSharedDir(CurrentPlatformBase, unittest.TestCase): - def setUp(self): - self.dir = get_config_var("DESTSHARED") - super(TestSharedDir, self).setUp() - - -if has_base_prefix: - - class TestBasePureLibDir(CurrentPlatformBase, unittest.TestCase): - def setUp(self): - base = sys.base_prefix - self.dir = get_python_lib(standard_lib=True, plat_specific=False, prefix=base) - super(TestBasePureLibDir, self).setUp() - - class TestBasePlatLibDir(CurrentPlatformBase, unittest.TestCase): - def setUp(self): - base = sys.base_prefix - self.dir = get_python_lib(standard_lib=True, plat_specific=True, prefix=base) - super(TestBasePlatLibDir, self).setUp() - - -if tk_libs: - tk_libs = tk_libs.strip(os.pathsep) - - class TestTkDir(CurrentPlatformBase, unittest.TestCase): - # Python 2.7 tk-libs includes a `test` package, however it is - # added to sys.path by test.test_tk as a top level directory - # so test.widget_tests becomes module name `widget_tests` - ignore_test = True - - def setUp(self): - base = get_python_lib(standard_lib=True, plat_specific=False) - self.dir = os.path.join(base, tk_libs) - super(TestTkDir, self).setUp() - - -if __name__ == "__main__": - unittest.main() From fd48323187cb80f1047ecb5d3c8b9671c03306dd Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Thu, 15 Jun 2023 21:27:00 -0400 Subject: [PATCH 28/36] Makefile: enforce 100% coverage --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index c26dea3..042a133 100644 --- a/Makefile +++ b/Makefile @@ -70,7 +70,7 @@ reformat: test tests: $(VENV)/pyvenv.cfg . $(VENV_BIN)/activate && \ pytest --cov=$(PY_MODULE) $(T) $(TEST_ARGS) && \ - python -m coverage report -m $(COV_ARGS) + python -m coverage report -m $(COV_ARGS) --fail-under 100 .PHONY: doc doc: $(VENV)/pyvenv.cfg From 572af87aa472ad10d263efc867c634bd288c22e3 Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Thu, 15 Jun 2023 21:30:02 -0400 Subject: [PATCH 29/36] README: mention the new `sys` APIs --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index df7d0f3..4563eb3 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,11 @@ This package includes lists of all of the standard libraries for Python 2.6, 2.7, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7, 3.8, and 3.9 along with the code for scraping the official Python docs to get said lists. +**IMPORTANT**: If you're on Python 3.10 or newer, you **probably don't need this library**. +See [`sys.stdlib_module_names`](https://docs.python.org/3/library/sys.html#sys.stdlib_module_names) +and [`sys.builtin_module_names`](https://docs.python.org/3/library/sys.html#sys.builtin_module_names) +for similar functionality. + ## Installation `stdlib-list` is available on PyPI: From b663cbfc8ca14a9c255228b34ad6d033a070e86c Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Thu, 15 Jun 2023 21:32:20 -0400 Subject: [PATCH 30/36] listgen: run for old Pythons, drop pull_request trigger --- .github/workflows/listgen.yml | 43 +++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/.github/workflows/listgen.yml b/.github/workflows/listgen.yml index 301fea3..c31923a 100644 --- a/.github/workflows/listgen.yml +++ b/.github/workflows/listgen.yml @@ -1,8 +1,9 @@ name: Generate stdlib lists on: - pull_request: workflow_dispatch: + schedule: + - cron: "0 0 * * 0" jobs: pre-list-legacy: @@ -60,6 +61,20 @@ jobs: rm pre-list.txt sort -o "${LISTGEN_PYTHON_VERSION}.txt" "${LISTGEN_PYTHON_VERSION}.txt" mv "${LISTGEN_PYTHON_VERSION}.txt" ./stdlib_list/lists/ + - name: create PR + uses: peter-evans/create-pull-request@v5 + with: + commit-message: "[BOT] update list for ${{ matrix.python }}" + branch: update-stdlib-list-${{ matrix.python }} + base: main + branch-suffix: timestamp + title: "[BOT] update list for ${{ matrix.python }}" + body: | + This is an automated pull request, updating `${{ matrix.python }}.txt` after a detected change. + + Please review manually before merging. + assignees: "woodruffw" + reviewers: "woodruffw" expand-list: strategy: @@ -84,17 +99,17 @@ jobs: sort -o "${LISTGEN_PYTHON_VERSION}.txt" "${LISTGEN_PYTHON_VERSION}.txt" mv "${LISTGEN_PYTHON_VERSION}.txt" ./stdlib_list/lists/ - # - name: create PR - # uses: peter-evans/create-pull-request@v5 - # with: - # commit-message: "[BOT] update list for ${{ matrix.python }}" - # branch: update-stdlib-list-${{ matrix.python }} - # base: main - # branch-suffix: timestamp - # title: "[BOT] update list for ${{ matrix.python }}" - # body: | - # This is an automated pull request, updating `${{ matrix.python }}.txt` after a detected change. + - name: create PR + uses: peter-evans/create-pull-request@v5 + with: + commit-message: "[BOT] update list for ${{ matrix.python }}" + branch: update-stdlib-list-${{ matrix.python }} + base: main + branch-suffix: timestamp + title: "[BOT] update list for ${{ matrix.python }}" + body: | + This is an automated pull request, updating `${{ matrix.python }}.txt` after a detected change. - # Please review manually before merging. - # assignees: "woodruffw" - # reviewers: "woodruffw" + Please review manually before merging. + assignees: "woodruffw" + reviewers: "woodruffw" From 01402ca59c565439d3f848143e3e7215cf04fd49 Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Thu, 15 Jun 2023 21:34:01 -0400 Subject: [PATCH 31/36] ci: enable caching --- .github/workflows/ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3d3cf32..0e43bc5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,9 +18,12 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 + - uses: actions/setup-python@v4 with: python-version: ${{ matrix.python }} + cache: pip + - name: test run: make test INSTALL_EXTRA=test From 795886de7f200a15fe6788deb2c9d4951e3f2ae5 Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Thu, 15 Jun 2023 21:34:44 -0400 Subject: [PATCH 32/36] ci: test on 3.10 and 3.11 --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0e43bc5..34cce10 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,6 +15,8 @@ jobs: - "3.7" - "3.8" - "3.9" + - "3.10" + - "3.11" runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 From 8875a7b69781c7054640ba72ee00aa130b8cfe3b Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Thu, 15 Jun 2023 21:37:59 -0400 Subject: [PATCH 33/36] base: update docstrings --- stdlib_list/base.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stdlib_list/base.py b/stdlib_list/base.py index cd6f15f..75aa30b 100644 --- a/stdlib_list/base.py +++ b/stdlib_list/base.py @@ -39,7 +39,7 @@ def stdlib_list(version=None): Libraries for that version. :param str|None version: The version (as a string) whose list of libraries you want - (one of ``"2.6"``, ``"2.7"``, ``"3.2"``, ``"3.3"``, ``"3.4"``, or ``"3.5"``). + (formatted as ``X.Y``, e.g. ``"2.7"`` or ``"3.10"``). If not specified, the current version of Python will be used. @@ -84,7 +84,7 @@ def in_stdlib(module_name, version=None): :param str|None module_name: The module name (as a string) to query for. :param str|None version: The version (as a string) whose list of libraries you want - (one of ``"2.6"``, ``"2.7"``, ``"3.2"``, ``"3.3"``, ``"3.4"``, or ``"3.5"``). + (formatted as ``X.Y``, e.g. ``"2.7"`` or ``"3.10"``). If not specified, the current version of Python will be used. From 185e89447b616e5ddde190cd101c9a0b8d922834 Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Thu, 15 Jun 2023 22:08:04 -0400 Subject: [PATCH 34/36] test_base: add another consistency test --- tests/test_base.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/test_base.py b/tests/test_base.py index 19c40b4..ad91eb4 100644 --- a/tests/test_base.py +++ b/tests/test_base.py @@ -25,3 +25,5 @@ def test_self_consistent(version): for mod_name in modules: assert stdlib_list.in_stdlib(mod_name, version) + + assert modules == stdlib_list.stdlib_list(version) From 92e5670fa9cc817eeab7af8832c1730722124e38 Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Mon, 19 Jun 2023 23:07:47 -0400 Subject: [PATCH 35/36] tests: test long_versions as well for consistency --- tests/test_base.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_base.py b/tests/test_base.py index ad91eb4..89fbc71 100644 --- a/tests/test_base.py +++ b/tests/test_base.py @@ -18,9 +18,9 @@ def test_get_canonical_version_raises(version): stdlib_list.get_canonical_version(version) -@pytest.mark.parametrize("version", stdlib_list.short_versions) +@pytest.mark.parametrize("version", [*stdlib_list.short_versions, *stdlib_list.long_versions]) def test_self_consistent(version): - list_path = f"lists/{version}.txt" + list_path = f"lists/{stdlib_list.get_canonical_version(version)}.txt" modules = pkgutil.get_data("stdlib_list", list_path).decode().splitlines() for mod_name in modules: From d624d8183e9942cc94ad796979526ba144f18255 Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Mon, 19 Jun 2023 23:08:43 -0400 Subject: [PATCH 36/36] listgen: every tuesday --- .github/workflows/listgen.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/listgen.yml b/.github/workflows/listgen.yml index c31923a..785c314 100644 --- a/.github/workflows/listgen.yml +++ b/.github/workflows/listgen.yml @@ -3,7 +3,7 @@ name: Generate stdlib lists on: workflow_dispatch: schedule: - - cron: "0 0 * * 0" + - cron: "0 0 * * 2" jobs: pre-list-legacy: