Files
eco/pyproject.toml
Henrik Lemke 0c47051feb
Publish to PyPI / Build distribution (push) Failing after 10s
Publish to PyPI / Publish to PyPI (push) Skipped
Finish PyPI/GitHub/RTD release setup: rename to eco-suite, add CI, fix broken base import
- pyproject.toml: rename package eco -> eco-suite (eco was already taken on
  PyPI); move escape-fel + dask-jobqueue into core dependencies since
  eco.elements.assembly unconditionally needs them (a bare `import eco` was
  broken without the psi extra, verified in a clean venv); drop git-URL
  installs for scilog/escape-fel now that both are on public PyPI; update
  project URLs to the GitHub mirror and ReadTheDocs.
- Add LICENSE (GPLv3, matching what pyproject.toml already declared).
- Add MANIFEST.in to keep the vendored eco/elements/textual test/ subproject
  out of the sdist (it was already excluded from the wheel, but not the
  sdist, via the existing packages.find/exclude-package-data config).
- Add .github/workflows/publish.yml (PyPI Trusted Publishing on v*.*.* tags)
  and .githooks/pre-push (auto-bump a patch tag on push to master), mirroring
  the escape-fel release setup.
2026-09-09 17:01:14 +02:00

198 lines
7.1 KiB
TOML

# Modern packaging config for eco (replaces the old setup.py).
# Modelled on the sibling project escape-fel: setuptools + setuptools-scm,
# PEP 621 metadata, package discovery restricted to the `eco` namespace.
#
# Dependency tiers (see the review notes):
# * [project.dependencies] -> "safe" + "normal" deps: pure-python or
# compiled packages that have first-class wheels on PyPI AND conda-forge.
# * [project.optional-dependencies] -> everything "complicated":
# - gui : desktop / notebook widget stacks
# - sheets : Google-sheets / spreadsheet export helpers
# - hardware : Raspberry-Pi / serial hardware (import-guarded in code)
# - psi : git-only PSI/lab packages (no PyPI release)
# - docs : Sphinx doc build
# - dev : test / lint tooling
#
# NOT declared here at all (installed via the conda environment instead):
# cam-server (cam_server), psi-bsread (bsread), mflow, jungfrau_utils,
# py-elog (elog), psi-datahub (datahub), xrayutilities, xraylib,
# data_api, cta_lib, detector_integration_api, bufferutils, bernina_urdf.
# These are PSI-internal / conda-channel-only; putting them in `dependencies`
# would make `pip install eco` fail on any clean machine.
[build-system]
requires = ["setuptools>=64", "setuptools-scm>=8"]
build-backend = "setuptools.build_meta"
[project]
name = "eco-suite"
description = "Experiment control and orchestration framework for the SwissFEL Bernina endstation"
readme = "Readme.md"
requires-python = ">=3.8"
license = { text = "GPL-3.0-or-later" }
authors = [{ name = "Paul Scherrer Institute" }]
maintainers = [{ name = "Bernina beamline" }]
keywords = ["swissfel", "beamline", "epics", "controls", "bernina", "psi"]
classifiers = [
"Programming Language :: Python :: 3",
"Operating System :: POSIX :: Linux",
"Intended Audience :: Science/Research",
"Topic :: Scientific/Engineering :: Physics",
]
dynamic = ["version"]
# --- "safe" + "normal" tiers: available on PyPI and conda-forge ------------
dependencies = [
"numpy",
"scipy",
"pandas",
"matplotlib",
"h5py",
"pyepics",
"pyzmq",
"requests",
"urllib3",
"colorama",
"rich",
"textual",
"tqdm",
"tabulate",
"wcwidth",
"pint",
"python-dateutil",
"six",
"markdown",
"ansi2html",
"ascii_graph",
"inputimeout",
"simple-pid",
"simple-term-menu",
"cachebox",
"lazy-object-proxy",
"numpy-stl",
"diffcalc-core",
"IPython",
# eco/elements/assembly.py unconditionally imports eco.acquisition.scan_data,
# which imports escape.swissfel -- so these two are load-bearing for a bare
# `import eco`, not optional. escape-fel is a public PyPI package (the
# `psi` extra below used to pull it via git, which both duplicated it here
# and left the base import broken without [psi] installed -- verified by
# `pip install .` + `import eco` in a clean venv).
"escape-fel",
"dask-jobqueue",
]
[project.optional-dependencies]
gui = [
"ipywidgets",
"ipyevents",
"qtpy",
# qtpy is only a shim over whichever Qt binding is present, so the binding
# itself has to be declared too -- and it must be one that ships
# QtWebEngine, since the native SVG panel window
# (eco.utilities.svg_interactor._build_qt_window) is a QWebEngineView.
# PyQt5 without PyQtWebEngine is exactly the broken combination that made
# `Assembly.show()` fall back to the browser view (qtpy defaults to PyQt5
# in a bare process, so it is not enough that some other binding works).
"PyQt5",
"PyQtWebEngine",
"qt-material",
"dash",
"flask",
"timg",
"pyttsx3",
"pillow",
"av",
]
sheets = [
"gspread",
"gspread-dataframe",
"gspread-formatting",
"oauth2client",
"openpyxl",
"xlwt",
]
hardware = [
"pyserial",
"gpiozero",
"adafruit-blinka",
"adafruit-circuitpython-ads1x15",
]
# Optional front-ends for `eco --ui lab` / `eco --ui voila`. Not required for
# the default IPython shell; install on demand.
lab = ["jupyterlab"]
voila = ["voila"]
# PSI-internal packages with no public PyPI release, plus scilog (which *is*
# on PyPI as `scilog`, so no git URL needed -- verified). escape-fel used to
# live here too, but it's both on PyPI and load-bearing for a bare `import
# eco` (see `dependencies` above), so it moved there instead.
psi = [
"scilog",
]
docs = [
"sphinx>=7,<9",
"furo>=2024.1.29",
"myst-parser>=2",
"sphinx-copybutton>=0.5",
"sphinx-design>=0.5",
]
dev = [
"pytest",
"eco[docs]",
]
# The `eco` command re-execs IPython (a core dependency) with the eco profile
# and runs the packaged startup script. Defaults come from an .ecorc file.
# The launcher lives in the top-level module `eco_cli` (NOT inside the eco
# package) so that starting it does not import eco/__init__.py.
[project.scripts]
eco = "eco_cli:main"
[project.urls]
Homepage = "https://github.com/paulscherrerinstitute/eco-suite"
Documentation = "https://eco-suite.readthedocs.io"
Repository = "https://github.com/paulscherrerinstitute/eco-suite"
Issues = "https://github.com/paulscherrerinstitute/eco-suite/issues"
"Internal source (PSI)" = "https://gitea.psi.ch/Bernina/eco"
# --- Package discovery ----------------------------------------------------
# Only ship the `eco` package tree. The nested vendored project under
# "eco/elements/textual test/" and the top-level tests/ are excluded (their
# dir names are not importable identifiers, but we exclude explicitly too).
[tool.setuptools.packages.find]
where = ["."]
include = ["eco*"]
exclude = ["tests*", "eco.elements.textual*", "*.tests*"]
# The standalone launcher module (top-level, not part of the eco package).
# include-package-data=false keeps wheel contents deterministic: only the
# discovered .py modules plus the explicit package-data below are shipped
# (otherwise setuptools sweeps in stray files like the vendored
# "eco/elements/textual test/" project tree).
[tool.setuptools]
py-modules = ["eco_cli"]
include-package-data = false
# Ship runtime data files that live inside the eco package tree but aren't
# .py source: the Voila/JupyterLab dashboard notebook, the namespace alias
# JSON files NamespaceCollection globs for (eco.aliases.aliases), and the
# beamline synoptic SVG that Namespace._show_svg points at (eco.bernina.bernina).
# include-package-data=false (below) means setuptools does NOT auto-sweep
# these in, so anything loaded from disk at runtime must be listed here
# explicitly or it silently goes missing from every install.
[tool.setuptools.package-data]
eco = ["voila_app.ipynb", "jupyterlab_app.ipynb"]
"eco.aliases" = ["namespaces/*.json"]
"eco.bernina" = ["beamline_interact.svg"]
# setuptools-scm's file-finder otherwise sweeps every git-tracked file under a
# package dir into the wheel. Keep the stray vendored experiment and *bak
# scratch files out.
[tool.setuptools.exclude-package-data]
"eco.elements" = ["textual test/*", "textual test/**", "*bak*.py"]
[tool.setuptools_scm]
# Version is derived from git tags (e.g. 0.0.2). A local venv build without
# git metadata falls back to this value.
fallback_version = "0.0.2"