Skip to content

Migrate to pyproject - #1141

Open
notoraptor wants to merge 22 commits into
Epistimio:developfrom
notoraptor:migrate-to-pyproject
Open

Migrate to pyproject#1141
notoraptor wants to merge 22 commits into
Epistimio:developfrom
notoraptor:migrate-to-pyproject

Conversation

@notoraptor

Copy link
Copy Markdown
Collaborator

Description

Migrate Orion's packaging from setup.py/setup.cfg/versioneer to a pure pyproject.toml using hatchling as build backend and hatch-vcs for versioning. This modernizes the build system to current PEP 517/621 standards and enables the use of uv for local development.

This also fixes compatibility issues with pandas 3.x and plotly >= 6, replaces the unmaintained falcon-cors (last release 2017) with Falcon 4's built-in CORS support, and fixes several CI and test issues.

Changes

Packaging migration

  • Replace setup.py, setup.cfg, versioneer.py, MANIFEST.in, .gitattributes with pyproject.toml (hatchling + hatch-vcs)
  • Move dashboard build files into src/orion/dashboard/ so they ship as regular package data (eliminates data_files mechanism)
  • Add uv.lock for reproducible dev environments
  • Update tox.ini (build, release, packaging, devel envs), conda/meta.yaml, and .github/workflows/build.yml (fetch-depth: 0 for version detection)

PyPI direct references

  • Extract extras with git dependencies (dehb, bohb, hebo, track) into src/orion/git_extras.toml — PyPI rejects direct references in metadata, which went unnoticed before due to a setuptools bug (fixed in v68.2.0)
  • Add orion install <extra> CLI command to install these git-based extras
  • Update ImportOptional.ensure() to suggest the correct install command

Compatibility fixes

  • Replace falcon-cors with Falcon 4's built-in CORSMiddleware — unblocks conda builds on Python >= 3.10
  • Fix pandas 3.x compatibility in analysis/base.py (ranking) and algo/mofa/mofa.py (backward-compatible with pandas 2.x)
  • Fix dashboard plot rendering: decode plotly >= 6 b64-encoded arrays for compatibility with the plotly.js 2.x frontend

Dashboard CI fixes

  • Fix build path in Playwright workflow (dashboard build moved to src/orion/dashboard/build)
  • Fix fake_orion_server.py: replace removed MyCORS with Falcon 4 CORS middleware
  • Run Playwright tests once instead of 4 times (the fake server eliminates the flakiness that motivated repeated runs)
  • Remove unused dashboard-src.yml.deactivated workflow

Test fixes

  • Fix tests creating stray directories in repo root (test_runner, test_all_options)
  • Isolate test_tmpdir_is_deleted from xdist parallel workers via tempfile.gettempdir monkeypatch
  • Migrate gradient_descent_algo test plugin from setuptools to hatchling

Checklist

Tests

  • I added corresponding tests for bug fixes and new features. If possible, the tests fail without the changes
  • All new and existing tests are passing ($ tox -e py310)

Documentation

  • I have updated the relevant documentation related to my changes

Quality

  • I have read the CONTRIBUTING doc
  • My commits messages follow this format
  • My code follows the style guidelines ($ tox -e lint)

notoraptor and others added 22 commits March 26, 2026 14:52
Move compiled dashboard files from dashboard/build/ to
src/orion/dashboard/build/ so they are distributed as regular
package data instead of data_files installed under sys.prefix.

This simplifies the dashboard lookup logic (no more sys.prefix /
site.USER_BASE / local fallback) and removes the data_files
mechanism from setup.py, which was the main blocker for migrating
away from setuptools in the future.

- Add src/orion/dashboard/__init__.py with get_build_path() helper
- Simplify src/orion/core/cli/frontend.py (remove 40+ lines)
- Configure BUILD_PATH in package.json so yarn builds directly
  into src/orion/dashboard/build/
- Update setup.py, MANIFEST.in, .gitignore, .pre-commit-config.yaml
- Simplify CI dashboard deployment tests in build.yml
- Adapt dashboard-build.yml auto-compile workflow
- Add CLAUDE.md to .gitignore

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace setup.py/setup.cfg/versioneer with a pure pyproject.toml
using hatchling as build backend and hatch-vcs for versioning.

- Create pyproject.toml with all metadata, dependencies, entry points,
  and optional dependencies (with PEP 508 environment markers replacing
  sys.version_info conditionals)
- Move pytest from core dependencies to test extra
- Replace versioneer import in src/orion/core/__init__.py with
  hatch-vcs generated _version.py
- Update tox.ini: build/release/packaging/devel environments
- Update conda/meta.yaml: hatchling build, remove dataclasses/pytest-runner
- Update build.yml: add fetch-depth: 0 for version detection
- Delete setup.py, setup.cfg, versioneer.py, MANIFEST.in, .gitattributes
- Remove _version.py from git tracking (now auto-generated)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Track uv.lock for reproducible dev environments (exempt from
*.lock ignore rule).  Also ignore GEMINI.md alongside CLAUDE.md.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add pytest>=3.0.0 back to core dependencies (used by
  orion.testing.algo at runtime, not just for tests)
- Migrate gradient_descent_algo test plugin from setuptools to
  hatchling (pyproject.toml replaces setup.py/setup.cfg/MANIFEST.in)
- Update developer docs: replace setup.py develop with pip install -e,
  remove versioneer references, modernize plugin template structure
- Regenerate uv.lock

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move extras with git direct references (dehb, bohb, hebo, track) out
of pyproject.toml into src/orion/git_extras.toml to comply with PyPI
restrictions on direct references in metadata.

- Add src/orion/git_extras.toml with PEP 508 dependency specs
- Add src/orion/core/cli/install.py (`orion install <extra>`,
  `orion install --list`) that reads the file, evaluates environment
  markers, and calls pip install
- Update ImportOptional.ensure() to suggest `orion install X` for
  git extras and `pip install orion[X]` for PyPI extras
- Remove allow-direct-references from hatch metadata config
- Add packaging and tomli (Python 3.10) to core dependencies

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Drop the unmaintained falcon-cors dependency (last release 2017) which
blocked conda builds on Python >= 3.10. Replace it with Falcon 4's
built-in CORSMiddleware plus a custom OriginEnforcerMiddleware that
preserves the 403 rejection behavior for disallowed origins.

- Replace falcon-cors with falcon.CORSMiddleware + OriginEnforcerMiddleware
- Remove falcon-cors from pyproject.toml and conda/meta.yaml
- Add missing runtime deps to conda/meta.yaml (joblib, pytest,
  packaging, tomli, typing_extensions)
- Update ci_build.sh to build for Python 3.10-3.14

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- analysis/base.py: Replace groupby().apply() with groupby().transform()
  for the ranking function. pandas 3 removed include_groups=True and
  drops groupby columns from apply results. transform avoids the issue
  entirely and is simpler.
- algo/mofa/mofa.py: Use .iloc[0] to extract scalars from filtered
  DataFrames. pandas 3 no longer allows float(Series) even for
  single-element Series.

Both fixes are backward-compatible with pandas 2.x.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Fix bug in SetupWorkingDir: use base_path (/tmp/orion/) instead of
  experiment.working_dir for TemporaryDirectory dir parameter
- Use tempfile.mkdtemp() in test FakeClient instead of working_dir=""
- Redirect TestExperimentConfig working_dir paths under tmp_path

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… 82)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- install.py: return 0 consistently from main() (R1710)
- module_import.py: replace global _get_git_extras() with instance
  attribute loaded via staticmethod (W0603)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The configspace extra was missing the <1 upper bound that dehb/bohb
had in setup.py. ConfigSpace >= 1 removed the `q` parameter used by
sample-space, breaking test_configspace on Python < 3.12.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Old Orion versions (0.2.3, 0.2.4.post1) import pkg_resources, which was
removed in setuptools>=82. Force-install setuptools<82 in the virtualenv
after installing the old version to restore pkg_resources availability.
Also include uv.lock update from the ConfigSpace<1 pin.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The execute() function splits on spaces and passes args directly to
subprocess (no shell), so shell-style quotes are passed literally to pip.
Remove the single quotes around setuptools<82.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
`python -m build` produces both .tar.gz and .whl, so `find dist/ -type f`
passed both to pip install, causing a ResolutionImpossible error.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Plotly Python 6 encodes numpy arrays as base64 typed arrays
({"dtype": ..., "bdata": ...}) in to_json(), but the dashboard
frontend uses plotly.js 2.x which does not support this format.

Decode b64 typed arrays back to plain JSON lists before sending
API responses. The decoding is a no-op with older plotly versions
that already produce plain lists.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- fake_orion_server.py: replace removed MyCORS with
  falcon.CORSMiddleware + OriginEnforcerMiddleware (broken since fa80f45)
- test_demo.py::test_tmpdir_is_deleted: monkeypatch tempfile.gettempdir
  to use pytest tmp_path, preventing parallel xdist workers from
  polluting the shared /tmp/orion/ directory

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The tests were originally run multiple times because the real Orion
backend on CI was too slow and caused flaky timeouts. Since the
introduction of the fake server (pre-recorded JSON responses), the
backend responds near-instantly, making repeated runs unnecessary.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant