Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,12 @@
"settings": {
// Discover the tests/ package from the Test Explorer.
"python.testing.unittestEnabled": true,
"python.testing.unittestArgs": ["-v", "-s", ".", "-p", "test*.py"]
"python.testing.unittestArgs": ["-v", "-s", "tests", "-p", "test*.py"]
}
}
},

// Compile + install the extension (non-editable: a clean .so in site-packages
// avoids the name clash with the list_reserve/ stub package) and add the
// `build` frontend so `python -m build` works.
"postCreateCommand": "pip install --upgrade pip && pip install . build"
// Compile + install the package in editable mode and add the `build` frontend
// so `python -m build` works.
"postCreateCommand": "pip install --upgrade pip && pip install -e . build"
}
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,4 @@ jobs:
pip install .
- name: Test
run: |
python -m unittest
python tools/run_installed_tests.py
1 change: 1 addition & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@
# from a PyPI source download. The tests/ package is not part of the wheel
# (packages = ["list_reserve"]), so the sdist is its only distribution channel.
recursive-include tests *.py
include tools/run_installed_tests.py
include LICENSE
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,12 +102,12 @@ supports Dev Containers ("Reopen in Container"), or run it headlessly with the

```bash
devcontainer up --workspace-folder .
devcontainer exec --workspace-folder . python -m unittest
devcontainer exec --workspace-folder . python tools/run_installed_tests.py
```

The container compiles the C extension on creation, so the tests are runnable immediately.
Since `list_reserve` is a C extension, re-run `pip install .` after editing
`src/list_reserve.c`.
The container installs the package in editable mode on creation, so the tests are
runnable immediately. Since `list_reserve` includes a C extension, re-run
`pip install -e .` after editing `src/list_reserve.c`.

## License

Expand Down
9 changes: 9 additions & 0 deletions list_reserve/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from ._list_reserve import allocated_bytes, capacity, reserve, shrink_to_fit, stats

__all__ = [
"allocated_bytes",
"capacity",
"reserve",
"shrink_to_fit",
"stats",
]
11 changes: 3 additions & 8 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -84,14 +84,9 @@ build = "cp310-* cp311-* cp312-* cp313-* cp314-*"
# internals.
skip = "pp* *t-*"

# cibuildwheel runs this against each installed wheel from a temp dir, so it
# tests the installed .so. `-s {project}` makes {project} the discovery
# top-level dir, so tests import as `tests.*` and `from tests._support import
# ...` resolves; `-s {project}/tests` would drop the `tests.` prefix and break
# that import. Quote the glob with double quotes (honored by both POSIX sh and
# Windows cmd; single quotes reach unittest literally on Windows and match
# nothing) so unittest, not the shell, expands it.
test-command = "python -m unittest discover -s {project} -p \"test_*.py\""
# Run tests from outside the source tree so `import list_reserve` resolves to the
# installed wheel instead of the local package directory.
test-command = "python \"{project}/tools/run_installed_tests.py\""

# Windows ARM64 is experimental and its tests cannot run on the build host, so
# skip them (the wheel is still built and shipped).
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@
# [tool.setuptools.ext-modules] table cannot yet express stably.
setup(
ext_modules=[
Extension("list_reserve", ["src/list_reserve.c"]),
Extension("list_reserve._list_reserve", ["src/list_reserve.c"]),
],
)
4 changes: 2 additions & 2 deletions src/list_reserve.c
Original file line number Diff line number Diff line change
Expand Up @@ -183,11 +183,11 @@ static PyMethodDef methods[] = {
{NULL}};

// module definition struct
static struct PyModuleDef module = {PyModuleDef_HEAD_INIT, "list_reserve",
static struct PyModuleDef module = {PyModuleDef_HEAD_INIT, "list_reserve._list_reserve",
"list memory allocation library", -1, methods};

// Initializes module
PyMODINIT_FUNC
PyInit_list_reserve(void) {
PyInit__list_reserve(void) {
return PyModule_Create(&module);
}
38 changes: 38 additions & 0 deletions tools/run_installed_tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
from __future__ import annotations

import shutil
import sys
import tempfile
import unittest
from pathlib import Path


def main() -> int:
project_root = Path(__file__).resolve().parents[1]
source_tests = project_root / "tests"

with tempfile.TemporaryDirectory(prefix="list-reserve-tests-") as tmp:
tmp_path = Path(tmp)
copied_tests = tmp_path / "tests"
shutil.copytree(
source_tests,
copied_tests,
ignore=shutil.ignore_patterns("__pycache__"),
)

sys.path = [
entry for entry in sys.path if Path(entry or ".").resolve() != project_root
]
sys.path.insert(0, str(tmp_path))

suite = unittest.defaultTestLoader.discover(
str(copied_tests),
pattern="test_*.py",
top_level_dir=str(tmp_path),
)
result = unittest.TextTestRunner(verbosity=2).run(suite)
return int(not result.wasSuccessful())


if __name__ == "__main__":
raise SystemExit(main())
Loading