From c5ec11feeddc10cb6bbdbf41476c46cce805d523 Mon Sep 17 00:00:00 2001 From: "Jonathan B. Coe" Date: Thu, 1 Jan 2026 20:48:56 +0000 Subject: [PATCH 01/29] Use ruff rather than black and isort for linting --- nle/scripts/collect_env.py | 5 +---- nle/tests/test_dataset.py | 23 +++++++++++++---------- nle/tests/test_db.py | 3 +-- nle/tests/test_nethack.py | 3 +-- nle/tests/test_populate_db.py | 6 ++++-- 5 files changed, 20 insertions(+), 20 deletions(-) diff --git a/nle/scripts/collect_env.py b/nle/scripts/collect_env.py index 4c6c3bccd..195047229 100644 --- a/nle/scripts/collect_env.py +++ b/nle/scripts/collect_env.py @@ -6,10 +6,7 @@ # Original version from: # https://github.com/pytorch/pytorch/blob/fa5bc9fa/torch/utils/collect_env.py -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function -from __future__ import unicode_literals +from __future__ import absolute_import, division, print_function, unicode_literals import locale import os diff --git a/nle/tests/test_dataset.py b/nle/tests/test_dataset.py index fbd183458..82f85cd40 100644 --- a/nle/tests/test_dataset.py +++ b/nle/tests/test_dataset.py @@ -4,16 +4,19 @@ import numpy as np import pytest -from test_converter import COLSROWS -from test_converter import FINALFRAME -from test_converter import FINALFRAMECOLORS -from test_converter import TIMESTAMPS -from test_converter import getfilename -from test_db import conn # noqa: F401 -from test_db import mockdata # noqa: F401 - -from nle.dataset import dataset -from nle.dataset import db +from test_converter import ( + COLSROWS, + FINALFRAME, + FINALFRAMECOLORS, + TIMESTAMPS, + getfilename, +) +from test_db import ( + conn, # noqa: F401 + mockdata, # noqa: F401 +) + +from nle.dataset import dataset, db class TestDataset: diff --git a/nle/tests/test_db.py b/nle/tests/test_db.py index 770cada33..3da9baa90 100644 --- a/nle/tests/test_db.py +++ b/nle/tests/test_db.py @@ -4,8 +4,7 @@ import test_converter import nle.env.tasks -from nle.dataset import db -from nle.dataset import populate_db +from nle.dataset import db, populate_db TTYRECS = [ ("aaa", test_converter.TTYREC_2020), diff --git a/nle/tests/test_nethack.py b/nle/tests/test_nethack.py index aa80b0618..0940ee6bd 100644 --- a/nle/tests/test_nethack.py +++ b/nle/tests/test_nethack.py @@ -7,8 +7,7 @@ import numpy as np import pytest -from nle import _pynethack -from nle import nethack +from nle import _pynethack, nethack # MORE + compass directions + long compass directions. ACTIONS = [ diff --git a/nle/tests/test_populate_db.py b/nle/tests/test_populate_db.py index 3ee5438fe..7d97aaadd 100644 --- a/nle/tests/test_populate_db.py +++ b/nle/tests/test_populate_db.py @@ -2,8 +2,10 @@ import pytest # NOQA: F401 from test_converter import getfilename -from test_db import conn # NOQA: F401 -from test_db import mockdata # NOQA: F401 +from test_db import ( + conn, # NOQA: F401 + mockdata, # NOQA: F401 +) from nle import nethack From 5035aea7ccde8c29c20519f0e3d064af04ce6b07 Mon Sep 17 00:00:00 2001 From: "Jonathan B. Coe" Date: Fri, 30 Jan 2026 21:32:58 +0000 Subject: [PATCH 02/29] Use force_single_line for import linting with ruff --- nle/scripts/collect_env.py | 5 ++++- nle/tests/test_dataset.py | 23 ++++++++++------------- nle/tests/test_db.py | 3 ++- nle/tests/test_nethack.py | 3 ++- nle/tests/test_populate_db.py | 6 ++---- 5 files changed, 20 insertions(+), 20 deletions(-) diff --git a/nle/scripts/collect_env.py b/nle/scripts/collect_env.py index 195047229..4c6c3bccd 100644 --- a/nle/scripts/collect_env.py +++ b/nle/scripts/collect_env.py @@ -6,7 +6,10 @@ # Original version from: # https://github.com/pytorch/pytorch/blob/fa5bc9fa/torch/utils/collect_env.py -from __future__ import absolute_import, division, print_function, unicode_literals +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals import locale import os diff --git a/nle/tests/test_dataset.py b/nle/tests/test_dataset.py index 82f85cd40..fbd183458 100644 --- a/nle/tests/test_dataset.py +++ b/nle/tests/test_dataset.py @@ -4,19 +4,16 @@ import numpy as np import pytest -from test_converter import ( - COLSROWS, - FINALFRAME, - FINALFRAMECOLORS, - TIMESTAMPS, - getfilename, -) -from test_db import ( - conn, # noqa: F401 - mockdata, # noqa: F401 -) - -from nle.dataset import dataset, db +from test_converter import COLSROWS +from test_converter import FINALFRAME +from test_converter import FINALFRAMECOLORS +from test_converter import TIMESTAMPS +from test_converter import getfilename +from test_db import conn # noqa: F401 +from test_db import mockdata # noqa: F401 + +from nle.dataset import dataset +from nle.dataset import db class TestDataset: diff --git a/nle/tests/test_db.py b/nle/tests/test_db.py index 3da9baa90..770cada33 100644 --- a/nle/tests/test_db.py +++ b/nle/tests/test_db.py @@ -4,7 +4,8 @@ import test_converter import nle.env.tasks -from nle.dataset import db, populate_db +from nle.dataset import db +from nle.dataset import populate_db TTYRECS = [ ("aaa", test_converter.TTYREC_2020), diff --git a/nle/tests/test_nethack.py b/nle/tests/test_nethack.py index 0940ee6bd..aa80b0618 100644 --- a/nle/tests/test_nethack.py +++ b/nle/tests/test_nethack.py @@ -7,7 +7,8 @@ import numpy as np import pytest -from nle import _pynethack, nethack +from nle import _pynethack +from nle import nethack # MORE + compass directions + long compass directions. ACTIONS = [ diff --git a/nle/tests/test_populate_db.py b/nle/tests/test_populate_db.py index 7d97aaadd..3ee5438fe 100644 --- a/nle/tests/test_populate_db.py +++ b/nle/tests/test_populate_db.py @@ -2,10 +2,8 @@ import pytest # NOQA: F401 from test_converter import getfilename -from test_db import ( - conn, # NOQA: F401 - mockdata, # NOQA: F401 -) +from test_db import conn # NOQA: F401 +from test_db import mockdata # NOQA: F401 from nle import nethack From 1222668726ebba89bdb4d1f767cf397abde950e7 Mon Sep 17 00:00:00 2001 From: "Jonathan B. Coe" Date: Fri, 30 Jan 2026 22:37:34 +0000 Subject: [PATCH 03/29] Use scikit-build and drop setup.py --- nle/__init__.py | 2 +- pyproject.toml | 1 + uv.lock | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/nle/__init__.py b/nle/__init__.py index db6b3d526..58a30fa79 100644 --- a/nle/__init__.py +++ b/nle/__init__.py @@ -6,4 +6,4 @@ # This is needed to register envs import nle.env -from .version import __version__ +# from .version import __version__ diff --git a/pyproject.toml b/pyproject.toml index d1ff3031e..06129960d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -28,6 +28,7 @@ file = "LICENSE" [project.urls] Homepage = "https://github.com/NetHack-LE/nle" + [build-system] # Lock build-deps as uv does not yet support locking of build deps: astral-sh/uv#5190 requires = ["scikit-build-core~=0.10", "pybind11~=2.2", "setuptools-scm~=9.2.2"] diff --git a/uv.lock b/uv.lock index 170285647..f63ee6922 100644 --- a/uv.lock +++ b/uv.lock @@ -444,6 +444,7 @@ wheels = [ [[package]] name = "nle" +version = "1.2.0" source = { editable = "." } dependencies = [ { name = "gymnasium" }, From dd784c31f05375031e8eaa2151b448fcb89bc6c8 Mon Sep 17 00:00:00 2001 From: "Jonathan B. Coe" Date: Sat, 31 Jan 2026 09:56:17 +0000 Subject: [PATCH 04/29] Derive version from Git tags --- uv.lock | 1 - 1 file changed, 1 deletion(-) diff --git a/uv.lock b/uv.lock index f63ee6922..170285647 100644 --- a/uv.lock +++ b/uv.lock @@ -444,7 +444,6 @@ wheels = [ [[package]] name = "nle" -version = "1.2.0" source = { editable = "." } dependencies = [ { name = "gymnasium" }, From 38f5d310a39d018d62eb39e8a9cc7e6cce327ec8 Mon Sep 17 00:00:00 2001 From: "Jonathan B. Coe" Date: Tue, 3 Feb 2026 11:07:45 +0000 Subject: [PATCH 05/29] De-pip test-and-deploy script --- .github/workflows/test_and_deploy.yml | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/.github/workflows/test_and_deploy.yml b/.github/workflows/test_and_deploy.yml index 60c492a25..dcfd05b3f 100644 --- a/.github/workflows/test_and_deploy.yml +++ b/.github/workflows/test_and_deploy.yml @@ -57,12 +57,12 @@ jobs: run: | SDISTNAME=$(ls dist/) MODE="[all]" - pip install "dist/$SDISTNAME$MODE" + uv pip install "dist/$SDISTNAME$MODE" - name: Run tests outside repo dir run: | REPONAME=$(basename $PWD) pushd .. - python -m pytest --import-mode=append -svx $REPONAME/nle/tests + uv run pytest --import-mode=append -svx $REPONAME/nle/tests popd test_sdist_3_13: name: Test sdist on MacOS w/ Py3.13 @@ -83,12 +83,12 @@ jobs: run: | SDISTNAME=$(ls dist/) MODE="[all]" - pip install "dist/$SDISTNAME$MODE" + uv pip install "dist/$SDISTNAME$MODE" - name: Run tests outside repo dir run: | REPONAME=$(basename $PWD) pushd .. - python -m pytest --import-mode=append -svx $REPONAME/nle/tests + uv run pytest --import-mode=append -svx $REPONAME/nle/tests popd - name: Save sdist if: ${{ always() }} @@ -134,8 +134,6 @@ jobs: uses: actions/setup-python@v5 with: python-version: 3.13 - - name: Ensure latest pip, wheel & setuptools - run: python -m pip install -q --upgrade pip wheel tools - uses: actions/checkout@v4 - name: Get wheels artifacts uses: actions/download-artifact@v4 @@ -146,12 +144,12 @@ jobs: run: | WHEELNAME=$(ls dist/*313*manylinux*x86_64*.whl) MODE="[all]" - pip install "$WHEELNAME$MODE" + uv pip install "$WHEELNAME$MODE" - name: Run tests outside repo dir run: | REPONAME=$(basename $PWD) pushd .. - python -m pytest --import-mode=append -svx $REPONAME/nle/tests + uv run pytest --import-mode=append -svx $REPONAME/nle/tests popd # Use prereleases to test publish the artefacts to testpypi From aee65061d3004498024a797330a41224f815859e Mon Sep 17 00:00:00 2001 From: "Jonathan B. Coe" Date: Tue, 3 Feb 2026 12:53:21 +0000 Subject: [PATCH 06/29] Use uv for test-and-deploy script --- .github/workflows/test_and_deploy.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/test_and_deploy.yml b/.github/workflows/test_and_deploy.yml index dcfd05b3f..58d3f8684 100644 --- a/.github/workflows/test_and_deploy.yml +++ b/.github/workflows/test_and_deploy.yml @@ -42,9 +42,9 @@ jobs: name: Test sdist on MacOS w/ Py3.10 needs: test_repo runs-on: macos-latest - steps: - - name: Setup Python 3.10 env - uses: actions/setup-python@v5 + steps: + - name: Setup Python 3.10 env using uv + uses: astral-sh/setup-uv@v5 with: python-version: '3.10' - name: Ensure latest pip, wheel & setuptools @@ -69,8 +69,8 @@ jobs: needs: test_repo runs-on: macos-latest steps: - - name: Setup Python 3.13 env - uses: actions/setup-python@v5 + - name: Setup Python 3.13 env using uv + uses: astral-sh/setup-uv@v5 with: python-version: 3.13 - name: Ensure latest pip, wheel & setuptools @@ -130,10 +130,10 @@ jobs: needs: build_wheels runs-on: ubuntu-latest steps: - - name: Setup Python 3.13 env - uses: actions/setup-python@v5 + - name: Setup Python 3.13 env using uv + uses: astral-sh/setup-uv@v5 with: - python-version: 3.13 + python-version: '3.13' - uses: actions/checkout@v4 - name: Get wheels artifacts uses: actions/download-artifact@v4 From 509c65b822c22b320236580e6faaa3f96457876d Mon Sep 17 00:00:00 2001 From: "Jonathan B. Coe" Date: Tue, 3 Feb 2026 14:19:03 +0000 Subject: [PATCH 07/29] Create venv with uv before uv pip install --- .github/workflows/test_and_deploy.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/test_and_deploy.yml b/.github/workflows/test_and_deploy.yml index 58d3f8684..ebcf998bc 100644 --- a/.github/workflows/test_and_deploy.yml +++ b/.github/workflows/test_and_deploy.yml @@ -57,6 +57,7 @@ jobs: run: | SDISTNAME=$(ls dist/) MODE="[all]" + uv venv uv pip install "dist/$SDISTNAME$MODE" - name: Run tests outside repo dir run: | @@ -83,6 +84,7 @@ jobs: run: | SDISTNAME=$(ls dist/) MODE="[all]" + uv venv uv pip install "dist/$SDISTNAME$MODE" - name: Run tests outside repo dir run: | From 3c29f19b5c0a68f9eb12d04a6ce47e8105501981 Mon Sep 17 00:00:00 2001 From: "Jonathan B. Coe" Date: Tue, 3 Feb 2026 14:58:14 +0000 Subject: [PATCH 08/29] Create venv with uv before using a wheel --- .github/workflows/test_and_deploy.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/test_and_deploy.yml b/.github/workflows/test_and_deploy.yml index ebcf998bc..76bf2a086 100644 --- a/.github/workflows/test_and_deploy.yml +++ b/.github/workflows/test_and_deploy.yml @@ -146,6 +146,7 @@ jobs: run: | WHEELNAME=$(ls dist/*313*manylinux*x86_64*.whl) MODE="[all]" + uv venv uv pip install "$WHEELNAME$MODE" - name: Run tests outside repo dir run: | From 9b763a0e1456188b580da64631cff1270f3324ab Mon Sep 17 00:00:00 2001 From: "Jonathan B. Coe" Date: Tue, 3 Feb 2026 15:22:34 +0000 Subject: [PATCH 09/29] Remove commented use of __version__ --- nle/__init__.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/nle/__init__.py b/nle/__init__.py index 58a30fa79..205d07cb5 100644 --- a/nle/__init__.py +++ b/nle/__init__.py @@ -5,5 +5,3 @@ # This is needed to register envs import nle.env - -# from .version import __version__ From 4f775eff742d58c8e998ef6146d0c6d00e0410d2 Mon Sep 17 00:00:00 2001 From: "Jonathan B. Coe" Date: Tue, 3 Feb 2026 16:41:22 +0000 Subject: [PATCH 10/29] Use uv minimally for CI --- .github/workflows/lint_python.yml | 1 - .github/workflows/test_package.yml | 12 ++++++------ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/.github/workflows/lint_python.yml b/.github/workflows/lint_python.yml index 1470294bb..48a2e7e99 100644 --- a/.github/workflows/lint_python.yml +++ b/.github/workflows/lint_python.yml @@ -17,6 +17,5 @@ jobs: python-version: "3.13" - uses: actions/checkout@v4 - - run: uv sync - run: uv run ruff format --check --diff . - run: uv run ruff check diff --git a/.github/workflows/test_package.yml b/.github/workflows/test_package.yml index 0338ddc48..13d39bf98 100644 --- a/.github/workflows/test_package.yml +++ b/.github/workflows/test_package.yml @@ -15,15 +15,15 @@ jobs: python-version: ['3.10', '3.11', '3.12'] fail-fast: false steps: - - name: Setup Python ${{ matrix.python-version }} env - uses: actions/setup-python@v5 + - name: Setup Python env using uv + uses: astral-sh/setup-uv@v5 with: python-version: ${{ matrix.python-version }} - - name: Ensure latest pip, wheel & setuptools - run: "python -m pip install -q --upgrade pip wheel setuptools" + - name: Create an empty venv + run: "uv venv" - name: Install nle via pip - run: "pip install nle" + run: "uv pip install nle" - name: Check nethack is installed run: | - python -c 'import nle; import gymnasium as gym; e = gym.make("NetHack-v0"); e.reset(); e.step(0)' + uv run python -c 'import nle; import gymnasium as gym; e = gym.make("NetHack-v0"); e.reset(); e.step(0)' \ No newline at end of file From 4f4b9f171127344770b1d6246b4c7f453d406687 Mon Sep 17 00:00:00 2001 From: "Jonathan B. Coe" Date: Wed, 4 Feb 2026 22:46:56 +0000 Subject: [PATCH 11/29] Generate nle/version.py so that __version__ is still defined --- nle/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/nle/__init__.py b/nle/__init__.py index 205d07cb5..db6b3d526 100644 --- a/nle/__init__.py +++ b/nle/__init__.py @@ -5,3 +5,5 @@ # This is needed to register envs import nle.env + +from .version import __version__ From d6ba28dd4e72a6ca511e16e3056608a962707cd3 Mon Sep 17 00:00:00 2001 From: "Jonathan B. Coe" Date: Sun, 8 Feb 2026 04:17:10 +0000 Subject: [PATCH 12/29] generate typestubs --- CMakeLists.txt | 34 ++++++++++++++++++++++++++++++++++ nle/typed.py | 0 2 files changed, 34 insertions(+) create mode 100644 nle/typed.py diff --git a/CMakeLists.txt b/CMakeLists.txt index 24a3073e0..4b419e417 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -70,6 +70,8 @@ FetchContent_Declare( GIT_HASH "259fc4103bad6bb484d5ff426ace56ac557107a4" EXCLUDE_FROM_ALL) FetchContent_MakeAvailable(deboost_context) +find_program(UV_EXECUTABLE uv REQUIRED) + add_compile_definitions( GCC_WARN NOCLIPPING @@ -204,6 +206,32 @@ set_target_properties(_pyconverter PROPERTIES CXX_STANDARD 14) target_include_directories( _pyconverter PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/third_party/converter) +set(STUB_DIR ${CMAKE_CURRENT_BINARY_DIR}/stubs) +set_directory_properties(PROPERTIES ADDITIONAL_CLEAN_FILES "${STUB_DIR}") +add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/stubs/nle/_pyconverter.pyi + COMMAND ${UV_EXECUTABLE} run --with pybind11-stubgen --with numpy python -m + pybind11_stubgen _pyconverter --output-dir ${STUB_DIR} + WORKING_DIRECTORY $ + DEPENDS _pyconverter + COMMENT "Generating type stubs with uv (deps: pybind11-stubgen)..." + VERBATIM) + +add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/stubs/nle/_pynethack/__init__.pyi + COMMAND + ${UV_EXECUTABLE} run --with pybind11-stubgen python -m pybind11_stubgen + _pynethack --output-dir ${STUB_DIR} --ignore-unresolved-names game_end_types + WORKING_DIRECTORY $ + DEPENDS _pynethack + COMMENT "Generating type stubs with uv (deps: numpy, pybind11-stubgen)..." + VERBATIM) + +add_custom_target( + my_module_stubs ALL + DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/stubs/nle/_pynethack/__init__.pyi + ${CMAKE_CURRENT_BINARY_DIR}/stubs/nle/_pyconverter.pyi) + # Only install if we are building as part of a Python project. if(DEFINED SKBUILD_PROJECT_VERSION) install( @@ -211,4 +239,10 @@ if(DEFINED SKBUILD_PROJECT_VERSION) RUNTIME DESTINATION ${PYTHON_PACKAGE_NAME} LIBRARY DESTINATION ${PYTHON_PACKAGE_NAME} ARCHIVE DESTINATION ${PYTHON_PACKAGE_NAME}) + + install( + DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/stubs/" + DESTINATION ${PYTHON_PACKAGE_NAME} + FILES_MATCHING + PATTERN "*.pyi") endif() diff --git a/nle/typed.py b/nle/typed.py new file mode 100644 index 000000000..e69de29bb From 6e8891e716c2b2ad54bddde9e653a8327cce083d Mon Sep 17 00:00:00 2001 From: "Jonathan B. Coe" Date: Wed, 11 Feb 2026 10:38:05 +0000 Subject: [PATCH 13/29] Use Python not uv to install typestubs. Update build-requirements to include numpy and pybind11_stubgen --- CMakeLists.txt | 17 ++++++++++------- pyproject.toml | 8 +++++++- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4b419e417..700b31ea3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -206,25 +206,28 @@ set_target_properties(_pyconverter PROPERTIES CXX_STANDARD 14) target_include_directories( _pyconverter PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/third_party/converter) +find_package( + Python + COMPONENTS Interpreter + REQUIRED) set(STUB_DIR ${CMAKE_CURRENT_BINARY_DIR}/stubs) set_directory_properties(PROPERTIES ADDITIONAL_CLEAN_FILES "${STUB_DIR}") add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/stubs/nle/_pyconverter.pyi - COMMAND ${UV_EXECUTABLE} run --with pybind11-stubgen --with numpy python -m - pybind11_stubgen _pyconverter --output-dir ${STUB_DIR} + COMMAND ${Python_INTERPRETER} -m pybind11_stubgen _pyconverter --output-dir + ${STUB_DIR} WORKING_DIRECTORY $ DEPENDS _pyconverter - COMMENT "Generating type stubs with uv (deps: pybind11-stubgen)..." + COMMENT "Generating type stubs with uv ..." VERBATIM) add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/stubs/nle/_pynethack/__init__.pyi - COMMAND - ${UV_EXECUTABLE} run --with pybind11-stubgen python -m pybind11_stubgen - _pynethack --output-dir ${STUB_DIR} --ignore-unresolved-names game_end_types + COMMAND ${Python_INTERPRETER} -m pybind11_stubgen _pynethack --output-dir + ${STUB_DIR} --ignore-unresolved-names game_end_types WORKING_DIRECTORY $ DEPENDS _pynethack - COMMENT "Generating type stubs with uv (deps: numpy, pybind11-stubgen)..." + COMMENT "Generating type stubs with uv ..." VERBATIM) add_custom_target( diff --git a/pyproject.toml b/pyproject.toml index 06129960d..c7d65b3d4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -31,7 +31,13 @@ Homepage = "https://github.com/NetHack-LE/nle" [build-system] # Lock build-deps as uv does not yet support locking of build deps: astral-sh/uv#5190 -requires = ["scikit-build-core~=0.10", "pybind11~=2.2", "setuptools-scm~=9.2.2"] +requires = [ + "scikit-build-core~=0.10", + "numpy", + "pybind11-stubgen", + "pybind11~=2.2", + "setuptools-scm~=9.2.2" +] build-backend = "scikit_build_core.build" [tool.scikit-build] From ab150966b60d6d0d50f32fcc55378f253c04b8d8 Mon Sep 17 00:00:00 2001 From: "Jonathan B. Coe" Date: Wed, 11 Feb 2026 10:42:23 +0000 Subject: [PATCH 14/29] Get CI scripts from main as they are unassociated with typestub generation --- .github/workflows/cmake.yml | 38 --------------------------- .github/workflows/lint_python.yml | 1 + .github/workflows/test_and_deploy.yml | 33 +++++++++++------------ .github/workflows/test_package.yml | 12 ++++----- 4 files changed, 23 insertions(+), 61 deletions(-) delete mode 100644 .github/workflows/cmake.yml diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml deleted file mode 100644 index 5d7efc700..000000000 --- a/.github/workflows/cmake.yml +++ /dev/null @@ -1,38 +0,0 @@ ---- -name: CMake Check -on: - push: - branches: [main] - paths: - - '.github/workflows/cmake.yml' - - 'CMakeLists.txt' - - 'src/**/*.c' - - 'include/nle/**/*.h' - - 'win/rl/**/*.cc' - pull_request: - paths: - - '.github/workflows/cmake.yml' - - 'CMakeLists.txt' - - 'src/**/*.c' - - 'include/nle/**/*.h' - - 'win/rl/**/*.cc' -jobs: - check_cc: - name: cmake-check - runs-on: ubuntu-latest - steps: - - name: Install non-python build dependencies - run: | - sudo apt-get update && sudo apt-get install -yq \ - apt-transport-https \ - bison \ - build-essential \ - flex \ - libbz2-dev \ - ninja-build \ - software-properties-common - - uses: actions/checkout@v4 - - name: Check CMake configure - run: cmake -B build -G Ninja - - name: CMake build - run: cmake --build build diff --git a/.github/workflows/lint_python.yml b/.github/workflows/lint_python.yml index 48a2e7e99..1470294bb 100644 --- a/.github/workflows/lint_python.yml +++ b/.github/workflows/lint_python.yml @@ -17,5 +17,6 @@ jobs: python-version: "3.13" - uses: actions/checkout@v4 + - run: uv sync - run: uv run ruff format --check --diff . - run: uv run ruff check diff --git a/.github/workflows/test_and_deploy.yml b/.github/workflows/test_and_deploy.yml index 76bf2a086..60c492a25 100644 --- a/.github/workflows/test_and_deploy.yml +++ b/.github/workflows/test_and_deploy.yml @@ -42,9 +42,9 @@ jobs: name: Test sdist on MacOS w/ Py3.10 needs: test_repo runs-on: macos-latest - steps: - - name: Setup Python 3.10 env using uv - uses: astral-sh/setup-uv@v5 + steps: + - name: Setup Python 3.10 env + uses: actions/setup-python@v5 with: python-version: '3.10' - name: Ensure latest pip, wheel & setuptools @@ -57,21 +57,20 @@ jobs: run: | SDISTNAME=$(ls dist/) MODE="[all]" - uv venv - uv pip install "dist/$SDISTNAME$MODE" + pip install "dist/$SDISTNAME$MODE" - name: Run tests outside repo dir run: | REPONAME=$(basename $PWD) pushd .. - uv run pytest --import-mode=append -svx $REPONAME/nle/tests + python -m pytest --import-mode=append -svx $REPONAME/nle/tests popd test_sdist_3_13: name: Test sdist on MacOS w/ Py3.13 needs: test_repo runs-on: macos-latest steps: - - name: Setup Python 3.13 env using uv - uses: astral-sh/setup-uv@v5 + - name: Setup Python 3.13 env + uses: actions/setup-python@v5 with: python-version: 3.13 - name: Ensure latest pip, wheel & setuptools @@ -84,13 +83,12 @@ jobs: run: | SDISTNAME=$(ls dist/) MODE="[all]" - uv venv - uv pip install "dist/$SDISTNAME$MODE" + pip install "dist/$SDISTNAME$MODE" - name: Run tests outside repo dir run: | REPONAME=$(basename $PWD) pushd .. - uv run pytest --import-mode=append -svx $REPONAME/nle/tests + python -m pytest --import-mode=append -svx $REPONAME/nle/tests popd - name: Save sdist if: ${{ always() }} @@ -132,10 +130,12 @@ jobs: needs: build_wheels runs-on: ubuntu-latest steps: - - name: Setup Python 3.13 env using uv - uses: astral-sh/setup-uv@v5 + - name: Setup Python 3.13 env + uses: actions/setup-python@v5 with: - python-version: '3.13' + python-version: 3.13 + - name: Ensure latest pip, wheel & setuptools + run: python -m pip install -q --upgrade pip wheel tools - uses: actions/checkout@v4 - name: Get wheels artifacts uses: actions/download-artifact@v4 @@ -146,13 +146,12 @@ jobs: run: | WHEELNAME=$(ls dist/*313*manylinux*x86_64*.whl) MODE="[all]" - uv venv - uv pip install "$WHEELNAME$MODE" + pip install "$WHEELNAME$MODE" - name: Run tests outside repo dir run: | REPONAME=$(basename $PWD) pushd .. - uv run pytest --import-mode=append -svx $REPONAME/nle/tests + python -m pytest --import-mode=append -svx $REPONAME/nle/tests popd # Use prereleases to test publish the artefacts to testpypi diff --git a/.github/workflows/test_package.yml b/.github/workflows/test_package.yml index 13d39bf98..0338ddc48 100644 --- a/.github/workflows/test_package.yml +++ b/.github/workflows/test_package.yml @@ -15,15 +15,15 @@ jobs: python-version: ['3.10', '3.11', '3.12'] fail-fast: false steps: - - name: Setup Python env using uv - uses: astral-sh/setup-uv@v5 + - name: Setup Python ${{ matrix.python-version }} env + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - - name: Create an empty venv - run: "uv venv" + - name: Ensure latest pip, wheel & setuptools + run: "python -m pip install -q --upgrade pip wheel setuptools" - name: Install nle via pip - run: "uv pip install nle" + run: "pip install nle" - name: Check nethack is installed run: | - uv run python -c 'import nle; import gymnasium as gym; e = gym.make("NetHack-v0"); e.reset(); e.step(0)' + python -c 'import nle; import gymnasium as gym; e = gym.make("NetHack-v0"); e.reset(); e.step(0)' \ No newline at end of file From ecde6bb469b071c4c9d92155a9fe699f5df7257a Mon Sep 17 00:00:00 2001 From: "Jonathan B. Coe" Date: Sun, 22 Feb 2026 00:44:41 +0000 Subject: [PATCH 15/29] No need for uv from within CMake --- CMakeLists.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 700b31ea3..b57dfefc1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -70,8 +70,6 @@ FetchContent_Declare( GIT_HASH "259fc4103bad6bb484d5ff426ace56ac557107a4" EXCLUDE_FROM_ALL) FetchContent_MakeAvailable(deboost_context) -find_program(UV_EXECUTABLE uv REQUIRED) - add_compile_definitions( GCC_WARN NOCLIPPING From c5c863aebba60ea70777b91c63ed0f7114f963cd Mon Sep 17 00:00:00 2001 From: "Jonathan B. Coe" Date: Fri, 6 Mar 2026 13:46:32 +0000 Subject: [PATCH 16/29] restore file --- .github/workflows/cmake.yml | 38 +++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 .github/workflows/cmake.yml diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml new file mode 100644 index 000000000..5d7efc700 --- /dev/null +++ b/.github/workflows/cmake.yml @@ -0,0 +1,38 @@ +--- +name: CMake Check +on: + push: + branches: [main] + paths: + - '.github/workflows/cmake.yml' + - 'CMakeLists.txt' + - 'src/**/*.c' + - 'include/nle/**/*.h' + - 'win/rl/**/*.cc' + pull_request: + paths: + - '.github/workflows/cmake.yml' + - 'CMakeLists.txt' + - 'src/**/*.c' + - 'include/nle/**/*.h' + - 'win/rl/**/*.cc' +jobs: + check_cc: + name: cmake-check + runs-on: ubuntu-latest + steps: + - name: Install non-python build dependencies + run: | + sudo apt-get update && sudo apt-get install -yq \ + apt-transport-https \ + bison \ + build-essential \ + flex \ + libbz2-dev \ + ninja-build \ + software-properties-common + - uses: actions/checkout@v4 + - name: Check CMake configure + run: cmake -B build -G Ninja + - name: CMake build + run: cmake --build build From 3dba5cd2bc7222a8ed82c473133489571c290014 Mon Sep 17 00:00:00 2001 From: "Jonathan B. Coe" Date: Fri, 6 Mar 2026 13:51:50 +0000 Subject: [PATCH 17/29] Fix comment --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b57dfefc1..15d69109e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -216,7 +216,7 @@ add_custom_command( ${STUB_DIR} WORKING_DIRECTORY $ DEPENDS _pyconverter - COMMENT "Generating type stubs with uv ..." + COMMENT "Generating type stubs ..." VERBATIM) add_custom_command( @@ -225,7 +225,7 @@ add_custom_command( ${STUB_DIR} --ignore-unresolved-names game_end_types WORKING_DIRECTORY $ DEPENDS _pynethack - COMMENT "Generating type stubs with uv ..." + COMMENT "Generating type stubs ..." VERBATIM) add_custom_target( From 0520e3fee7bede51e39f23805323344cd540db57 Mon Sep 17 00:00:00 2001 From: "Jonathan B. Coe" Date: Fri, 6 Mar 2026 14:37:06 +0000 Subject: [PATCH 18/29] Use an isolated uv venv with build deps installed for cmake CI build --- .github/workflows/cmake.yml | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 5d7efc700..8b7133b74 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -31,8 +31,21 @@ jobs: libbz2-dev \ ninja-build \ software-properties-common + - name: Install Python 3.12 with the latest version of uv. + uses: astral-sh/setup-uv@v7 + with: + python-version: '3.12' - uses: actions/checkout@v4 + - name: Create venv and install build dependencies + run: | + uv venv --isolated + source .venv/bin/activate + uv pip install scikit-build-core~=0.10 numpy pybind11-stubgen pybind11~=2.2 setuptools-scm~=9.2.2 - name: Check CMake configure - run: cmake -B build -G Ninja + run: | + source .venv/bin/activate + cmake -B build -G Ninja - name: CMake build - run: cmake --build build + run: | + source .venv/bin/activate + cmake --build build From 6f181ccd35808f2bd97459c24a6bc01f7192c3c0 Mon Sep 17 00:00:00 2001 From: "Jonathan B. Coe" Date: Fri, 6 Mar 2026 14:44:26 +0000 Subject: [PATCH 19/29] FInd Python earlier --- CMakeLists.txt | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 15d69109e..54229ca85 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -54,6 +54,13 @@ message(STATUS "HACKDIR set to: ${HACKDIR}") set(VARDIR ${HACKDIR}) set(INSTDIR ${HACKDIR}) +# A Python interepreter is needed to generate typestubs. +message(STATUS "DEBUG: Python_EXECUTABLE is set to: ${Python_EXECUTABLE}") +find_package( + Python + COMPONENTS Interpreter + REQUIRED) + # pybind11 via FetchContent include(FetchContent) FetchContent_Declare( @@ -204,10 +211,6 @@ set_target_properties(_pyconverter PROPERTIES CXX_STANDARD 14) target_include_directories( _pyconverter PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/third_party/converter) -find_package( - Python - COMPONENTS Interpreter - REQUIRED) set(STUB_DIR ${CMAKE_CURRENT_BINARY_DIR}/stubs) set_directory_properties(PROPERTIES ADDITIONAL_CLEAN_FILES "${STUB_DIR}") add_custom_command( From 8998c1d8f232964d7d11033cc00991fee72d1e6f Mon Sep 17 00:00:00 2001 From: "Jonathan B. Coe" Date: Wed, 18 Mar 2026 22:35:46 +0000 Subject: [PATCH 20/29] Use FindPython from pybind11 --- CMakeLists.txt | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fad2c219e..119d7b8d6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -69,13 +69,8 @@ message(STATUS "HACKDIR set to: ${HACKDIR}") set(VARDIR ${HACKDIR}) set(INSTDIR ${HACKDIR}) -# A Python interepreter is needed to generate typestubs. -message(STATUS "DEBUG: Python_EXECUTABLE is set to: ${Python_EXECUTABLE}") -find_package( - Python - COMPONENTS Interpreter - REQUIRED) - +# Use FindPython in PyBind11 to find Python. +set(PYBIND11_FINDPYTHON NEW) # pybind11 via FetchContent include(FetchContent) FetchContent_Declare( @@ -84,6 +79,7 @@ FetchContent_Declare( GIT_TAG v3.0.1 EXCLUDE_FROM_ALL) FetchContent_MakeAvailable(pybind11) +message(STATUS "Python_EXECUTABLE is set to: ${Python_EXECUTABLE}") # de-boost-ified version of boost.context via FetchContent FetchContent_Declare( @@ -233,7 +229,7 @@ set(STUB_DIR ${CMAKE_CURRENT_BINARY_DIR}/stubs) set_directory_properties(PROPERTIES ADDITIONAL_CLEAN_FILES "${STUB_DIR}") add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/stubs/nle/_pyconverter.pyi - COMMAND ${Python_INTERPRETER} -m pybind11_stubgen _pyconverter --output-dir + COMMAND ${Python_EXECUTABLE} -m pybind11_stubgen _pyconverter --output-dir ${STUB_DIR} WORKING_DIRECTORY $ DEPENDS _pyconverter @@ -242,7 +238,7 @@ add_custom_command( add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/stubs/nle/_pynethack/__init__.pyi - COMMAND ${Python_INTERPRETER} -m pybind11_stubgen _pynethack --output-dir + COMMAND ${Python_EXECUTABLE} -m pybind11_stubgen _pynethack --output-dir ${STUB_DIR} --ignore-unresolved-names game_end_types WORKING_DIRECTORY $ DEPENDS _pynethack From 1d2bd7060344365cd3a955edd78f8c96ff57e732 Mon Sep 17 00:00:00 2001 From: "Jonathan B. Coe" Date: Wed, 18 Mar 2026 22:37:18 +0000 Subject: [PATCH 21/29] Revert unintended change --- .github/workflows/cmake.yml | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 8b7133b74..5d7efc700 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -31,21 +31,8 @@ jobs: libbz2-dev \ ninja-build \ software-properties-common - - name: Install Python 3.12 with the latest version of uv. - uses: astral-sh/setup-uv@v7 - with: - python-version: '3.12' - uses: actions/checkout@v4 - - name: Create venv and install build dependencies - run: | - uv venv --isolated - source .venv/bin/activate - uv pip install scikit-build-core~=0.10 numpy pybind11-stubgen pybind11~=2.2 setuptools-scm~=9.2.2 - name: Check CMake configure - run: | - source .venv/bin/activate - cmake -B build -G Ninja + run: cmake -B build -G Ninja - name: CMake build - run: | - source .venv/bin/activate - cmake --build build + run: cmake --build build From 2b5546c97a4dad3b8867857cad2af6862f2bac28 Mon Sep 17 00:00:00 2001 From: "Jonathan B. Coe" Date: Wed, 18 Mar 2026 22:40:30 +0000 Subject: [PATCH 22/29] Revert "Revert unintended change" This reverts commit 1d2bd7060344365cd3a955edd78f8c96ff57e732. --- .github/workflows/cmake.yml | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 5d7efc700..8b7133b74 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -31,8 +31,21 @@ jobs: libbz2-dev \ ninja-build \ software-properties-common + - name: Install Python 3.12 with the latest version of uv. + uses: astral-sh/setup-uv@v7 + with: + python-version: '3.12' - uses: actions/checkout@v4 + - name: Create venv and install build dependencies + run: | + uv venv --isolated + source .venv/bin/activate + uv pip install scikit-build-core~=0.10 numpy pybind11-stubgen pybind11~=2.2 setuptools-scm~=9.2.2 - name: Check CMake configure - run: cmake -B build -G Ninja + run: | + source .venv/bin/activate + cmake -B build -G Ninja - name: CMake build - run: cmake --build build + run: | + source .venv/bin/activate + cmake --build build From 98a723d460e5c068230808dac71de58b062e7ffa Mon Sep 17 00:00:00 2001 From: "Jonathan B. Coe" Date: Wed, 18 Mar 2026 22:41:31 +0000 Subject: [PATCH 23/29] Robust FindPython for CMake --- pyproject.toml | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index ad96068d7..1b97d019a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -32,17 +32,22 @@ Homepage = "https://github.com/NetHack-LE/nle" [build-system] # Lock build-deps as uv does not yet support locking of build deps: astral-sh/uv#5190 requires = [ - "scikit-build-core~=0.10", - "numpy", - "pybind11-stubgen", - "pybind11~=2.2", - "setuptools-scm~=9.2.2" + "scikit-build-core~=0.10", + "numpy", + "pybind11-stubgen", + "pybind11~=2.2", + "setuptools-scm~=9.2.2", ] build-backend = "scikit_build_core.build" [tool.scikit-build] cmake.build-type = "Release" -cmake.args = ["-DHACKDIR=nle/nethackdir", "-DPYTHON_PACKAGE_NAME=nle"] +cmake.args = [ + "-DHACKDIR=nle/nethackdir", + "-DPYTHON_PACKAGE_NAME=nle", + # Force CMake to ignore the cached path if it's not found + "-DPython_FIND_STRATEGY=LOCATION", +] minimum-version = "build-system.requires" metadata.version.provider = "scikit_build_core.metadata.setuptools_scm" build-dir = "build/{wheel_tag}" From fd8c64043e10c19a826a24f9e57965ea9d01e073 Mon Sep 17 00:00:00 2001 From: "Jonathan B. Coe" Date: Wed, 18 Mar 2026 23:03:13 +0000 Subject: [PATCH 24/29] Re-find python --- pyproject.toml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 1b97d019a..ba6e08b47 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -45,7 +45,10 @@ cmake.build-type = "Release" cmake.args = [ "-DHACKDIR=nle/nethackdir", "-DPYTHON_PACKAGE_NAME=nle", - # Force CMake to ignore the cached path if it's not found + # This policy forces CMake to look at the current PATH/environment + # before checking the CMakeCache.txt for a Python interpreter. + "-DCMAKE_POLICY_DEFAULT_CMP0094=NEW", + # This ensures the search prefers the 'LOCATION' provided by the current environment. "-DPython_FIND_STRATEGY=LOCATION", ] minimum-version = "build-system.requires" From 21ce9d7fd7e368f3fef5bb7cdffceec2350939cd Mon Sep 17 00:00:00 2001 From: "Jonathan B. Coe" Date: Wed, 18 Mar 2026 23:20:30 +0000 Subject: [PATCH 25/29] =?UTF-8?q?Python::Interpreter=20is=20a=20CMake=20im?= =?UTF-8?q?ported=20executable=20target=20=E2=80=94=20when=20used=20as=20a?= =?UTF-8?q?=20COMMAND,=20CMake=20resolves=20it=20to=20the=20actual=20execu?= =?UTF-8?q?table=20at=20build=20time=20via=20the=20target=20machinery,=20n?= =?UTF-8?q?ot=20by=20embedding=20a=20string=20path=20at=20configure=20time?= =?UTF-8?q?.=20This=20is=20the=20distinction:=20a=20target=20reference=20s?= =?UTF-8?q?tays=20late-bound,=20a=20variable=20like=20${Python=5FEXECUTABL?= =?UTF-8?q?E}=20gets=20expanded=20to=20a=20string=20immediately=20at=20con?= =?UTF-8?q?figure=20time=20and=20baked=20into=20build.ninja.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 119d7b8d6..fb51f3193 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -69,8 +69,6 @@ message(STATUS "HACKDIR set to: ${HACKDIR}") set(VARDIR ${HACKDIR}) set(INSTDIR ${HACKDIR}) -# Use FindPython in PyBind11 to find Python. -set(PYBIND11_FINDPYTHON NEW) # pybind11 via FetchContent include(FetchContent) FetchContent_Declare( @@ -229,7 +227,7 @@ set(STUB_DIR ${CMAKE_CURRENT_BINARY_DIR}/stubs) set_directory_properties(PROPERTIES ADDITIONAL_CLEAN_FILES "${STUB_DIR}") add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/stubs/nle/_pyconverter.pyi - COMMAND ${Python_EXECUTABLE} -m pybind11_stubgen _pyconverter --output-dir + COMMAND Python::Interpreter -m pybind11_stubgen _pyconverter --output-dir ${STUB_DIR} WORKING_DIRECTORY $ DEPENDS _pyconverter @@ -238,7 +236,7 @@ add_custom_command( add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/stubs/nle/_pynethack/__init__.pyi - COMMAND ${Python_EXECUTABLE} -m pybind11_stubgen _pynethack --output-dir + COMMAND Python::Interpreter -m pybind11_stubgen _pynethack --output-dir ${STUB_DIR} --ignore-unresolved-names game_end_types WORKING_DIRECTORY $ DEPENDS _pynethack From cabe0f16d3d0a2c3e65b674f860f4161751ea3fd Mon Sep 17 00:00:00 2001 From: "Jonathan B. Coe" Date: Thu, 19 Mar 2026 00:04:28 +0000 Subject: [PATCH 26/29] Cleaner but still broken build --- CMakeLists.txt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fb51f3193..119d7b8d6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -69,6 +69,8 @@ message(STATUS "HACKDIR set to: ${HACKDIR}") set(VARDIR ${HACKDIR}) set(INSTDIR ${HACKDIR}) +# Use FindPython in PyBind11 to find Python. +set(PYBIND11_FINDPYTHON NEW) # pybind11 via FetchContent include(FetchContent) FetchContent_Declare( @@ -227,7 +229,7 @@ set(STUB_DIR ${CMAKE_CURRENT_BINARY_DIR}/stubs) set_directory_properties(PROPERTIES ADDITIONAL_CLEAN_FILES "${STUB_DIR}") add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/stubs/nle/_pyconverter.pyi - COMMAND Python::Interpreter -m pybind11_stubgen _pyconverter --output-dir + COMMAND ${Python_EXECUTABLE} -m pybind11_stubgen _pyconverter --output-dir ${STUB_DIR} WORKING_DIRECTORY $ DEPENDS _pyconverter @@ -236,7 +238,7 @@ add_custom_command( add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/stubs/nle/_pynethack/__init__.pyi - COMMAND Python::Interpreter -m pybind11_stubgen _pynethack --output-dir + COMMAND ${Python_EXECUTABLE} -m pybind11_stubgen _pynethack --output-dir ${STUB_DIR} --ignore-unresolved-names game_end_types WORKING_DIRECTORY $ DEPENDS _pynethack From a6ee360d6458c223be51e3258deb49a910584849 Mon Sep 17 00:00:00 2001 From: "Jonathan B. Coe" Date: Thu, 19 Mar 2026 00:33:16 +0000 Subject: [PATCH 27/29] Undo ineffective changes --- pyproject.toml | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index ba6e08b47..1f0d9695d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -42,15 +42,7 @@ build-backend = "scikit_build_core.build" [tool.scikit-build] cmake.build-type = "Release" -cmake.args = [ - "-DHACKDIR=nle/nethackdir", - "-DPYTHON_PACKAGE_NAME=nle", - # This policy forces CMake to look at the current PATH/environment - # before checking the CMakeCache.txt for a Python interpreter. - "-DCMAKE_POLICY_DEFAULT_CMP0094=NEW", - # This ensures the search prefers the 'LOCATION' provided by the current environment. - "-DPython_FIND_STRATEGY=LOCATION", -] +cmake.args = ["-DHACKDIR=nle/nethackdir", "-DPYTHON_PACKAGE_NAME=nle"] minimum-version = "build-system.requires" metadata.version.provider = "scikit_build_core.metadata.setuptools_scm" build-dir = "build/{wheel_tag}" From 0b15b800737d17b3c705ab73be1a9a4460f4bf47 Mon Sep 17 00:00:00 2001 From: "Jonathan B. Coe" Date: Fri, 20 Mar 2026 20:05:43 +0000 Subject: [PATCH 28/29] Revert "Fast rebuilds of C/C++ code when needed. (#106)" This reverts commit 0b9648399a4ec53652a78e0ef3993ba82860b281. Fast rebuilds with uv and scikit-build and use of Python tooling within a CMake build are incompatible. The isolated environment used for the build means that the Python executable cached in the build directory is not valid when the build directory is used for a rebuild. --- CMakeLists.txt | 12 ------------ pyproject.toml | 2 -- 2 files changed, 14 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 119d7b8d6..cb9515145 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,18 +12,6 @@ endif() string(REGEX MATCH "^[0-9]+(\\.[0-9]+)*" CMAKE_NLE_VERSION "${NLE_VERSION}") project(nle VERSION ${CMAKE_NLE_VERSION}) -# Only enable ccache if this is the main project, not a sub-dependency. -if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) - find_program(CCACHE_EXECUTABLE ccache) - if(CCACHE_EXECUTABLE) - message(STATUS "ccache found, enabling for C and C++") - set(CMAKE_C_COMPILER_LAUNCHER "${CCACHE_EXECUTABLE}") - set(CMAKE_CXX_COMPILER_LAUNCHER "${CCACHE_EXECUTABLE}") - else() - message(STATUS "ccache not found, proceeding without it") - endif() -endif() - if(CMAKE_BUILD_TYPE MATCHES Debug) message("Debug build.") # Unclear if this is even necessary. `dsymutil rlmain -o rlmain.dSYM` seems to diff --git a/pyproject.toml b/pyproject.toml index 1f0d9695d..b9c809e2b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -45,8 +45,6 @@ cmake.build-type = "Release" cmake.args = ["-DHACKDIR=nle/nethackdir", "-DPYTHON_PACKAGE_NAME=nle"] minimum-version = "build-system.requires" metadata.version.provider = "scikit_build_core.metadata.setuptools_scm" -build-dir = "build/{wheel_tag}" -editable.rebuild = true generate = [ { path = "nle/version.py", template = '__version__ = "${version}"' }, ] From 78f5c33198e769a137b05902706f8bebe8598dba Mon Sep 17 00:00:00 2001 From: "Jonathan B. Coe" Date: Sat, 21 Mar 2026 14:21:35 +0000 Subject: [PATCH 29/29] Try to integrate pyrefly --- CMakeLists.txt | 5 ++ nle/nethack/__init__.py | 160 +++++++++++++++++++++++++++++++++- nle/tests/test_dataset.py | 14 +-- nle/tests/test_db.py | 3 +- nle/tests/test_populate_db.py | 6 +- nle/tests/test_tiles.py | 2 +- nle/typed.py | 0 pyproject.toml | 10 ++- uv.lock | 22 ++++- 9 files changed, 207 insertions(+), 15 deletions(-) delete mode 100644 nle/typed.py diff --git a/CMakeLists.txt b/CMakeLists.txt index cb9515145..cbc4a3cb6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -238,6 +238,8 @@ add_custom_target( DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/stubs/nle/_pynethack/__init__.pyi ${CMAKE_CURRENT_BINARY_DIR}/stubs/nle/_pyconverter.pyi) +file(TOUCH ${CMAKE_CURRENT_BINARY_DIR}/py.typed) + set(TILE_FILES "win/share/monsters.txt" "win/share/objects.txt" "win/share/other.txt") @@ -251,6 +253,9 @@ if(DEFINED SKBUILD_PROJECT_VERSION) LIBRARY DESTINATION ${PYTHON_PACKAGE_NAME} ARCHIVE DESTINATION ${PYTHON_PACKAGE_NAME}) + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/py.typed + DESTINATION ${PYTHON_PACKAGE_NAME}) + install( DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/stubs/" DESTINATION ${PYTHON_PACKAGE_NAME} diff --git a/nle/nethack/__init__.py b/nle/nethack/__init__.py index a80008b04..39989c1b1 100644 --- a/nle/nethack/__init__.py +++ b/nle/nethack/__init__.py @@ -1,5 +1,163 @@ # Copyright (c) Facebook, Inc. and its affiliates. -from nle._pynethack.nethack import * # noqa: F403 +import nle._pynethack.nethack +from nle._pynethack.nethack import AMULET_CLASS +from nle._pynethack.nethack import ARMOR_CLASS +from nle._pynethack.nethack import ASCENDED +from nle._pynethack.nethack import BALL_CLASS +from nle._pynethack.nethack import BL_MASK_BITS +from nle._pynethack.nethack import BL_MASK_BLIND +from nle._pynethack.nethack import BL_MASK_CONF +from nle._pynethack.nethack import BL_MASK_DEAF +from nle._pynethack.nethack import BL_MASK_FLY +from nle._pynethack.nethack import BL_MASK_FOODPOIS +from nle._pynethack.nethack import BL_MASK_HALLU +from nle._pynethack.nethack import BL_MASK_LEV +from nle._pynethack.nethack import BL_MASK_RIDE +from nle._pynethack.nethack import BL_MASK_SLIME +from nle._pynethack.nethack import BL_MASK_STONE +from nle._pynethack.nethack import BL_MASK_STRNGL +from nle._pynethack.nethack import BL_MASK_STUN +from nle._pynethack.nethack import BL_MASK_TERMILL +from nle._pynethack.nethack import BURNING +from nle._pynethack.nethack import CHAIN_CLASS +from nle._pynethack.nethack import CHOKING +from nle._pynethack.nethack import COIN_CLASS +from nle._pynethack.nethack import COLNO +from nle._pynethack.nethack import CRUSHING +from nle._pynethack.nethack import DIED +from nle._pynethack.nethack import DISSOLVED +from nle._pynethack.nethack import DROWNING +from nle._pynethack.nethack import ESCAPED +from nle._pynethack.nethack import EXPL_MAX +from nle._pynethack.nethack import FOOD_CLASS +from nle._pynethack.nethack import GEM_CLASS +from nle._pynethack.nethack import GENOCIDED +from nle._pynethack.nethack import GLYPH_BODY_OFF +from nle._pynethack.nethack import GLYPH_CMAP_OFF +from nle._pynethack.nethack import GLYPH_DETECT_OFF +from nle._pynethack.nethack import GLYPH_EXPLODE_OFF +from nle._pynethack.nethack import GLYPH_INVIS_OFF +from nle._pynethack.nethack import GLYPH_INVISIBLE +from nle._pynethack.nethack import GLYPH_MON_OFF +from nle._pynethack.nethack import GLYPH_OBJ_OFF +from nle._pynethack.nethack import GLYPH_PET_OFF +from nle._pynethack.nethack import GLYPH_RIDDEN_OFF +from nle._pynethack.nethack import GLYPH_STATUE_OFF +from nle._pynethack.nethack import GLYPH_SWALLOW_OFF +from nle._pynethack.nethack import GLYPH_WARNING_OFF +from nle._pynethack.nethack import GLYPH_ZAP_OFF +from nle._pynethack.nethack import ILLOBJ_CLASS +from nle._pynethack.nethack import MAX_GLYPH +from nle._pynethack.nethack import MAXEXPCHARS +from nle._pynethack.nethack import MAXMCLASSES +from nle._pynethack.nethack import MAXOCLASSES +from nle._pynethack.nethack import MAXPCHARS +from nle._pynethack.nethack import MAXWIN +from nle._pynethack.nethack import MG_BW_LAVA +from nle._pynethack.nethack import MG_CORPSE +from nle._pynethack.nethack import MG_DETECT +from nle._pynethack.nethack import MG_INVIS +from nle._pynethack.nethack import MG_OBJPILE +from nle._pynethack.nethack import MG_PET +from nle._pynethack.nethack import MG_RIDDEN +from nle._pynethack.nethack import MG_STATUE +from nle._pynethack.nethack import NHW_MAP +from nle._pynethack.nethack import NHW_MENU +from nle._pynethack.nethack import NHW_MESSAGE +from nle._pynethack.nethack import NHW_STATUS +from nle._pynethack.nethack import NHW_TEXT +from nle._pynethack.nethack import NLE_BL_AC +from nle._pynethack.nethack import NLE_BL_ALIGN +from nle._pynethack.nethack import NLE_BL_CAP +from nle._pynethack.nethack import NLE_BL_CHA +from nle._pynethack.nethack import NLE_BL_CON +from nle._pynethack.nethack import NLE_BL_CONDITION +from nle._pynethack.nethack import NLE_BL_DEPTH +from nle._pynethack.nethack import NLE_BL_DEX +from nle._pynethack.nethack import NLE_BL_DLEVEL +from nle._pynethack.nethack import NLE_BL_DNUM +from nle._pynethack.nethack import NLE_BL_ENE +from nle._pynethack.nethack import NLE_BL_ENEMAX +from nle._pynethack.nethack import NLE_BL_EXP +from nle._pynethack.nethack import NLE_BL_GOLD +from nle._pynethack.nethack import NLE_BL_HD +from nle._pynethack.nethack import NLE_BL_HP +from nle._pynethack.nethack import NLE_BL_HPMAX +from nle._pynethack.nethack import NLE_BL_HUNGER +from nle._pynethack.nethack import NLE_BL_INT +from nle._pynethack.nethack import NLE_BL_SCORE +from nle._pynethack.nethack import NLE_BL_STR25 +from nle._pynethack.nethack import NLE_BL_STR125 +from nle._pynethack.nethack import NLE_BL_TIME +from nle._pynethack.nethack import NLE_BL_WIS +from nle._pynethack.nethack import NLE_BL_X +from nle._pynethack.nethack import NLE_BL_XP +from nle._pynethack.nethack import NLE_BL_Y +from nle._pynethack.nethack import NLE_BLSTATS_SIZE +from nle._pynethack.nethack import NLE_INTERNAL_SIZE +from nle._pynethack.nethack import NLE_INVENTORY_SIZE +from nle._pynethack.nethack import NLE_INVENTORY_STR_LENGTH +from nle._pynethack.nethack import NLE_MESSAGE_SIZE +from nle._pynethack.nethack import NLE_MISC_SIZE +from nle._pynethack.nethack import NLE_PROGRAM_STATE_SIZE +from nle._pynethack.nethack import NLE_SCREEN_DESCRIPTION_LENGTH +from nle._pynethack.nethack import NLE_TERM_CO +from nle._pynethack.nethack import NLE_TERM_LI +from nle._pynethack.nethack import NO_GLYPH +from nle._pynethack.nethack import NUM_OBJECTS +from nle._pynethack.nethack import NUM_ZAP +from nle._pynethack.nethack import NUMMONS +from nle._pynethack.nethack import OBJ_DESCR +from nle._pynethack.nethack import OBJ_NAME +from nle._pynethack.nethack import PANICKED +from nle._pynethack.nethack import POISONING +from nle._pynethack.nethack import POTION_CLASS +from nle._pynethack.nethack import QUIT +from nle._pynethack.nethack import RANDOM_CLASS +from nle._pynethack.nethack import RING_CLASS +from nle._pynethack.nethack import ROCK_CLASS +from nle._pynethack.nethack import ROWNO +from nle._pynethack.nethack import SCROLL_CLASS +from nle._pynethack.nethack import SPBOOK_CLASS +from nle._pynethack.nethack import STARVING +from nle._pynethack.nethack import STONING +from nle._pynethack.nethack import TILE_X +from nle._pynethack.nethack import TILE_Y +from nle._pynethack.nethack import TILE_Z +from nle._pynethack.nethack import TOOL_CLASS +from nle._pynethack.nethack import TRICKED +from nle._pynethack.nethack import TURNED_SLIME +from nle._pynethack.nethack import VENOM_CLASS +from nle._pynethack.nethack import WAND_CLASS +from nle._pynethack.nethack import WARNCOUNT +from nle._pynethack.nethack import WEAPON_CLASS +from nle._pynethack.nethack import class_sym +from nle._pynethack.nethack import game_end_types +from nle._pynethack.nethack import glyph2tile +from nle._pynethack.nethack import glyph_is_body +from nle._pynethack.nethack import glyph_is_cmap +from nle._pynethack.nethack import glyph_is_detected_monster +from nle._pynethack.nethack import glyph_is_invisible +from nle._pynethack.nethack import glyph_is_monster +from nle._pynethack.nethack import glyph_is_normal_monster +from nle._pynethack.nethack import glyph_is_normal_object +from nle._pynethack.nethack import glyph_is_object +from nle._pynethack.nethack import glyph_is_pet +from nle._pynethack.nethack import glyph_is_ridden_monster +from nle._pynethack.nethack import glyph_is_statue +from nle._pynethack.nethack import glyph_is_swallow +from nle._pynethack.nethack import glyph_is_trap +from nle._pynethack.nethack import glyph_is_warning +from nle._pynethack.nethack import glyph_to_cmap +from nle._pynethack.nethack import glyph_to_mon +from nle._pynethack.nethack import glyph_to_obj +from nle._pynethack.nethack import glyph_to_swallow +from nle._pynethack.nethack import glyph_to_trap +from nle._pynethack.nethack import glyph_to_warning +from nle._pynethack.nethack import objclass +from nle._pynethack.nethack import objdescr +from nle._pynethack.nethack import permonst +from nle._pynethack.nethack import symdef from nle.nethack.actions import * # noqa: F403 from nle.nethack.nethack import BLSTATS_SHAPE from nle.nethack.nethack import DUNGEON_SHAPE diff --git a/nle/tests/test_dataset.py b/nle/tests/test_dataset.py index fd66015f2..c91151999 100644 --- a/nle/tests/test_dataset.py +++ b/nle/tests/test_dataset.py @@ -4,16 +4,16 @@ import numpy as np import pytest -from test_converter import COLSROWS -from test_converter import FINALFRAME -from test_converter import FINALFRAMECOLORS -from test_converter import TIMESTAMPS -from test_converter import getfilename -from test_db import conn # noqa: F401 -from test_db import mockdata # noqa: F401 from nle.dataset import dataset from nle.dataset import db +from nle.tests.test_converter import COLSROWS +from nle.tests.test_converter import FINALFRAME +from nle.tests.test_converter import FINALFRAMECOLORS +from nle.tests.test_converter import TIMESTAMPS +from nle.tests.test_converter import getfilename +from nle.tests.test_db import conn # noqa: F401 +from nle.tests.test_db import mockdata # noqa: F401 class TestDataset: diff --git a/nle/tests/test_db.py b/nle/tests/test_db.py index 770cada33..69fd4baee 100644 --- a/nle/tests/test_db.py +++ b/nle/tests/test_db.py @@ -1,9 +1,10 @@ import os import pytest -import test_converter import nle.env.tasks +import nle.nethack +import nle.tests.test_converter as test_converter from nle.dataset import db from nle.dataset import populate_db diff --git a/nle/tests/test_populate_db.py b/nle/tests/test_populate_db.py index 3ee5438fe..d7cebaf45 100644 --- a/nle/tests/test_populate_db.py +++ b/nle/tests/test_populate_db.py @@ -1,11 +1,11 @@ import json import pytest # NOQA: F401 -from test_converter import getfilename -from test_db import conn # NOQA: F401 -from test_db import mockdata # NOQA: F401 from nle import nethack +from nle.tests.test_converter import getfilename +from nle.tests.test_db import conn # NOQA: F401 +from nle.tests.test_db import mockdata # NOQA: F401 TTYRECS_TABLE_OFFSET = 0 GAMES_TABLE_OFFSET = 5 diff --git a/nle/tests/test_tiles.py b/nle/tests/test_tiles.py index 42d866c8a..f80a4b3be 100644 --- a/nle/tests/test_tiles.py +++ b/nle/tests/test_tiles.py @@ -2,7 +2,7 @@ import numpy as np import pytest -import nle +import nle.nethack class TestTileset: diff --git a/nle/typed.py b/nle/typed.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/pyproject.toml b/pyproject.toml index b9c809e2b..520cd9da6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -49,6 +49,9 @@ generate = [ { path = "nle/version.py", template = '__version__ = "${version}"' }, ] +#[tool.uv] +#managed = false + [tool.setuptools_scm] # This section is necessary to activate setuptools-scm, but can be empty @@ -60,7 +63,7 @@ nle-ttyplay2 = "nle.scripts.ttyplay2:main" nle-read-tty = "nle.scripts.read_tty:main" [dependency-groups] -dev = ["nle[dev]"] +dev = ["nle[dev]", "pyrefly>=0.57.1"] [project.optional-dependencies] agent = ["torch>=1.3.1"] @@ -122,3 +125,8 @@ before-all = "rm -rf {project}/build {project}/*.so {project}/CMakeCache.txt && [tool.pytest.ini_options] testpaths = ["nle/tests"] + +[tool.pyrefly] +disable-search-path-heuristics = true +project-includes = ["."] +project-excludes = ["src/**"] diff --git a/uv.lock b/uv.lock index 170285647..f9470b464 100644 --- a/uv.lock +++ b/uv.lock @@ -485,6 +485,7 @@ dev = [ [package.dev-dependencies] dev = [ { name = "nle", extra = ["dev"] }, + { name = "pyrefly" }, ] [package.metadata] @@ -507,7 +508,10 @@ requires-dist = [ provides-extras = ["agent", "dev", "all"] [package.metadata.requires-dev] -dev = [{ name = "nle", extras = ["dev"] }] +dev = [ + { name = "nle", extras = ["dev"] }, + { name = "pyrefly", specifier = ">=0.57.1" }, +] [[package]] name = "nodeenv" @@ -898,6 +902,22 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" }, ] +[[package]] +name = "pyrefly" +version = "0.57.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c9/c1/c17211e5bbd2b90a24447484713da7cc2cee4e9455e57b87016ffc69d426/pyrefly-0.57.1.tar.gz", hash = "sha256:b05f6f5ee3a6a5d502ca19d84cb9ab62d67f05083819964a48c1510f2993efc6", size = 5310800, upload-time = "2026-03-18T18:42:35.614Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/58/8af37856c8d45b365ece635a6728a14b0356b08d1ff1ac601d7120def1e0/pyrefly-0.57.1-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:91974bfbe951eebf5a7bc959c1f3921f0371c789cad84761511d695e9ab2265f", size = 12681847, upload-time = "2026-03-18T18:42:10.963Z" }, + { url = "https://files.pythonhosted.org/packages/5f/d7/fae6dd9d0355fc5b8df7793f1423b7433ca8e10b698ea934c35f0e4e6522/pyrefly-0.57.1-py3-none-macosx_11_0_arm64.whl", hash = "sha256:808087298537c70f5e7cdccb5bbaad482e7e056e947c0adf00fb612cbace9fdc", size = 12219634, upload-time = "2026-03-18T18:42:13.469Z" }, + { url = "https://files.pythonhosted.org/packages/29/8f/9511ae460f0690e837b9ba0f7e5e192079e16ff9a9ba8a272450e81f11f8/pyrefly-0.57.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b01f454fa5539e070c0cba17ddec46b3d2107d571d519bd8eca8f3142ba02a6", size = 34947757, upload-time = "2026-03-18T18:42:17.152Z" }, + { url = "https://files.pythonhosted.org/packages/07/43/f053bf9c65218f70e6a49561e9942c7233f8c3e4da8d42e5fe2aae50b3d2/pyrefly-0.57.1-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:02ad59ea722191f51635f23e37574662116b82ca9d814529f7cb5528f041f381", size = 37621018, upload-time = "2026-03-18T18:42:20.79Z" }, + { url = "https://files.pythonhosted.org/packages/0e/76/9cea46de01665bbc125e4f215340c9365c8d56cda6198ff238a563ea8e75/pyrefly-0.57.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:54bc0afe56776145e37733ff763e7e9679ee8a76c467b617dc3f227d4124a9e2", size = 40203649, upload-time = "2026-03-18T18:42:24.519Z" }, + { url = "https://files.pythonhosted.org/packages/fd/8b/2fb4a96d75e2a57df698a43e2970e441ba2704e3906cdc0386a055daa05a/pyrefly-0.57.1-py3-none-win32.whl", hash = "sha256:468e5839144b25bb0dce839bfc5fd879c9f38e68ebf5de561f30bed9ae19d8ca", size = 11732953, upload-time = "2026-03-18T18:42:27.379Z" }, + { url = "https://files.pythonhosted.org/packages/13/5a/4a197910fe2e9b102b15ae5e7687c45b7b5981275a11a564b41e185dd907/pyrefly-0.57.1-py3-none-win_amd64.whl", hash = "sha256:46db9c97093673c4fb7fab96d610e74d140661d54688a92d8e75ad885a56c141", size = 12537319, upload-time = "2026-03-18T18:42:30.196Z" }, + { url = "https://files.pythonhosted.org/packages/b5/c6/bc442874be1d9b63da1f9debb4f04b7d0c590a8dc4091921f3c288207242/pyrefly-0.57.1-py3-none-win_arm64.whl", hash = "sha256:feb1bbe3b0d8d5a70121dcdf1476e6a99cc056a26a49379a156f040729244dcb", size = 12013455, upload-time = "2026-03-18T18:42:32.928Z" }, +] + [[package]] name = "pytest" version = "9.0.2"