acprof 0.3.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (704) hide show
  1. acprof/__init__.py +3 -0
  2. acprof/__main__.py +5 -0
  3. acprof/_bundle/.dockerignore +20 -0
  4. acprof/_bundle/LICENSE +202 -0
  5. acprof/_bundle/NOTICE +43 -0
  6. acprof/_bundle/acprof/__init__.py +3 -0
  7. acprof/_bundle/acprof/__main__.py +5 -0
  8. acprof/_bundle/acprof/analysis/__init__.py +1 -0
  9. acprof/_bundle/acprof/analysis/audit.py +276 -0
  10. acprof/_bundle/acprof/analysis/comparison.py +364 -0
  11. acprof/_bundle/acprof/analysis/compatibility.py +223 -0
  12. acprof/_bundle/acprof/analysis/conditions.py +185 -0
  13. acprof/_bundle/acprof/analysis/independent_comparison.py +191 -0
  14. acprof/_bundle/acprof/analysis/latency_model.py +1106 -0
  15. acprof/_bundle/acprof/analysis/latency_report.py +577 -0
  16. acprof/_bundle/acprof/analysis/model.py +276 -0
  17. acprof/_bundle/acprof/analysis/precision.py +51 -0
  18. acprof/_bundle/acprof/analysis/uncertainty.py +144 -0
  19. acprof/_bundle/acprof/application/__init__.py +1 -0
  20. acprof/_bundle/acprof/application/download.py +14 -0
  21. acprof/_bundle/acprof/application/errors.py +5 -0
  22. acprof/_bundle/acprof/application/notifications.py +302 -0
  23. acprof/_bundle/acprof/application/preparation.py +333 -0
  24. acprof/_bundle/acprof/application/resources.py +66 -0
  25. acprof/_bundle/acprof/application/run.py +462 -0
  26. acprof/_bundle/acprof/application/terminal_log.py +136 -0
  27. acprof/_bundle/acprof/artifact_layout.py +261 -0
  28. acprof/_bundle/acprof/artifacts.py +161 -0
  29. acprof/_bundle/acprof/capabilities.py +404 -0
  30. acprof/_bundle/acprof/cli/__init__.py +1 -0
  31. acprof/_bundle/acprof/cli/audit.py +74 -0
  32. acprof/_bundle/acprof/cli/auto.py +41 -0
  33. acprof/_bundle/acprof/cli/backfill_compute.py +498 -0
  34. acprof/_bundle/acprof/cli/compare.py +34 -0
  35. acprof/_bundle/acprof/cli/coverage.py +70 -0
  36. acprof/_bundle/acprof/cli/doctor.py +47 -0
  37. acprof/_bundle/acprof/cli/inspect.py +101 -0
  38. acprof/_bundle/acprof/cli/load.py +190 -0
  39. acprof/_bundle/acprof/cli/main.py +64 -0
  40. acprof/_bundle/acprof/cli/model_store.py +22 -0
  41. acprof/_bundle/acprof/cli/plot.py +211 -0
  42. acprof/_bundle/acprof/cli/posthoc.py +113 -0
  43. acprof/_bundle/acprof/cli/probe.py +186 -0
  44. acprof/_bundle/acprof/cli/report.py +35 -0
  45. acprof/_bundle/acprof/cli/results.py +37 -0
  46. acprof/_bundle/acprof/cli/run.py +54 -0
  47. acprof/_bundle/acprof/cli/stats.py +94 -0
  48. acprof/_bundle/acprof/cli/tui.py +65 -0
  49. acprof/_bundle/acprof/config.py +177 -0
  50. acprof/_bundle/acprof/container/__init__.py +1 -0
  51. acprof/_bundle/acprof/container/compat/__init__.py +1 -0
  52. acprof/_bundle/acprof/container/compat/transformers_dynamic.py +54 -0
  53. acprof/_bundle/acprof/container/compat/transformers_model_types.json +1091 -0
  54. acprof/_bundle/acprof/container/compute_profile_runner.py +392 -0
  55. acprof/_bundle/acprof/container/download_model.py +165 -0
  56. acprof/_bundle/acprof/container/execution.py +73 -0
  57. acprof/_bundle/acprof/container/handlers/__init__.py +298 -0
  58. acprof/_bundle/acprof/container/handlers/audio.py +743 -0
  59. acprof/_bundle/acprof/container/handlers/custom_pipeline.py +74 -0
  60. acprof/_bundle/acprof/container/handlers/cv.py +321 -0
  61. acprof/_bundle/acprof/container/handlers/diffusion.py +728 -0
  62. acprof/_bundle/acprof/container/handlers/moss.py +64 -0
  63. acprof/_bundle/acprof/container/handlers/multimodal.py +609 -0
  64. acprof/_bundle/acprof/container/handlers/nlp.py +747 -0
  65. acprof/_bundle/acprof/container/handlers/onnx_tasks.py +231 -0
  66. acprof/_bundle/acprof/container/handlers/onnxruntime.py +90 -0
  67. acprof/_bundle/acprof/container/handlers/structured.py +185 -0
  68. acprof/_bundle/acprof/container/handlers/timeseries.py +178 -0
  69. acprof/_bundle/acprof/container/load_policy.py +81 -0
  70. acprof/_bundle/acprof/container/loading_quality.py +48 -0
  71. acprof/_bundle/acprof/container/local_pipeline.py +31 -0
  72. acprof/_bundle/acprof/container/model_files.py +280 -0
  73. acprof/_bundle/acprof/container/model_probe.py +80 -0
  74. acprof/_bundle/acprof/container/onnx_session.py +150 -0
  75. acprof/_bundle/acprof/container/runtime_manifest.py +150 -0
  76. acprof/_bundle/acprof/container/runtime_validate.py +156 -0
  77. acprof/_bundle/acprof/container/server.py +209 -0
  78. acprof/_bundle/acprof/container/torch_execution.py +55 -0
  79. acprof/_bundle/acprof/container/validation.py +172 -0
  80. acprof/_bundle/acprof/cpu_affinity.py +35 -0
  81. acprof/_bundle/acprof/dependency_locks.py +129 -0
  82. acprof/_bundle/acprof/experiment.py +356 -0
  83. acprof/_bundle/acprof/extensions/__init__.py +294 -0
  84. acprof/_bundle/acprof/extensions/builtin/manifest.json +3591 -0
  85. acprof/_bundle/acprof/extensions/onnxruntime/manifest.json +191 -0
  86. acprof/_bundle/acprof/extensions/schema.py +238 -0
  87. acprof/_bundle/acprof/extensions/transformers/4.57.6.json +1639 -0
  88. acprof/_bundle/acprof/extensions/transformers/5.10.4.json +1812 -0
  89. acprof/_bundle/acprof/failures.py +115 -0
  90. acprof/_bundle/acprof/hardware_conditions.py +18 -0
  91. acprof/_bundle/acprof/hf_download.py +143 -0
  92. acprof/_bundle/acprof/hf_endpoints.py +62 -0
  93. acprof/_bundle/acprof/hf_transport.py +238 -0
  94. acprof/_bundle/acprof/host/__init__.py +1 -0
  95. acprof/_bundle/acprof/host/automation.py +161 -0
  96. acprof/_bundle/acprof/host/client.py +520 -0
  97. acprof/_bundle/acprof/host/collection_history.py +77 -0
  98. acprof/_bundle/acprof/host/collection_workflow.py +285 -0
  99. acprof/_bundle/acprof/host/command.py +119 -0
  100. acprof/_bundle/acprof/host/container_lifecycle.py +225 -0
  101. acprof/_bundle/acprof/host/container_state.py +128 -0
  102. acprof/_bundle/acprof/host/coverage_state.py +259 -0
  103. acprof/_bundle/acprof/host/detect.py +669 -0
  104. acprof/_bundle/acprof/host/docker_runtime.py +359 -0
  105. acprof/_bundle/acprof/host/doctor.py +158 -0
  106. acprof/_bundle/acprof/host/env_utils.py +233 -0
  107. acprof/_bundle/acprof/host/execution_conditions.py +87 -0
  108. acprof/_bundle/acprof/host/gpu_device.py +66 -0
  109. acprof/_bundle/acprof/host/hardware_conditions.py +130 -0
  110. acprof/_bundle/acprof/host/images/__init__.py +1 -0
  111. acprof/_bundle/acprof/host/images/dependencies.py +169 -0
  112. acprof/_bundle/acprof/host/images/environment.py +313 -0
  113. acprof/_bundle/acprof/host/images/graph.py +143 -0
  114. acprof/_bundle/acprof/host/images/identity.py +6 -0
  115. acprof/_bundle/acprof/host/images/inventory.py +445 -0
  116. acprof/_bundle/acprof/host/images/runtime.py +457 -0
  117. acprof/_bundle/acprof/host/images/scan.py +154 -0
  118. acprof/_bundle/acprof/host/input_plan.py +1056 -0
  119. acprof/_bundle/acprof/host/interface_probe.py +141 -0
  120. acprof/_bundle/acprof/host/largest_scale_probe.py +566 -0
  121. acprof/_bundle/acprof/host/matrix_plan.py +98 -0
  122. acprof/_bundle/acprof/host/measurement/__init__.py +1 -0
  123. acprof/_bundle/acprof/host/measurement/boundary.py +162 -0
  124. acprof/_bundle/acprof/host/measurement/capture.py +139 -0
  125. acprof/_bundle/acprof/host/measurement/checkpoint.py +275 -0
  126. acprof/_bundle/acprof/host/measurement/config.py +212 -0
  127. acprof/_bundle/acprof/host/measurement/diagnostics.py +247 -0
  128. acprof/_bundle/acprof/host/measurement/energy_validation.py +172 -0
  129. acprof/_bundle/acprof/host/measurement/errors.py +25 -0
  130. acprof/_bundle/acprof/host/measurement/execution.py +396 -0
  131. acprof/_bundle/acprof/host/measurement/load.py +237 -0
  132. acprof/_bundle/acprof/host/measurement/metrics.py +975 -0
  133. acprof/_bundle/acprof/host/measurement/monitors.py +143 -0
  134. acprof/_bundle/acprof/host/measurement/publication.py +171 -0
  135. acprof/_bundle/acprof/host/measurement/requests.py +97 -0
  136. acprof/_bundle/acprof/host/measurement/types.py +82 -0
  137. acprof/_bundle/acprof/host/model_coverage.py +337 -0
  138. acprof/_bundle/acprof/host/model_errors.py +116 -0
  139. acprof/_bundle/acprof/host/model_inspection.py +107 -0
  140. acprof/_bundle/acprof/host/model_schema.py +35 -0
  141. acprof/_bundle/acprof/host/model_store.py +733 -0
  142. acprof/_bundle/acprof/host/network_preflight.py +229 -0
  143. acprof/_bundle/acprof/host/orchestrator.py +1133 -0
  144. acprof/_bundle/acprof/host/permissions.py +117 -0
  145. acprof/_bundle/acprof/host/platform_metadata.py +63 -0
  146. acprof/_bundle/acprof/host/posthoc/__init__.py +12 -0
  147. acprof/_bundle/acprof/host/posthoc/backfill.py +415 -0
  148. acprof/_bundle/acprof/host/posthoc/context.py +400 -0
  149. acprof/_bundle/acprof/host/posthoc/plans.py +597 -0
  150. acprof/_bundle/acprof/host/posthoc/service.py +303 -0
  151. acprof/_bundle/acprof/host/posthoc/storage.py +491 -0
  152. acprof/_bundle/acprof/host/preflight.py +370 -0
  153. acprof/_bundle/acprof/host/profiling/__init__.py +1 -0
  154. acprof/_bundle/acprof/host/profiling/compute.py +436 -0
  155. acprof/_bundle/acprof/host/profiling/compute_plan.py +261 -0
  156. acprof/_bundle/acprof/host/profiling/execution.py +547 -0
  157. acprof/_bundle/acprof/host/profiling/execution_plan.py +576 -0
  158. acprof/_bundle/acprof/host/profiling/progress.py +83 -0
  159. acprof/_bundle/acprof/host/profiling/support.py +252 -0
  160. acprof/_bundle/acprof/host/profiling/tools/__init__.py +1 -0
  161. acprof/_bundle/acprof/host/profiling/tools/advisor.py +164 -0
  162. acprof/_bundle/acprof/host/profiling/tools/compute_parsers.py +409 -0
  163. acprof/_bundle/acprof/host/profiling/tools/execution_environment.py +135 -0
  164. acprof/_bundle/acprof/host/profiling/tools/execution_parsers.py +364 -0
  165. acprof/_bundle/acprof/host/profiling/tools/massif.py +418 -0
  166. acprof/_bundle/acprof/host/profiling/tools/ncu.py +696 -0
  167. acprof/_bundle/acprof/host/profiling/tools/nsys.py +326 -0
  168. acprof/_bundle/acprof/host/profiling/tools/tool_discovery.py +229 -0
  169. acprof/_bundle/acprof/host/profiling/tools/torch.py +158 -0
  170. acprof/_bundle/acprof/host/result_cleanup.py +65 -0
  171. acprof/_bundle/acprof/host/run_state.py +639 -0
  172. acprof/_bundle/acprof/host/runtime_settings.py +10 -0
  173. acprof/_bundle/acprof/host/runtime_validation.py +302 -0
  174. acprof/_bundle/acprof/host/source_bundle.py +96 -0
  175. acprof/_bundle/acprof/host/startup_probe.py +95 -0
  176. acprof/_bundle/acprof/host/static_metadata.py +936 -0
  177. acprof/_bundle/acprof/host/task_support.py +121 -0
  178. acprof/_bundle/acprof/installation.py +26 -0
  179. acprof/_bundle/acprof/latency_slo.py +62 -0
  180. acprof/_bundle/acprof/messages.py +26 -0
  181. acprof/_bundle/acprof/metric_registry.py +315 -0
  182. acprof/_bundle/acprof/model_candidates.py +297 -0
  183. acprof/_bundle/acprof/model_contract.py +234 -0
  184. acprof/_bundle/acprof/model_dependencies.py +93 -0
  185. acprof/_bundle/acprof/model_dependency_domain.py +45 -0
  186. acprof/_bundle/acprof/model_dependency_eval.py +438 -0
  187. acprof/_bundle/acprof/model_dependency_flow.py +200 -0
  188. acprof/_bundle/acprof/model_evidence.py +115 -0
  189. acprof/_bundle/acprof/model_metadata_analysis.py +156 -0
  190. acprof/_bundle/acprof/model_repository.py +149 -0
  191. acprof/_bundle/acprof/model_resolution.py +129 -0
  192. acprof/_bundle/acprof/model_review.py +155 -0
  193. acprof/_bundle/acprof/model_source_analysis.py +299 -0
  194. acprof/_bundle/acprof/model_spec.py +204 -0
  195. acprof/_bundle/acprof/model_support.py +105 -0
  196. acprof/_bundle/acprof/model_transforms.py +81 -0
  197. acprof/_bundle/acprof/monitors/__init__.py +1 -0
  198. acprof/_bundle/acprof/monitors/common.py +63 -0
  199. acprof/_bundle/acprof/monitors/energy_cpu.py +651 -0
  200. acprof/_bundle/acprof/monitors/energy_nvml.py +381 -0
  201. acprof/_bundle/acprof/monitors/gpu_metrics.py +123 -0
  202. acprof/_bundle/acprof/monitors/interfaces.py +74 -0
  203. acprof/_bundle/acprof/monitors/perf_mips.py +617 -0
  204. acprof/_bundle/acprof/monitors/rapl_topology.py +100 -0
  205. acprof/_bundle/acprof/monitors/resource_metrics.py +472 -0
  206. acprof/_bundle/acprof/monitors/resource_readers.py +435 -0
  207. acprof/_bundle/acprof/monitors/resource_usage.py +450 -0
  208. acprof/_bundle/acprof/monitors/sampling.py +79 -0
  209. acprof/_bundle/acprof/network_policy.py +182 -0
  210. acprof/_bundle/acprof/notifications.py +279 -0
  211. acprof/_bundle/acprof/packet/__init__.py +1 -0
  212. acprof/_bundle/acprof/packet/merge_packet_latency.py +369 -0
  213. acprof/_bundle/acprof/packet/sniff_parse_pcap.py +240 -0
  214. acprof/_bundle/acprof/pixel_metrics.py +103 -0
  215. acprof/_bundle/acprof/platform.py +180 -0
  216. acprof/_bundle/acprof/plotting/__init__.py +1 -0
  217. acprof/_bundle/acprof/plotting/config.py +487 -0
  218. acprof/_bundle/acprof/plotting/data.py +236 -0
  219. acprof/_bundle/acprof/plotting/diagnostics.py +747 -0
  220. acprof/_bundle/acprof/plotting/latency.py +638 -0
  221. acprof/_bundle/acprof/plotting/metrics.py +648 -0
  222. acprof/_bundle/acprof/plotting/plotly-LICENSE.txt +21 -0
  223. acprof/_bundle/acprof/plotting/report.py +66 -0
  224. acprof/_bundle/acprof/plotting/styles.py +111 -0
  225. acprof/_bundle/acprof/precision.py +42 -0
  226. acprof/_bundle/acprof/preparation_events.py +78 -0
  227. acprof/_bundle/acprof/progress_events.py +105 -0
  228. acprof/_bundle/acprof/quality.py +153 -0
  229. acprof/_bundle/acprof/resource_budget.py +29 -0
  230. acprof/_bundle/acprof/result_csv.py +263 -0
  231. acprof/_bundle/acprof/result_layers.py +365 -0
  232. acprof/_bundle/acprof/run_args.py +223 -0
  233. acprof/_bundle/acprof/run_options.py +225 -0
  234. acprof/_bundle/acprof/runtime_dependencies.py +195 -0
  235. acprof/_bundle/acprof/runtime_profiles.py +258 -0
  236. acprof/_bundle/acprof/runtime_settings.py +72 -0
  237. acprof/_bundle/acprof/source_identity.py +68 -0
  238. acprof/_bundle/acprof/telemetry.py +225 -0
  239. acprof/_bundle/acprof/testing/__init__.py +1 -0
  240. acprof/_bundle/acprof/testing/evidence.py +117 -0
  241. acprof/_bundle/acprof/testing/plugin.py +126 -0
  242. acprof/_bundle/acprof/testing/provenance.py +53 -0
  243. acprof/_bundle/acprof/testing/sharding.py +14 -0
  244. acprof/_bundle/acprof/tui/__init__.py +1 -0
  245. acprof/_bundle/acprof/tui/app.py +934 -0
  246. acprof/_bundle/acprof/tui/app_contracts.py +43 -0
  247. acprof/_bundle/acprof/tui/catalog_controller.py +120 -0
  248. acprof/_bundle/acprof/tui/commands.py +209 -0
  249. acprof/_bundle/acprof/tui/configuration_controller.py +436 -0
  250. acprof/_bundle/acprof/tui/diagnostics.py +340 -0
  251. acprof/_bundle/acprof/tui/downloads.py +56 -0
  252. acprof/_bundle/acprof/tui/environment.py +248 -0
  253. acprof/_bundle/acprof/tui/experiment_catalog.py +279 -0
  254. acprof/_bundle/acprof/tui/experiment_controller.py +132 -0
  255. acprof/_bundle/acprof/tui/experiment_picker.py +273 -0
  256. acprof/_bundle/acprof/tui/field_validation.py +62 -0
  257. acprof/_bundle/acprof/tui/i18n.py +57 -0
  258. acprof/_bundle/acprof/tui/image_controller.py +525 -0
  259. acprof/_bundle/acprof/tui/images.py +737 -0
  260. acprof/_bundle/acprof/tui/input.py +191 -0
  261. acprof/_bundle/acprof/tui/localization_controller.py +110 -0
  262. acprof/_bundle/acprof/tui/log.py +310 -0
  263. acprof/_bundle/acprof/tui/model_candidates.py +278 -0
  264. acprof/_bundle/acprof/tui/model_controller.py +111 -0
  265. acprof/_bundle/acprof/tui/model_input.py +12 -0
  266. acprof/_bundle/acprof/tui/model_store.py +166 -0
  267. acprof/_bundle/acprof/tui/preflight_controller.py +271 -0
  268. acprof/_bundle/acprof/tui/preparation.py +269 -0
  269. acprof/_bundle/acprof/tui/presentation.py +46 -0
  270. acprof/_bundle/acprof/tui/process.py +111 -0
  271. acprof/_bundle/acprof/tui/process_controller.py +218 -0
  272. acprof/_bundle/acprof/tui/profile_controller.py +109 -0
  273. acprof/_bundle/acprof/tui/progress.py +195 -0
  274. acprof/_bundle/acprof/tui/recovery.py +114 -0
  275. acprof/_bundle/acprof/tui/recovery_controller.py +169 -0
  276. acprof/_bundle/acprof/tui/rendering.py +75 -0
  277. acprof/_bundle/acprof/tui/reports.py +303 -0
  278. acprof/_bundle/acprof/tui/result_controller.py +279 -0
  279. acprof/_bundle/acprof/tui/review_inputs.py +54 -0
  280. acprof/_bundle/acprof/tui/run_form.py +125 -0
  281. acprof/_bundle/acprof/tui/run_planning.py +97 -0
  282. acprof/_bundle/acprof/tui/run_results.py +175 -0
  283. acprof/_bundle/acprof/tui/scrollbar.py +65 -0
  284. acprof/_bundle/acprof/tui/settings.py +203 -0
  285. acprof/_bundle/acprof/tui/slash_controller.py +95 -0
  286. acprof/_bundle/acprof/tui/stages.py +97 -0
  287. acprof/_bundle/acprof/tui/storage.py +150 -0
  288. acprof/_bundle/acprof/tui/table.py +213 -0
  289. acprof/_bundle/acprof/tui/themes.py +112 -0
  290. acprof/_bundle/acprof/tui/translation_catalog.py +1861 -0
  291. acprof/_bundle/acprof/tui/tui.tcss +373 -0
  292. acprof/_bundle/acprof/tui/views.py +706 -0
  293. acprof/_bundle/acprof/window_records.py +165 -0
  294. acprof/_bundle/acprof/workloads/__init__.py +222 -0
  295. acprof/_bundle/acprof/workloads/audio.py +621 -0
  296. acprof/_bundle/acprof/workloads/contract.py +116 -0
  297. acprof/_bundle/acprof/workloads/cv.py +240 -0
  298. acprof/_bundle/acprof/workloads/diffusion.py +410 -0
  299. acprof/_bundle/acprof/workloads/multimodal.py +329 -0
  300. acprof/_bundle/acprof/workloads/nlp.py +151 -0
  301. acprof/_bundle/acprof/workloads/structured.py +151 -0
  302. acprof/_bundle/acprof/workloads/timeseries.py +69 -0
  303. acprof/_bundle/assets/audio/librispeech-clean-test-en-30s/audio.wav +0 -0
  304. acprof/_bundle/assets/audio/librispeech-clean-test-en-30s/source.json +81 -0
  305. acprof/_bundle/dockerfiles/environment_tools.py +314 -0
  306. acprof/_bundle/dockerfiles/locks/audio-cpu.artifacts.json +503 -0
  307. acprof/_bundle/dockerfiles/locks/audio-cpu.txt +143 -0
  308. acprof/_bundle/dockerfiles/locks/audio-cu124.artifacts.json +600 -0
  309. acprof/_bundle/dockerfiles/locks/audio-cu124.txt +171 -0
  310. acprof/_bundle/dockerfiles/locks/audio-cu128.artifacts.json +544 -0
  311. acprof/_bundle/dockerfiles/locks/audio-cu128.txt +155 -0
  312. acprof/_bundle/dockerfiles/locks/custom-multimodal-cpu.artifacts.json +510 -0
  313. acprof/_bundle/dockerfiles/locks/custom-multimodal-cpu.txt +145 -0
  314. acprof/_bundle/dockerfiles/locks/custom-multimodal-cu124.artifacts.json +607 -0
  315. acprof/_bundle/dockerfiles/locks/custom-multimodal-cu124.txt +173 -0
  316. acprof/_bundle/dockerfiles/locks/custom-multimodal-cu128.artifacts.json +642 -0
  317. acprof/_bundle/dockerfiles/locks/custom-multimodal-cu128.txt +183 -0
  318. acprof/_bundle/dockerfiles/locks/cv-cpu.artifacts.json +279 -0
  319. acprof/_bundle/dockerfiles/locks/cv-cpu.txt +79 -0
  320. acprof/_bundle/dockerfiles/locks/cv-cu124.artifacts.json +376 -0
  321. acprof/_bundle/dockerfiles/locks/cv-cu124.txt +107 -0
  322. acprof/_bundle/dockerfiles/locks/cv-cu128.artifacts.json +411 -0
  323. acprof/_bundle/dockerfiles/locks/cv-cu128.txt +117 -0
  324. acprof/_bundle/dockerfiles/locks/diffusion-cpu.artifacts.json +335 -0
  325. acprof/_bundle/dockerfiles/locks/diffusion-cpu.txt +95 -0
  326. acprof/_bundle/dockerfiles/locks/diffusion-cu124.artifacts.json +432 -0
  327. acprof/_bundle/dockerfiles/locks/diffusion-cu124.txt +123 -0
  328. acprof/_bundle/dockerfiles/locks/diffusion-cu128.artifacts.json +467 -0
  329. acprof/_bundle/dockerfiles/locks/diffusion-cu128.txt +133 -0
  330. acprof/_bundle/dockerfiles/locks/moss-transformers5104.artifacts.json +621 -0
  331. acprof/_bundle/dockerfiles/locks/moss-transformers5104.txt +177 -0
  332. acprof/_bundle/dockerfiles/locks/multimodal-transformers4576.artifacts.json +635 -0
  333. acprof/_bundle/dockerfiles/locks/multimodal-transformers4576.txt +181 -0
  334. acprof/_bundle/dockerfiles/locks/nlp-cpu.artifacts.json +363 -0
  335. acprof/_bundle/dockerfiles/locks/nlp-cpu.txt +103 -0
  336. acprof/_bundle/dockerfiles/locks/nlp-cu124.artifacts.json +460 -0
  337. acprof/_bundle/dockerfiles/locks/nlp-cu124.txt +131 -0
  338. acprof/_bundle/dockerfiles/locks/nlp-cu128.artifacts.json +495 -0
  339. acprof/_bundle/dockerfiles/locks/nlp-cu128.txt +141 -0
  340. acprof/_bundle/dockerfiles/locks/onnxruntime-cpu.artifacts.json +261 -0
  341. acprof/_bundle/dockerfiles/locks/onnxruntime-cpu.txt +73 -0
  342. acprof/_bundle/dockerfiles/locks/platform-cpu.artifacts.json +99 -0
  343. acprof/_bundle/dockerfiles/locks/platform-cpu.txt +27 -0
  344. acprof/_bundle/dockerfiles/locks/platform-cu124.artifacts.json +196 -0
  345. acprof/_bundle/dockerfiles/locks/platform-cu124.txt +55 -0
  346. acprof/_bundle/dockerfiles/locks/platform-cu128.artifacts.json +231 -0
  347. acprof/_bundle/dockerfiles/locks/platform-cu128.txt +65 -0
  348. acprof/_bundle/dockerfiles/locks/platform-python-cpu.artifacts.json +37 -0
  349. acprof/_bundle/dockerfiles/locks/platform-python-cpu.txt +9 -0
  350. acprof/_bundle/dockerfiles/locks/structured-cpu.artifacts.json +279 -0
  351. acprof/_bundle/dockerfiles/locks/structured-cpu.txt +79 -0
  352. acprof/_bundle/dockerfiles/locks/structured-cu124.artifacts.json +376 -0
  353. acprof/_bundle/dockerfiles/locks/structured-cu124.txt +107 -0
  354. acprof/_bundle/dockerfiles/locks/structured-cu128.artifacts.json +411 -0
  355. acprof/_bundle/dockerfiles/locks/structured-cu128.txt +117 -0
  356. acprof/_bundle/dockerfiles/locks/system-trixie-amd64.json +620 -0
  357. acprof/_bundle/dockerfiles/locks/timeseries-cpu.artifacts.json +314 -0
  358. acprof/_bundle/dockerfiles/locks/timeseries-cpu.txt +89 -0
  359. acprof/_bundle/dockerfiles/locks/timeseries-cu124.artifacts.json +411 -0
  360. acprof/_bundle/dockerfiles/locks/timeseries-cu124.txt +117 -0
  361. acprof/_bundle/dockerfiles/locks/timeseries-cu128.artifacts.json +446 -0
  362. acprof/_bundle/dockerfiles/locks/timeseries-cu128.txt +127 -0
  363. acprof/_bundle/dockerfiles/locks/transformers5104-cpu.artifacts.json +594 -0
  364. acprof/_bundle/dockerfiles/locks/transformers5104-cpu.txt +169 -0
  365. acprof/_bundle/dockerfiles/locks/transformers5104-cu124.artifacts.json +691 -0
  366. acprof/_bundle/dockerfiles/locks/transformers5104-cu124.txt +197 -0
  367. acprof/_bundle/dockerfiles/locks/transformers5104-cu128.artifacts.json +726 -0
  368. acprof/_bundle/dockerfiles/locks/transformers5104-cu128.txt +207 -0
  369. acprof/_bundle/dockerfiles/platform.Dockerfile +22 -0
  370. acprof/_bundle/dockerfiles/requirements/audio.in +5 -0
  371. acprof/_bundle/dockerfiles/requirements/custom-multimodal.in +2 -0
  372. acprof/_bundle/dockerfiles/requirements/cv.in +4 -0
  373. acprof/_bundle/dockerfiles/requirements/diffusion.in +6 -0
  374. acprof/_bundle/dockerfiles/requirements/moss-transformers5104.in +9 -0
  375. acprof/_bundle/dockerfiles/requirements/multimodal-transformers4576.in +3 -0
  376. acprof/_bundle/dockerfiles/requirements/nlp.in +7 -0
  377. acprof/_bundle/dockerfiles/requirements/onnxruntime.in +9 -0
  378. acprof/_bundle/dockerfiles/requirements/service.in +8 -0
  379. acprof/_bundle/dockerfiles/requirements/structured.in +4 -0
  380. acprof/_bundle/dockerfiles/requirements/timeseries.in +2 -0
  381. acprof/_bundle/dockerfiles/requirements/timm.in +1 -0
  382. acprof/_bundle/dockerfiles/requirements/transformers5104.in +4 -0
  383. acprof/_bundle/dockerfiles/runtime-final.Dockerfile +34 -0
  384. acprof/_bundle/dockerfiles/runtime-model.Dockerfile +19 -0
  385. acprof/_bundle/dockerfiles/runtime.Dockerfile +23 -0
  386. acprof/_bundle/examples/coverage/regression.json +17 -0
  387. acprof/_bundle/examples/hardware-validation.json +19 -0
  388. acprof/_bundle/examples/multimodal/ultravox.model.json +29 -0
  389. acprof/_bundle/examples/nlp/smoke.py +111 -0
  390. acprof/_bundle/examples/onnxruntime/fixtures.py +164 -0
  391. acprof/_bundle/examples/onnxruntime/iris.json +16 -0
  392. acprof/_bundle/examples/onnxruntime/iris.model.json +7 -0
  393. acprof/_bundle/examples/onnxruntime/real_models.py +155 -0
  394. acprof/_bundle/examples/onnxruntime/smoke.py +68 -0
  395. acprof/_bundle/examples/structured/chronos_smoke.py +56 -0
  396. acprof/_bundle/examples/structured/export_models.py +71 -0
  397. acprof/_bundle/examples/structured/smoke.py +71 -0
  398. acprof/_bundle/licenses/CC-BY-4.0.txt +156 -0
  399. acprof/analysis/__init__.py +1 -0
  400. acprof/analysis/audit.py +276 -0
  401. acprof/analysis/comparison.py +364 -0
  402. acprof/analysis/compatibility.py +223 -0
  403. acprof/analysis/conditions.py +185 -0
  404. acprof/analysis/independent_comparison.py +191 -0
  405. acprof/analysis/latency_model.py +1106 -0
  406. acprof/analysis/latency_report.py +577 -0
  407. acprof/analysis/model.py +276 -0
  408. acprof/analysis/precision.py +51 -0
  409. acprof/analysis/uncertainty.py +144 -0
  410. acprof/application/__init__.py +1 -0
  411. acprof/application/download.py +14 -0
  412. acprof/application/errors.py +5 -0
  413. acprof/application/notifications.py +302 -0
  414. acprof/application/preparation.py +333 -0
  415. acprof/application/resources.py +66 -0
  416. acprof/application/run.py +462 -0
  417. acprof/application/terminal_log.py +136 -0
  418. acprof/artifact_layout.py +261 -0
  419. acprof/artifacts.py +161 -0
  420. acprof/capabilities.py +404 -0
  421. acprof/cli/__init__.py +1 -0
  422. acprof/cli/audit.py +74 -0
  423. acprof/cli/auto.py +41 -0
  424. acprof/cli/backfill_compute.py +498 -0
  425. acprof/cli/compare.py +34 -0
  426. acprof/cli/coverage.py +70 -0
  427. acprof/cli/doctor.py +47 -0
  428. acprof/cli/inspect.py +101 -0
  429. acprof/cli/load.py +190 -0
  430. acprof/cli/main.py +64 -0
  431. acprof/cli/model_store.py +22 -0
  432. acprof/cli/plot.py +211 -0
  433. acprof/cli/posthoc.py +113 -0
  434. acprof/cli/probe.py +186 -0
  435. acprof/cli/report.py +35 -0
  436. acprof/cli/results.py +37 -0
  437. acprof/cli/run.py +54 -0
  438. acprof/cli/stats.py +94 -0
  439. acprof/cli/tui.py +65 -0
  440. acprof/config.py +177 -0
  441. acprof/container/__init__.py +1 -0
  442. acprof/container/compat/__init__.py +1 -0
  443. acprof/container/compat/transformers_dynamic.py +54 -0
  444. acprof/container/compat/transformers_model_types.json +1091 -0
  445. acprof/container/compute_profile_runner.py +392 -0
  446. acprof/container/download_model.py +165 -0
  447. acprof/container/execution.py +73 -0
  448. acprof/container/handlers/__init__.py +298 -0
  449. acprof/container/handlers/audio.py +743 -0
  450. acprof/container/handlers/custom_pipeline.py +74 -0
  451. acprof/container/handlers/cv.py +321 -0
  452. acprof/container/handlers/diffusion.py +728 -0
  453. acprof/container/handlers/moss.py +64 -0
  454. acprof/container/handlers/multimodal.py +609 -0
  455. acprof/container/handlers/nlp.py +747 -0
  456. acprof/container/handlers/onnx_tasks.py +231 -0
  457. acprof/container/handlers/onnxruntime.py +90 -0
  458. acprof/container/handlers/structured.py +185 -0
  459. acprof/container/handlers/timeseries.py +178 -0
  460. acprof/container/load_policy.py +81 -0
  461. acprof/container/loading_quality.py +48 -0
  462. acprof/container/local_pipeline.py +31 -0
  463. acprof/container/model_files.py +280 -0
  464. acprof/container/model_probe.py +80 -0
  465. acprof/container/onnx_session.py +150 -0
  466. acprof/container/runtime_manifest.py +150 -0
  467. acprof/container/runtime_validate.py +156 -0
  468. acprof/container/server.py +209 -0
  469. acprof/container/torch_execution.py +55 -0
  470. acprof/container/validation.py +172 -0
  471. acprof/cpu_affinity.py +35 -0
  472. acprof/dependency_locks.py +129 -0
  473. acprof/experiment.py +356 -0
  474. acprof/extensions/__init__.py +294 -0
  475. acprof/extensions/builtin/manifest.json +3591 -0
  476. acprof/extensions/onnxruntime/manifest.json +191 -0
  477. acprof/extensions/schema.py +238 -0
  478. acprof/extensions/transformers/4.57.6.json +1639 -0
  479. acprof/extensions/transformers/5.10.4.json +1812 -0
  480. acprof/failures.py +115 -0
  481. acprof/hardware_conditions.py +18 -0
  482. acprof/hf_download.py +143 -0
  483. acprof/hf_endpoints.py +62 -0
  484. acprof/hf_transport.py +238 -0
  485. acprof/host/__init__.py +1 -0
  486. acprof/host/automation.py +161 -0
  487. acprof/host/client.py +520 -0
  488. acprof/host/collection_history.py +77 -0
  489. acprof/host/collection_workflow.py +285 -0
  490. acprof/host/command.py +119 -0
  491. acprof/host/container_lifecycle.py +225 -0
  492. acprof/host/container_state.py +128 -0
  493. acprof/host/coverage_state.py +259 -0
  494. acprof/host/detect.py +669 -0
  495. acprof/host/docker_runtime.py +359 -0
  496. acprof/host/doctor.py +158 -0
  497. acprof/host/env_utils.py +233 -0
  498. acprof/host/execution_conditions.py +87 -0
  499. acprof/host/gpu_device.py +66 -0
  500. acprof/host/hardware_conditions.py +130 -0
  501. acprof/host/images/__init__.py +1 -0
  502. acprof/host/images/dependencies.py +169 -0
  503. acprof/host/images/environment.py +313 -0
  504. acprof/host/images/graph.py +143 -0
  505. acprof/host/images/identity.py +6 -0
  506. acprof/host/images/inventory.py +445 -0
  507. acprof/host/images/runtime.py +457 -0
  508. acprof/host/images/scan.py +154 -0
  509. acprof/host/input_plan.py +1056 -0
  510. acprof/host/interface_probe.py +141 -0
  511. acprof/host/largest_scale_probe.py +566 -0
  512. acprof/host/matrix_plan.py +98 -0
  513. acprof/host/measurement/__init__.py +1 -0
  514. acprof/host/measurement/boundary.py +162 -0
  515. acprof/host/measurement/capture.py +139 -0
  516. acprof/host/measurement/checkpoint.py +275 -0
  517. acprof/host/measurement/config.py +212 -0
  518. acprof/host/measurement/diagnostics.py +247 -0
  519. acprof/host/measurement/energy_validation.py +172 -0
  520. acprof/host/measurement/errors.py +25 -0
  521. acprof/host/measurement/execution.py +396 -0
  522. acprof/host/measurement/load.py +237 -0
  523. acprof/host/measurement/metrics.py +975 -0
  524. acprof/host/measurement/monitors.py +143 -0
  525. acprof/host/measurement/publication.py +171 -0
  526. acprof/host/measurement/requests.py +97 -0
  527. acprof/host/measurement/types.py +82 -0
  528. acprof/host/model_coverage.py +337 -0
  529. acprof/host/model_errors.py +116 -0
  530. acprof/host/model_inspection.py +107 -0
  531. acprof/host/model_schema.py +35 -0
  532. acprof/host/model_store.py +733 -0
  533. acprof/host/network_preflight.py +229 -0
  534. acprof/host/orchestrator.py +1133 -0
  535. acprof/host/permissions.py +117 -0
  536. acprof/host/platform_metadata.py +63 -0
  537. acprof/host/posthoc/__init__.py +12 -0
  538. acprof/host/posthoc/backfill.py +415 -0
  539. acprof/host/posthoc/context.py +400 -0
  540. acprof/host/posthoc/plans.py +597 -0
  541. acprof/host/posthoc/service.py +303 -0
  542. acprof/host/posthoc/storage.py +491 -0
  543. acprof/host/preflight.py +370 -0
  544. acprof/host/profiling/__init__.py +1 -0
  545. acprof/host/profiling/compute.py +436 -0
  546. acprof/host/profiling/compute_plan.py +261 -0
  547. acprof/host/profiling/execution.py +547 -0
  548. acprof/host/profiling/execution_plan.py +576 -0
  549. acprof/host/profiling/progress.py +83 -0
  550. acprof/host/profiling/support.py +252 -0
  551. acprof/host/profiling/tools/__init__.py +1 -0
  552. acprof/host/profiling/tools/advisor.py +164 -0
  553. acprof/host/profiling/tools/compute_parsers.py +409 -0
  554. acprof/host/profiling/tools/execution_environment.py +135 -0
  555. acprof/host/profiling/tools/execution_parsers.py +364 -0
  556. acprof/host/profiling/tools/massif.py +418 -0
  557. acprof/host/profiling/tools/ncu.py +696 -0
  558. acprof/host/profiling/tools/nsys.py +326 -0
  559. acprof/host/profiling/tools/tool_discovery.py +229 -0
  560. acprof/host/profiling/tools/torch.py +158 -0
  561. acprof/host/result_cleanup.py +65 -0
  562. acprof/host/run_state.py +639 -0
  563. acprof/host/runtime_settings.py +10 -0
  564. acprof/host/runtime_validation.py +302 -0
  565. acprof/host/source_bundle.py +96 -0
  566. acprof/host/startup_probe.py +95 -0
  567. acprof/host/static_metadata.py +936 -0
  568. acprof/host/task_support.py +121 -0
  569. acprof/installation.py +26 -0
  570. acprof/latency_slo.py +62 -0
  571. acprof/messages.py +26 -0
  572. acprof/metric_registry.py +315 -0
  573. acprof/model_candidates.py +297 -0
  574. acprof/model_contract.py +234 -0
  575. acprof/model_dependencies.py +93 -0
  576. acprof/model_dependency_domain.py +45 -0
  577. acprof/model_dependency_eval.py +438 -0
  578. acprof/model_dependency_flow.py +200 -0
  579. acprof/model_evidence.py +115 -0
  580. acprof/model_metadata_analysis.py +156 -0
  581. acprof/model_repository.py +149 -0
  582. acprof/model_resolution.py +129 -0
  583. acprof/model_review.py +155 -0
  584. acprof/model_source_analysis.py +299 -0
  585. acprof/model_spec.py +204 -0
  586. acprof/model_support.py +105 -0
  587. acprof/model_transforms.py +81 -0
  588. acprof/monitors/__init__.py +1 -0
  589. acprof/monitors/common.py +63 -0
  590. acprof/monitors/energy_cpu.py +651 -0
  591. acprof/monitors/energy_nvml.py +381 -0
  592. acprof/monitors/gpu_metrics.py +123 -0
  593. acprof/monitors/interfaces.py +74 -0
  594. acprof/monitors/perf_mips.py +617 -0
  595. acprof/monitors/rapl_topology.py +100 -0
  596. acprof/monitors/resource_metrics.py +472 -0
  597. acprof/monitors/resource_readers.py +435 -0
  598. acprof/monitors/resource_usage.py +450 -0
  599. acprof/monitors/sampling.py +79 -0
  600. acprof/network_policy.py +182 -0
  601. acprof/notifications.py +279 -0
  602. acprof/packet/__init__.py +1 -0
  603. acprof/packet/merge_packet_latency.py +369 -0
  604. acprof/packet/sniff_parse_pcap.py +240 -0
  605. acprof/pixel_metrics.py +103 -0
  606. acprof/platform.py +180 -0
  607. acprof/plotting/__init__.py +1 -0
  608. acprof/plotting/config.py +487 -0
  609. acprof/plotting/data.py +236 -0
  610. acprof/plotting/diagnostics.py +747 -0
  611. acprof/plotting/latency.py +638 -0
  612. acprof/plotting/metrics.py +648 -0
  613. acprof/plotting/plotly-LICENSE.txt +21 -0
  614. acprof/plotting/report.css +61 -0
  615. acprof/plotting/report.html +68 -0
  616. acprof/plotting/report.js +295 -0
  617. acprof/plotting/report.py +66 -0
  618. acprof/plotting/styles.py +111 -0
  619. acprof/plotting/view_model.js +145 -0
  620. acprof/precision.py +42 -0
  621. acprof/preparation_events.py +78 -0
  622. acprof/progress_events.py +105 -0
  623. acprof/quality.py +153 -0
  624. acprof/resource_budget.py +29 -0
  625. acprof/result_csv.py +263 -0
  626. acprof/result_layers.py +365 -0
  627. acprof/run_args.py +223 -0
  628. acprof/run_options.py +225 -0
  629. acprof/runtime_dependencies.py +195 -0
  630. acprof/runtime_profiles.py +258 -0
  631. acprof/runtime_settings.py +72 -0
  632. acprof/source_identity.py +68 -0
  633. acprof/telemetry.py +225 -0
  634. acprof/testing/__init__.py +1 -0
  635. acprof/testing/evidence.py +117 -0
  636. acprof/testing/plugin.py +126 -0
  637. acprof/testing/provenance.py +53 -0
  638. acprof/testing/sharding.py +14 -0
  639. acprof/tui/__init__.py +1 -0
  640. acprof/tui/app.py +934 -0
  641. acprof/tui/app_contracts.py +43 -0
  642. acprof/tui/catalog_controller.py +120 -0
  643. acprof/tui/commands.py +209 -0
  644. acprof/tui/configuration_controller.py +436 -0
  645. acprof/tui/diagnostics.py +340 -0
  646. acprof/tui/downloads.py +56 -0
  647. acprof/tui/environment.py +248 -0
  648. acprof/tui/experiment_catalog.py +279 -0
  649. acprof/tui/experiment_controller.py +132 -0
  650. acprof/tui/experiment_picker.py +273 -0
  651. acprof/tui/field_validation.py +62 -0
  652. acprof/tui/i18n.py +57 -0
  653. acprof/tui/image_controller.py +525 -0
  654. acprof/tui/images.py +737 -0
  655. acprof/tui/input.py +191 -0
  656. acprof/tui/localization_controller.py +110 -0
  657. acprof/tui/log.py +310 -0
  658. acprof/tui/model_candidates.py +278 -0
  659. acprof/tui/model_controller.py +111 -0
  660. acprof/tui/model_input.py +12 -0
  661. acprof/tui/model_store.py +166 -0
  662. acprof/tui/preflight_controller.py +271 -0
  663. acprof/tui/preparation.py +269 -0
  664. acprof/tui/presentation.py +46 -0
  665. acprof/tui/process.py +111 -0
  666. acprof/tui/process_controller.py +218 -0
  667. acprof/tui/profile_controller.py +109 -0
  668. acprof/tui/progress.py +195 -0
  669. acprof/tui/recovery.py +114 -0
  670. acprof/tui/recovery_controller.py +169 -0
  671. acprof/tui/rendering.py +75 -0
  672. acprof/tui/reports.py +303 -0
  673. acprof/tui/result_controller.py +279 -0
  674. acprof/tui/review_inputs.py +54 -0
  675. acprof/tui/run_form.py +125 -0
  676. acprof/tui/run_planning.py +97 -0
  677. acprof/tui/run_results.py +175 -0
  678. acprof/tui/scrollbar.py +65 -0
  679. acprof/tui/settings.py +203 -0
  680. acprof/tui/slash_controller.py +95 -0
  681. acprof/tui/stages.py +97 -0
  682. acprof/tui/storage.py +150 -0
  683. acprof/tui/table.py +213 -0
  684. acprof/tui/themes.py +112 -0
  685. acprof/tui/translation_catalog.py +1861 -0
  686. acprof/tui/tui.tcss +373 -0
  687. acprof/tui/views.py +706 -0
  688. acprof/window_records.py +165 -0
  689. acprof/workloads/__init__.py +222 -0
  690. acprof/workloads/audio.py +621 -0
  691. acprof/workloads/contract.py +116 -0
  692. acprof/workloads/cv.py +240 -0
  693. acprof/workloads/diffusion.py +410 -0
  694. acprof/workloads/multimodal.py +329 -0
  695. acprof/workloads/nlp.py +151 -0
  696. acprof/workloads/structured.py +151 -0
  697. acprof/workloads/timeseries.py +69 -0
  698. acprof-0.3.0.dist-info/METADATA +117 -0
  699. acprof-0.3.0.dist-info/RECORD +704 -0
  700. acprof-0.3.0.dist-info/WHEEL +4 -0
  701. acprof-0.3.0.dist-info/entry_points.txt +2 -0
  702. acprof-0.3.0.dist-info/licenses/LICENSE +202 -0
  703. acprof-0.3.0.dist-info/licenses/NOTICE +43 -0
  704. acprof-0.3.0.dist-info/licenses/licenses/CC-BY-4.0.txt +156 -0
@@ -0,0 +1,436 @@
1
+ """Configuration form actions and preference dialogs for the TUI.
2
+
3
+ Owns the form, persisted preferences and preview state. The App supplies
4
+ widgets, lifecycle admission and its project/interpreter paths.
5
+ """
6
+ from __future__ import annotations
7
+
8
+ from dataclasses import replace
9
+ from pathlib import Path
10
+ from typing import TYPE_CHECKING
11
+
12
+ from textual.screen import ModalScreen
13
+ from textual.timer import Timer
14
+ from textual.widget import Widget
15
+ from textual.widgets import Button, Checkbox, Collapsible, ContentSwitcher, Label, Select, Static
16
+
17
+ from acprof.experiment import ConfigIssue, RunConfig, RunConfigError, build_run_command
18
+ from acprof.messages import join_messages, message
19
+ from acprof.tui import run_form, run_planning
20
+ from acprof.tui.commands import format_command
21
+ from acprof.tui.i18n import error_message, message_id
22
+ from acprof.tui.input import BarCursorInput as Input
23
+ from acprof.tui.log import SelectableLog
24
+ from acprof.tui.scrollbar import SolidScrollBarRender
25
+ from acprof.tui.settings import (
26
+ UiPreferences,
27
+ default_settings_path,
28
+ load_settings,
29
+ save_settings,
30
+ )
31
+ from acprof.tui.views import LogPanel
32
+
33
+ if TYPE_CHECKING:
34
+ from acprof.tui.app import AcprofTui
35
+
36
+ class ConfigurationController:
37
+ """Own configuration state and operations; the App owns lifecycle and scheduling."""
38
+
39
+ def __init__(self, app: AcprofTui, initial_config: RunConfig | None = None, *, settings_path: Path | None = None) -> None:
40
+ self.app = app
41
+ self.settings_path = settings_path or default_settings_path(app.project_dir)
42
+ self.saved_settings, self.settings_warning = load_settings(self.settings_path, app.project_dir)
43
+ self.preferences = self.saved_settings.ui
44
+ config = self.saved_settings.run_defaults or RunConfig.smoke()
45
+ if self.saved_settings.last_model:
46
+ config = replace(config, model=self.saved_settings.last_model,
47
+ revision=config.revision if config.model == self.saved_settings.last_model else "")
48
+ self.initial_config = initial_config if initial_config is not None else config
49
+ self.extra_options = dict(self.initial_config.extra_options)
50
+ self.planned_input: dict | None = None
51
+ self.planned_input_identity: tuple[object, ...] | None = None
52
+ self.environment_open: bool = False
53
+ self.config_issues: tuple[ConfigIssue, ...] = ()
54
+ self.field_errors_visible = False
55
+ self.applying_config = False
56
+ self.preview_timer: Timer | None = None
57
+ self.selected_preset: str | None = None
58
+ self.initial_preset: str = run_form.infer_preset(self.initial_config)
59
+
60
+ def apply_ui_preferences(self) -> None:
61
+ self.app.localization.apply_language()
62
+ self.app.theme = self.preferences.theme
63
+ log = self.app.query_one("#run-log", SelectableLog)
64
+ log.wrap = self.preferences.log_wrap
65
+ log.max_lines = self.preferences.log_max_lines
66
+ self.app.query_one("#bottom-panel").set_class(
67
+ not self.preferences.show_command_bar, "command-hidden",
68
+ )
69
+
70
+ def ui_preference_changed(self) -> None:
71
+ if not self.app.form_ready or self.app.is_busy():
72
+ return
73
+ preferences = UiPreferences(
74
+ language=self.select("ui-language"),
75
+ theme=self.select("ui-theme"),
76
+ log_max_lines=int(str(self.app.query_one("#ui-log-lines", Select).value or UiPreferences().log_max_lines)),
77
+ log_wrap=self.checked("ui-log-wrap"),
78
+ show_command_bar=self.checked("ui-command-bar"),
79
+ )
80
+ if preferences == self.preferences:
81
+ return
82
+ self.preferences = preferences
83
+ self.apply_ui_preferences()
84
+ self.app.localization.set_text(self.app.query_one('#settings-status', Static), '已应用 · 点击保存设置可在下次启动时沿用')
85
+ self.app.query_one('#settings-status').set_classes('page-summary stage-running')
86
+
87
+ def restore_ui_defaults(self) -> None:
88
+ if self.app.is_busy():
89
+ return
90
+ defaults = UiPreferences()
91
+ with self.app.prevent(Select.Changed, Checkbox.Changed):
92
+ self.app.query_one("#ui-language", Select).value = defaults.language
93
+ self.app.query_one("#ui-theme", Select).value = defaults.theme
94
+ self.app.query_one("#ui-log-lines", Select).value = defaults.log_max_lines
95
+ self.app.query_one("#ui-log-wrap", Checkbox).value = defaults.log_wrap
96
+ self.app.query_one("#ui-command-bar", Checkbox).value = defaults.show_command_bar
97
+ self.preferences = defaults
98
+ self.apply_ui_preferences()
99
+ self.app.localization.set_text(self.app.query_one('#settings-status', Static), '界面已恢复默认 · 点击保存设置可保留')
100
+ self.app.query_one('#settings-status').set_classes('page-summary stage-running')
101
+
102
+ def save_settings(self, *, remember_run: bool) -> None:
103
+ if self.app.is_busy():
104
+ self.app.notify("任务完成后可保存设置", severity="warning")
105
+ return
106
+ try:
107
+ config = (
108
+ replace(self.collect_config(allow_empty_model=True), rebuild_image=False)
109
+ if remember_run else self.saved_settings.run_defaults
110
+ )
111
+ settings = replace(
112
+ self.saved_settings,
113
+ ui=self.saved_settings.ui if remember_run else self.preferences,
114
+ run_defaults=config,
115
+ )
116
+ save_settings(self.settings_path, settings, self.app.project_dir)
117
+ except (OSError, ValueError, RunConfigError) as exc:
118
+ self.app.notify(error_message(exc), title="设置未保存", severity="error")
119
+ self.app.localization.set_text(self.app.query_one('#settings-status', Static), '保存失败 · 请检查配置或文件权限')
120
+ self.app.query_one('#settings-status').set_classes('page-summary stage-error')
121
+ return
122
+ self.saved_settings = settings
123
+ self.settings_warning = ""
124
+ message = "已记住当前实验配置" if remember_run else "界面设置已保存"
125
+ if not remember_run:
126
+ self.app.localization.set_text(self.app.query_one('#settings-status', Static), message)
127
+ self.app.query_one('#settings-status').set_classes('page-summary stage-success')
128
+ self.app.notify(message, timeout=3)
129
+
130
+ def save_ui_settings(self) -> None:
131
+ self.save_settings(remember_run=False)
132
+
133
+ def save_run_default(self) -> None:
134
+ self.save_settings(remember_run=True)
135
+
136
+ def show_settings(self) -> None:
137
+ self.app.activate_tab("settings-tab")
138
+
139
+ def open_environment_settings(self) -> None:
140
+ if self.app.is_busy() or self.app.preflight.check_running:
141
+ return
142
+ from acprof.tui.environment import EnvironmentSettingsScreen
143
+ try:
144
+ screen = EnvironmentSettingsScreen(
145
+ self.app.project_dir, self.settings_path.parent, sniff_iface=self.input("sniff-iface"),
146
+ )
147
+ except (OSError, ValueError) as read_error:
148
+ self.app.notify(message_id('ui.0293', type(read_error).__name__), severity="error")
149
+ return
150
+ self.environment_open = True
151
+ self.app.set_busy(True)
152
+ self.app.push_screen(screen, self.environment_closed)
153
+
154
+ def environment_closed(self, _saved: bool | None) -> None:
155
+ self.environment_open = False
156
+ self.app.set_busy(False)
157
+
158
+ def open_run_settings(self) -> None:
159
+ self.app.activate_tab("run-tab")
160
+ pages = self.app.query_one("#experiment-pages", ContentSwitcher)
161
+ show_advanced = pages.current != "advanced-form"
162
+ self.show_run_form("advanced-form" if show_advanced else "run-form")
163
+
164
+ def show_run_form(self, page: str) -> None:
165
+ self.app.query_one("#experiment-pages", ContentSwitcher).current = page
166
+ show_advanced = page == "advanced-form"
167
+ self.app.localization.set_text(
168
+ self.app.query_one("#open-run-settings", Button),
169
+ "返回基本配置" if show_advanced else "高级参数", "label",
170
+ )
171
+
172
+ def gpu_options(self) -> list[tuple[str, str]]:
173
+ options = [("仅 CPU", "off"), ("仅 GPU", "on"), ("CPU + GPU", "off,on")]
174
+ if self.initial_config.gpus not in {value for _, value in options}:
175
+ options.append((message_id('ui.0740', self.initial_config.gpus), self.initial_config.gpus))
176
+ return options
177
+
178
+ def input(self, widget_id: str) -> str:
179
+ return self.app.query_one(f"#{widget_id}", Input).value.strip()
180
+
181
+ def select(self, widget_id: str) -> str:
182
+ value = self.app.query_one(f"#{widget_id}", Select).value
183
+ return "" if value is Select.NULL else str(value)
184
+
185
+ def checked(self, widget_id: str) -> bool:
186
+ return bool(self.app.query_one(f"#{widget_id}", Checkbox).value)
187
+
188
+ def configure_interaction(self) -> None:
189
+ # Textual ignores another click while a button's active effect lasts
190
+ # (200 ms by default). Use focus/hover styling for immediate feedback.
191
+ for button in self.app.query(Button):
192
+ button.active_effect_duration = 0
193
+ for field in self.app.query(Input):
194
+ # The app toggles the native caret without Input's repaint timer.
195
+ field.cursor_blink = False
196
+
197
+ def configure_scrollbars(self) -> None:
198
+ # Instance-level renderers keep this behavior local to this TUI.
199
+ for widget in self.app.query(Widget):
200
+ if widget.is_scrollable:
201
+ setattr(widget.vertical_scrollbar, "renderer", SolidScrollBarRender)
202
+ setattr(widget.horizontal_scrollbar, "renderer", SolidScrollBarRender)
203
+
204
+ def copy_log_selection(self) -> None:
205
+ log = self.app.query_one("#run-log", SelectableLog)
206
+ if log.copy_selection():
207
+ self.app.notify("已复制日志选区", timeout=2)
208
+ else:
209
+ self.app.notify("先在日志中拖动选择文字,Ctrl+A 可全选", timeout=3)
210
+
211
+ def follow_latest_log(self) -> None:
212
+ self.app.query_one("#run-log", SelectableLog).follow_tail()
213
+
214
+ def toggle_log_view_button(self) -> None:
215
+ self.toggle_log_view()
216
+
217
+ def toggle_log_view(self) -> None:
218
+ if isinstance(self.app.screen, ModalScreen):
219
+ return
220
+ panel = self.app.query_one("#log-panel", LogPanel)
221
+ if self.app.screen.maximized is panel:
222
+ self.app.screen.minimize()
223
+ else:
224
+ self.app.activate_tab("monitor-tab")
225
+ self.app.screen.maximize(panel, container=False)
226
+ self.app.query_one("#run-log", SelectableLog).focus()
227
+
228
+ def cancel_preview_timer(self) -> None:
229
+ if self.preview_timer is not None:
230
+ self.preview_timer.stop()
231
+ self.preview_timer = None
232
+
233
+ def configuration_changed(self) -> None:
234
+ if not self.app.is_running or not self.app.form_ready or self.applying_config or self.app.is_busy():
235
+ return
236
+ self.cancel_preview_timer()
237
+ # Coalesce typing and preset field updates into one validation/render.
238
+ self.preview_timer = self.app.set_timer(0.05, self.sync_form_state)
239
+
240
+ def sync_form_state(self) -> None:
241
+ self.preview_timer = None
242
+ # Timer callbacks already queued before shutdown can run after the
243
+ # form has been removed; do not query widgets during that phase.
244
+ if not self.app.is_running or not self.app.form_ready or self.app.is_busy() or self.applying_config:
245
+ return
246
+ self.refresh_command_preview(notify=False, sync_preset=True)
247
+
248
+ def run_preset_changed(self, event: Select.Changed) -> None:
249
+ if not self.app.form_ready or self.applying_config or self.app.is_busy():
250
+ return
251
+ preset = str(event.value)
252
+ if self.selected_preset == preset:
253
+ return
254
+ self.selected_preset = preset
255
+ if preset == "smoke":
256
+ self.app.experiments.preset_smoke()
257
+ elif preset == "main":
258
+ self.app.experiments.preset_main()
259
+
260
+ def collect_config(self, *, allow_empty_model: bool = False) -> RunConfig:
261
+ return run_form.collect_config(
262
+ {key: self.input(key) for key in run_form.INPUT_FIELDS},
263
+ {key: self.select(key) for key in run_form.SELECT_FIELDS},
264
+ {key: self.checked(key) for key in (*run_form.CHECKED_FIELDS, *run_form.PROFILER_CHECKBOXES)},
265
+ project_dir=self.app.project_dir, allow_empty_model=allow_empty_model, extra_options=self.extra_options,
266
+ )
267
+
268
+ def apply_config(self, config: RunConfig, *, preset: str = "custom") -> None:
269
+ self.cancel_preview_timer()
270
+ self.applying_config = True
271
+ self.extra_options = dict(config.extra_options)
272
+ values, selects, checks = run_form.config_values(config)
273
+ # Value watchers post Changed messages asynchronously. Suppressing
274
+ # them here avoids dozens of queued debounce timers after a preset.
275
+ try:
276
+ with self.app.prevent(Input.Changed, Select.Changed, Checkbox.Changed):
277
+ with self.app.batch_update():
278
+ for widget_id, value in values.items():
279
+ self.app.query_one(f"#{widget_id}", Input).value = value
280
+ for widget_id, value in selects.items():
281
+ self.app.query_one(f"#{widget_id}", Select).value = value
282
+ for widget_id, checked_value in checks.items():
283
+ self.app.query_one(f"#{widget_id}", Checkbox).value = checked_value
284
+ self.app.query_one("#run-preset", Select).value = preset
285
+ self.selected_preset = preset
286
+ finally:
287
+ self.applying_config = False
288
+ if self.app.form_ready:
289
+ self.refresh_command_preview(notify=False, sync_preset=True)
290
+
291
+ def show_config_error(self, exc: RunConfigError) -> None:
292
+ text = join_messages("\n", (message("• {0}", issue.reason) for issue in exc.issues))
293
+ self.app.notify(text, title="配置有误", severity="error", timeout=8)
294
+ if not any(issue.field for issue in exc.issues):
295
+ return
296
+ self.field_errors_visible = True
297
+ control = self.update_field_errors(exc.issues)
298
+ if control is None:
299
+ return
300
+ ancestors = list(control.ancestors)
301
+ page = next((item.id for item in ancestors if item.id in {"run-form", "advanced-form"}), None)
302
+ if page is not None:
303
+ self.app.activate_tab("run-tab")
304
+ self.show_run_form(page)
305
+ for ancestor in ancestors:
306
+ if isinstance(ancestor, Collapsible):
307
+ ancestor.collapsed = False
308
+ self.app.call_after_refresh(self.focus_config_field, control)
309
+
310
+ def update_field_errors(self, issues):
311
+ from acprof.tui.field_validation import render_field_issues
312
+ self.config_issues = tuple(issues)
313
+ return render_field_issues(self.app, self.config_issues, self.app.localization.tr)
314
+
315
+ def focus_config_field(self, control: Widget) -> None:
316
+ if (control.is_mounted and not control.is_disabled and not self.app.is_busy()
317
+ and not self.app.latest_snapshot.measurement_active):
318
+ control.focus(scroll_visible=False)
319
+ control.scroll_visible(animate=False, immediate=True)
320
+
321
+ def refresh_command_preview(
322
+ self, *, notify: bool = True, sync_preset: bool = False
323
+ ) -> bool:
324
+ self.app.preflight.refresh_preflight_state()
325
+ config = None
326
+ try:
327
+ config = self.collect_config(allow_empty_model=True)
328
+ self.update_plan_summary(config)
329
+ command = build_run_command(
330
+ config,
331
+ project_dir=self.app.project_dir,
332
+ python_executable=self.app.python_executable,
333
+ )
334
+ except RunConfigError as exc:
335
+ if self.field_errors_visible:
336
+ self.update_field_errors(exc.issues)
337
+ self.app.localization.set_text(
338
+ self.app.query_one("#config-summary", Static),
339
+ message_id('ui.0744', join_messages("; ", (item.reason for item in exc.issues[:2]))),
340
+ )
341
+ self.app.localization.set_text(
342
+ self.app.query_one("#command-preview", Static),
343
+ message_id('ui.0745', join_messages("; ", (item.reason for item in exc.issues))),
344
+ )
345
+ if notify:
346
+ self.show_config_error(exc)
347
+ return False
348
+ finally:
349
+ if sync_preset and config is not None:
350
+ selected_preset = self.select("run-preset")
351
+ if selected_preset != "custom":
352
+ adjusted = not run_form.matches_preset(config, selected_preset)
353
+ options = tuple((message_id('ui.0187', message(label)) if key == selected_preset and adjusted else label, key)
354
+ for label, key in run_form.PRESET_OPTIONS)
355
+ widget = self.app.query_one("#run-preset", Select)
356
+ self.app.localization.localized_selects[widget] = options
357
+ with self.app.prevent(Select.Changed):
358
+ widget.set_options((self.app.localization.tr(label), key) for label, key in options)
359
+ widget.value = selected_preset
360
+ if self.field_errors_visible:
361
+ self.update_field_errors(())
362
+ case_count = (
363
+ len(config.cpus.split(","))
364
+ * len(config.mems.split(","))
365
+ * len(config.gpus.split(","))
366
+ )
367
+ scale_summary = (
368
+ message_id('ui.0746', len(config.input_scales.split(',')))
369
+ if config.input_scales
370
+ else message("最小单一尺度" if config.input_scale_policy == "minimal" else "自动规划")
371
+ )
372
+ profiler_summary = (
373
+ message_id('ui.0748')
374
+ if config.compute_profile_tool == "none"
375
+ and config.execution_profile_tool == "none"
376
+ else (
377
+ message_id('ui.0749', config.compute_profile_tool, config.execution_profile_tool)
378
+ )
379
+ )
380
+ self.app.localization.set_text(self.app.query_one("#config-summary", Static), message_id(
381
+ 'ui.0750',
382
+ case_count, scale_summary, config.request_timeout_seconds,
383
+ profiler_summary, config.output_dir,
384
+ ))
385
+ self.app.localization.set_text(self.app.query_one('#command-preview', Static), format_command(command))
386
+ if notify:
387
+ self.app.notify("命令预览已更新", timeout=2)
388
+ return True
389
+
390
+ def update_plan_summary(self, config: RunConfig) -> None:
391
+ planned = self.planned_input if self.planned_input_identity == run_planning.input_identity(config) else None
392
+ summary = self.app.query_one("#run-plan-summary", Static)
393
+ self.app.localization.set_text(summary, run_planning.plan_summary(config, planned))
394
+ self.app.localization.set_text(summary, run_planning.preparation_details(config, planned), "tooltip")
395
+ unit = run_planning.input_unit(config, planned)
396
+ self.app.localization.set_text(self.app.query_one("#input-scales-label", Label), message_id('ui.0627', unit))
397
+ if planned and planned.get("scales"):
398
+ placeholder = ",".join(f"{value:g}" for value in planned["scales"]) + f" {unit}"
399
+ else:
400
+ placeholder = message_id('ui.0628', message("最小单一尺度" if config.input_scale_policy == "minimal" else "自动范围"), unit)
401
+ self.app.localization.set_text(self.app.query_one("#input-scales", Input), placeholder, "placeholder")
402
+
403
+ def remember_last_used(
404
+ self, *, model: str = "", result_dir: str = "", result_csv: str = "",
405
+ ) -> None:
406
+ """Remember confirmed inputs, preserving explicitly saved preferences."""
407
+ updates = {}
408
+ report_source = self.app.query_one("#report-source", Input)
409
+ if result_csv and report_source.value in {"", self.saved_settings.last_result_csv}:
410
+ report_source.value = result_csv
411
+ if model.strip():
412
+ updates["last_model"] = model.strip()
413
+ for widget_id, value in (("result-dir", result_dir), ("result-csv", result_csv)):
414
+ if value:
415
+ self.app.query_one(f"#{widget_id}", Input).value = value
416
+ updates[f"last_{widget_id.replace('-', '_')}"] = value
417
+ settings = replace(
418
+ self.saved_settings,
419
+ last_model=updates.get("last_model", self.saved_settings.last_model),
420
+ last_result_dir=updates.get("last_result_dir", self.saved_settings.last_result_dir),
421
+ last_result_csv=updates.get("last_result_csv", self.saved_settings.last_result_csv),
422
+ )
423
+ if settings == self.saved_settings:
424
+ return
425
+ if self.settings_warning:
426
+ self.app.notify(
427
+ "本地设置无法读取,已保留原文件。可在设置页主动保存后恢复自动记忆。",
428
+ title="自动记忆未保存", severity="warning",
429
+ )
430
+ return
431
+ try:
432
+ save_settings(self.settings_path, settings, self.app.project_dir)
433
+ except (OSError, ValueError, RunConfigError) as exc:
434
+ self.app.notify(error_message(exc), title="自动记忆未保存", severity="warning")
435
+ return
436
+ self.saved_settings = settings