forked from sbryngelson/ANEForge
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathpyproject.toml
More file actions
146 lines (134 loc) · 6.83 KB
/
Copy pathpyproject.toml
File metadata and controls
146 lines (134 loc) · 6.83 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
[build-system]
requires = ["hatchling", "hatch-vcs"]
build-backend = "hatchling.build"
[project]
name = "aneforge"
# The version is derived from the git tag at build time (hatch-vcs); cut a release
# by tagging vX.Y.Z. aneforge.__version__ reads it back from the installed metadata.
dynamic = ["version"]
description = "Direct Apple Neural Engine (ANE) backend. A CoreML-free Python frontend that compiles operator graphs into a single fused e5rt program and dispatches them to the ANE."
readme = "README.md"
# The core package (aneforge/*.py, aneforge/_bridges/*.py) imports only numpy as a
# third-party dependency. Several core modules use PEP 604 unions (``int | None``)
# in runtime-evaluated function signatures without ``from __future__ import
# annotations``, which requires Python >= 3.10. Developed/verified on Python 3.14.
requires-python = ">=3.10"
license = "MIT"
license-files = ["LICENSE"]
authors = [{ name = "Spencer Bryngelson", email = "shb@gatech.edu" }]
keywords = ["apple-neural-engine", "ane", "apple-silicon", "machine-learning", "inference", "espresso", "e5rt"]
# Only numpy is imported by the core package. torch / torchvision / transformers
# are LAZY imports inside aneforge.models (pretrained loaders only) and are NOT
# required to import or run aneforge itself; install them yourself if you call the
# pretrained-model loaders. mlx / torch are only used by the GPU-comparison
# benchmark tools (see the [project.optional-dependencies] `bench` extra).
dependencies = [
"numpy",
]
# IMPORTANT (platform): aneforge only *runs* on Apple Silicon macOS. It dispatches
# to the ANE through the built ``libane_e5rt_dispatch.dylib`` (one-time clang++
# build, see README "Install"). It cannot dispatch on non-Apple hardware; the wheel
# installs anywhere and imports (the off-device tooling works), but compiling or
# dispatching to the ANE needs the dylib + Apple Silicon.
classifiers = [
"Development Status :: 3 - Alpha",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
"Operating System :: MacOS :: MacOS X",
"Intended Audience :: Science/Research",
"Topic :: Scientific/Engineering :: Artificial Intelligence",
]
[project.optional-dependencies]
# Optional deps for the GPU/CPU cross-comparison benchmark tools, which compare the
# ANE against the Apple GPU via MLX and use torch for reference numerics. Not needed
# by the aneforge package itself.
bench = [
"mlx>=0.31",
"torch",
]
# Pretrained model loaders (aneforge.models.load / load_resnet18), the LLM/MoE GGUF
# loader (aneforge.moe.load_gguf needs gguf), and the diffusion examples. Imported
# lazily; only install if you use them.
models = [
"torch",
"torchvision",
"transformers",
"gguf",
]
# ONNX model import (aneforge.onnx.load_onnx / onnx_to_tensor). Imported lazily; the
# core package stays numpy-only. Only install if you import ONNX models.
onnx = ["onnx>=1.16"]
# MLPerf-style benchmark harness (bench/mlperf/): the real MLCommons LoadGen driver plus
# the ResNet-50 workload deps (ONNX import, onnxruntime reference, torchvision demo model,
# Pillow preprocessing). loadgen is a C++ build if no wheel is available for your Python.
mlperf = [
"mlcommons-loadgen",
"onnx>=1.16",
"onnxruntime>=1.18",
"torchvision",
"pillow",
"opencv-python", # exact MLPerf ResNet-50 preprocessing (cv2 INTER_AREA resize + decode)
]
# Linting + test runner (CI and local dev). ruff is the linter; the corpus/pytest
# suites need real ANE hardware to run.
dev = [
"ruff",
"pyright==1.1.410", # type checker; pinned so a new release can't add errors out from under CI
"pylint", # CI 2-space + trailing-whitespace lock (W0311/C0303); see .github/workflows/ci.yml
"pre-commit", # local hooks mirroring CI; see .pre-commit-config.yaml
"pytest",
"pytest-forked", # per-test process isolation (--forked); see tests/conftest.py
"onnx>=1.16", # ONNX importer tests (tests/test_onnx.py); lazy in aneforge.onnx
"onnxruntime>=1.18", # reference numerics for ONNX importer tests
]
[project.urls]
Homepage = "https://github.com/sbryngelson/ANEForge"
Repository = "https://github.com/sbryngelson/ANEForge"
Documentation = "https://aneforge.readthedocs.io"
Issues = "https://github.com/sbryngelson/ANEForge/issues"
[tool.hatch.version]
source = "vcs"
# PyPI/TestPyPI reject PEP 440 local versions (the "+gHASH" suffix hatch-vcs adds to
# untagged dev builds). Drop the local segment so dev builds (e.g. 0.1.5.dev23) are
# uploadable; tagged releases (vX.Y.Z) are unaffected — they have no local segment.
raw-options = { local_scheme = "no-local-version" }
[tool.hatch.build.hooks.vcs]
version-file = "aneforge/_version.py"
[tool.hatch.build.targets.wheel]
# Ship the aneforge package and everything tracked under it — including the e5rt
# dispatch shim SOURCE in aneforge/_lib/ (ane_e5rt_dispatch.mm + e5rt_api.h +
# build.sh), which loads at runtime via _runtime.py::_find_dylib. The built
# libane_e5rt_dispatch.dylib is gitignored (compiled per-machine by
# `sh aneforge/_lib/build.sh`), so hatchling excludes it automatically.
packages = ["aneforge"]
[tool.pytest.ini_options]
# Collect only the tracked correctness suites. The RE/paper test tooling (fuzzers,
# capability census) lives in the gitignored utils/ dir and is intentionally excluded.
testpaths = ["tests"]
# Run each test in its own forked subprocess: every compile allocates an ANE program
# and a single process accumulates them across the suite (the training/streaming tests
# build hundreds), approaching the per-PID program limit and causing sporadic
# late-suite failures. A fresh process per test resets that; fork overhead is negligible
# beside the ANE compile time. Requires pytest-forked (in the `dev` extra); the env it
# needs is set in tests/conftest.py.
addopts = "--forked"
[tool.ruff]
line-length = 120
indent-width = 2 # tinygrad-compact: the codebase is 2-space (also enforced via pylint W0311 in CI)
# Lint the shippable code only; utils/ is gitignored local tooling.
extend-exclude = ["utils"]
[tool.ruff.lint]
# E4/E7/E9 + F (pyflakes), plus flake8-comprehensions (C4) and flake8-builtins (A).
select = ["E4", "E7", "E9", "F", "C4", "A"]
# Minus the dense-style idioms this codebase uses deliberately: multi-import lines,
# module imports after a sys.path shim, semicolon / colon multi-statements, assigned
# lambdas, and short math names (l, I, af, ...).
ignore = ["E401", "E402", "E701", "E702", "E703", "E731", "E741"]
[tool.ruff.lint.flake8-builtins]
# `input` and `compile` are intentional public-API op names (af.input / af.compile),
# like torch/tinygrad; allow them while A still catches accidental builtin shadowing.
builtins-ignorelist = ["input", "compile"]