From 39c39a625873da33f4a319303aa7885cf66c88d3 Mon Sep 17 00:00:00 2001 From: Paul Melnikow Date: Wed, 18 Feb 2026 12:54:42 -0600 Subject: [PATCH 01/11] Test Python + NumPy in CI --- .github/workflows/{wheels.yml => python.yml} | 116 ++++++- azure-pipelines.yml | 149 --------- python/tests/README.md | 3 + python/tests/pyproject.toml | 12 + python/tests/tinyobjloader_tests/__init__.py | 0 python/tests/tinyobjloader_tests/loader.py | 33 ++ .../tests/tinyobjloader_tests/test_loader.py | 33 ++ python/tests/uv.lock | 303 ++++++++++++++++++ setup.py | 4 - 9 files changed, 483 insertions(+), 170 deletions(-) rename .github/workflows/{wheels.yml => python.yml} (50%) create mode 100644 python/tests/README.md create mode 100644 python/tests/pyproject.toml create mode 100644 python/tests/tinyobjloader_tests/__init__.py create mode 100644 python/tests/tinyobjloader_tests/loader.py create mode 100644 python/tests/tinyobjloader_tests/test_loader.py create mode 100644 python/tests/uv.lock diff --git a/.github/workflows/wheels.yml b/.github/workflows/python.yml similarity index 50% rename from .github/workflows/wheels.yml rename to .github/workflows/python.yml index b37104a2..60664b32 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/python.yml @@ -1,12 +1,103 @@ -name: Build and upload to PyPI +name: Python # Build on every branch push, tag push, and pull request change: on: [push, pull_request] jobs: + check_format: + name: Check Python code format + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install uv + uses: astral-sh/setup-uv@v4 + with: + version: "latest" + + - name: Set up Python and install dependencies + working-directory: python/tests + run: uv sync --project . --python 3.13 + + - name: Check code format + working-directory: python/tests + run: uv run --project . black --check .. + + build_wheels_quick: + name: Build wheels for quick testing + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + fetch-tags: true # Optional, use if you use setuptools_scm + + - name: Build wheels + uses: pypa/cibuildwheel@v2.16.5 + env: + CIBW_ARCHS_LINUX: "x86_64" + CIBW_SKIP: pp* cp36-* cp37-* cp38-* *-musllinux_* - build_wheels: - name: Build wheels on ${{ matrix.os }} + - uses: actions/upload-artifact@v4 + with: + name: cibw-wheels-quick + path: ./wheelhouse/*.whl + + test_wheels: + name: Test wheels with Python ${{ matrix.python-version }} and NumPy ${{ matrix.numpy-version }} + needs: [build_wheels_quick] + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + include: + - python-version: "3.9" + numpy-version: "1.25.2" + - python-version: "3.10" + numpy-version: "1.26.4" + - python-version: "3.11" + numpy-version: "1.26.4" + - python-version: "3.12" + numpy-version: "1.26.4" + - python-version: "3.11" + numpy-version: "2.4.2" + - python-version: "3.12" + numpy-version: "2.4.2" + + steps: + - uses: actions/checkout@v4 + + - name: Install uv + uses: astral-sh/setup-uv@v4 + with: + version: "latest" + + - name: Download wheel artifacts + uses: actions/download-artifact@v4 + with: + pattern: cibw-wheels-quick + path: dist + merge-multiple: true + + - name: Set up Python ${{ matrix.python-version }} and install dependencies + working-directory: python/tests + run: uv sync --project . --python ${{ matrix.python-version }} + + - name: Install NumPy ${{ matrix.numpy-version }} + working-directory: python/tests + run: | + uv pip install --project . --only-binary :all: numpy==${{ matrix.numpy-version }} + + - name: Install manylinux wheel built for Python ${{ matrix.python-version }} + working-directory: python/tests + run: uv pip install --project . ../../dist/*cp$(echo ${{ matrix.python-version }} | tr -d .)*.whl + + - name: Run tests + working-directory: python/tests + run: uv run --project . pytest + + build_wheels_main: + name: Build remaining wheels on ${{ matrix.os }} runs-on: ${{ matrix.os }} strategy: matrix: @@ -20,28 +111,23 @@ jobs: - name: Build wheels uses: pypa/cibuildwheel@v2.16.5 - # to supply options, put them in 'env', like: - # env: - # CIBW_SOME_OPTION: value - # Disable building PyPy wheels on all platforms env: CIBW_ARCHS_MACOS: "x86_64 universal2 arm64" CIBW_ARCHS_WINDOWS: "AMD64 x86" # disable aarm64 build since its too slow to build(docker + qemu) CIBW_ARCHS_LINUX: "x86_64 i686" - # it looks cibuildwheel fails to add version string to wheel file for python 3.6, so skip it - CIBW_SKIP: pp* + CIBW_SKIP: pp* cp36-* cp37-* cp38-* *-manylinux_x86_64 - uses: actions/upload-artifact@v4 with: - name: cibw-wheels-${{ matrix.os }}-${{ strategy.job-index }} + name: cibw-wheels-main-${{ matrix.os }}-${{ strategy.job-index }} path: ./wheelhouse/*.whl # It looks cibuildwheels did not clean build folder(CMake), and it results to Windows arm64 build failure(trying to reuse x86 build of .obj) # So supply separated build job for Windows ARM64 build # TODO: clean build folder using CIBW_BEFORE_ALL? - build_win_arm64_wheels: - name: Build ARM64 wheels on Windows. + build_wheels_win_arm64: + name: Build ARM64 wheels on Windows runs-on: windows-latest steps: - uses: actions/checkout@v4 @@ -51,10 +137,6 @@ jobs: - name: Build wheels uses: pypa/cibuildwheel@v2.16.5 - # to supply options, put them in 'env', like: - # env: - # CIBW_SOME_OPTION: value - # Disable building PyPy wheels on all platforms env: CIBW_ARCHS_WINDOWS: "ARM64" CIBW_SKIP: pp* @@ -82,7 +164,7 @@ jobs: path: dist/*.tar.gz upload_all: - needs: [build_wheels, build_wheels, make_sdist] + needs: [build_wheels_quick, build_wheels_main, build_wheels_win_arm64, make_sdist] runs-on: ubuntu-latest environment: release permissions: diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 2580f172..dbc3e166 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -1,25 +1,3 @@ -# -# Python wheels build is now done in Github Actions + Cirrus CI(for arm build) -# so python build is disabled in Azure pipelines. -# - -variables: - # https://cibuildwheel.readthedocs.io/en/stable/cpp_standards/ - # cibuildwheel now supports python 3.6+(as of 2022 Oct) - #CIBW_SKIP: "pp*" - CIBW_BEFORE_BUILD: "pip install pybind11" - CIBW_ARCHS_LINUXBEFORE_BUILD: "pip install pybind11" - # disable aarch64 build for a while since it(pulling docker aarch64 image) exceeds Azure's 60 min limit - # NOTE: aarch64 linux support in Azure pipeline is not yet officially supported(as of 2022 Oct) https://github.com/microsoft/azure-pipelines-agent/issues/3935 - #CIBW_ARCHS_LINUX: auto aarch64 - CIBW_ARCHS_MACOS: x86_64 universal2 arm64 - #CIBW_BEFORE_BUILD_MACOS: "pip install -U pip setuptools" - #CIBW_BEFORE_BUILD_LINUX: "pip install -U pip setuptools" - #CIBW_TEST_COMMAND: TODO "python -c \"import tinyobjloader; tinyobjloader.test()\"" - CIBW_BUILD_VERBOSITY: "2" - #CIBW_MANYLINUX_X86_64_IMAGE: manylinux2014 - #CIBW_MANYLINUX_I686_IMAGE: manylinux2014 - jobs: - job: unit_linux pool: { vmImage: "ubuntu-latest" } @@ -29,133 +7,6 @@ jobs: make && ./tester displayName: Run unit tests - - job: python_format - pool: { vmImage: "ubuntu-latest" } - steps: - - task: UsePythonVersion@0 - - script: | - # 19.10b0 triggers 'cannot import name '_unicodefun' from 'click'' error. - # https://stackoverflow.com/questions/71673404/importerror-cannot-import-name-unicodefun-from-click - #pip install black==19.10b0 - #pip install black==22.3.0 - pip install black==22.10.0 - - black --check python/ - displayName: Check Python code format - - # Disabled: python build - ## - ## Ubuntu16.04 seems now deprecated(as of 2021/12/01), - ## so use `ubuntu-latest` - #- job: linux - # pool: {vmImage: "ubuntu-latest"} - # steps: - # - task: UsePythonVersion@0 - # - bash: | - # python3 -m pip install --upgrade pip - # pip3 install cibuildwheel twine - - # # Use pipx to build source dist - # pip3 install pipx - - # # Source dist - # pipx run build --sdist - # ls -la dist/* - - # # build binary wheels - # cibuildwheel --platform linux --output-dir wheelhouse . - - # - task: CopyFiles@2 - # inputs: - # contents: 'wheelhouse/**' - # targetFolder: $(Build.ArtifactStagingDirectory) - - # - task: CopyFiles@2 - # inputs: - # contents: 'dist/**' - # targetFolder: $(Build.ArtifactStagingDirectory) - - # - task: PublishBuildArtifacts@1 - # inputs: - # path: $(Build.ArtifactStagingDirectory) - # artifactName: tinyobjDeployLinux - - #- job: macos - # pool: {vmImage: 'macOS-latest'} - # variables: - # # Support C++11: https://github.com/joerick/cibuildwheel/pull/156 - # MACOSX_DEPLOYMENT_TARGET: 10.9 - # steps: - # - task: UsePythonVersion@0 - # - bash: | - # python3 -m pip install --upgrade pip - # pip3 install cibuildwheel - # cibuildwheel --platform macos --output-dir wheelhouse . - # - task: CopyFiles@2 - # inputs: - # contents: 'wheelhouse/*.whl' - # targetFolder: $(Build.ArtifactStagingDirectory) - # - task: PublishBuildArtifacts@1 - # inputs: - # path: $(Build.ArtifactStagingDirectory) - # artifactName: tinyobjDeployMacOS - - #- job: windows - # pool: {vmImage: 'windows-latest'} - # steps: - # - task: UsePythonVersion@0 - # - bash: | - # python -m pip install --upgrade pip - # pip install cibuildwheel - # cibuildwheel --platform windows --output-dir wheelhouse . - # - task: CopyFiles@2 - # inputs: - # contents: 'wheelhouse/*.whl' - # targetFolder: $(Build.ArtifactStagingDirectory) - # - task: PublishBuildArtifacts@1 - # inputs: - # path: $(Build.ArtifactStagingDirectory) - # artifactName: tinyobjDeployWindows - - #- job: deployPyPI - # # Based on vispy: https://github.com/vispy/vispy/blob/master/azure-pipelines.yml - # pool: {vmImage: 'ubuntu-latest'} - # condition: and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/tags/v')) - # dependsOn: - # - linux - # - macos - # - windows - # steps: - # - task: UsePythonVersion@0 - - # # TODO(syoyo): Use buildType: specific to download multiple artifacts at once? - # - task: DownloadBuildArtifacts@0 - # inputs: - # artifactName: 'tinyobjDeployLinux' - # downloadPath: $(Pipeline.Workspace) - - # - task: DownloadBuildArtifacts@0 - # inputs: - # artifactName: 'tinyobjDeployMacOS' - # downloadPath: $(Pipeline.Workspace) - - # - task: DownloadBuildArtifacts@0 - # inputs: - # artifactName: 'tinyobjDeployWindows' - # downloadPath: $(Pipeline.Workspace) - - # # Publish to PyPI through twine - # - bash: | - # cd $(Pipeline.Workspace) - # find . - # python -m pip install --upgrade pip - # pip install twine - # echo tinyobjDeployLinux/dist/* - # echo tinyobjDeployLinux/wheelhouse/* tinyobjDeployMacOS/wheelhouse/* tinyobjDeployWindows/wheelhouse/* - # twine upload -u "__token__" --skip-existing tinyobjDeployLinux/dist/* tinyobjDeployLinux/wheelhouse/* tinyobjDeployMacOS/wheelhouse/* tinyobjDeployWindows/wheelhouse/* - # env: - # TWINE_PASSWORD: $(pypiToken2) - trigger: branches: include: diff --git a/python/tests/README.md b/python/tests/README.md new file mode 100644 index 00000000..720808e1 --- /dev/null +++ b/python/tests/README.md @@ -0,0 +1,3 @@ +# tinyobjloader Python tests + +This folder hosts a project for running the Python binding tests. diff --git a/python/tests/pyproject.toml b/python/tests/pyproject.toml new file mode 100644 index 00000000..8157856b --- /dev/null +++ b/python/tests/pyproject.toml @@ -0,0 +1,12 @@ +[project] +name = "tinyobjloader-tests" +version = "0.0.1" +description = "Tests for tinyobjloader Python bindings" +readme = "README.md" +requires-python = ">=3.9" + +dependencies = ["pytest>=8.0", "black==22.10.0"] + +[build-system] +requires = ["hatchling>=1.24"] +build-backend = "hatchling.build" diff --git a/python/tests/tinyobjloader_tests/__init__.py b/python/tests/tinyobjloader_tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/python/tests/tinyobjloader_tests/loader.py b/python/tests/tinyobjloader_tests/loader.py new file mode 100644 index 00000000..3374e561 --- /dev/null +++ b/python/tests/tinyobjloader_tests/loader.py @@ -0,0 +1,33 @@ +from tinyobjloader import ObjReader, ObjReaderConfig + + +class LoadException(Exception): + pass + + +class Loader: + """ + A light wrapper around ObjReader to provide a convenient interface for testing. + """ + + def __init__(self, triangulate=True): + self.reader = ObjReader() + config = ObjReaderConfig() + config.triangulate = triangulate + self.config = config + + def load(self, mesh_path): + if not self.reader.ParseFromFile(mesh_path, self.config): + raise LoadException(self.reader.Error() or self.reader.Warning()) + + def loads(self, mesh_string): + if not self.reader.ParseFromString(mesh_string, "", self.config): + raise LoadException(self.reader.Error() or self.reader.Warning()) + + @property + def shapes(self): + return self.reader.GetShapes() + + @property + def attrib(self): + return self.reader.GetAttrib() diff --git a/python/tests/tinyobjloader_tests/test_loader.py b/python/tests/tinyobjloader_tests/test_loader.py new file mode 100644 index 00000000..c94bb0a2 --- /dev/null +++ b/python/tests/tinyobjloader_tests/test_loader.py @@ -0,0 +1,33 @@ +import numpy as np + +from .loader import Loader, LoadException + +TWO_QUADS = """ +v 0 0 0 +v 0 0 0 +v 0 0 0 +v 0 0 0 +f 1 2 3 4 +v 46.367584 82.676086 8.867414 +v 46.524185 82.81955 8.825487 +v 46.59864 83.086678 8.88121 +v 46.461926 82.834091 8.953863 +f 5 6 7 8 +""" + + +def test_numpy_face_vertices_two_quads(): + # Set up. + loader = Loader(triangulate=False) + loader.loads(TWO_QUADS) + + shapes = loader.shapes + assert len(shapes) == 1 + + # Confidence check. + (shape,) = shapes + expected_num_face_vertices = [4, 4] + assert shape.mesh.num_face_vertices == expected_num_face_vertices + + # Test. + np.testing.assert_array_equal(shape.mesh.numpy_num_face_vertices(), expected_num_face_vertices) diff --git a/python/tests/uv.lock b/python/tests/uv.lock new file mode 100644 index 00000000..98022816 --- /dev/null +++ b/python/tests/uv.lock @@ -0,0 +1,303 @@ +version = 1 +revision = 3 +requires-python = ">=3.9" +resolution-markers = [ + "python_full_version >= '3.10'", + "python_full_version < '3.10'", +] + +[[package]] +name = "black" +version = "22.10.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click", version = "8.1.8", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "click", version = "8.3.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "mypy-extensions" }, + { name = "pathspec" }, + { name = "platformdirs", version = "4.4.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "platformdirs", version = "4.9.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, + { name = "typing-extensions", marker = "python_full_version < '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a3/89/629fca2eea0899c06befaa58dc0f49d56807d454202bb2e54bd0d98c77f3/black-22.10.0.tar.gz", hash = "sha256:f513588da599943e0cde4e32cc9879e825d58720d6557062d1098c5ad80080e1", size = 547735, upload-time = "2022-10-06T22:44:48.253Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ae/49/ea03c318a25be359b8e5178a359d47e2da8f7524e1522c74b8f74c66b6f8/black-22.10.0-1fixedarch-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:5cc42ca67989e9c3cf859e84c2bf014f6633db63d1cbdf8fdb666dcd9e77e3fa", size = 1413786, upload-time = "2022-10-07T18:06:56.738Z" }, + { url = "https://files.pythonhosted.org/packages/a6/84/5c3f3ffc4143fa7e208d745d2239d915e74d3709fdbc64c3e98d3fd27e56/black-22.10.0-1fixedarch-cp311-cp311-macosx_11_0_x86_64.whl", hash = "sha256:5d8f74030e67087b219b032aa33a919fae8806d49c867846bfacde57f43972ef", size = 1395367, upload-time = "2022-10-07T18:07:10.109Z" }, + { url = "https://files.pythonhosted.org/packages/f2/23/f4278377cabf882298b4766e977fd04377f288d1ccef706953076a1e0598/black-22.10.0-1fixedarch-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:e41a86c6c650bcecc6633ee3180d80a025db041a8e2398dcc059b3afa8382cd4", size = 1412948, upload-time = "2022-10-07T18:06:45.929Z" }, + { url = "https://files.pythonhosted.org/packages/2c/11/f2737cd3b458d91401801e83a014e87c63e8904dc063200f77826c352f54/black-22.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2039230db3c6c639bd84efe3292ec7b06e9214a2992cd9beb293d639c6402edb", size = 1248864, upload-time = "2022-10-07T18:34:56.303Z" }, + { url = "https://files.pythonhosted.org/packages/a5/5f/9cfc6dd95965f8df30194472543e6f0515a10d78ea5378426ef1546735c7/black-22.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14ff67aec0a47c424bc99b71005202045dc09270da44a27848d534600ac64fc7", size = 1542985, upload-time = "2022-10-06T22:54:23.32Z" }, + { url = "https://files.pythonhosted.org/packages/ff/ce/22281871536b3d79474fd44d48dad48f7cbc5c3982bddf6a7495e7079d00/black-22.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:819dc789f4498ecc91438a7de64427c73b45035e2e3680c92e18795a839ebb66", size = 1198188, upload-time = "2022-10-06T22:58:56.509Z" }, + { url = "https://files.pythonhosted.org/packages/e2/2f/a8406a9e337a213802aa90a3e9fbf90c86f3edce92f527255fd381309b77/black-22.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5b9b29da4f564ba8787c119f37d174f2b69cdfdf9015b7d8c5c16121ddc054ae", size = 1233231, upload-time = "2022-10-07T18:35:05.895Z" }, + { url = "https://files.pythonhosted.org/packages/b0/9e/fa912c5ae4b8eb6d36982fc8ac2d779cf944dbd7c3c1fe7a28acf462c1ed/black-22.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8b49776299fece66bffaafe357d929ca9451450f5466e997a7285ab0fe28e3b", size = 1527386, upload-time = "2022-10-06T22:54:25.636Z" }, + { url = "https://files.pythonhosted.org/packages/56/df/913d71817c7034edba25d596c54f782c2f809b6af30367d2f00309e8890a/black-22.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:21199526696b8f09c3997e2b4db8d0b108d801a348414264d2eb8eb2532e540d", size = 1201344, upload-time = "2022-10-06T22:58:58.134Z" }, + { url = "https://files.pythonhosted.org/packages/69/84/903cdf41514088d5a716538cb189c471ab34e56ae9a1c2da6b8bfe8e4dbf/black-22.10.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:974308c58d057a651d182208a484ce80a26dac0caef2895836a92dd6ebd725e0", size = 1248291, upload-time = "2022-10-07T18:34:48.48Z" }, + { url = "https://files.pythonhosted.org/packages/b9/51/403b0b0eb9fb412ca02b79dc38472469f2f88c9aacc6bb5262143e4ff0bc/black-22.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72ef3925f30e12a184889aac03d77d031056860ccae8a1e519f6cbb742736383", size = 1542631, upload-time = "2022-10-06T22:54:31.965Z" }, + { url = "https://files.pythonhosted.org/packages/ab/15/61119d166a44699827c112d7c4726421f14323c2cb7aa9f4c26628f237f9/black-22.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:432247333090c8c5366e69627ccb363bc58514ae3e63f7fc75c54b1ea80fa7de", size = 1197402, upload-time = "2022-10-06T22:59:03.766Z" }, + { url = "https://files.pythonhosted.org/packages/ce/6f/74492b8852ee4f2ad2178178f6b65bc8fc80ad539abe56c1c23eab6732e2/black-22.10.0-py3-none-any.whl", hash = "sha256:c957b2b4ea88587b46cf49d1dc17681c1e672864fd7af32fc1e9664d572b3458", size = 165761, upload-time = "2022-10-06T22:44:46.108Z" }, +] + +[[package]] +name = "click" +version = "8.1.8" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.10'", +] +dependencies = [ + { name = "colorama", marker = "python_full_version < '3.10' and sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b9/2e/0090cbf739cee7d23781ad4b89a9894a41538e4fcf4c31dcdd705b78eb8b/click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a", size = 226593, upload-time = "2024-12-21T18:38:44.339Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7e/d4/7ebdbd03970677812aac39c869717059dbb71a4cfc033ca6e5221787892c/click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2", size = 98188, upload-time = "2024-12-21T18:38:41.666Z" }, +] + +[[package]] +name = "click" +version = "8.3.1" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.10'", +] +dependencies = [ + { name = "colorama", marker = "python_full_version >= '3.10' and sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/3d/fa/656b739db8587d7b5dfa22e22ed02566950fbfbcdc20311993483657a5c0/click-8.3.1.tar.gz", hash = "sha256:12ff4785d337a1bb490bb7e9c2b1ee5da3112e94a8622f26a6c77f5d2fc6842a", size = 295065, upload-time = "2025-11-15T20:45:42.706Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl", hash = "sha256:981153a64e25f12d547d3426c367a4857371575ee7ad18df2a6183ab0545b2a6", size = 108274, upload-time = "2025-11-15T20:45:41.139Z" }, +] + +[[package]] +name = "colorama" +version = "0.4.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, +] + +[[package]] +name = "exceptiongroup" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598", size = 16740, upload-time = "2025-11-21T23:01:53.443Z" }, +] + +[[package]] +name = "iniconfig" +version = "2.1.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.10'", +] +sdist = { url = "https://files.pythonhosted.org/packages/f2/97/ebf4da567aa6827c909642694d71c9fcf53e5b504f2d96afea02718862f3/iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7", size = 4793, upload-time = "2025-03-19T20:09:59.721Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2c/e1/e6716421ea10d38022b952c159d5161ca1193197fb744506875fbb87ea7b/iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760", size = 6050, upload-time = "2025-03-19T20:10:01.071Z" }, +] + +[[package]] +name = "iniconfig" +version = "2.3.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.10'", +] +sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" }, +] + +[[package]] +name = "mypy-extensions" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/6e/371856a3fb9d31ca8dac321cda606860fa4548858c0cc45d9d1d4ca2628b/mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558", size = 6343, upload-time = "2025-04-22T14:54:24.164Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", size = 4963, upload-time = "2025-04-22T14:54:22.983Z" }, +] + +[[package]] +name = "packaging" +version = "26.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/65/ee/299d360cdc32edc7d2cf530f3accf79c4fca01e96ffc950d8a52213bd8e4/packaging-26.0.tar.gz", hash = "sha256:00243ae351a257117b6a241061796684b084ed1c516a08c48a3f7e147a9d80b4", size = 143416, upload-time = "2026-01-21T20:50:39.064Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/b9/c538f279a4e237a006a2c98387d081e9eb060d203d8ed34467cc0f0b9b53/packaging-26.0-py3-none-any.whl", hash = "sha256:b36f1fef9334a5588b4166f8bcd26a14e521f2b55e6b9de3aaa80d3ff7a37529", size = 74366, upload-time = "2026-01-21T20:50:37.788Z" }, +] + +[[package]] +name = "pathspec" +version = "1.0.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/fa/36/e27608899f9b8d4dff0617b2d9ab17ca5608956ca44461ac14ac48b44015/pathspec-1.0.4.tar.gz", hash = "sha256:0210e2ae8a21a9137c0d470578cb0e595af87edaa6ebf12ff176f14a02e0e645", size = 131200, upload-time = "2026-01-27T03:59:46.938Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ef/3c/2c197d226f9ea224a9ab8d197933f9da0ae0aac5b6e0f884e2b8d9c8e9f7/pathspec-1.0.4-py3-none-any.whl", hash = "sha256:fb6ae2fd4e7c921a165808a552060e722767cfa526f99ca5156ed2ce45a5c723", size = 55206, upload-time = "2026-01-27T03:59:45.137Z" }, +] + +[[package]] +name = "platformdirs" +version = "4.4.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.10'", +] +sdist = { url = "https://files.pythonhosted.org/packages/23/e8/21db9c9987b0e728855bd57bff6984f67952bea55d6f75e055c46b5383e8/platformdirs-4.4.0.tar.gz", hash = "sha256:ca753cf4d81dc309bc67b0ea38fd15dc97bc30ce419a7f58d13eb3bf14c4febf", size = 21634, upload-time = "2025-08-26T14:32:04.268Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/40/4b/2028861e724d3bd36227adfa20d3fd24c3fc6d52032f4a93c133be5d17ce/platformdirs-4.4.0-py3-none-any.whl", hash = "sha256:abd01743f24e5287cd7a5db3752faf1a2d65353f38ec26d98e25a6db65958c85", size = 18654, upload-time = "2025-08-26T14:32:02.735Z" }, +] + +[[package]] +name = "platformdirs" +version = "4.9.2" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.10'", +] +sdist = { url = "https://files.pythonhosted.org/packages/1b/04/fea538adf7dbbd6d186f551d595961e564a3b6715bdf276b477460858672/platformdirs-4.9.2.tar.gz", hash = "sha256:9a33809944b9db043ad67ca0db94b14bf452cc6aeaac46a88ea55b26e2e9d291", size = 28394, upload-time = "2026-02-16T03:56:10.574Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/48/31/05e764397056194206169869b50cf2fee4dbbbc71b344705b9c0d878d4d8/platformdirs-4.9.2-py3-none-any.whl", hash = "sha256:9170634f126f8efdae22fb58ae8a0eaa86f38365bc57897a6c4f781d1f5875bd", size = 21168, upload-time = "2026-02-16T03:56:08.891Z" }, +] + +[[package]] +name = "pluggy" +version = "1.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" }, +] + +[[package]] +name = "pygments" +version = "2.19.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b0/77/a5b8c569bf593b0140bde72ea885a803b82086995367bf2037de0159d924/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", size = 4968631, upload-time = "2025-06-21T13:39:12.283Z" } +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 = "pytest" +version = "8.4.2" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.10'", +] +dependencies = [ + { name = "colorama", marker = "python_full_version < '3.10' and sys_platform == 'win32'" }, + { name = "exceptiongroup", marker = "python_full_version < '3.10'" }, + { name = "iniconfig", version = "2.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "packaging", marker = "python_full_version < '3.10'" }, + { name = "pluggy", marker = "python_full_version < '3.10'" }, + { name = "pygments", marker = "python_full_version < '3.10'" }, + { name = "tomli", marker = "python_full_version < '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a3/5c/00a0e072241553e1a7496d638deababa67c5058571567b92a7eaa258397c/pytest-8.4.2.tar.gz", hash = "sha256:86c0d0b93306b961d58d62a4db4879f27fe25513d4b969df351abdddb3c30e01", size = 1519618, upload-time = "2025-09-04T14:34:22.711Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a8/a4/20da314d277121d6534b3a980b29035dcd51e6744bd79075a6ce8fa4eb8d/pytest-8.4.2-py3-none-any.whl", hash = "sha256:872f880de3fc3a5bdc88a11b39c9710c3497a547cfa9320bc3c5e62fbf272e79", size = 365750, upload-time = "2025-09-04T14:34:20.226Z" }, +] + +[[package]] +name = "pytest" +version = "9.0.2" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.10'", +] +dependencies = [ + { name = "colorama", marker = "python_full_version >= '3.10' and sys_platform == 'win32'" }, + { name = "exceptiongroup", marker = "python_full_version == '3.10.*'" }, + { name = "iniconfig", version = "2.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "packaging", marker = "python_full_version >= '3.10'" }, + { name = "pluggy", marker = "python_full_version >= '3.10'" }, + { name = "pygments", marker = "python_full_version >= '3.10'" }, + { name = "tomli", marker = "python_full_version == '3.10.*'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d1/db/7ef3487e0fb0049ddb5ce41d3a49c235bf9ad299b6a25d5780a89f19230f/pytest-9.0.2.tar.gz", hash = "sha256:75186651a92bd89611d1d9fc20f0b4345fd827c41ccd5c299a868a05d70edf11", size = 1568901, upload-time = "2025-12-06T21:30:51.014Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3b/ab/b3226f0bd7cdcf710fbede2b3548584366da3b19b5021e74f5bde2a8fa3f/pytest-9.0.2-py3-none-any.whl", hash = "sha256:711ffd45bf766d5264d487b917733b453d917afd2b0ad65223959f59089f875b", size = 374801, upload-time = "2025-12-06T21:30:49.154Z" }, +] + +[[package]] +name = "tinyobjloader-tests" +version = "0.0.1" +source = { editable = "." } +dependencies = [ + { name = "black" }, + { name = "pytest", version = "8.4.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "pytest", version = "9.0.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, +] + +[package.metadata] +requires-dist = [ + { name = "black", specifier = "==22.10.0" }, + { name = "pytest", specifier = ">=8.0" }, +] + +[[package]] +name = "tomli" +version = "2.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/82/30/31573e9457673ab10aa432461bee537ce6cef177667deca369efb79df071/tomli-2.4.0.tar.gz", hash = "sha256:aa89c3f6c277dd275d8e243ad24f3b5e701491a860d5121f2cdd399fbb31fc9c", size = 17477, upload-time = "2026-01-11T11:22:38.165Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3c/d9/3dc2289e1f3b32eb19b9785b6a006b28ee99acb37d1d47f78d4c10e28bf8/tomli-2.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b5ef256a3fd497d4973c11bf142e9ed78b150d36f5773f1ca6088c230ffc5867", size = 153663, upload-time = "2026-01-11T11:21:45.27Z" }, + { url = "https://files.pythonhosted.org/packages/51/32/ef9f6845e6b9ca392cd3f64f9ec185cc6f09f0a2df3db08cbe8809d1d435/tomli-2.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5572e41282d5268eb09a697c89a7bee84fae66511f87533a6f88bd2f7b652da9", size = 148469, upload-time = "2026-01-11T11:21:46.873Z" }, + { url = "https://files.pythonhosted.org/packages/d6/c2/506e44cce89a8b1b1e047d64bd495c22c9f71f21e05f380f1a950dd9c217/tomli-2.4.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:551e321c6ba03b55676970b47cb1b73f14a0a4dce6a3e1a9458fd6d921d72e95", size = 236039, upload-time = "2026-01-11T11:21:48.503Z" }, + { url = "https://files.pythonhosted.org/packages/b3/40/e1b65986dbc861b7e986e8ec394598187fa8aee85b1650b01dd925ca0be8/tomli-2.4.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5e3f639a7a8f10069d0e15408c0b96a2a828cfdec6fca05296ebcdcc28ca7c76", size = 243007, upload-time = "2026-01-11T11:21:49.456Z" }, + { url = "https://files.pythonhosted.org/packages/9c/6f/6e39ce66b58a5b7ae572a0f4352ff40c71e8573633deda43f6a379d56b3e/tomli-2.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1b168f2731796b045128c45982d3a4874057626da0e2ef1fdd722848b741361d", size = 240875, upload-time = "2026-01-11T11:21:50.755Z" }, + { url = "https://files.pythonhosted.org/packages/aa/ad/cb089cb190487caa80204d503c7fd0f4d443f90b95cf4ef5cf5aa0f439b0/tomli-2.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:133e93646ec4300d651839d382d63edff11d8978be23da4cc106f5a18b7d0576", size = 246271, upload-time = "2026-01-11T11:21:51.81Z" }, + { url = "https://files.pythonhosted.org/packages/0b/63/69125220e47fd7a3a27fd0de0c6398c89432fec41bc739823bcc66506af6/tomli-2.4.0-cp311-cp311-win32.whl", hash = "sha256:b6c78bdf37764092d369722d9946cb65b8767bfa4110f902a1b2542d8d173c8a", size = 96770, upload-time = "2026-01-11T11:21:52.647Z" }, + { url = "https://files.pythonhosted.org/packages/1e/0d/a22bb6c83f83386b0008425a6cd1fa1c14b5f3dd4bad05e98cf3dbbf4a64/tomli-2.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:d3d1654e11d724760cdb37a3d7691f0be9db5fbdaef59c9f532aabf87006dbaa", size = 107626, upload-time = "2026-01-11T11:21:53.459Z" }, + { url = "https://files.pythonhosted.org/packages/2f/6d/77be674a3485e75cacbf2ddba2b146911477bd887dda9d8c9dfb2f15e871/tomli-2.4.0-cp311-cp311-win_arm64.whl", hash = "sha256:cae9c19ed12d4e8f3ebf46d1a75090e4c0dc16271c5bce1c833ac168f08fb614", size = 94842, upload-time = "2026-01-11T11:21:54.831Z" }, + { url = "https://files.pythonhosted.org/packages/3c/43/7389a1869f2f26dba52404e1ef13b4784b6b37dac93bac53457e3ff24ca3/tomli-2.4.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:920b1de295e72887bafa3ad9f7a792f811847d57ea6b1215154030cf131f16b1", size = 154894, upload-time = "2026-01-11T11:21:56.07Z" }, + { url = "https://files.pythonhosted.org/packages/e9/05/2f9bf110b5294132b2edf13fe6ca6ae456204f3d749f623307cbb7a946f2/tomli-2.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7d6d9a4aee98fac3eab4952ad1d73aee87359452d1c086b5ceb43ed02ddb16b8", size = 149053, upload-time = "2026-01-11T11:21:57.467Z" }, + { url = "https://files.pythonhosted.org/packages/e8/41/1eda3ca1abc6f6154a8db4d714a4d35c4ad90adc0bcf700657291593fbf3/tomli-2.4.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:36b9d05b51e65b254ea6c2585b59d2c4cb91c8a3d91d0ed0f17591a29aaea54a", size = 243481, upload-time = "2026-01-11T11:21:58.661Z" }, + { url = "https://files.pythonhosted.org/packages/d2/6d/02ff5ab6c8868b41e7d4b987ce2b5f6a51d3335a70aa144edd999e055a01/tomli-2.4.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1c8a885b370751837c029ef9bc014f27d80840e48bac415f3412e6593bbc18c1", size = 251720, upload-time = "2026-01-11T11:22:00.178Z" }, + { url = "https://files.pythonhosted.org/packages/7b/57/0405c59a909c45d5b6f146107c6d997825aa87568b042042f7a9c0afed34/tomli-2.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8768715ffc41f0008abe25d808c20c3d990f42b6e2e58305d5da280ae7d1fa3b", size = 247014, upload-time = "2026-01-11T11:22:01.238Z" }, + { url = "https://files.pythonhosted.org/packages/2c/0e/2e37568edd944b4165735687cbaf2fe3648129e440c26d02223672ee0630/tomli-2.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7b438885858efd5be02a9a133caf5812b8776ee0c969fea02c45e8e3f296ba51", size = 251820, upload-time = "2026-01-11T11:22:02.727Z" }, + { url = "https://files.pythonhosted.org/packages/5a/1c/ee3b707fdac82aeeb92d1a113f803cf6d0f37bdca0849cb489553e1f417a/tomli-2.4.0-cp312-cp312-win32.whl", hash = "sha256:0408e3de5ec77cc7f81960c362543cbbd91ef883e3138e81b729fc3eea5b9729", size = 97712, upload-time = "2026-01-11T11:22:03.777Z" }, + { url = "https://files.pythonhosted.org/packages/69/13/c07a9177d0b3bab7913299b9278845fc6eaaca14a02667c6be0b0a2270c8/tomli-2.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:685306e2cc7da35be4ee914fd34ab801a6acacb061b6a7abca922aaf9ad368da", size = 108296, upload-time = "2026-01-11T11:22:04.86Z" }, + { url = "https://files.pythonhosted.org/packages/18/27/e267a60bbeeee343bcc279bb9e8fbed0cbe224bc7b2a3dc2975f22809a09/tomli-2.4.0-cp312-cp312-win_arm64.whl", hash = "sha256:5aa48d7c2356055feef06a43611fc401a07337d5b006be13a30f6c58f869e3c3", size = 94553, upload-time = "2026-01-11T11:22:05.854Z" }, + { url = "https://files.pythonhosted.org/packages/34/91/7f65f9809f2936e1f4ce6268ae1903074563603b2a2bd969ebbda802744f/tomli-2.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:84d081fbc252d1b6a982e1870660e7330fb8f90f676f6e78b052ad4e64714bf0", size = 154915, upload-time = "2026-01-11T11:22:06.703Z" }, + { url = "https://files.pythonhosted.org/packages/20/aa/64dd73a5a849c2e8f216b755599c511badde80e91e9bc2271baa7b2cdbb1/tomli-2.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9a08144fa4cba33db5255f9b74f0b89888622109bd2776148f2597447f92a94e", size = 149038, upload-time = "2026-01-11T11:22:07.56Z" }, + { url = "https://files.pythonhosted.org/packages/9e/8a/6d38870bd3d52c8d1505ce054469a73f73a0fe62c0eaf5dddf61447e32fa/tomli-2.4.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c73add4bb52a206fd0c0723432db123c0c75c280cbd67174dd9d2db228ebb1b4", size = 242245, upload-time = "2026-01-11T11:22:08.344Z" }, + { url = "https://files.pythonhosted.org/packages/59/bb/8002fadefb64ab2669e5b977df3f5e444febea60e717e755b38bb7c41029/tomli-2.4.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1fb2945cbe303b1419e2706e711b7113da57b7db31ee378d08712d678a34e51e", size = 250335, upload-time = "2026-01-11T11:22:09.951Z" }, + { url = "https://files.pythonhosted.org/packages/a5/3d/4cdb6f791682b2ea916af2de96121b3cb1284d7c203d97d92d6003e91c8d/tomli-2.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bbb1b10aa643d973366dc2cb1ad94f99c1726a02343d43cbc011edbfac579e7c", size = 245962, upload-time = "2026-01-11T11:22:11.27Z" }, + { url = "https://files.pythonhosted.org/packages/f2/4a/5f25789f9a460bd858ba9756ff52d0830d825b458e13f754952dd15fb7bb/tomli-2.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4cbcb367d44a1f0c2be408758b43e1ffb5308abe0ea222897d6bfc8e8281ef2f", size = 250396, upload-time = "2026-01-11T11:22:12.325Z" }, + { url = "https://files.pythonhosted.org/packages/aa/2f/b73a36fea58dfa08e8b3a268750e6853a6aac2a349241a905ebd86f3047a/tomli-2.4.0-cp313-cp313-win32.whl", hash = "sha256:7d49c66a7d5e56ac959cb6fc583aff0651094ec071ba9ad43df785abc2320d86", size = 97530, upload-time = "2026-01-11T11:22:13.865Z" }, + { url = "https://files.pythonhosted.org/packages/3b/af/ca18c134b5d75de7e8dc551c5234eaba2e8e951f6b30139599b53de9c187/tomli-2.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:3cf226acb51d8f1c394c1b310e0e0e61fecdd7adcb78d01e294ac297dd2e7f87", size = 108227, upload-time = "2026-01-11T11:22:15.224Z" }, + { url = "https://files.pythonhosted.org/packages/22/c3/b386b832f209fee8073c8138ec50f27b4460db2fdae9ffe022df89a57f9b/tomli-2.4.0-cp313-cp313-win_arm64.whl", hash = "sha256:d20b797a5c1ad80c516e41bc1fb0443ddb5006e9aaa7bda2d71978346aeb9132", size = 94748, upload-time = "2026-01-11T11:22:16.009Z" }, + { url = "https://files.pythonhosted.org/packages/f3/c4/84047a97eb1004418bc10bdbcfebda209fca6338002eba2dc27cc6d13563/tomli-2.4.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:26ab906a1eb794cd4e103691daa23d95c6919cc2fa9160000ac02370cc9dd3f6", size = 154725, upload-time = "2026-01-11T11:22:17.269Z" }, + { url = "https://files.pythonhosted.org/packages/a8/5d/d39038e646060b9d76274078cddf146ced86dc2b9e8bbf737ad5983609a0/tomli-2.4.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:20cedb4ee43278bc4f2fee6cb50daec836959aadaf948db5172e776dd3d993fc", size = 148901, upload-time = "2026-01-11T11:22:18.287Z" }, + { url = "https://files.pythonhosted.org/packages/73/e5/383be1724cb30f4ce44983d249645684a48c435e1cd4f8b5cded8a816d3c/tomli-2.4.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:39b0b5d1b6dd03684b3fb276407ebed7090bbec989fa55838c98560c01113b66", size = 243375, upload-time = "2026-01-11T11:22:19.154Z" }, + { url = "https://files.pythonhosted.org/packages/31/f0/bea80c17971c8d16d3cc109dc3585b0f2ce1036b5f4a8a183789023574f2/tomli-2.4.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a26d7ff68dfdb9f87a016ecfd1e1c2bacbe3108f4e0f8bcd2228ef9a766c787d", size = 250639, upload-time = "2026-01-11T11:22:20.168Z" }, + { url = "https://files.pythonhosted.org/packages/2c/8f/2853c36abbb7608e3f945d8a74e32ed3a74ee3a1f468f1ffc7d1cb3abba6/tomli-2.4.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:20ffd184fb1df76a66e34bd1b36b4a4641bd2b82954befa32fe8163e79f1a702", size = 246897, upload-time = "2026-01-11T11:22:21.544Z" }, + { url = "https://files.pythonhosted.org/packages/49/f0/6c05e3196ed5337b9fe7ea003e95fd3819a840b7a0f2bf5a408ef1dad8ed/tomli-2.4.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:75c2f8bbddf170e8effc98f5e9084a8751f8174ea6ccf4fca5398436e0320bc8", size = 254697, upload-time = "2026-01-11T11:22:23.058Z" }, + { url = "https://files.pythonhosted.org/packages/f3/f5/2922ef29c9f2951883525def7429967fc4d8208494e5ab524234f06b688b/tomli-2.4.0-cp314-cp314-win32.whl", hash = "sha256:31d556d079d72db7c584c0627ff3a24c5d3fb4f730221d3444f3efb1b2514776", size = 98567, upload-time = "2026-01-11T11:22:24.033Z" }, + { url = "https://files.pythonhosted.org/packages/7b/31/22b52e2e06dd2a5fdbc3ee73226d763b184ff21fc24e20316a44ccc4d96b/tomli-2.4.0-cp314-cp314-win_amd64.whl", hash = "sha256:43e685b9b2341681907759cf3a04e14d7104b3580f808cfde1dfdb60ada85475", size = 108556, upload-time = "2026-01-11T11:22:25.378Z" }, + { url = "https://files.pythonhosted.org/packages/48/3d/5058dff3255a3d01b705413f64f4306a141a8fd7a251e5a495e3f192a998/tomli-2.4.0-cp314-cp314-win_arm64.whl", hash = "sha256:3d895d56bd3f82ddd6faaff993c275efc2ff38e52322ea264122d72729dca2b2", size = 96014, upload-time = "2026-01-11T11:22:26.138Z" }, + { url = "https://files.pythonhosted.org/packages/b8/4e/75dab8586e268424202d3a1997ef6014919c941b50642a1682df43204c22/tomli-2.4.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:5b5807f3999fb66776dbce568cc9a828544244a8eb84b84b9bafc080c99597b9", size = 163339, upload-time = "2026-01-11T11:22:27.143Z" }, + { url = "https://files.pythonhosted.org/packages/06/e3/b904d9ab1016829a776d97f163f183a48be6a4deb87304d1e0116a349519/tomli-2.4.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c084ad935abe686bd9c898e62a02a19abfc9760b5a79bc29644463eaf2840cb0", size = 159490, upload-time = "2026-01-11T11:22:28.399Z" }, + { url = "https://files.pythonhosted.org/packages/e3/5a/fc3622c8b1ad823e8ea98a35e3c632ee316d48f66f80f9708ceb4f2a0322/tomli-2.4.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0f2e3955efea4d1cfbcb87bc321e00dc08d2bcb737fd1d5e398af111d86db5df", size = 269398, upload-time = "2026-01-11T11:22:29.345Z" }, + { url = "https://files.pythonhosted.org/packages/fd/33/62bd6152c8bdd4c305ad9faca48f51d3acb2df1f8791b1477d46ff86e7f8/tomli-2.4.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0e0fe8a0b8312acf3a88077a0802565cb09ee34107813bba1c7cd591fa6cfc8d", size = 276515, upload-time = "2026-01-11T11:22:30.327Z" }, + { url = "https://files.pythonhosted.org/packages/4b/ff/ae53619499f5235ee4211e62a8d7982ba9e439a0fb4f2f351a93d67c1dd2/tomli-2.4.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:413540dce94673591859c4c6f794dfeaa845e98bf35d72ed59636f869ef9f86f", size = 273806, upload-time = "2026-01-11T11:22:32.56Z" }, + { url = "https://files.pythonhosted.org/packages/47/71/cbca7787fa68d4d0a9f7072821980b39fbb1b6faeb5f5cf02f4a5559fa28/tomli-2.4.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:0dc56fef0e2c1c470aeac5b6ca8cc7b640bb93e92d9803ddaf9ea03e198f5b0b", size = 281340, upload-time = "2026-01-11T11:22:33.505Z" }, + { url = "https://files.pythonhosted.org/packages/f5/00/d595c120963ad42474cf6ee7771ad0d0e8a49d0f01e29576ee9195d9ecdf/tomli-2.4.0-cp314-cp314t-win32.whl", hash = "sha256:d878f2a6707cc9d53a1be1414bbb419e629c3d6e67f69230217bb663e76b5087", size = 108106, upload-time = "2026-01-11T11:22:34.451Z" }, + { url = "https://files.pythonhosted.org/packages/de/69/9aa0c6a505c2f80e519b43764f8b4ba93b5a0bbd2d9a9de6e2b24271b9a5/tomli-2.4.0-cp314-cp314t-win_amd64.whl", hash = "sha256:2add28aacc7425117ff6364fe9e06a183bb0251b03f986df0e78e974047571fd", size = 120504, upload-time = "2026-01-11T11:22:35.764Z" }, + { url = "https://files.pythonhosted.org/packages/b3/9f/f1668c281c58cfae01482f7114a4b88d345e4c140386241a1a24dcc9e7bc/tomli-2.4.0-cp314-cp314t-win_arm64.whl", hash = "sha256:2b1e3b80e1d5e52e40e9b924ec43d81570f0e7d09d11081b797bc4692765a3d4", size = 99561, upload-time = "2026-01-11T11:22:36.624Z" }, + { url = "https://files.pythonhosted.org/packages/23/d1/136eb2cb77520a31e1f64cbae9d33ec6df0d78bdf4160398e86eec8a8754/tomli-2.4.0-py3-none-any.whl", hash = "sha256:1f776e7d669ebceb01dee46484485f43a4048746235e683bcdffacdf1fb4785a", size = 14477, upload-time = "2026-01-11T11:22:37.446Z" }, +] + +[[package]] +name = "typing-extensions" +version = "4.15.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" }, +] diff --git a/setup.py b/setup.py index cb950871..98d6d486 100644 --- a/setup.py +++ b/setup.py @@ -12,9 +12,6 @@ except: __version__ = "2.0.0rc10" -with open("README.md", "r", encoding="utf8") as fh: - long_description = fh.read() - # The main interface is through Pybind11Extension. # * You can add cxx_std=11/14/17, and then build_ext can be removed. # * You can set include_pybind11=false to add the include directory yourself, @@ -44,7 +41,6 @@ # "Issue Tracker": "https://github.com/tinyobjloader/tinyobjloader/issues", #}, description="Tiny but powerful Wavefront OBJ loader", - long_description=long_description, long_description_content_type='text/markdown', classifiers=[ "Development Status :: 5 - Production/Stable", From 5fe03442600722a0ac7ded94c01ee61aff594a95 Mon Sep 17 00:00:00 2001 From: Paul Melnikow Date: Thu, 19 Feb 2026 18:34:49 -0500 Subject: [PATCH 02/11] Add comments --- .github/workflows/python.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml index 60664b32..260adb08 100644 --- a/.github/workflows/python.yml +++ b/.github/workflows/python.yml @@ -36,6 +36,9 @@ jobs: uses: pypa/cibuildwheel@v2.16.5 env: CIBW_ARCHS_LINUX: "x86_64" + # We do not need to support Python 3.6–3.8, and we only need + # manylinux for testing. PyPy isn't useful as this is a binary + # extension. CIBW_SKIP: pp* cp36-* cp37-* cp38-* *-musllinux_* - uses: actions/upload-artifact@v4 @@ -116,6 +119,9 @@ jobs: CIBW_ARCHS_WINDOWS: "AMD64 x86" # disable aarm64 build since its too slow to build(docker + qemu) CIBW_ARCHS_LINUX: "x86_64 i686" + # We do not need to support Python 3.6–3.8, and the quick build + # has already taken care of manylinux. PyPy isn't useful as this is + # a binary extension. CIBW_SKIP: pp* cp36-* cp37-* cp38-* *-manylinux_x86_64 - uses: actions/upload-artifact@v4 From af5bb2119ac8cb4496713445278ccf2c0630a093 Mon Sep 17 00:00:00 2001 From: Paul Melnikow Date: Thu, 19 Feb 2026 18:37:54 -0500 Subject: [PATCH 03/11] Add more tests --- python/tests/tinyobjloader_tests/loader.py | 2 +- .../tests/tinyobjloader_tests/test_loader.py | 77 +++++++++++++++++++ 2 files changed, 78 insertions(+), 1 deletion(-) diff --git a/python/tests/tinyobjloader_tests/loader.py b/python/tests/tinyobjloader_tests/loader.py index 3374e561..9d7b3dad 100644 --- a/python/tests/tinyobjloader_tests/loader.py +++ b/python/tests/tinyobjloader_tests/loader.py @@ -10,7 +10,7 @@ class Loader: A light wrapper around ObjReader to provide a convenient interface for testing. """ - def __init__(self, triangulate=True): + def __init__(self, triangulate): self.reader = ObjReader() config = ObjReaderConfig() config.triangulate = triangulate diff --git a/python/tests/tinyobjloader_tests/test_loader.py b/python/tests/tinyobjloader_tests/test_loader.py index c94bb0a2..15d1756d 100644 --- a/python/tests/tinyobjloader_tests/test_loader.py +++ b/python/tests/tinyobjloader_tests/test_loader.py @@ -15,8 +15,22 @@ f 5 6 7 8 """ +MIXED_ARITY = """ +v 0 1 1 +v 0 2 2 +v 0 3 3 +v 0 4 4 +v 0 5 5 +f 1 2 3 4 +f 1 4 5 +""" + def test_numpy_face_vertices_two_quads(): + """ + Test for https://github.com/tinyobjloader/tinyobjloader/issues/400 + """ + # Set up. loader = Loader(triangulate=False) loader.loads(TWO_QUADS) @@ -31,3 +45,66 @@ def test_numpy_face_vertices_two_quads(): # Test. np.testing.assert_array_equal(shape.mesh.numpy_num_face_vertices(), expected_num_face_vertices) + + +def test_numpy_face_vertices_two_quads_with_triangulate(): + """ + Test for https://github.com/tinyobjloader/tinyobjloader/issues/400 + """ + + # Set up. + loader = Loader(triangulate=True) + loader.loads(TWO_QUADS) + + shapes = loader.shapes + assert len(shapes) == 1 + + # Confidence check. + (shape,) = shapes + expected_num_face_vertices = [3, 3, 3, 3] + assert shape.mesh.num_face_vertices == expected_num_face_vertices + + # Test. + np.testing.assert_array_equal(shape.mesh.numpy_num_face_vertices(), expected_num_face_vertices) + + +def test_numpy_face_vertices_mixed_arity(): + """ + Test for https://github.com/tinyobjloader/tinyobjloader/issues/400 + """ + + # Set up. + loader = Loader(triangulate=False) + loader.loads(MIXED_ARITY) + + shapes = loader.shapes + assert len(shapes) == 1 + + # Confidence check. + (shape,) = shapes + expected_num_face_vertices = [4, 3] + assert shape.mesh.num_face_vertices == expected_num_face_vertices + + # Test. + np.testing.assert_array_equal(shape.mesh.numpy_num_face_vertices(), expected_num_face_vertices) + + +def test_numpy_face_vertices_mixed_arity_with_triangulate(): + """ + Test for https://github.com/tinyobjloader/tinyobjloader/issues/400 + """ + + # Set up. + loader = Loader(triangulate=True) + loader.loads(MIXED_ARITY) + + shapes = loader.shapes + assert len(shapes) == 1 + + # Confidence check. + (shape,) = shapes + expected_num_face_vertices = [3, 3, 3] + assert shape.mesh.num_face_vertices == expected_num_face_vertices + + # Test. + np.testing.assert_array_equal(shape.mesh.numpy_num_face_vertices(), expected_num_face_vertices) From c39279424955354fbdc070dd4e5be0aa6315fe79 Mon Sep 17 00:00:00 2001 From: Paul Melnikow Date: Thu, 19 Feb 2026 18:56:10 -0500 Subject: [PATCH 04/11] Add more Python tests --- .../tests/tinyobjloader_tests/test_loader.py | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/python/tests/tinyobjloader_tests/test_loader.py b/python/tests/tinyobjloader_tests/test_loader.py index 15d1756d..b173404a 100644 --- a/python/tests/tinyobjloader_tests/test_loader.py +++ b/python/tests/tinyobjloader_tests/test_loader.py @@ -108,3 +108,67 @@ def test_numpy_face_vertices_mixed_arity_with_triangulate(): # Test. np.testing.assert_array_equal(shape.mesh.numpy_num_face_vertices(), expected_num_face_vertices) + + +def test_numpy_index_array_two_quads(): + """ + Test for https://github.com/tinyobjloader/tinyobjloader/issues/401 + """ + + # Set up. + loader = Loader(triangulate=False) + loader.loads(TWO_QUADS) + + shapes = loader.shapes + assert len(shapes) == 1 + + # Confidence check. + (shape,) = shapes + expected_vertex_index = [0, 1, 2, 3, 4, 5, 6, 7] + assert [x.vertex_index for x in shape.mesh.indices] == expected_vertex_index + + # Test. + expected_numpy_indices = [0, -1, -1, 1, -1, -1, 2, -1, -1, 3, -1, -1, 4, -1, -1, 5, -1, -1, 6, -1, -1, 7, -1, -1] + np.testing.assert_array_equal(shape.mesh.numpy_indices(), expected_numpy_indices) + + +def test_numpy_vertex_array_two_quads(): + """ + Test for https://github.com/tinyobjloader/tinyobjloader/issues/401 + """ + + # Set up. + loader = Loader(triangulate=False) + loader.loads(TWO_QUADS) + + # Confidence check. + expected_vertices = [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 46.367584, + 82.676086, + 8.867414, + 46.524185, + 82.81955, + 8.825487, + 46.59864, + 83.086678, + 8.88121, + 46.461926, + 82.834091, + 8.953863, + ] + assert loader.attrib.vertices == expected_vertices + + # Test. + np.testing.assert_array_equal(loader.attrib.numpy_vertices(), expected_vertices) From 54f3ef94e4e410d325495f53c20f86336ff5821a Mon Sep 17 00:00:00 2001 From: Paul Melnikow Date: Thu, 19 Feb 2026 19:02:38 -0500 Subject: [PATCH 05/11] assert_array_almost_equal --- python/tests/tinyobjloader_tests/test_loader.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/tests/tinyobjloader_tests/test_loader.py b/python/tests/tinyobjloader_tests/test_loader.py index b173404a..c2c2a11b 100644 --- a/python/tests/tinyobjloader_tests/test_loader.py +++ b/python/tests/tinyobjloader_tests/test_loader.py @@ -171,4 +171,4 @@ def test_numpy_vertex_array_two_quads(): assert loader.attrib.vertices == expected_vertices # Test. - np.testing.assert_array_equal(loader.attrib.numpy_vertices(), expected_vertices) + np.testing.assert_array_almost_equal(loader.attrib.numpy_vertices(), expected_vertices, decimal=6) From 9ebc6a2e6cf0fb1ae147fc063a8a393032acc178 Mon Sep 17 00:00:00 2001 From: Paul Melnikow Date: Thu, 19 Feb 2026 19:06:19 -0500 Subject: [PATCH 06/11] Try decimal=5 --- python/tests/tinyobjloader_tests/test_loader.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/tests/tinyobjloader_tests/test_loader.py b/python/tests/tinyobjloader_tests/test_loader.py index c2c2a11b..41e6f6e9 100644 --- a/python/tests/tinyobjloader_tests/test_loader.py +++ b/python/tests/tinyobjloader_tests/test_loader.py @@ -171,4 +171,4 @@ def test_numpy_vertex_array_two_quads(): assert loader.attrib.vertices == expected_vertices # Test. - np.testing.assert_array_almost_equal(loader.attrib.numpy_vertices(), expected_vertices, decimal=6) + np.testing.assert_array_almost_equal(loader.attrib.numpy_vertices(), expected_vertices, decimal=5) From 24666b3ce5c8e210153bd1b03f30a940f6a12595 Mon Sep 17 00:00:00 2001 From: Paul Melnikow Date: Fri, 20 Feb 2026 13:38:38 -0500 Subject: [PATCH 07/11] Try to fix vertex test --- python/tests/tinyobjloader_tests/test_loader.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/tests/tinyobjloader_tests/test_loader.py b/python/tests/tinyobjloader_tests/test_loader.py index 41e6f6e9..d9441fef 100644 --- a/python/tests/tinyobjloader_tests/test_loader.py +++ b/python/tests/tinyobjloader_tests/test_loader.py @@ -168,7 +168,7 @@ def test_numpy_vertex_array_two_quads(): 82.834091, 8.953863, ] - assert loader.attrib.vertices == expected_vertices + np.testing.assert_array_almost_equal(loader.attrib.vertices, expected_vertices, decimal=6) # Test. - np.testing.assert_array_almost_equal(loader.attrib.numpy_vertices(), expected_vertices, decimal=5) + np.testing.assert_array_almost_equal(loader.attrib.numpy_vertices(), expected_vertices, decimal=6) From b545df667e1a6a8682b1fbca2e5e2cb54842d4df Mon Sep 17 00:00:00 2001 From: Paul Melnikow Date: Fri, 20 Feb 2026 13:45:38 -0500 Subject: [PATCH 08/11] Update a comment --- python/tests/tinyobjloader_tests/test_loader.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/python/tests/tinyobjloader_tests/test_loader.py b/python/tests/tinyobjloader_tests/test_loader.py index d9441fef..8d7b8f50 100644 --- a/python/tests/tinyobjloader_tests/test_loader.py +++ b/python/tests/tinyobjloader_tests/test_loader.py @@ -70,7 +70,9 @@ def test_numpy_face_vertices_two_quads_with_triangulate(): def test_numpy_face_vertices_mixed_arity(): """ - Test for https://github.com/tinyobjloader/tinyobjloader/issues/400 + Test for: + - https://github.com/tinyobjloader/tinyobjloader/issues/400 + - https://github.com/tinyobjloader/tinyobjloader/issues/402 """ # Set up. From 089b386dbf215b48a58eedc8a9e12251c46d82c8 Mon Sep 17 00:00:00 2001 From: Paul Melnikow Date: Fri, 20 Feb 2026 14:59:26 -0500 Subject: [PATCH 09/11] =?UTF-8?q?Move=20python=20tests=20out=20of=20python?= =?UTF-8?q?=20so=20they=20don=E2=80=99t=20end=20up=20in=20the=20wheel?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/python.yml | 14 +++++++------- {python/tests => tests/python}/README.md | 0 {python/tests => tests/python}/pyproject.toml | 0 .../python}/tinyobjloader_tests/__init__.py | 0 .../python}/tinyobjloader_tests/loader.py | 0 .../python}/tinyobjloader_tests/test_loader.py | 0 {python/tests => tests/python}/uv.lock | 0 7 files changed, 7 insertions(+), 7 deletions(-) rename {python/tests => tests/python}/README.md (100%) rename {python/tests => tests/python}/pyproject.toml (100%) rename {python/tests => tests/python}/tinyobjloader_tests/__init__.py (100%) rename {python/tests => tests/python}/tinyobjloader_tests/loader.py (100%) rename {python/tests => tests/python}/tinyobjloader_tests/test_loader.py (100%) rename {python/tests => tests/python}/uv.lock (100%) diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml index 260adb08..66d9329c 100644 --- a/.github/workflows/python.yml +++ b/.github/workflows/python.yml @@ -16,12 +16,12 @@ jobs: version: "latest" - name: Set up Python and install dependencies - working-directory: python/tests + working-directory: tests/python run: uv sync --project . --python 3.13 - name: Check code format - working-directory: python/tests - run: uv run --project . black --check .. + working-directory: tests/python + run: uv run --project . black --check ../.. build_wheels_quick: name: Build wheels for quick testing @@ -83,20 +83,20 @@ jobs: merge-multiple: true - name: Set up Python ${{ matrix.python-version }} and install dependencies - working-directory: python/tests + working-directory: tests/python run: uv sync --project . --python ${{ matrix.python-version }} - name: Install NumPy ${{ matrix.numpy-version }} - working-directory: python/tests + working-directory: tests/python run: | uv pip install --project . --only-binary :all: numpy==${{ matrix.numpy-version }} - name: Install manylinux wheel built for Python ${{ matrix.python-version }} - working-directory: python/tests + working-directory: tests/python run: uv pip install --project . ../../dist/*cp$(echo ${{ matrix.python-version }} | tr -d .)*.whl - name: Run tests - working-directory: python/tests + working-directory: tests/python run: uv run --project . pytest build_wheels_main: diff --git a/python/tests/README.md b/tests/python/README.md similarity index 100% rename from python/tests/README.md rename to tests/python/README.md diff --git a/python/tests/pyproject.toml b/tests/python/pyproject.toml similarity index 100% rename from python/tests/pyproject.toml rename to tests/python/pyproject.toml diff --git a/python/tests/tinyobjloader_tests/__init__.py b/tests/python/tinyobjloader_tests/__init__.py similarity index 100% rename from python/tests/tinyobjloader_tests/__init__.py rename to tests/python/tinyobjloader_tests/__init__.py diff --git a/python/tests/tinyobjloader_tests/loader.py b/tests/python/tinyobjloader_tests/loader.py similarity index 100% rename from python/tests/tinyobjloader_tests/loader.py rename to tests/python/tinyobjloader_tests/loader.py diff --git a/python/tests/tinyobjloader_tests/test_loader.py b/tests/python/tinyobjloader_tests/test_loader.py similarity index 100% rename from python/tests/tinyobjloader_tests/test_loader.py rename to tests/python/tinyobjloader_tests/test_loader.py diff --git a/python/tests/uv.lock b/tests/python/uv.lock similarity index 100% rename from python/tests/uv.lock rename to tests/python/uv.lock From c6d987b032d81c4c78c936973343f2eea0e25725 Mon Sep 17 00:00:00 2001 From: Paul Melnikow Date: Fri, 20 Feb 2026 15:06:41 -0500 Subject: [PATCH 10/11] Add some excludes --- pyproject.toml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index d3ba7cf3..89faa52e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,6 +14,15 @@ build-backend = "setuptools.build_meta" [tool.black] line-length = 140 +force-exclude = ''' +( + ^deps/.*$ + | ^tests/kuroga.py$ + | ^python/build/.*$ + | ^python/dist/.*$ + | ^python/tinyobjloader.egg-info/.*$ +) +''' [project] name = "tinyobjloader" From ff2e15be97dfb3f88e2082ce23ebbb220f34c135 Mon Sep 17 00:00:00 2001 From: Paul Melnikow Date: Fri, 20 Feb 2026 15:11:52 -0500 Subject: [PATCH 11/11] Reformat and exclude some python files --- fuzzer/runner.py | 3 ++- pyproject.toml | 6 ++++-- setup.py | 27 ++++++++++++++------------- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/fuzzer/runner.py b/fuzzer/runner.py index 0c06d4ba..a647d3ce 100644 --- a/fuzzer/runner.py +++ b/fuzzer/runner.py @@ -2,10 +2,11 @@ import glob import subprocess + def main(): for g in glob.glob("../tests/afl/id*"): print(g) - + cmd = ["../a.out", g] proc = subprocess.Popen(cmd) diff --git a/pyproject.toml b/pyproject.toml index 89faa52e..4f5cc706 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,8 +16,10 @@ build-backend = "setuptools.build_meta" line-length = 140 force-exclude = ''' ( - ^deps/.*$ - | ^tests/kuroga.py$ + /deps/.*$ + | /kuroga.py$ + | /config-msvc.py$ + | /config-posix.py$ | ^python/build/.*$ | ^python/dist/.*$ | ^python/tinyobjloader.egg-info/.*$ diff --git a/setup.py b/setup.py index 98d6d486..7b4daedd 100644 --- a/setup.py +++ b/setup.py @@ -1,9 +1,9 @@ # Adapted from https://github.com/pybind/python_example/blob/master/setup.py import sys -#from pybind11 import get_cmake_dir +# from pybind11 import get_cmake_dir # Available at setup time due to pyproject.toml -from pybind11.setup_helpers import Pybind11Extension#, build_ext +from pybind11.setup_helpers import Pybind11Extension # , build_ext from setuptools import setup try: @@ -22,26 +22,27 @@ # reproducible builds (https://github.com/pybind/python_example/pull/53) ext_modules = [ - Pybind11Extension("tinyobjloader", + Pybind11Extension( + "tinyobjloader", sorted(["python/bindings.cc", "python/tiny_obj_loader.cc"]), # Example: passing in the version to the compiled code - define_macros = [('VERSION_INFO', __version__)], + define_macros=[("VERSION_INFO", __version__)], cxx_std=11, - ), + ), ] setup( name="tinyobjloader", - packages=['python'], - #version=__version__, + packages=["python"], + # version=__version__, author="Syoyo Fujita", author_email="syoyo@lighttransport.com", url="https://github.com/tinyobjloader/tinyobjloader", - #project_urls={ + # project_urls={ # "Issue Tracker": "https://github.com/tinyobjloader/tinyobjloader/issues", - #}, + # }, description="Tiny but powerful Wavefront OBJ loader", - long_description_content_type='text/markdown', + long_description_content_type="text/markdown", classifiers=[ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", @@ -56,10 +57,10 @@ "Programming Language :: Python :: 3", ], ext_modules=ext_modules, - #extras_require={"test": "pytest"}, + # extras_require={"test": "pytest"}, # Currently, build_ext only provides an optional "highest supported C++ # level" feature, but in the future it may provide more features. # cmdclass={"build_ext": build_ext}, - #zip_safe=False, - #python_requires=">=3.6", + # zip_safe=False, + # python_requires=">=3.6", )