-
Notifications
You must be signed in to change notification settings - Fork 164
Expand file tree
/
Copy pathpyproject.toml
More file actions
236 lines (230 loc) · 11.9 KB
/
Copy pathpyproject.toml
File metadata and controls
236 lines (230 loc) · 11.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
[build-system]
# >=77: PEP 639 SPDX `license = "MIT"` string + `license-files` support
requires = ["setuptools>=77"]
build-backend = "setuptools.build_meta"
[project]
name = "hypertools"
version = "1.0.0"
description = "A python package for visualizing and manipulating high-dimensional data"
readme = "readme.md"
# PEP 639 SPDX expression (the `license = { text = ... }` table form is
# deprecated and made setuptools emit a build warning; audit X5-010)
license = "MIT"
license-files = ["LICENSE"]
authors = [
{ name = "Contextual Dynamics Lab", email = "contextualdynamics@gmail.com" },
]
requires-python = ">=3.10"
keywords = [
"visualization", "dimensionality reduction", "high-dimensional data",
"machine learning", "data science", "clustering", "alignment",
"hyperalignment", "PCA", "UMAP", "time series", "plotting",
]
classifiers = [
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Science/Research",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
# NOTE: no 3.14 classifier -- CI tests 3.10-3.13 only, and dependency
# resolution is not a compatibility test for a compiled scientific
# stack. Add a 3.14 job + behavioral tests before advertising it
# (2026-07 release review, issue #5).
"Topic :: Scientific/Engineering :: Visualization",
"Topic :: Multimedia :: Graphics",
"Operating System :: POSIX",
"Operating System :: Unix",
"Operating System :: MacOS",
"Operating System :: Microsoft :: Windows",
]
dependencies = [
# NOTE (2026-07 red-team): these floors must be co-installable with the
# numpy>=2.0 floor below. matplotlib<3.9, pandas<2.2.2, numba<0.60 and
# scikit-learn<1.4.2 each require/only-support numpy<2, so a floor-pinned
# resolver (`uv --resolution lowest`, a minimum-pinned lockfile) would hit
# ResolutionImpossible. Default (newest-first) installs are unaffected.
"scikit-learn>=1.4.2", # 1.4.2 is the first with numpy-2 runtime support
# pandas 3.0+ supported as of datawrangler 0.5.0 (data-wrangler#30/#31 fixed
# the pandas-3 type detection); the <3 ceiling is lifted (CI exercises
# pandas 3.x). 2.2.2 is the first pandas that supports numpy 2 (2.2.0/.1
# require numpy<2).
"pandas>=2.2.2",
"seaborn>=0.13.0",
"matplotlib>=3.9.0", # 3.8.x requires numpy<2; 3.9.0 supports numpy 2
"scipy>=1.13.0",
"numpy>=2.0.0",
"umap-learn>=0.5.5",
# umap-learn's own numba floor (>=0.51) lets uv resolve unbuildable
# numba 0.53/llvmlite 0.36 on py3.12+ (audit X5-003); pin a real floor.
# numba<0.60 requires numpy<1.27; 0.61.0 is the first supporting py3.10-3.13
# with numpy 2 (matches requires-python>=3.10 + the 3.13 CI cell).
"numba>=0.61.0",
"requests>=2.31.0",
"dill>=0.3.8",
"ipympl>=0.9.3",
# Timeseries forecasting (hyp.predict 'Kalman'/'ARIMA') and Kalman imputation
# (hyp.impute 'Kalman'). Both are pure-python and lightweight, so they live in
# the base install -- `hyp.predict(x, model='Kalman')` / `model='ARIMA'` work
# out of the box with a bare `pip install hypertools` (QC 2026-07: Colab hit
# ModuleNotFoundError when these were extras-only). The heavier skaters laplace
# ensemble stays in the [predict] extra.
"pykalman>=0.11",
"statsmodels>=0.14",
# HyperTools 1.0: data-wrangling core (funnel/stack/unstack/format detection, model
# dispatch, text+HF embeddings). 0.5.0+ adds pandas 3.0 support (dw#30/#31).
# https://github.com/ContextLab/data-wrangler
"pydata-wrangler>=0.5.1",
]
[project.optional-dependencies]
# Interactive plotly backend (auto-enabled on Colab/Kaggle, where plotly ships
# preinstalled; local users opt in with `pip install hypertools[interactive]`).
# plotly>=6.1.1 + kaleido>=1.0 pinned together: kaleido 1.x requires plotly>=6.1.1
# for static image export (write_image); with plotly<6.1.1, an unbounded kaleido
# resolves to 1.x and fig.write_image() breaks (QC 2026-07: Colab's preinstalled
# plotly 5.24.1 + kaleido 1.3.0 produced exactly this failure). Raising the plotly
# floor upgrades such environments to a compatible pair.
interactive = ["plotly>=6.1.1", "kaleido>=1.0"]
# Transformer / sentence-transformers text embeddings via datawrangler's hf extra
# (torch/transformers/sentence-transformers/tokenizers/datasets). Opt-in; never in base install.
text = ["pydata-wrangler[hf]>=0.5.1"]
# Extra forecasters beyond the base install: the skaters laplace ensemble
# (hyp.predict model='Laplace'). Kalman filtering (pykalman) and ARIMA
# (statsmodels) moved to the core dependencies above, so 'Kalman'/'ARIMA' --
# and GaussianProcess, sklearn autoregression, and the sklearn imputers --
# all work without this extra.
predict = ["skaters>=0.11"]
# Hugging Face timeseries forecasting (hyp.predict model='Chronos'): pulls
# torch. Opt-in; never in base install.
predict-hf = ["chronos-forecasting>=2.0"]
# hyp.load Excel support (.xlsx via openpyxl). .xls (legacy OLE format)
# needs xlrd, which is NOT bundled here -- a friendly ImportError points
# users at `pip install xlrd` if they hit a .xls file without it.
io = ["openpyxl>=3.1.0"]
# NOTE: there is deliberately no `legacy`/`deepdish` extra. Loading legacy
# (<1.0) hosted .geo files stored in the deepdish/HDF5 format needs `deepdish`,
# which is unmaintained and imports only under numpy<2 (it references the
# numpy-2-removed `np.ComplexWarning`) -- so it cannot coexist with this
# package's `numpy>=2.0` core requirement. hyp.load() of such a file raises a
# friendly HypertoolsIOError telling the user to read it in a numpy<2 env.
# 3-D `density=` smooth iso-surfaces (marching cubes) via scikit-image.
# Opt-in; without it, plot(..., density=True) on 3-D matplotlib plots falls
# back to a translucent scatter "fog" and emits a UserWarning suggesting
# this extra (or backend='plotly', which always renders a full go.Volume
# without needing scikit-image at all).
density3d = ["scikit-image>=0.22.0"]
# hyp.reduce's six torch-backed autoencoder reducers (GH #162,
# hypertools/reduce/autoencoders.py: Autoencoder, DeepAutoencoder,
# SparseAutoencoder, ConvolutionalAutoencoder, SequenceAutoencoder,
# VariationalAutoencoder). Opt-in; never in base install -- resolving one
# of these reduce= names without this extra raises a friendly ImportError.
torch = ["torch>=2.0"]
# hyp.load('kaggle/<owner>/<dataset>') (GH #116): anonymous dataset
# downloads via kagglehub. Opt-in; never in base install -- resolving a
# 'kaggle/...' name without this extra raises a friendly ImportError.
kaggle = ["kagglehub>=0.3"]
# hyp.io.lsl_stream() (GH #130): Lab Streaming Layer input, via pylsl (which
# wraps the native liblsl library -- https://labstreaminglayer.org). Opt-in;
# never in base install -- calling lsl_stream() without this extra raises a
# friendly ImportError. pylsl's macOS/most-Linux wheels bundle liblsl; see
# .github/workflows/test.yml for the per-OS native-library provisioning
# needed in CI.
lsl = ["pylsl>=1.16"]
# hyp.tools.text2mat vectorizer=/semantic= gensim wrappers (GH #198):
# Word2Vec/Doc2Vec/FastText (vectorizer stage) and LdaModel/LsiModel/
# HdpModel (semantic stage), resolved after the scikit-learn registry and
# before the Hugging Face fallback. Opt-in; never in base install --
# requesting a gensim name without this extra raises a friendly
# ImportError. gensim>=4.3 supports numpy>=2.
gensim = ["gensim>=4.3"]
dev = [
"pytest>=8.0.0",
"pytest-cov>=4.1.0",
"nbformat>=5.9.0",
"nbclient>=0.9.0",
"ipykernel>=6.29.0",
# match the [interactive] pin (kaleido 1.x needs plotly>=6.1.1 for write_image)
"plotly>=6.1.1",
"kaleido>=1.0",
# real Hugging Face streaming tests (tests/test_streaming.py)
"datasets>=2.20.0",
# kill hung tests (kaleido subprocesses have wedged for 6h on Windows CI)
"pytest-timeout>=2.3.0",
# exercise the skaters laplace forecaster in CI (pykalman/statsmodels are now
# core deps, so Kalman/ARIMA are always available); [predict-hf] stays out of
# CI (model download) -- its tests importorskip
"skaters>=0.11",
# exercise hyp.load .xlsx support (tests/test_load_sources.py)
"openpyxl>=3.1.0",
# tests/test_packaging_artifacts.py builds real wheel/sdist artifacts via
# `python -m build --no-isolation`; CI run 29582796739 errored all 10 of
# those tests because `build` was not installed (it was only ever present
# locally by happenstance)
"build>=1.2",
# exercise the 3-D density= iso-surface path (tests/test_density.py);
# the scikit-image-absent fallback is exercised separately, in a
# subprocess with a real import-system blocker (see that test module)
"scikit-image>=0.22.0",
# exercise the six torch-backed autoencoder reducers (GH #162,
# tests/test_autoencoders.py); the torch-absent ImportError path is
# exercised separately, in a subprocess with a real import-system
# blocker (see that test module)
"torch>=2.0",
# exercise hyp.load('kaggle/<owner>/<dataset>') (GH #116,
# tests/test_load_538_kaggle.py)
"kagglehub>=0.3",
# exercise hyp.io.lsl_stream() (GH #130, tests/test_lsl_streaming.py);
# see .github/workflows/test.yml for the per-OS native liblsl
# provisioning needed for pylsl to actually import/connect in CI
"pylsl>=1.16",
# exercise the gensim vectorizer=/semantic= wrappers (GH #198,
# tests/test_gensim_text.py); the gensim-absent ImportError path is
# exercised separately, in a subprocess with a real import-system
# blocker (see that test module)
"gensim>=4.3",
]
[project.urls]
Homepage = "https://github.com/ContextLab/hypertools"
Documentation = "https://hypertools.readthedocs.io"
Repository = "https://github.com/ContextLab/hypertools"
Changelog = "https://github.com/ContextLab/hypertools/blob/master/CHANGELOG.md"
Issues = "https://github.com/ContextLab/hypertools/issues"
# NOTE (2026-07 audit X5-packaging-001): the include pattern must be
# ["hypertools", "hypertools.*"] with namespaces disabled -- the previous
# ["hypertools*"] glob plus implicit namespace-package discovery swept ANY
# hypertools*-named directory in the repo root (e.g. a local hypertools-dev/
# virtualenv) into the wheel and sdist.
[tool.setuptools.packages.find]
include = ["hypertools", "hypertools.*"]
namespaces = false
# ship the published-defaults config (2026-07 audit X5-packaging-002 /
# X7-code-org-rest-004: without this, config.ini was missing from wheels and
# sdists, so get_default_options() was silently empty in every pip install)
[tool.setuptools.package-data]
"hypertools.core" = ["config.ini"]
# vendored Noto Sans (SIL OFL 1.1) -- the bundled default sans-serif face, so
# plots render identically on every platform instead of falling back to
# whatever the machine happens to have installed. Ship the license and
# provenance README alongside the font, as the OFL requires. Also ship the
# Apache-2.0 license text + third-party notices for the vendored Apache-2.0
# code (brainiak.py, ppca.py), as Apache 2.0 requires on redistribution.
"hypertools.external" = [
"fonts/*.ttf", "fonts/OFL.txt", "fonts/README.md",
"LICENSE-APACHE-2.0.txt", "THIRD_PARTY_NOTICES.md",
]
[tool.pytest.ini_options]
testpaths = ["tests"]
# safety net for hung external processes (kaleido/ffmpeg/network): no test
# legitimately takes over 20 minutes; without this a wedged kaleido burned a
# 6-hour Windows CI job. thread method: kaleido hangs are in native calls.
timeout = 1200
timeout_method = "thread"
# 'bigdata' tests download hundreds of MB over a real network connection
# (e.g. the Google Drive large-file interstitial test); excluded from the
# default/CI run, opt in with `pytest -m bigdata`.
markers = [
"bigdata: real multi-hundred-MB network download (deselected by default)",
]
# a user-supplied `-m` on the command line (e.g. `pytest -m bigdata`)
# overrides this addopts value entirely, re-including bigdata tests.
addopts = "-m 'not bigdata'"