Skip to content

Commit 39c39a6

Browse files
committed
Test Python + NumPy in CI
1 parent 8a3f8b9 commit 39c39a6

File tree

9 files changed

+483
-170
lines changed

9 files changed

+483
-170
lines changed
Lines changed: 99 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,103 @@
1-
name: Build and upload to PyPI
1+
name: Python
22

33
# Build on every branch push, tag push, and pull request change:
44
on: [push, pull_request]
55

66
jobs:
7+
check_format:
8+
name: Check Python code format
9+
runs-on: ubuntu-latest
10+
steps:
11+
- uses: actions/checkout@v4
12+
13+
- name: Install uv
14+
uses: astral-sh/setup-uv@v4
15+
with:
16+
version: "latest"
17+
18+
- name: Set up Python and install dependencies
19+
working-directory: python/tests
20+
run: uv sync --project . --python 3.13
21+
22+
- name: Check code format
23+
working-directory: python/tests
24+
run: uv run --project . black --check ..
25+
26+
build_wheels_quick:
27+
name: Build wheels for quick testing
28+
runs-on: ubuntu-latest
29+
steps:
30+
- uses: actions/checkout@v4
31+
with:
32+
fetch-depth: 0
33+
fetch-tags: true # Optional, use if you use setuptools_scm
34+
35+
- name: Build wheels
36+
uses: pypa/cibuildwheel@v2.16.5
37+
env:
38+
CIBW_ARCHS_LINUX: "x86_64"
39+
CIBW_SKIP: pp* cp36-* cp37-* cp38-* *-musllinux_*
740

8-
build_wheels:
9-
name: Build wheels on ${{ matrix.os }}
41+
- uses: actions/upload-artifact@v4
42+
with:
43+
name: cibw-wheels-quick
44+
path: ./wheelhouse/*.whl
45+
46+
test_wheels:
47+
name: Test wheels with Python ${{ matrix.python-version }} and NumPy ${{ matrix.numpy-version }}
48+
needs: [build_wheels_quick]
49+
runs-on: ubuntu-latest
50+
strategy:
51+
fail-fast: false
52+
matrix:
53+
include:
54+
- python-version: "3.9"
55+
numpy-version: "1.25.2"
56+
- python-version: "3.10"
57+
numpy-version: "1.26.4"
58+
- python-version: "3.11"
59+
numpy-version: "1.26.4"
60+
- python-version: "3.12"
61+
numpy-version: "1.26.4"
62+
- python-version: "3.11"
63+
numpy-version: "2.4.2"
64+
- python-version: "3.12"
65+
numpy-version: "2.4.2"
66+
67+
steps:
68+
- uses: actions/checkout@v4
69+
70+
- name: Install uv
71+
uses: astral-sh/setup-uv@v4
72+
with:
73+
version: "latest"
74+
75+
- name: Download wheel artifacts
76+
uses: actions/download-artifact@v4
77+
with:
78+
pattern: cibw-wheels-quick
79+
path: dist
80+
merge-multiple: true
81+
82+
- name: Set up Python ${{ matrix.python-version }} and install dependencies
83+
working-directory: python/tests
84+
run: uv sync --project . --python ${{ matrix.python-version }}
85+
86+
- name: Install NumPy ${{ matrix.numpy-version }}
87+
working-directory: python/tests
88+
run: |
89+
uv pip install --project . --only-binary :all: numpy==${{ matrix.numpy-version }}
90+
91+
- name: Install manylinux wheel built for Python ${{ matrix.python-version }}
92+
working-directory: python/tests
93+
run: uv pip install --project . ../../dist/*cp$(echo ${{ matrix.python-version }} | tr -d .)*.whl
94+
95+
- name: Run tests
96+
working-directory: python/tests
97+
run: uv run --project . pytest
98+
99+
build_wheels_main:
100+
name: Build remaining wheels on ${{ matrix.os }}
10101
runs-on: ${{ matrix.os }}
11102
strategy:
12103
matrix:
@@ -20,28 +111,23 @@ jobs:
20111

21112
- name: Build wheels
22113
uses: pypa/cibuildwheel@v2.16.5
23-
# to supply options, put them in 'env', like:
24-
# env:
25-
# CIBW_SOME_OPTION: value
26-
# Disable building PyPy wheels on all platforms
27114
env:
28115
CIBW_ARCHS_MACOS: "x86_64 universal2 arm64"
29116
CIBW_ARCHS_WINDOWS: "AMD64 x86"
30117
# disable aarm64 build since its too slow to build(docker + qemu)
31118
CIBW_ARCHS_LINUX: "x86_64 i686"
32-
# it looks cibuildwheel fails to add version string to wheel file for python 3.6, so skip it
33-
CIBW_SKIP: pp*
119+
CIBW_SKIP: pp* cp36-* cp37-* cp38-* *-manylinux_x86_64
34120

35121
- uses: actions/upload-artifact@v4
36122
with:
37-
name: cibw-wheels-${{ matrix.os }}-${{ strategy.job-index }}
123+
name: cibw-wheels-main-${{ matrix.os }}-${{ strategy.job-index }}
38124
path: ./wheelhouse/*.whl
39125

40126
# It looks cibuildwheels did not clean build folder(CMake), and it results to Windows arm64 build failure(trying to reuse x86 build of .obj)
41127
# So supply separated build job for Windows ARM64 build
42128
# TODO: clean build folder using CIBW_BEFORE_ALL?
43-
build_win_arm64_wheels:
44-
name: Build ARM64 wheels on Windows.
129+
build_wheels_win_arm64:
130+
name: Build ARM64 wheels on Windows
45131
runs-on: windows-latest
46132
steps:
47133
- uses: actions/checkout@v4
@@ -51,10 +137,6 @@ jobs:
51137

52138
- name: Build wheels
53139
uses: pypa/cibuildwheel@v2.16.5
54-
# to supply options, put them in 'env', like:
55-
# env:
56-
# CIBW_SOME_OPTION: value
57-
# Disable building PyPy wheels on all platforms
58140
env:
59141
CIBW_ARCHS_WINDOWS: "ARM64"
60142
CIBW_SKIP: pp*
@@ -82,7 +164,7 @@ jobs:
82164
path: dist/*.tar.gz
83165

84166
upload_all:
85-
needs: [build_wheels, build_wheels, make_sdist]
167+
needs: [build_wheels_quick, build_wheels_main, build_wheels_win_arm64, make_sdist]
86168
runs-on: ubuntu-latest
87169
environment: release
88170
permissions:

azure-pipelines.yml

Lines changed: 0 additions & 149 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,3 @@
1-
#
2-
# Python wheels build is now done in Github Actions + Cirrus CI(for arm build)
3-
# so python build is disabled in Azure pipelines.
4-
#
5-
6-
variables:
7-
# https://cibuildwheel.readthedocs.io/en/stable/cpp_standards/
8-
# cibuildwheel now supports python 3.6+(as of 2022 Oct)
9-
#CIBW_SKIP: "pp*"
10-
CIBW_BEFORE_BUILD: "pip install pybind11"
11-
CIBW_ARCHS_LINUXBEFORE_BUILD: "pip install pybind11"
12-
# disable aarch64 build for a while since it(pulling docker aarch64 image) exceeds Azure's 60 min limit
13-
# 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
14-
#CIBW_ARCHS_LINUX: auto aarch64
15-
CIBW_ARCHS_MACOS: x86_64 universal2 arm64
16-
#CIBW_BEFORE_BUILD_MACOS: "pip install -U pip setuptools"
17-
#CIBW_BEFORE_BUILD_LINUX: "pip install -U pip setuptools"
18-
#CIBW_TEST_COMMAND: TODO "python -c \"import tinyobjloader; tinyobjloader.test()\""
19-
CIBW_BUILD_VERBOSITY: "2"
20-
#CIBW_MANYLINUX_X86_64_IMAGE: manylinux2014
21-
#CIBW_MANYLINUX_I686_IMAGE: manylinux2014
22-
231
jobs:
242
- job: unit_linux
253
pool: { vmImage: "ubuntu-latest" }
@@ -29,133 +7,6 @@ jobs:
297
make && ./tester
308
displayName: Run unit tests
319
32-
- job: python_format
33-
pool: { vmImage: "ubuntu-latest" }
34-
steps:
35-
- task: UsePythonVersion@0
36-
- script: |
37-
# 19.10b0 triggers 'cannot import name '_unicodefun' from 'click'' error.
38-
# https://stackoverflow.com/questions/71673404/importerror-cannot-import-name-unicodefun-from-click
39-
#pip install black==19.10b0
40-
#pip install black==22.3.0
41-
pip install black==22.10.0
42-
43-
black --check python/
44-
displayName: Check Python code format
45-
46-
# Disabled: python build
47-
##
48-
## Ubuntu16.04 seems now deprecated(as of 2021/12/01),
49-
## so use `ubuntu-latest`
50-
#- job: linux
51-
# pool: {vmImage: "ubuntu-latest"}
52-
# steps:
53-
# - task: UsePythonVersion@0
54-
# - bash: |
55-
# python3 -m pip install --upgrade pip
56-
# pip3 install cibuildwheel twine
57-
58-
# # Use pipx to build source dist
59-
# pip3 install pipx
60-
61-
# # Source dist
62-
# pipx run build --sdist
63-
# ls -la dist/*
64-
65-
# # build binary wheels
66-
# cibuildwheel --platform linux --output-dir wheelhouse .
67-
68-
# - task: CopyFiles@2
69-
# inputs:
70-
# contents: 'wheelhouse/**'
71-
# targetFolder: $(Build.ArtifactStagingDirectory)
72-
73-
# - task: CopyFiles@2
74-
# inputs:
75-
# contents: 'dist/**'
76-
# targetFolder: $(Build.ArtifactStagingDirectory)
77-
78-
# - task: PublishBuildArtifacts@1
79-
# inputs:
80-
# path: $(Build.ArtifactStagingDirectory)
81-
# artifactName: tinyobjDeployLinux
82-
83-
#- job: macos
84-
# pool: {vmImage: 'macOS-latest'}
85-
# variables:
86-
# # Support C++11: https://github.com/joerick/cibuildwheel/pull/156
87-
# MACOSX_DEPLOYMENT_TARGET: 10.9
88-
# steps:
89-
# - task: UsePythonVersion@0
90-
# - bash: |
91-
# python3 -m pip install --upgrade pip
92-
# pip3 install cibuildwheel
93-
# cibuildwheel --platform macos --output-dir wheelhouse .
94-
# - task: CopyFiles@2
95-
# inputs:
96-
# contents: 'wheelhouse/*.whl'
97-
# targetFolder: $(Build.ArtifactStagingDirectory)
98-
# - task: PublishBuildArtifacts@1
99-
# inputs:
100-
# path: $(Build.ArtifactStagingDirectory)
101-
# artifactName: tinyobjDeployMacOS
102-
103-
#- job: windows
104-
# pool: {vmImage: 'windows-latest'}
105-
# steps:
106-
# - task: UsePythonVersion@0
107-
# - bash: |
108-
# python -m pip install --upgrade pip
109-
# pip install cibuildwheel
110-
# cibuildwheel --platform windows --output-dir wheelhouse .
111-
# - task: CopyFiles@2
112-
# inputs:
113-
# contents: 'wheelhouse/*.whl'
114-
# targetFolder: $(Build.ArtifactStagingDirectory)
115-
# - task: PublishBuildArtifacts@1
116-
# inputs:
117-
# path: $(Build.ArtifactStagingDirectory)
118-
# artifactName: tinyobjDeployWindows
119-
120-
#- job: deployPyPI
121-
# # Based on vispy: https://github.com/vispy/vispy/blob/master/azure-pipelines.yml
122-
# pool: {vmImage: 'ubuntu-latest'}
123-
# condition: and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/tags/v'))
124-
# dependsOn:
125-
# - linux
126-
# - macos
127-
# - windows
128-
# steps:
129-
# - task: UsePythonVersion@0
130-
131-
# # TODO(syoyo): Use buildType: specific to download multiple artifacts at once?
132-
# - task: DownloadBuildArtifacts@0
133-
# inputs:
134-
# artifactName: 'tinyobjDeployLinux'
135-
# downloadPath: $(Pipeline.Workspace)
136-
137-
# - task: DownloadBuildArtifacts@0
138-
# inputs:
139-
# artifactName: 'tinyobjDeployMacOS'
140-
# downloadPath: $(Pipeline.Workspace)
141-
142-
# - task: DownloadBuildArtifacts@0
143-
# inputs:
144-
# artifactName: 'tinyobjDeployWindows'
145-
# downloadPath: $(Pipeline.Workspace)
146-
147-
# # Publish to PyPI through twine
148-
# - bash: |
149-
# cd $(Pipeline.Workspace)
150-
# find .
151-
# python -m pip install --upgrade pip
152-
# pip install twine
153-
# echo tinyobjDeployLinux/dist/*
154-
# echo tinyobjDeployLinux/wheelhouse/* tinyobjDeployMacOS/wheelhouse/* tinyobjDeployWindows/wheelhouse/*
155-
# twine upload -u "__token__" --skip-existing tinyobjDeployLinux/dist/* tinyobjDeployLinux/wheelhouse/* tinyobjDeployMacOS/wheelhouse/* tinyobjDeployWindows/wheelhouse/*
156-
# env:
157-
# TWINE_PASSWORD: $(pypiToken2)
158-
15910
trigger:
16011
branches:
16112
include:

python/tests/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# tinyobjloader Python tests
2+
3+
This folder hosts a project for running the Python binding tests.

python/tests/pyproject.toml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[project]
2+
name = "tinyobjloader-tests"
3+
version = "0.0.1"
4+
description = "Tests for tinyobjloader Python bindings"
5+
readme = "README.md"
6+
requires-python = ">=3.9"
7+
8+
dependencies = ["pytest>=8.0", "black==22.10.0"]
9+
10+
[build-system]
11+
requires = ["hatchling>=1.24"]
12+
build-backend = "hatchling.build"

python/tests/tinyobjloader_tests/__init__.py

Whitespace-only changes.
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
from tinyobjloader import ObjReader, ObjReaderConfig
2+
3+
4+
class LoadException(Exception):
5+
pass
6+
7+
8+
class Loader:
9+
"""
10+
A light wrapper around ObjReader to provide a convenient interface for testing.
11+
"""
12+
13+
def __init__(self, triangulate=True):
14+
self.reader = ObjReader()
15+
config = ObjReaderConfig()
16+
config.triangulate = triangulate
17+
self.config = config
18+
19+
def load(self, mesh_path):
20+
if not self.reader.ParseFromFile(mesh_path, self.config):
21+
raise LoadException(self.reader.Error() or self.reader.Warning())
22+
23+
def loads(self, mesh_string):
24+
if not self.reader.ParseFromString(mesh_string, "", self.config):
25+
raise LoadException(self.reader.Error() or self.reader.Warning())
26+
27+
@property
28+
def shapes(self):
29+
return self.reader.GetShapes()
30+
31+
@property
32+
def attrib(self):
33+
return self.reader.GetAttrib()

0 commit comments

Comments
 (0)