sushihub 0.1.0__tar.gz

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 (95) hide show
  1. sushihub-0.1.0/PKG-INFO +166 -0
  2. sushihub-0.1.0/README.md +149 -0
  3. sushihub-0.1.0/pyproject.toml +40 -0
  4. sushihub-0.1.0/setup.cfg +4 -0
  5. sushihub-0.1.0/sushihub.egg-info/PKG-INFO +166 -0
  6. sushihub-0.1.0/sushihub.egg-info/SOURCES.txt +93 -0
  7. sushihub-0.1.0/sushihub.egg-info/dependency_links.txt +1 -0
  8. sushihub-0.1.0/sushihub.egg-info/entry_points.txt +3 -0
  9. sushihub-0.1.0/sushihub.egg-info/requires.txt +12 -0
  10. sushihub-0.1.0/sushihub.egg-info/top_level.txt +1 -0
  11. sushihub-0.1.0/sushistack/__init__.py +12 -0
  12. sushihub-0.1.0/sushistack/__main__.py +6 -0
  13. sushihub-0.1.0/sushistack/catalog.toml +35 -0
  14. sushihub-0.1.0/sushistack/cli.py +375 -0
  15. sushihub-0.1.0/sushistack/config.py +363 -0
  16. sushihub-0.1.0/sushistack/console.py +44 -0
  17. sushihub-0.1.0/sushistack/defaults.toml +57 -0
  18. sushihub-0.1.0/sushistack/describe.py +170 -0
  19. sushihub-0.1.0/sushistack/gui_config.py +118 -0
  20. sushihub-0.1.0/sushistack/gui_env.py +33 -0
  21. sushihub-0.1.0/sushistack/manifests/base.deps.toml +66 -0
  22. sushihub-0.1.0/sushistack/manifests/gui.deps.toml +21 -0
  23. sushihub-0.1.0/sushistack/py.typed +0 -0
  24. sushihub-0.1.0/sushistack/services/__init__.py +1 -0
  25. sushihub-0.1.0/sushistack/services/binary.py +100 -0
  26. sushihub-0.1.0/sushistack/services/catalog.py +90 -0
  27. sushihub-0.1.0/sushistack/services/cli_install.py +117 -0
  28. sushihub-0.1.0/sushistack/services/customize.py +144 -0
  29. sushihub-0.1.0/sushistack/services/discovery.py +91 -0
  30. sushihub-0.1.0/sushistack/services/git_ops.py +45 -0
  31. sushihub-0.1.0/sushistack/services/git_state.py +83 -0
  32. sushihub-0.1.0/sushistack/services/gui.py +240 -0
  33. sushihub-0.1.0/sushistack/services/hub_install.py +61 -0
  34. sushihub-0.1.0/sushistack/services/identity.py +352 -0
  35. sushihub-0.1.0/sushistack/services/licence_file.py +71 -0
  36. sushihub-0.1.0/sushistack/services/links.py +48 -0
  37. sushihub-0.1.0/sushistack/services/modules.py +349 -0
  38. sushihub-0.1.0/sushistack/services/pipx.py +60 -0
  39. sushihub-0.1.0/sushistack/services/presence.py +146 -0
  40. sushihub-0.1.0/sushistack/services/releases.py +245 -0
  41. sushihub-0.1.0/sushistack/services/session.py +120 -0
  42. sushihub-0.1.0/sushistack/services/setup.py +114 -0
  43. sushihub-0.1.0/sushistack/services/status_report.py +161 -0
  44. sushihub-0.1.0/sushistack/services/token_store.py +101 -0
  45. sushihub-0.1.0/sushistack/services/update_check.py +38 -0
  46. sushihub-0.1.0/sushistack/setup/__init__.py +26 -0
  47. sushihub-0.1.0/sushistack/setup/apt.py +86 -0
  48. sushihub-0.1.0/sushistack/setup/dependency_source.py +272 -0
  49. sushihub-0.1.0/sushistack/setup/factory.py +126 -0
  50. sushihub-0.1.0/sushistack/setup/gpu_backends/__init__.py +7 -0
  51. sushihub-0.1.0/sushistack/setup/gpu_backends/adapter_builder.py +364 -0
  52. sushihub-0.1.0/sushistack/setup/gpu_backends/backend.py +121 -0
  53. sushihub-0.1.0/sushistack/setup/gpu_backends/compiler_identity.py +40 -0
  54. sushihub-0.1.0/sushistack/setup/gpu_backends/cuda.py +265 -0
  55. sushihub-0.1.0/sushistack/setup/gpu_backends/level_zero.py +96 -0
  56. sushihub-0.1.0/sushistack/setup/gpu_backends/provisioning.py +86 -0
  57. sushihub-0.1.0/sushistack/setup/gpu_backends/registry.py +52 -0
  58. sushihub-0.1.0/sushistack/setup/gpu_backends/rocm.py +86 -0
  59. sushihub-0.1.0/sushistack/setup/gpu_backends/windows_installer.py +229 -0
  60. sushihub-0.1.0/sushistack/setup/ordering.py +46 -0
  61. sushihub-0.1.0/sushistack/setup/package_managers.py +852 -0
  62. sushihub-0.1.0/sushistack/setup/pipeline.py +175 -0
  63. sushihub-0.1.0/sushistack/setup/probe.py +453 -0
  64. sushihub-0.1.0/sushistack/setup/selection.py +67 -0
  65. sushihub-0.1.0/sushistack/setup/steps.py +976 -0
  66. sushihub-0.1.0/sushistack/setup/toolchains.py +597 -0
  67. sushihub-0.1.0/tests/test_adapter_builder.py +457 -0
  68. sushihub-0.1.0/tests/test_add_binary.py +243 -0
  69. sushihub-0.1.0/tests/test_add_provisions.py +48 -0
  70. sushihub-0.1.0/tests/test_catalog.py +110 -0
  71. sushihub-0.1.0/tests/test_cli_install.py +106 -0
  72. sushihub-0.1.0/tests/test_compiler_identity.py +66 -0
  73. sushihub-0.1.0/tests/test_describe.py +57 -0
  74. sushihub-0.1.0/tests/test_detect_rows.py +34 -0
  75. sushihub-0.1.0/tests/test_git_state.py +110 -0
  76. sushihub-0.1.0/tests/test_gpu_backend_registry.py +106 -0
  77. sushihub-0.1.0/tests/test_gpu_backend_specs.py +340 -0
  78. sushihub-0.1.0/tests/test_gpu_provisioning.py +350 -0
  79. sushihub-0.1.0/tests/test_gui_build.py +214 -0
  80. sushihub-0.1.0/tests/test_hub_install.py +55 -0
  81. sushihub-0.1.0/tests/test_identity.py +519 -0
  82. sushihub-0.1.0/tests/test_init.py +66 -0
  83. sushihub-0.1.0/tests/test_json_streams.py +204 -0
  84. sushihub-0.1.0/tests/test_link.py +109 -0
  85. sushihub-0.1.0/tests/test_ordering.py +25 -0
  86. sushihub-0.1.0/tests/test_presence.py +208 -0
  87. sushihub-0.1.0/tests/test_releases.py +240 -0
  88. sushihub-0.1.0/tests/test_selection.py +70 -0
  89. sushihub-0.1.0/tests/test_status_payload.py +118 -0
  90. sushihub-0.1.0/tests/test_toolchains.py +106 -0
  91. sushihub-0.1.0/tests/test_update_check.py +47 -0
  92. sushihub-0.1.0/tests/test_vcpkg_features.py +34 -0
  93. sushihub-0.1.0/tests/test_windows_cuda_install.py +439 -0
  94. sushihub-0.1.0/tests/test_workspace_resolution.py +92 -0
  95. sushihub-0.1.0/tests/test_workspace_upgrade.py +110 -0
@@ -0,0 +1,166 @@
1
+ Metadata-Version: 2.4
2
+ Name: sushihub
3
+ Version: 0.1.0
4
+ Summary: SushiStack CLI — shared dependency provisioning and module manager for the stack
5
+ Author-email: Mustafa Garip <mustafagarip@sushisystems.io>
6
+ Requires-Python: >=3.10
7
+ Description-Content-Type: text/markdown
8
+ Requires-Dist: click>=8.0
9
+ Requires-Dist: sushicore>=0.2.0
10
+ Requires-Dist: typer>=0.12
11
+ Requires-Dist: rich>=13.0
12
+ Requires-Dist: keyring>=24
13
+ Requires-Dist: tomli>=2.0; python_version < "3.11"
14
+ Provides-Extra: test
15
+ Requires-Dist: pytest>=7.0; extra == "test"
16
+ Requires-Dist: jsonschema>=4.0; extra == "test"
17
+
18
+ # The `hub` command
19
+
20
+ `hub` provisions the shared dependency tree and manages the module checkouts of a SushiStack
21
+ workspace. The one thing it builds is the desktop application in `sushihub/gui`, which belongs
22
+ to the workspace rather than to a module. Every module has its own CLI: `sr` (sushiruntime),
23
+ `se` (sushiengine), `sa` (sushiai), `sb` (sushiblas).
24
+
25
+ ## Layout
26
+
27
+ ```
28
+ sushihub/cli/
29
+ sushistack/ the Python package behind `hub`
30
+ cli.py the Typer application: one function per subcommand
31
+ config.py workspace root, the workspace file, the packaged defaults
32
+ gui_config.py the desktop application's profile, config and root
33
+ gui_env.py its build environment, vcvars snapshot included
34
+ services/ module lifecycle, Sushi Account, releases, the licence file, the gui build policy
35
+ setup/ the dependency engine: manifests, package managers, toolchains, the pipeline
36
+ defaults.toml defaults for the [tool], [cli] and [identity] tables
37
+ manifests/ dependency fragments this package ships (*.deps.toml)
38
+ install.py installs `hub` into a pipx venv and injects sushicore
39
+ pyproject.toml
40
+ ```
41
+
42
+ ## Commands
43
+
44
+ `--json` and `--describe` are global: they go before the subcommand, and no row below repeats
45
+ them. See "Machine-readable output".
46
+
47
+ | Command | What it does |
48
+ |---|---|
49
+ | `hub init` | Write the `.sushistack` workspace marker and add `dependencies/` to `.gitignore`. |
50
+ | `hub install [--customize] [--dry-run] [--yes] [--refresh-toolchains]` | Download and install shared dependencies. `--customize` opens an interactive picker over the toolchains and the GPU toolkit, which is on by default. `--yes` answers the LLVM-download prompt for unattended runs. `--refresh-toolchains` re-downloads an installed SYCL toolchain, which is otherwise reused forever; reused installs report the release they came from and say when they carry no sanitizer runtime. |
51
+ | `hub add <sushiruntime\|sushiengine\|sushiai\|sushiblas\|all> [--dry-run] [--skip-install] [--binary]` | Bring one or more modules into the workspace, install each one's CLI, and provision what they declare. `--skip-install` leaves the dependencies to a later `hub install`. `--binary` installs sushiengine from its release rather than its source; see "Binary installs". Aliases: `sr`, `se`, `sa`, `sb`. |
52
+ | `hub link <module> <path> [--dry-run] [--skip-install]` | Register an existing checkout outside the workspace as a module, without cloning, then provision what it declares. `--skip-install` leaves that to a later `hub install`. Same names and aliases as `hub add`. |
53
+ | `hub install-cli <module…> [--dry-run]` | Install a module's own CLI into an isolated pipx venv and inject `sushicore`. Always editable. Same names, aliases and `all` as `hub add`. |
54
+ | `hub update [module…] [--dry-run]` | Run `git pull --ff-only` on present modules, cloned or linked. A binary install asks Sushi Account for the latest release and downloads it when the version differs. No arguments means all. |
55
+ | `hub sync [--dry-run]` | Install missing dependencies, then update every module. |
56
+ | `hub status [--json] [--check-updates]` | Which modules are present, in which form, on which branch and how far from upstream, and whether dependencies are installed. It reads the disk only; `--check-updates` first fetches every checkout and asks Sushi Account for each binary install's latest release. Its `--json` is the global flag under another name, kept for scripts written against the old spelling. |
57
+ | `hub doctor` | Check tools, compilers and dependencies; report what is missing. |
58
+ | `hub remove [--gpu] [--all] [--dry-run] [--yes]` | Remove installed dependencies. `--all` removes the whole `dependencies/` tree and asks first unless `--yes` is given. |
59
+ | `hub home` | Print the workspace root and the `dependencies/` path. |
60
+ | `hub gui build [--type debug\|release\|relwithdebinfo] [--clean] [-D VAR=VALUE…]` | Configure and compile the desktop application into `sushihub/gui/build/hub`, under the Visual Studio environment on Windows, against the shared vcpkg tree. |
61
+ | `hub gui test [--filter <pattern>] [--repeat <n>]` | Run the application's CTest suites. `--filter` selects by test name, `--repeat` re-runs each until it fails. |
62
+ | `hub gui run [target] [-- args…]` | Launch a program from the application's build tree; the application itself when no target is named. |
63
+ | `hub gui clean` | Remove `sushihub/gui/build/hub`. The presets' own build trees are untouched. |
64
+ | `hub login` | Sign in to Sushi Account: print a code, open the browser at the device page, wait for the grant, and store the session in this machine's credential store. |
65
+ | `hub logout` | Forget the stored Sushi Account session. Sushi Account is not told. |
66
+ | `hub whoami` | Print the signed-in account: its id, its email and how many licences it holds. |
67
+ | `hub license` | Print one row per licence on the account: product, holder (`account` or `org`), expiry. |
68
+
69
+ Tab completion: run `hub --install-completion` once.
70
+
71
+ ## Machine-readable output
72
+
73
+ `hub --json <command>` writes one JSON event per line to stdout and nothing else there. Everything
74
+ a human would read instead — the setup progress bar, a config file rendered before it is written —
75
+ goes to stderr, so a caller parses stdout line by line and never has to strip a table out of it.
76
+ Every command ends with one `result` event carrying its exit status and whatever it computed:
77
+ `hub --json status` puts the module list there, `hub --json home` the workspace and dependency paths.
78
+ The status payload's shape is fixed by `../contract/status.schema.json`.
79
+ A question becomes a `prompt` event answered by one line on stdin.
80
+
81
+ `hub --describe` prints the command catalogue instead: every subcommand, its arguments and options
82
+ with their types, defaults and choices. It is a serialisation of the Typer application, not a
83
+ second declaration, so a new `hub` command shows up in the catalogue the moment it exists.
84
+
85
+ Both halves are JSON Schema in `../contract/`, and `../contract/README.md` writes out the event
86
+ shapes, the stdout rule and the prompt rule for whoever is on the other end.
87
+
88
+ ## Signing in
89
+
90
+ sushiengine is sold; the other four modules are not. `hub login` is how a machine proves a licence,
91
+ and nothing else in `hub` needs it: cloning an open-source module asks only for a Git identity.
92
+
93
+ `hub login` asks Sushi Account for a device code, prints it with the page to type it into, opens that page
94
+ in the browser, and polls until you approve it there. What comes back — an access token, a refresh
95
+ token and an expiry — goes into the operating system's credential store through `keyring`, under
96
+ service `sushistack` and username `sushi-account`. A later command that needs the account refreshes the
97
+ access token when it is within 30 seconds of expiry; when the refresh is refused, the stored session
98
+ is dropped and the command says nobody is signed in.
99
+
100
+ Sushi Account lives at `https://account.sushisystems.io`, from `[identity] url` in `config.toml`.
101
+ `SUSHI_ACCOUNT_URL` overrides it, which is how the tests point every Sushi Account call at a fake server on
102
+ `127.0.0.1`. The six endpoints are written out in `../contract/sushi-account.md`; sushiweb has not built
103
+ them yet.
104
+
105
+ ## Binary installs
106
+
107
+ `hub add sushiengine` decides between the two forms rather than being told. It asks the private
108
+ repository whether this machine's Git identity reaches it, with `git ls-remote --exit-code` under a
109
+ 15-second timeout. If it does, the module is cloned like any other. If it does not, `hub` needs a
110
+ Sushi Account session: with one it downloads the release, without one it names both ways in and stops.
111
+ `--binary` skips the question and goes straight to the release. The other four modules are open
112
+ source and have one path; `--binary` on any of them is refused.
113
+
114
+ The download is what `sushiweb` signed a URL for. `hub` streams it, refuses to unpack it when either
115
+ the size or the sha256 differs from what Sushi Account declared, unpacks it into a directory beside
116
+ `<workspace>/sushiengine`, and renames that over the module last, so a download that fails leaves
117
+ the install that was there untouched. The release carries `sushi-release.json` at its top level:
118
+ that file is what makes the directory a binary install, and `hub status` reads the version out of it
119
+ ("binary 1.4.2"). Beside it `hub` writes `sushi-licence.jwt`, the licence token Sushi Account issued,
120
+ which the engine reads at start-up and verifies offline against Sushi Account's JWKS.
121
+
122
+ A release brings its own sushiruntime and sushiblas, so it declares no dependency fragment and
123
+ nothing provisions after it: a licensed user never downloads a SYCL toolchain. It also installs no
124
+ module CLI; `se` arrives inside the package.
125
+
126
+ `hub update sushiengine` asks for the latest release, says the install is already the latest when
127
+ the versions match, and downloads the new one and writes the licence file again when they do not.
128
+ `hub add sushiengine` on a directory that is already a binary install leaves it alone.
129
+
130
+ ## How dependencies are chosen
131
+
132
+ `hub install` merges every `*.deps.toml` fragment the `sushistack` package ships with each present
133
+ module's own
134
+ `cli/sushistack.deps.toml`, keeps the entries that name a package for the current platform, and
135
+ installs the ones that are missing. No dependency name lives in the installer code. The SYCL
136
+ toolchains are sushiruntime's entries, not this repository's; the GPU toolkit is on for every
137
+ workspace and follows the detected GPU vendor (`sushistack/setup/selection.py`); the base fragment carries
138
+ only cmake, ninja, gtest, opencl and pkgconf.
139
+
140
+ A shipped fragment is owned by the name in its filename, with `base.deps.toml` the exception
141
+ that owns nothing and is owned by `shared`. So `gui.deps.toml`, which names the desktop
142
+ application's imgui, glfw3 and nlohmann-json, is owned by `gui` and `hub doctor` groups those
143
+ three rows under it.
144
+
145
+ The toolchain selection follows the same rule: a component is installed when a present module's
146
+ fragment declares a dependency of that name, so an empty workspace gets the base tools alone.
147
+ `hub add` and `hub link` run the provision pipeline for the module they bring in, unless you pass
148
+ `--skip-install`.
149
+
150
+ ## Files it reads and writes
151
+
152
+ | File | Owner | Purpose |
153
+ |---|---|---|
154
+ | `<workspace>/.sushistack/` | `hub init` | Marks the workspace root; every `hub` and module CLI walks up to it. |
155
+ | `<workspace>/.sushistack/workspace.toml` | `hub init`, `hub install`, `hub link` | Everything the workspace owns: its format version, the resolved toolchain paths for this machine, and the modules linked from outside the tree. |
156
+ | `<workspace>/sushiengine/sushi-release.json` | the release | Product, version, platform and what the package bundles. Its presence is what makes the directory a binary install. |
157
+ | `<workspace>/sushiengine/sushi-licence.jwt` | `hub add`, `hub update` | The licence token the engine reads at start-up. Nothing but the token. |
158
+ | `<workspace>/dependencies/` | `hub install`, `hub remove` | Toolchains, vcpkg, portable cmake and ninja, with a stamp per installed toolchain. |
159
+ | OS credential store, `sushistack` / `sushi-account` | `hub login`, `hub logout` | The Sushi Account session as one JSON document: both tokens and the access token's expiry. |
160
+
161
+ ## Where sushicore comes from
162
+
163
+ `hub` imports `sushicore` for its console, its config schema and its workspace helpers. The package
164
+ is not on any index; `install.py` injects the checkout under `<workspace>/sushicore` into the
165
+ pipx venv, editable. `SUSHICORE_DIR` or `hub link sushicore <path>` points it elsewhere. See
166
+ `../../sushicore/docs/README.md`.
@@ -0,0 +1,149 @@
1
+ # The `hub` command
2
+
3
+ `hub` provisions the shared dependency tree and manages the module checkouts of a SushiStack
4
+ workspace. The one thing it builds is the desktop application in `sushihub/gui`, which belongs
5
+ to the workspace rather than to a module. Every module has its own CLI: `sr` (sushiruntime),
6
+ `se` (sushiengine), `sa` (sushiai), `sb` (sushiblas).
7
+
8
+ ## Layout
9
+
10
+ ```
11
+ sushihub/cli/
12
+ sushistack/ the Python package behind `hub`
13
+ cli.py the Typer application: one function per subcommand
14
+ config.py workspace root, the workspace file, the packaged defaults
15
+ gui_config.py the desktop application's profile, config and root
16
+ gui_env.py its build environment, vcvars snapshot included
17
+ services/ module lifecycle, Sushi Account, releases, the licence file, the gui build policy
18
+ setup/ the dependency engine: manifests, package managers, toolchains, the pipeline
19
+ defaults.toml defaults for the [tool], [cli] and [identity] tables
20
+ manifests/ dependency fragments this package ships (*.deps.toml)
21
+ install.py installs `hub` into a pipx venv and injects sushicore
22
+ pyproject.toml
23
+ ```
24
+
25
+ ## Commands
26
+
27
+ `--json` and `--describe` are global: they go before the subcommand, and no row below repeats
28
+ them. See "Machine-readable output".
29
+
30
+ | Command | What it does |
31
+ |---|---|
32
+ | `hub init` | Write the `.sushistack` workspace marker and add `dependencies/` to `.gitignore`. |
33
+ | `hub install [--customize] [--dry-run] [--yes] [--refresh-toolchains]` | Download and install shared dependencies. `--customize` opens an interactive picker over the toolchains and the GPU toolkit, which is on by default. `--yes` answers the LLVM-download prompt for unattended runs. `--refresh-toolchains` re-downloads an installed SYCL toolchain, which is otherwise reused forever; reused installs report the release they came from and say when they carry no sanitizer runtime. |
34
+ | `hub add <sushiruntime\|sushiengine\|sushiai\|sushiblas\|all> [--dry-run] [--skip-install] [--binary]` | Bring one or more modules into the workspace, install each one's CLI, and provision what they declare. `--skip-install` leaves the dependencies to a later `hub install`. `--binary` installs sushiengine from its release rather than its source; see "Binary installs". Aliases: `sr`, `se`, `sa`, `sb`. |
35
+ | `hub link <module> <path> [--dry-run] [--skip-install]` | Register an existing checkout outside the workspace as a module, without cloning, then provision what it declares. `--skip-install` leaves that to a later `hub install`. Same names and aliases as `hub add`. |
36
+ | `hub install-cli <module…> [--dry-run]` | Install a module's own CLI into an isolated pipx venv and inject `sushicore`. Always editable. Same names, aliases and `all` as `hub add`. |
37
+ | `hub update [module…] [--dry-run]` | Run `git pull --ff-only` on present modules, cloned or linked. A binary install asks Sushi Account for the latest release and downloads it when the version differs. No arguments means all. |
38
+ | `hub sync [--dry-run]` | Install missing dependencies, then update every module. |
39
+ | `hub status [--json] [--check-updates]` | Which modules are present, in which form, on which branch and how far from upstream, and whether dependencies are installed. It reads the disk only; `--check-updates` first fetches every checkout and asks Sushi Account for each binary install's latest release. Its `--json` is the global flag under another name, kept for scripts written against the old spelling. |
40
+ | `hub doctor` | Check tools, compilers and dependencies; report what is missing. |
41
+ | `hub remove [--gpu] [--all] [--dry-run] [--yes]` | Remove installed dependencies. `--all` removes the whole `dependencies/` tree and asks first unless `--yes` is given. |
42
+ | `hub home` | Print the workspace root and the `dependencies/` path. |
43
+ | `hub gui build [--type debug\|release\|relwithdebinfo] [--clean] [-D VAR=VALUE…]` | Configure and compile the desktop application into `sushihub/gui/build/hub`, under the Visual Studio environment on Windows, against the shared vcpkg tree. |
44
+ | `hub gui test [--filter <pattern>] [--repeat <n>]` | Run the application's CTest suites. `--filter` selects by test name, `--repeat` re-runs each until it fails. |
45
+ | `hub gui run [target] [-- args…]` | Launch a program from the application's build tree; the application itself when no target is named. |
46
+ | `hub gui clean` | Remove `sushihub/gui/build/hub`. The presets' own build trees are untouched. |
47
+ | `hub login` | Sign in to Sushi Account: print a code, open the browser at the device page, wait for the grant, and store the session in this machine's credential store. |
48
+ | `hub logout` | Forget the stored Sushi Account session. Sushi Account is not told. |
49
+ | `hub whoami` | Print the signed-in account: its id, its email and how many licences it holds. |
50
+ | `hub license` | Print one row per licence on the account: product, holder (`account` or `org`), expiry. |
51
+
52
+ Tab completion: run `hub --install-completion` once.
53
+
54
+ ## Machine-readable output
55
+
56
+ `hub --json <command>` writes one JSON event per line to stdout and nothing else there. Everything
57
+ a human would read instead — the setup progress bar, a config file rendered before it is written —
58
+ goes to stderr, so a caller parses stdout line by line and never has to strip a table out of it.
59
+ Every command ends with one `result` event carrying its exit status and whatever it computed:
60
+ `hub --json status` puts the module list there, `hub --json home` the workspace and dependency paths.
61
+ The status payload's shape is fixed by `../contract/status.schema.json`.
62
+ A question becomes a `prompt` event answered by one line on stdin.
63
+
64
+ `hub --describe` prints the command catalogue instead: every subcommand, its arguments and options
65
+ with their types, defaults and choices. It is a serialisation of the Typer application, not a
66
+ second declaration, so a new `hub` command shows up in the catalogue the moment it exists.
67
+
68
+ Both halves are JSON Schema in `../contract/`, and `../contract/README.md` writes out the event
69
+ shapes, the stdout rule and the prompt rule for whoever is on the other end.
70
+
71
+ ## Signing in
72
+
73
+ sushiengine is sold; the other four modules are not. `hub login` is how a machine proves a licence,
74
+ and nothing else in `hub` needs it: cloning an open-source module asks only for a Git identity.
75
+
76
+ `hub login` asks Sushi Account for a device code, prints it with the page to type it into, opens that page
77
+ in the browser, and polls until you approve it there. What comes back — an access token, a refresh
78
+ token and an expiry — goes into the operating system's credential store through `keyring`, under
79
+ service `sushistack` and username `sushi-account`. A later command that needs the account refreshes the
80
+ access token when it is within 30 seconds of expiry; when the refresh is refused, the stored session
81
+ is dropped and the command says nobody is signed in.
82
+
83
+ Sushi Account lives at `https://account.sushisystems.io`, from `[identity] url` in `config.toml`.
84
+ `SUSHI_ACCOUNT_URL` overrides it, which is how the tests point every Sushi Account call at a fake server on
85
+ `127.0.0.1`. The six endpoints are written out in `../contract/sushi-account.md`; sushiweb has not built
86
+ them yet.
87
+
88
+ ## Binary installs
89
+
90
+ `hub add sushiengine` decides between the two forms rather than being told. It asks the private
91
+ repository whether this machine's Git identity reaches it, with `git ls-remote --exit-code` under a
92
+ 15-second timeout. If it does, the module is cloned like any other. If it does not, `hub` needs a
93
+ Sushi Account session: with one it downloads the release, without one it names both ways in and stops.
94
+ `--binary` skips the question and goes straight to the release. The other four modules are open
95
+ source and have one path; `--binary` on any of them is refused.
96
+
97
+ The download is what `sushiweb` signed a URL for. `hub` streams it, refuses to unpack it when either
98
+ the size or the sha256 differs from what Sushi Account declared, unpacks it into a directory beside
99
+ `<workspace>/sushiengine`, and renames that over the module last, so a download that fails leaves
100
+ the install that was there untouched. The release carries `sushi-release.json` at its top level:
101
+ that file is what makes the directory a binary install, and `hub status` reads the version out of it
102
+ ("binary 1.4.2"). Beside it `hub` writes `sushi-licence.jwt`, the licence token Sushi Account issued,
103
+ which the engine reads at start-up and verifies offline against Sushi Account's JWKS.
104
+
105
+ A release brings its own sushiruntime and sushiblas, so it declares no dependency fragment and
106
+ nothing provisions after it: a licensed user never downloads a SYCL toolchain. It also installs no
107
+ module CLI; `se` arrives inside the package.
108
+
109
+ `hub update sushiengine` asks for the latest release, says the install is already the latest when
110
+ the versions match, and downloads the new one and writes the licence file again when they do not.
111
+ `hub add sushiengine` on a directory that is already a binary install leaves it alone.
112
+
113
+ ## How dependencies are chosen
114
+
115
+ `hub install` merges every `*.deps.toml` fragment the `sushistack` package ships with each present
116
+ module's own
117
+ `cli/sushistack.deps.toml`, keeps the entries that name a package for the current platform, and
118
+ installs the ones that are missing. No dependency name lives in the installer code. The SYCL
119
+ toolchains are sushiruntime's entries, not this repository's; the GPU toolkit is on for every
120
+ workspace and follows the detected GPU vendor (`sushistack/setup/selection.py`); the base fragment carries
121
+ only cmake, ninja, gtest, opencl and pkgconf.
122
+
123
+ A shipped fragment is owned by the name in its filename, with `base.deps.toml` the exception
124
+ that owns nothing and is owned by `shared`. So `gui.deps.toml`, which names the desktop
125
+ application's imgui, glfw3 and nlohmann-json, is owned by `gui` and `hub doctor` groups those
126
+ three rows under it.
127
+
128
+ The toolchain selection follows the same rule: a component is installed when a present module's
129
+ fragment declares a dependency of that name, so an empty workspace gets the base tools alone.
130
+ `hub add` and `hub link` run the provision pipeline for the module they bring in, unless you pass
131
+ `--skip-install`.
132
+
133
+ ## Files it reads and writes
134
+
135
+ | File | Owner | Purpose |
136
+ |---|---|---|
137
+ | `<workspace>/.sushistack/` | `hub init` | Marks the workspace root; every `hub` and module CLI walks up to it. |
138
+ | `<workspace>/.sushistack/workspace.toml` | `hub init`, `hub install`, `hub link` | Everything the workspace owns: its format version, the resolved toolchain paths for this machine, and the modules linked from outside the tree. |
139
+ | `<workspace>/sushiengine/sushi-release.json` | the release | Product, version, platform and what the package bundles. Its presence is what makes the directory a binary install. |
140
+ | `<workspace>/sushiengine/sushi-licence.jwt` | `hub add`, `hub update` | The licence token the engine reads at start-up. Nothing but the token. |
141
+ | `<workspace>/dependencies/` | `hub install`, `hub remove` | Toolchains, vcpkg, portable cmake and ninja, with a stamp per installed toolchain. |
142
+ | OS credential store, `sushistack` / `sushi-account` | `hub login`, `hub logout` | The Sushi Account session as one JSON document: both tokens and the access token's expiry. |
143
+
144
+ ## Where sushicore comes from
145
+
146
+ `hub` imports `sushicore` for its console, its config schema and its workspace helpers. The package
147
+ is not on any index; `install.py` injects the checkout under `<workspace>/sushicore` into the
148
+ pipx venv, editable. `SUSHICORE_DIR` or `hub link sushicore <path>` points it elsewhere. See
149
+ `../../sushicore/docs/README.md`.
@@ -0,0 +1,40 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "sushihub"
7
+ version = "0.1.0"
8
+ description = "SushiStack CLI — shared dependency provisioning and module manager for the stack"
9
+ readme = "README.md"
10
+ authors = [{ name = "Mustafa Garip", email = "mustafagarip@sushisystems.io" }]
11
+ requires-python = ">=3.10"
12
+ dependencies = [
13
+ # click is imported directly by describe.py, which walks a Typer app's click
14
+ # objects to build the --describe contract. Typer no longer pins it, so it is
15
+ # declared here rather than relied on transitively.
16
+ "click>=8.0",
17
+ "sushicore>=0.2.0",
18
+ "typer>=0.12",
19
+ "rich>=13.0",
20
+ "keyring>=24",
21
+ "tomli>=2.0; python_version < '3.11'",
22
+ ]
23
+
24
+ [project.optional-dependencies]
25
+ test = ["pytest>=7.0", "jsonschema>=4.0"]
26
+
27
+ [project.scripts]
28
+ hub = "sushistack.cli:app"
29
+ sushihub = "sushistack.cli:app"
30
+
31
+ [tool.setuptools.packages.find]
32
+ where = ["."]
33
+ include = ["sushistack*"]
34
+
35
+ # The tool's own data travels with the tool: the module catalog, the committed
36
+ # defaults and the dependency fragments every workspace shares. A workspace is
37
+ # no longer a checkout, so none of these can be read out of one.
38
+
39
+ [tool.setuptools.package-data]
40
+ sushistack = ["py.typed", "catalog.toml", "defaults.toml", "manifests/*.deps.toml"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,166 @@
1
+ Metadata-Version: 2.4
2
+ Name: sushihub
3
+ Version: 0.1.0
4
+ Summary: SushiStack CLI — shared dependency provisioning and module manager for the stack
5
+ Author-email: Mustafa Garip <mustafagarip@sushisystems.io>
6
+ Requires-Python: >=3.10
7
+ Description-Content-Type: text/markdown
8
+ Requires-Dist: click>=8.0
9
+ Requires-Dist: sushicore>=0.2.0
10
+ Requires-Dist: typer>=0.12
11
+ Requires-Dist: rich>=13.0
12
+ Requires-Dist: keyring>=24
13
+ Requires-Dist: tomli>=2.0; python_version < "3.11"
14
+ Provides-Extra: test
15
+ Requires-Dist: pytest>=7.0; extra == "test"
16
+ Requires-Dist: jsonschema>=4.0; extra == "test"
17
+
18
+ # The `hub` command
19
+
20
+ `hub` provisions the shared dependency tree and manages the module checkouts of a SushiStack
21
+ workspace. The one thing it builds is the desktop application in `sushihub/gui`, which belongs
22
+ to the workspace rather than to a module. Every module has its own CLI: `sr` (sushiruntime),
23
+ `se` (sushiengine), `sa` (sushiai), `sb` (sushiblas).
24
+
25
+ ## Layout
26
+
27
+ ```
28
+ sushihub/cli/
29
+ sushistack/ the Python package behind `hub`
30
+ cli.py the Typer application: one function per subcommand
31
+ config.py workspace root, the workspace file, the packaged defaults
32
+ gui_config.py the desktop application's profile, config and root
33
+ gui_env.py its build environment, vcvars snapshot included
34
+ services/ module lifecycle, Sushi Account, releases, the licence file, the gui build policy
35
+ setup/ the dependency engine: manifests, package managers, toolchains, the pipeline
36
+ defaults.toml defaults for the [tool], [cli] and [identity] tables
37
+ manifests/ dependency fragments this package ships (*.deps.toml)
38
+ install.py installs `hub` into a pipx venv and injects sushicore
39
+ pyproject.toml
40
+ ```
41
+
42
+ ## Commands
43
+
44
+ `--json` and `--describe` are global: they go before the subcommand, and no row below repeats
45
+ them. See "Machine-readable output".
46
+
47
+ | Command | What it does |
48
+ |---|---|
49
+ | `hub init` | Write the `.sushistack` workspace marker and add `dependencies/` to `.gitignore`. |
50
+ | `hub install [--customize] [--dry-run] [--yes] [--refresh-toolchains]` | Download and install shared dependencies. `--customize` opens an interactive picker over the toolchains and the GPU toolkit, which is on by default. `--yes` answers the LLVM-download prompt for unattended runs. `--refresh-toolchains` re-downloads an installed SYCL toolchain, which is otherwise reused forever; reused installs report the release they came from and say when they carry no sanitizer runtime. |
51
+ | `hub add <sushiruntime\|sushiengine\|sushiai\|sushiblas\|all> [--dry-run] [--skip-install] [--binary]` | Bring one or more modules into the workspace, install each one's CLI, and provision what they declare. `--skip-install` leaves the dependencies to a later `hub install`. `--binary` installs sushiengine from its release rather than its source; see "Binary installs". Aliases: `sr`, `se`, `sa`, `sb`. |
52
+ | `hub link <module> <path> [--dry-run] [--skip-install]` | Register an existing checkout outside the workspace as a module, without cloning, then provision what it declares. `--skip-install` leaves that to a later `hub install`. Same names and aliases as `hub add`. |
53
+ | `hub install-cli <module…> [--dry-run]` | Install a module's own CLI into an isolated pipx venv and inject `sushicore`. Always editable. Same names, aliases and `all` as `hub add`. |
54
+ | `hub update [module…] [--dry-run]` | Run `git pull --ff-only` on present modules, cloned or linked. A binary install asks Sushi Account for the latest release and downloads it when the version differs. No arguments means all. |
55
+ | `hub sync [--dry-run]` | Install missing dependencies, then update every module. |
56
+ | `hub status [--json] [--check-updates]` | Which modules are present, in which form, on which branch and how far from upstream, and whether dependencies are installed. It reads the disk only; `--check-updates` first fetches every checkout and asks Sushi Account for each binary install's latest release. Its `--json` is the global flag under another name, kept for scripts written against the old spelling. |
57
+ | `hub doctor` | Check tools, compilers and dependencies; report what is missing. |
58
+ | `hub remove [--gpu] [--all] [--dry-run] [--yes]` | Remove installed dependencies. `--all` removes the whole `dependencies/` tree and asks first unless `--yes` is given. |
59
+ | `hub home` | Print the workspace root and the `dependencies/` path. |
60
+ | `hub gui build [--type debug\|release\|relwithdebinfo] [--clean] [-D VAR=VALUE…]` | Configure and compile the desktop application into `sushihub/gui/build/hub`, under the Visual Studio environment on Windows, against the shared vcpkg tree. |
61
+ | `hub gui test [--filter <pattern>] [--repeat <n>]` | Run the application's CTest suites. `--filter` selects by test name, `--repeat` re-runs each until it fails. |
62
+ | `hub gui run [target] [-- args…]` | Launch a program from the application's build tree; the application itself when no target is named. |
63
+ | `hub gui clean` | Remove `sushihub/gui/build/hub`. The presets' own build trees are untouched. |
64
+ | `hub login` | Sign in to Sushi Account: print a code, open the browser at the device page, wait for the grant, and store the session in this machine's credential store. |
65
+ | `hub logout` | Forget the stored Sushi Account session. Sushi Account is not told. |
66
+ | `hub whoami` | Print the signed-in account: its id, its email and how many licences it holds. |
67
+ | `hub license` | Print one row per licence on the account: product, holder (`account` or `org`), expiry. |
68
+
69
+ Tab completion: run `hub --install-completion` once.
70
+
71
+ ## Machine-readable output
72
+
73
+ `hub --json <command>` writes one JSON event per line to stdout and nothing else there. Everything
74
+ a human would read instead — the setup progress bar, a config file rendered before it is written —
75
+ goes to stderr, so a caller parses stdout line by line and never has to strip a table out of it.
76
+ Every command ends with one `result` event carrying its exit status and whatever it computed:
77
+ `hub --json status` puts the module list there, `hub --json home` the workspace and dependency paths.
78
+ The status payload's shape is fixed by `../contract/status.schema.json`.
79
+ A question becomes a `prompt` event answered by one line on stdin.
80
+
81
+ `hub --describe` prints the command catalogue instead: every subcommand, its arguments and options
82
+ with their types, defaults and choices. It is a serialisation of the Typer application, not a
83
+ second declaration, so a new `hub` command shows up in the catalogue the moment it exists.
84
+
85
+ Both halves are JSON Schema in `../contract/`, and `../contract/README.md` writes out the event
86
+ shapes, the stdout rule and the prompt rule for whoever is on the other end.
87
+
88
+ ## Signing in
89
+
90
+ sushiengine is sold; the other four modules are not. `hub login` is how a machine proves a licence,
91
+ and nothing else in `hub` needs it: cloning an open-source module asks only for a Git identity.
92
+
93
+ `hub login` asks Sushi Account for a device code, prints it with the page to type it into, opens that page
94
+ in the browser, and polls until you approve it there. What comes back — an access token, a refresh
95
+ token and an expiry — goes into the operating system's credential store through `keyring`, under
96
+ service `sushistack` and username `sushi-account`. A later command that needs the account refreshes the
97
+ access token when it is within 30 seconds of expiry; when the refresh is refused, the stored session
98
+ is dropped and the command says nobody is signed in.
99
+
100
+ Sushi Account lives at `https://account.sushisystems.io`, from `[identity] url` in `config.toml`.
101
+ `SUSHI_ACCOUNT_URL` overrides it, which is how the tests point every Sushi Account call at a fake server on
102
+ `127.0.0.1`. The six endpoints are written out in `../contract/sushi-account.md`; sushiweb has not built
103
+ them yet.
104
+
105
+ ## Binary installs
106
+
107
+ `hub add sushiengine` decides between the two forms rather than being told. It asks the private
108
+ repository whether this machine's Git identity reaches it, with `git ls-remote --exit-code` under a
109
+ 15-second timeout. If it does, the module is cloned like any other. If it does not, `hub` needs a
110
+ Sushi Account session: with one it downloads the release, without one it names both ways in and stops.
111
+ `--binary` skips the question and goes straight to the release. The other four modules are open
112
+ source and have one path; `--binary` on any of them is refused.
113
+
114
+ The download is what `sushiweb` signed a URL for. `hub` streams it, refuses to unpack it when either
115
+ the size or the sha256 differs from what Sushi Account declared, unpacks it into a directory beside
116
+ `<workspace>/sushiengine`, and renames that over the module last, so a download that fails leaves
117
+ the install that was there untouched. The release carries `sushi-release.json` at its top level:
118
+ that file is what makes the directory a binary install, and `hub status` reads the version out of it
119
+ ("binary 1.4.2"). Beside it `hub` writes `sushi-licence.jwt`, the licence token Sushi Account issued,
120
+ which the engine reads at start-up and verifies offline against Sushi Account's JWKS.
121
+
122
+ A release brings its own sushiruntime and sushiblas, so it declares no dependency fragment and
123
+ nothing provisions after it: a licensed user never downloads a SYCL toolchain. It also installs no
124
+ module CLI; `se` arrives inside the package.
125
+
126
+ `hub update sushiengine` asks for the latest release, says the install is already the latest when
127
+ the versions match, and downloads the new one and writes the licence file again when they do not.
128
+ `hub add sushiengine` on a directory that is already a binary install leaves it alone.
129
+
130
+ ## How dependencies are chosen
131
+
132
+ `hub install` merges every `*.deps.toml` fragment the `sushistack` package ships with each present
133
+ module's own
134
+ `cli/sushistack.deps.toml`, keeps the entries that name a package for the current platform, and
135
+ installs the ones that are missing. No dependency name lives in the installer code. The SYCL
136
+ toolchains are sushiruntime's entries, not this repository's; the GPU toolkit is on for every
137
+ workspace and follows the detected GPU vendor (`sushistack/setup/selection.py`); the base fragment carries
138
+ only cmake, ninja, gtest, opencl and pkgconf.
139
+
140
+ A shipped fragment is owned by the name in its filename, with `base.deps.toml` the exception
141
+ that owns nothing and is owned by `shared`. So `gui.deps.toml`, which names the desktop
142
+ application's imgui, glfw3 and nlohmann-json, is owned by `gui` and `hub doctor` groups those
143
+ three rows under it.
144
+
145
+ The toolchain selection follows the same rule: a component is installed when a present module's
146
+ fragment declares a dependency of that name, so an empty workspace gets the base tools alone.
147
+ `hub add` and `hub link` run the provision pipeline for the module they bring in, unless you pass
148
+ `--skip-install`.
149
+
150
+ ## Files it reads and writes
151
+
152
+ | File | Owner | Purpose |
153
+ |---|---|---|
154
+ | `<workspace>/.sushistack/` | `hub init` | Marks the workspace root; every `hub` and module CLI walks up to it. |
155
+ | `<workspace>/.sushistack/workspace.toml` | `hub init`, `hub install`, `hub link` | Everything the workspace owns: its format version, the resolved toolchain paths for this machine, and the modules linked from outside the tree. |
156
+ | `<workspace>/sushiengine/sushi-release.json` | the release | Product, version, platform and what the package bundles. Its presence is what makes the directory a binary install. |
157
+ | `<workspace>/sushiengine/sushi-licence.jwt` | `hub add`, `hub update` | The licence token the engine reads at start-up. Nothing but the token. |
158
+ | `<workspace>/dependencies/` | `hub install`, `hub remove` | Toolchains, vcpkg, portable cmake and ninja, with a stamp per installed toolchain. |
159
+ | OS credential store, `sushistack` / `sushi-account` | `hub login`, `hub logout` | The Sushi Account session as one JSON document: both tokens and the access token's expiry. |
160
+
161
+ ## Where sushicore comes from
162
+
163
+ `hub` imports `sushicore` for its console, its config schema and its workspace helpers. The package
164
+ is not on any index; `install.py` injects the checkout under `<workspace>/sushicore` into the
165
+ pipx venv, editable. `SUSHICORE_DIR` or `hub link sushicore <path>` points it elsewhere. See
166
+ `../../sushicore/docs/README.md`.
@@ -0,0 +1,93 @@
1
+ README.md
2
+ pyproject.toml
3
+ sushihub.egg-info/PKG-INFO
4
+ sushihub.egg-info/SOURCES.txt
5
+ sushihub.egg-info/dependency_links.txt
6
+ sushihub.egg-info/entry_points.txt
7
+ sushihub.egg-info/requires.txt
8
+ sushihub.egg-info/top_level.txt
9
+ sushistack/__init__.py
10
+ sushistack/__main__.py
11
+ sushistack/catalog.toml
12
+ sushistack/cli.py
13
+ sushistack/config.py
14
+ sushistack/console.py
15
+ sushistack/defaults.toml
16
+ sushistack/describe.py
17
+ sushistack/gui_config.py
18
+ sushistack/gui_env.py
19
+ sushistack/py.typed
20
+ sushistack/manifests/base.deps.toml
21
+ sushistack/manifests/gui.deps.toml
22
+ sushistack/services/__init__.py
23
+ sushistack/services/binary.py
24
+ sushistack/services/catalog.py
25
+ sushistack/services/cli_install.py
26
+ sushistack/services/customize.py
27
+ sushistack/services/discovery.py
28
+ sushistack/services/git_ops.py
29
+ sushistack/services/git_state.py
30
+ sushistack/services/gui.py
31
+ sushistack/services/hub_install.py
32
+ sushistack/services/identity.py
33
+ sushistack/services/licence_file.py
34
+ sushistack/services/links.py
35
+ sushistack/services/modules.py
36
+ sushistack/services/pipx.py
37
+ sushistack/services/presence.py
38
+ sushistack/services/releases.py
39
+ sushistack/services/session.py
40
+ sushistack/services/setup.py
41
+ sushistack/services/status_report.py
42
+ sushistack/services/token_store.py
43
+ sushistack/services/update_check.py
44
+ sushistack/setup/__init__.py
45
+ sushistack/setup/apt.py
46
+ sushistack/setup/dependency_source.py
47
+ sushistack/setup/factory.py
48
+ sushistack/setup/ordering.py
49
+ sushistack/setup/package_managers.py
50
+ sushistack/setup/pipeline.py
51
+ sushistack/setup/probe.py
52
+ sushistack/setup/selection.py
53
+ sushistack/setup/steps.py
54
+ sushistack/setup/toolchains.py
55
+ sushistack/setup/gpu_backends/__init__.py
56
+ sushistack/setup/gpu_backends/adapter_builder.py
57
+ sushistack/setup/gpu_backends/backend.py
58
+ sushistack/setup/gpu_backends/compiler_identity.py
59
+ sushistack/setup/gpu_backends/cuda.py
60
+ sushistack/setup/gpu_backends/level_zero.py
61
+ sushistack/setup/gpu_backends/provisioning.py
62
+ sushistack/setup/gpu_backends/registry.py
63
+ sushistack/setup/gpu_backends/rocm.py
64
+ sushistack/setup/gpu_backends/windows_installer.py
65
+ tests/test_adapter_builder.py
66
+ tests/test_add_binary.py
67
+ tests/test_add_provisions.py
68
+ tests/test_catalog.py
69
+ tests/test_cli_install.py
70
+ tests/test_compiler_identity.py
71
+ tests/test_describe.py
72
+ tests/test_detect_rows.py
73
+ tests/test_git_state.py
74
+ tests/test_gpu_backend_registry.py
75
+ tests/test_gpu_backend_specs.py
76
+ tests/test_gpu_provisioning.py
77
+ tests/test_gui_build.py
78
+ tests/test_hub_install.py
79
+ tests/test_identity.py
80
+ tests/test_init.py
81
+ tests/test_json_streams.py
82
+ tests/test_link.py
83
+ tests/test_ordering.py
84
+ tests/test_presence.py
85
+ tests/test_releases.py
86
+ tests/test_selection.py
87
+ tests/test_status_payload.py
88
+ tests/test_toolchains.py
89
+ tests/test_update_check.py
90
+ tests/test_vcpkg_features.py
91
+ tests/test_windows_cuda_install.py
92
+ tests/test_workspace_resolution.py
93
+ tests/test_workspace_upgrade.py
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ hub = sushistack.cli:app
3
+ sushihub = sushistack.cli:app
@@ -0,0 +1,12 @@
1
+ click>=8.0
2
+ sushicore>=0.2.0
3
+ typer>=0.12
4
+ rich>=13.0
5
+ keyring>=24
6
+
7
+ [:python_version < "3.11"]
8
+ tomli>=2.0
9
+
10
+ [test]
11
+ pytest>=7.0
12
+ jsonschema>=4.0