1{
2 lib,
3 buildPythonPackage,
4 fetchFromGitHub,
5
6 cmake,
7 ninja,
8 # build-system
9 hatchling,
10 scikit-build-core,
11 hatch-vcs,
12 nanobind,
13 # deps
14 antlr4-python3-runtime,
15 atopile-easyeda2kicad,
16 black,
17 case-converter,
18 cookiecutter,
19 dataclasses-json,
20 deprecated,
21 fastapi-github-oidc,
22 freetype-py,
23 gitpython,
24 kicad-python,
25 kicadcliwrapper,
26 matplotlib,
27 mcp,
28 more-itertools,
29 natsort,
30 numpy,
31 ordered-set,
32 pathvalidate,
33 pint,
34 posthog,
35 psutil,
36 pydantic-settings,
37 pygls,
38 questionary,
39 requests,
40 rich,
41 ruamel-yaml,
42 ruff,
43 semver,
44 sexpdata,
45 shapely,
46 truststore,
47 typer,
48 urllib3,
49 zstd,
50 pythonOlder,
51
52 # tests
53 pytestCheckHook,
54
55 pytest-benchmark,
56 pytest-timeout,
57 pytest-datafiles,
58 pytest-xdist,
59 hypothesis,
60 writableTmpDirAsHomeHook,
61}:
62
63buildPythonPackage rec {
64 pname = "atopile";
65 version = "0.12.4";
66 pyproject = true;
67
68 disabled = pythonOlder "3.13";
69
70 src = fetchFromGitHub {
71 owner = "atopile";
72 repo = "atopile";
73 tag = "v${version}";
74 hash = "sha256-SB6D1738t3kQJI+V9ClVsByHm6BsLl078N/wDAHJE6E=";
75 };
76
77 build-system = [
78 hatchling
79 scikit-build-core
80 hatch-vcs
81 nanobind
82 ];
83
84 dontUseCmakeConfigure = true; # skip cmake configure invocation
85
86 nativeBuildInputs = [
87 cmake
88 ninja
89 ];
90
91 dependencies = [
92 antlr4-python3-runtime
93 atopile-easyeda2kicad
94 black # used as a dependency
95 case-converter
96 cookiecutter
97 dataclasses-json
98 deprecated
99 fastapi-github-oidc
100 freetype-py
101 gitpython
102 kicad-python
103 kicadcliwrapper
104 matplotlib
105 mcp
106 more-itertools
107 natsort
108 numpy
109 ordered-set
110 pathvalidate
111 pint
112 posthog
113 psutil
114 pydantic-settings
115 pygls
116 questionary
117 requests
118 rich
119 ruamel-yaml
120 ruff
121 semver
122 sexpdata
123 shapely
124 truststore
125 typer
126 urllib3
127 zstd
128 ];
129
130 pythonRelaxDeps = [
131 "posthog"
132 "prompt-toolkit"
133 "zstd"
134 ];
135
136 pythonImportsCheck = [ "atopile" ];
137
138 nativeCheckInputs = [
139 writableTmpDirAsHomeHook
140 pytestCheckHook
141 pytest-xdist
142 pytest-benchmark
143 pytest-datafiles
144 pytest-timeout
145 hypothesis
146 ];
147
148 preCheck = ''
149 # do not report worker logs to filee
150 substituteInPlace test/conftest.py \
151 --replace-fail "worker_id =" "worker_id = None #"
152
153 # unrecognized flags
154 substituteInPlace pyproject.toml \
155 --replace-fail "--html=artifacts/test-report.html" "" \
156 --replace-fail "--self-contained-html" "" \
157 --replace-fail "--numprocesses=auto" "" \
158
159 # Replace this function call that cause test to hang
160 substituteInPlace \
161 test/cli/test_packages.py \
162 test/library/test_names.py \
163 test/test_examples.py \
164 test/test_parse_utils.py \
165 --replace-fail "_repo_root()" "Path('$(pwd)')"
166
167 # Fix crash due to empty list in fixture tests
168 substituteInPlace \
169 test/test_examples.py \
170 test/test_parse_utils.py \
171 --replace-fail "p.stem" "p.stem if isinstance(p, Path) else p"
172 '';
173
174 disabledTestPaths = [
175 # timouts
176 "test/test_cli.py"
177 "test/cli/test_packages.py"
178 "test/end_to_end/test_net_naming.py"
179 "test/end_to_end/test_pcb_export.py"
180 "test/exporters/bom/test_bom.py"
181 "test/front_end/test_front_end_pick.py"
182 "test/libs/picker/test_pickers.py"
183 ];
184
185 disabledTests = [
186 # timeout
187 "test_build_error_logging"
188 "test_performance_mifs_bus_params"
189 "test_resistor"
190 "test_reserved_attrs"
191 "test_examples_build"
192 "test_net_names_deterministic"
193 # requires internet
194 "test_simple_pick"
195 "test_simple_negative_pick"
196 "test_jlcpcb_pick_resistor"
197 "test_jlcpcb_pick_capacitor"
198 "test_regression_rp2040_usb_diffpair_full"
199 "test_model_translations"
200
201 # FileNotFoundError: [Errno 2] No such file or directory: '/build/source/build/logs/latest'
202 "test_muster_diamond_dependencies"
203 "test_muster_disconnected_components"
204 "test_muster_register_decorator"
205 "test_muster_select_skips_targets_with_failed_dependencies"
206 "test_muster_select_skips_targets_with_partial_failed_dependencies"
207 "test_muster_select_yields_targets_with_all_successful_dependencies"
208 "test_muster_specific_targets_with_dependencies"
209 ];
210
211 # in order to use pytest marker, we need to use ppytestFlagsArray
212 # using pytestFlags causes `ERROR: file or directory not found: slow`
213 pytestFlagsArray = [
214 "-m='not slow and not not_in_ci and not regression'"
215 "--timeout=10" # any test taking long, timouts with more than 60s
216 "--benchmark-disable"
217 "--tb=line"
218 ];
219
220 doCheck = true;
221
222 meta = {
223 description = "Design circuit boards with code";
224 homepage = "https://atopile.io";
225 downloadPage = "https://github.com/atopile/atopile";
226 changelog = "https://github.com/atopile/atopile/releases/tag/${src.tag}";
227 license = with lib.licenses; [ mit ];
228 maintainers = with lib.maintainers; [ sigmanificient ];
229 mainProgram = "ato";
230 };
231}