Skip to content

Commit cc463b7

Browse files
committed
[v0.1.0] 2025-09-06
πŸŽ‰++ PyPI Package Distribution ++ πŸŽ‰ - PyHelios now available on PyPI with `pip install pyhelios` ## Package Distribution - Added comprehensive wheel building infrastructure with GitHub Actions CI/CD - Cross-platform wheel support for Windows, macOS (x86_64 + ARM64), and Linux - Automated CUDA toolkit installation and multi-architecture GPU support - Smart platform detection for optimal plugin selection (macOS excludes GPU, Windows/Linux includes GPU when available) - Added wheel preparation script for native library packaging - Added MANIFEST.in for proper PyPI package structure ## Bug Fixes - Fixed PluginMetadata constructor calls in build_helios.py - Corrected plugin metadata parameter handling for GPU/visualization exclusions - Enhanced build system robustness for different plugin configurations
1 parent b6b7855 commit cc463b7

12 files changed

Lines changed: 1010 additions & 18 deletions

File tree

β€Ž.claude/agents/code-reviewer.mdβ€Ž

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ When reviewing code changes since the last commit, you will:
1515
3. Evaluate code against established best practices for the specific language and framework
1616
4. Look for potential security vulnerabilities, performance issues, and maintainability concerns
1717
5. Check for consistency with existing codebase patterns and conventions
18+
6. **ALWAYS check git status** to identify any new files that should be added to version control
1819

1920
**CRITICAL ISSUES TO CATCH:**
2021
- **Incomplete implementations**: Placeholder comments like "TODO", "FIXME", or unfinished logic
@@ -24,6 +25,9 @@ When reviewing code changes since the last commit, you will:
2425
- **Performance anti-patterns**: Inefficient algorithms, memory leaks, unnecessary database queries
2526
- **Error handling gaps**: Missing exception handling, inadequate error messages, swallowed exceptions
2627
- **Testing gaps**: Untestable code, missing edge case coverage, brittle test dependencies
28+
- **Git control gaps**: New files that should be added to version control but are missing from git
29+
- **Syntax errors**: Always run syntax checks on new Python files (python -m py_compile file.py)
30+
- **Missing imports**: Check that all required modules are imported in new files
2731

2832
**BEST PRACTICES ENFORCEMENT:**
2933
- Code readability and self-documenting practices
Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
name: Build Wheels
2+
3+
on:
4+
push:
5+
tags: [ 'v*' ]
6+
workflow_dispatch:
7+
8+
jobs:
9+
build_wheels:
10+
name: Build wheels on ${{ matrix.os }}
11+
runs-on: ${{ matrix.os }}
12+
strategy:
13+
matrix:
14+
include:
15+
- os: ubuntu-24.04
16+
arch: x86_64
17+
- os: windows-2022
18+
arch: AMD64
19+
- os: macos-13
20+
arch: x86_64
21+
- os: macos-14
22+
arch: arm64
23+
24+
steps:
25+
- name: Checkout PyHelios
26+
uses: actions/checkout@v4
27+
with:
28+
submodules: recursive
29+
fetch-depth: 0 # Required for setuptools-scm
30+
31+
- name: Set up Python
32+
uses: actions/setup-python@v4
33+
with:
34+
python-version: '3.8' # Use lowest supported version for compatibility
35+
36+
- name: Setup MSVC (Windows)
37+
if: runner.os == 'Windows'
38+
uses: ilammy/msvc-dev-cmd@v1
39+
40+
- name: Install Helios dependencies (Linux)
41+
if: runner.os == 'Linux'
42+
run: |
43+
cd helios-core/utilities
44+
sudo bash dependencies.sh ALL
45+
46+
- name: Install Helios dependencies (macOS)
47+
if: runner.os == 'macOS'
48+
run: |
49+
cd helios-core/utilities
50+
# Install base + visualization dependencies (no GPU/CUDA for macOS builds)
51+
bash dependencies.sh BASE
52+
bash dependencies.sh VIS
53+
54+
- name: Debug environment (macOS)
55+
if: runner.os == 'macOS'
56+
run: |
57+
echo "=== Directory structure ==="
58+
ls -la
59+
echo "=== PyHelios build scripts ==="
60+
ls -la build_scripts/
61+
echo "=== Helios core ==="
62+
ls -la helios-core/ || echo "helios-core not found"
63+
echo "=== Python version and location ==="
64+
python --version
65+
which python
66+
echo "=== Environment ==="
67+
env | grep -E "(PYTHON|PATH)" | head -10
68+
69+
- name: Install CUDA Toolkit (Windows)
70+
if: runner.os == 'Windows'
71+
shell: powershell
72+
run: |
73+
# Download CUDA 12.6 installer
74+
Invoke-WebRequest -Uri "https://developer.download.nvidia.com/compute/cuda/12.6.2/network_installers/cuda_12.6.2_windows_network.exe" -OutFile "cuda_installer.exe"
75+
# Install CUDA toolkit components needed for compilation
76+
Start-Process -FilePath ".\cuda_installer.exe" -ArgumentList "-s","nvcc_12.6","cudart_12.6","nvrtc_12.6","nvrtc_dev_12.6","visual_studio_integration_12.6" -Wait
77+
# Add CUDA to PATH for subsequent steps
78+
echo "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.6\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
79+
80+
- name: Install cibuildwheel and repair tools
81+
run: |
82+
python -m pip install --upgrade pip
83+
python -m pip install cibuildwheel
84+
# Install platform-specific wheel repair tools
85+
if [ "${{ runner.os }}" = "Linux" ]; then
86+
python -m pip install auditwheel
87+
elif [ "${{ runner.os }}" = "macOS" ]; then
88+
python -m pip install delocate
89+
fi
90+
91+
- name: Build wheels
92+
run: python -m cibuildwheel --output-dir wheelhouse
93+
env:
94+
# Build for Python 3.8+ on all platforms
95+
CIBW_BUILD: cp38-* cp39-* cp310-* cp311-* cp312-*
96+
97+
# Skip 32-bit builds and PyPy
98+
CIBW_SKIP: "*-win32 *-manylinux_i686 *-musllinux* pp*"
99+
100+
# Architecture configuration based on runner
101+
CIBW_ARCHS: ${{ matrix.arch }}
102+
103+
# Platform-specific build commands with broad CUDA compatibility
104+
CIBW_BEFORE_BUILD_MACOS: "python build_scripts/prepare_wheel.py --buildmode release --nogpu --verbose"
105+
CIBW_BEFORE_BUILD_WINDOWS: "set CMAKE_RC_COMPILER= && set PYHELIOS_CUDA_ARCHITECTURES=50;60;70;75;80;86;90 && python build_scripts/prepare_wheel.py --buildmode release --verbose"
106+
CIBW_BEFORE_BUILD_LINUX: "export PYHELIOS_CUDA_ARCHITECTURES=50;60;70;75;80;86;90 && python build_scripts/prepare_wheel.py --buildmode release --verbose"
107+
108+
# Test wheel installation
109+
CIBW_TEST_COMMAND: "python -c 'import pyhelios; print(f\"PyHelios {pyhelios.__version__} imported successfully\")'"
110+
CIBW_TEST_REQUIRES: "pytest"
111+
112+
# Repair wheels to bundle dependencies
113+
CIBW_REPAIR_WHEEL_COMMAND_MACOS: "delocate-wheel --require-archs {delocate_archs} -w {dest_dir} -v {wheel}"
114+
CIBW_REPAIR_WHEEL_COMMAND_LINUX: "auditwheel repair -w {dest_dir} {wheel}"
115+
116+
- name: Debug build failure
117+
if: failure()
118+
run: |
119+
echo "=== Build Failure Diagnostics ==="
120+
echo "Build directory contents:"
121+
find pyhelios_build -name "*.so" -o -name "*.dll" -o -name "*.dylib" 2>/dev/null || echo "No build directory found"
122+
echo ""
123+
echo "Plugin directory contents:"
124+
ls -la pyhelios/plugins/ 2>/dev/null || echo "No plugins directory found"
125+
echo ""
126+
echo "Wheel directory contents:"
127+
ls -la wheelhouse/ 2>/dev/null || echo "No wheelhouse directory found"
128+
echo ""
129+
echo "Python environment:"
130+
python --version
131+
pip list | grep -E "(cibuildwheel|auditwheel|delocate)" || echo "Wheel tools not found"
132+
133+
- name: Upload wheels as artifacts
134+
uses: actions/upload-artifact@v4
135+
with:
136+
name: wheels-${{ matrix.os }}-${{ matrix.arch }}
137+
path: wheelhouse/*.whl
138+
retention-days: 7
139+
140+
test_wheels:
141+
name: Test wheels on ${{ matrix.os }} Python ${{ matrix.python-version }}
142+
runs-on: ${{ matrix.os }}
143+
needs: build_wheels
144+
strategy:
145+
matrix:
146+
include:
147+
- os: ubuntu-24.04
148+
python-version: '3.8'
149+
- os: ubuntu-24.04
150+
python-version: '3.11'
151+
- os: windows-2022
152+
python-version: '3.8'
153+
- os: windows-2022
154+
python-version: '3.11'
155+
- os: macos-13
156+
python-version: '3.8'
157+
- os: macos-13
158+
python-version: '3.11'
159+
- os: macos-14
160+
python-version: '3.8'
161+
- os: macos-14
162+
python-version: '3.11'
163+
164+
steps:
165+
- name: Set up Python ${{ matrix.python-version }}
166+
uses: actions/setup-python@v4
167+
with:
168+
python-version: ${{ matrix.python-version }}
169+
170+
- name: Download wheels
171+
uses: actions/download-artifact@v4
172+
with:
173+
pattern: wheels-*
174+
merge-multiple: true
175+
path: wheelhouse
176+
177+
- name: Install wheel
178+
run: |
179+
python -m pip install --upgrade pip
180+
python -m pip install --find-links wheelhouse --no-index pyhelios
181+
182+
- name: Test basic functionality
183+
run: |
184+
python -c "
185+
import pyhelios
186+
from pyhelios import Context, WeberPennTree, WPTType
187+
from pyhelios.types import vec2, vec3, RGBcolor
188+
print(f'PyHelios version: {pyhelios.__version__}')
189+
190+
# Test basic Context operations
191+
context = Context()
192+
center = vec3(1, 2, 3)
193+
color = RGBcolor(0.5, 0.5, 0.5)
194+
uuid = context.addPatch(center=center, size=vec2(1, 1), color=color)
195+
print(f'Added patch with UUID: {uuid}')
196+
197+
# Test plugin availability reporting
198+
from pyhelios.plugins import print_plugin_status
199+
print_plugin_status()
200+
"
201+
202+
publish:
203+
name: Publish to PyPI
204+
runs-on: ubuntu-latest
205+
needs: [build_wheels, test_wheels]
206+
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
207+
environment:
208+
name: pypi
209+
url: https://pypi.org/p/pyhelios
210+
permissions:
211+
id-token: write # Required for trusted publishing
212+
213+
steps:
214+
- name: Download all wheels
215+
uses: actions/download-artifact@v4
216+
with:
217+
pattern: wheels-*
218+
merge-multiple: true
219+
path: wheelhouse
220+
221+
- name: Publish to PyPI
222+
uses: pypa/gh-action-pypi-publish@release/v1
223+
with:
224+
packages-dir: wheelhouse/
225+
verify-metadata: false # Skip metadata verification due to dynamic versioning

β€Ž.gitignoreβ€Ž

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ build/
1212
# Auto-generated version file (setuptools-scm)
1313
pyhelios/_version.py
1414

15+
# Auto-generated documentation
16+
docs/generated/
17+
1518
# IDEs and editors
1619
.vscode/
1720
.idea/

β€ŽMANIFEST.inβ€Ž

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Include build scripts
2+
include build_scripts/*.py
3+
include build_scripts/build_helios
4+
5+
# Include documentation
6+
include README.md
7+
include docs/CHANGELOG.md
8+
graft docs/examples
9+
recursive-exclude docs/generated *
10+
11+
# Include configuration files
12+
include pyproject.toml
13+
include requirements*.txt
14+
include pytest.ini
15+
16+
# Include native libraries that get built
17+
recursive-include pyhelios/plugins *.dll *.so *.dylib
18+
19+
# Exclude test and development files
20+
recursive-exclude tests *
21+
recursive-exclude .github *
22+
recursive-exclude pyhelios_build *
23+
exclude test_*.py
24+
exclude .gitignore
25+
exclude .gitmodules

β€ŽREADME.mdβ€Ž

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<br><br>
22

3-
[![Test Linux](https://github.com/PlantSimulationLab/PyHelios/actions/workflows/pytest-linux.yml/badge.svg?branch=master)](https://github.com/PlantSimulationLab/PyHelios/actions/workflows/pytest-linux.yml) [![Test Windows](https://github.com/PlantSimulationLab/PyHelios/actions/workflows/pytest-windows.yml/badge.svg?branch=master)](https://github.com/PlantSimulationLab/PyHelios/actions/workflows/pytest-windows.yml) [![Test MacOS](https://github.com/PlantSimulationLab/PyHelios/actions/workflows/pytest-macos.yml/badge.svg?branch=master)](https://github.com/PlantSimulationLab/PyHelios/actions/workflows/pytest-macos.yml)
3+
[![Build Wheels](https://github.com/PlantSimulationLab/PyHelios/actions/workflows/build-wheels.yml/badge.svg?branch=master)](https://github.com/PlantSimulationLab/PyHelios/actions/workflows/build-wheels.yml) [![Test Linux](https://github.com/PlantSimulationLab/PyHelios/actions/workflows/pytest-linux.yml/badge.svg?branch=master)](https://github.com/PlantSimulationLab/PyHelios/actions/workflows/pytest-linux.yml) [![Test Windows](https://github.com/PlantSimulationLab/PyHelios/actions/workflows/pytest-windows.yml/badge.svg?branch=master)](https://github.com/PlantSimulationLab/PyHelios/actions/workflows/pytest-windows.yml) [![Test MacOS](https://github.com/PlantSimulationLab/PyHelios/actions/workflows/pytest-macos.yml/badge.svg?branch=master)](https://github.com/PlantSimulationLab/PyHelios/actions/workflows/pytest-macos.yml)
44

55
<div align="center">
66
<img src="https://raw.githubusercontent.com/PlantSimulationLab/PyHelios/master/docs/images/PyHelios_logo_whiteborder.png" alt="" width="300" />
@@ -22,6 +22,21 @@ See the Helios C++ documentation for a more in-depth description of Helios: http
2222

2323
### Installation
2424

25+
**Easy Install (Recommended):**
26+
```bash
27+
pip install pyhelios
28+
```
29+
30+
This installs pre-built PyHelios with platform-appropriate plugins:
31+
- **macOS**: All plugins except GPU-accelerated ones (automatically detected)
32+
- **Windows/Linux**: All plugins including GPU acceleration (when hardware supports it)
33+
34+
PyHelios will gracefully handle GPU features - if you don't have CUDA-capable hardware, GPU plugins will display helpful error messages with setup instructions.
35+
36+
### Build from Source
37+
38+
If you need to customize plugins or build from source:
39+
2540
#### Windows
2641

2742
**Prerequisites:**
@@ -82,6 +97,35 @@ source helios-core/utilities/dependencies.sh
8297
pip install -e .
8398
```
8499

100+
### GPU Features Setup
101+
102+
If you want to use GPU-accelerated features (radiation modeling, aerial LiDAR), ensure you have:
103+
104+
**Requirements:**
105+
- NVIDIA GPU with CUDA support
106+
- NVIDIA drivers installed
107+
- CUDA Toolkit (version 11.8 or 12.x)
108+
109+
**Verification:**
110+
```bash
111+
nvidia-smi # Should show GPU information
112+
nvcc --version # Should show CUDA compiler version
113+
```
114+
115+
**Testing GPU Features:**
116+
```python
117+
from pyhelios import Context, RadiationModel
118+
119+
context = Context()
120+
try:
121+
radiation = RadiationModel(context)
122+
print("GPU radiation modeling available!")
123+
except RuntimeError as e:
124+
print(f"GPU features unavailable: {e}")
125+
```
126+
127+
If GPU features fail, PyHelios will provide specific guidance on installation and setup requirements.
128+
85129
### First Example
86130

87131
```python

0 commit comments

Comments
Β (0)