de-shell 0.2.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 (57) hide show
  1. de_shell/__init__.py +25 -0
  2. de_shell/actions/__init__.py +0 -0
  3. de_shell/actions/context.py +62 -0
  4. de_shell/actions/figure_registry.py +53 -0
  5. de_shell/actions/lifecycle.py +295 -0
  6. de_shell/actions/registry.py +141 -0
  7. de_shell/actions/wizard.py +115 -0
  8. de_shell/app.py +170 -0
  9. de_shell/compute.py +103 -0
  10. de_shell/debug_flags.py +69 -0
  11. de_shell/ipc.py +236 -0
  12. de_shell/js/__init__.py +38 -0
  13. de_shell/js/__main__.py +4 -0
  14. de_shell/js/main/backendProcess.test.ts +70 -0
  15. de_shell/js/main/backendProcess.ts +330 -0
  16. de_shell/js/main/config.ts +53 -0
  17. de_shell/js/main/dialogs.ts +62 -0
  18. de_shell/js/main/envProgress.ts +126 -0
  19. de_shell/js/main/errorReport.ts +261 -0
  20. de_shell/js/main/index.ts +57 -0
  21. de_shell/js/main/problemLog.ts +53 -0
  22. de_shell/js/main/pythonEnv.test.ts +125 -0
  23. de_shell/js/main/pythonEnv.ts +442 -0
  24. de_shell/js/main/sentryEnvelope.test.ts +94 -0
  25. de_shell/js/main/sentryEnvelope.ts +100 -0
  26. de_shell/js/main/updater.ts +322 -0
  27. de_shell/js/main/updaterErrors.test.ts +111 -0
  28. de_shell/js/main/updaterErrors.ts +65 -0
  29. de_shell/js/main/window.ts +141 -0
  30. de_shell/js/package.json +5 -0
  31. de_shell/js/preload/index.ts +130 -0
  32. de_shell/js/renderer/FigureFrame.tsx +88 -0
  33. de_shell/js/renderer/figureBridge.react.ts +58 -0
  34. de_shell/js/renderer/figureBridge.test.ts +184 -0
  35. de_shell/js/renderer/figureBridge.ts +169 -0
  36. de_shell/js/renderer/index.ts +34 -0
  37. de_shell/js/renderer/protocol.ts +164 -0
  38. de_shell/js/renderer/shellState.test.ts +193 -0
  39. de_shell/js/renderer/shellState.ts +310 -0
  40. de_shell/js/testing/harness.cjs +244 -0
  41. de_shell/js/testing/harness.test.cjs +73 -0
  42. de_shell/log_stream.py +185 -0
  43. de_shell/plotting/__init__.py +0 -0
  44. de_shell/plotting/colormaps.py +27 -0
  45. de_shell/plotting/figure.py +601 -0
  46. de_shell/plotting/selectors/__init__.py +0 -0
  47. de_shell/plotting/selectors/utils.py +29 -0
  48. de_shell/plotting/stream.py +172 -0
  49. de_shell/process_guard.py +190 -0
  50. de_shell/session.py +211 -0
  51. de_shell/testing/__init__.py +0 -0
  52. de_shell/timing.py +28 -0
  53. de_shell-0.2.0.dist-info/METADATA +196 -0
  54. de_shell-0.2.0.dist-info/RECORD +57 -0
  55. de_shell-0.2.0.dist-info/WHEEL +5 -0
  56. de_shell-0.2.0.dist-info/licenses/LICENSE +21 -0
  57. de_shell-0.2.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,196 @@
1
+ Metadata-Version: 2.4
2
+ Name: de-shell
3
+ Version: 0.2.0
4
+ Summary: The Electron + Python desktop-app shell Direct Electron's apps (SpyDE, Ground Crew, Autopilot) are assembled from
5
+ Author-email: Carter Francis <cartsfrancis@gmail.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/CSSFrancis/de-shell
8
+ Project-URL: Repository, https://github.com/CSSFrancis/de-shell
9
+ Project-URL: Issues, https://github.com/CSSFrancis/de-shell/issues
10
+ Project-URL: Changelog, https://github.com/CSSFrancis/de-shell/blob/main/CHANGELOG.md
11
+ Keywords: electron,desktop,anyplotlib,electron-microscopy,direct-electron
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Intended Audience :: Science/Research
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Programming Language :: JavaScript
23
+ Classifier: Topic :: Scientific/Engineering
24
+ Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
25
+ Requires-Python: >=3.10
26
+ Description-Content-Type: text/markdown
27
+ License-File: LICENSE
28
+ Requires-Dist: numpy>=1.20.0
29
+ Requires-Dist: anyplotlib>=0.7.3
30
+ Requires-Dist: pyyaml
31
+ Provides-Extra: tests
32
+ Requires-Dist: pytest>=3.6; extra == "tests"
33
+ Requires-Dist: pytest-timeout; extra == "tests"
34
+ Dynamic: license-file
35
+
36
+ # DE Shell
37
+
38
+ [![PyPI](https://img.shields.io/pypi/v/de-shell.svg)](https://pypi.org/project/de-shell/)
39
+ [![CI](https://github.com/CSSFrancis/de-shell/actions/workflows/ci.yml/badge.svg)](https://github.com/CSSFrancis/de-shell/actions/workflows/ci.yml)
40
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
41
+
42
+ The substrate Direct Electron's desktop apps are assembled from: **SpyDE**
43
+ (offline analysis), **Ground Crew** (manual camera control) and **Autopilot**
44
+ (automated acquisition). Each app is an Electron window over a Python
45
+ sidecar, and everything the three have in common lives here — the
46
+ Python↔JS message pipe, the window and its menus, the figure bridge over
47
+ [anyplotlib](https://pypi.org/project/anyplotlib/), the sidecar process
48
+ manager and its Python environment, the updater, the problem reporter, the
49
+ Playwright harness.
50
+
51
+ It contains **no domain logic**. No detectors, no microscopes, no signal
52
+ types, no analysis. `tests/test_boundary.py` enforces that in a clean
53
+ subprocess: the shell must stay installable without the science stack, so
54
+ the live in-memory apps never acquire it transitively.
55
+
56
+ ```bash
57
+ pip install de-shell
58
+ ```
59
+
60
+ ## One package
61
+
62
+ The shell is **one pip package**, and the TypeScript rides inside the wheel:
63
+
64
+ ```
65
+ pyproject.toml the package: de-shell
66
+ de_shell/ app loop, session base, actions, IPC, figures, compute, logging
67
+ de_shell/js/ the TypeScript half, one folder per Electron target
68
+ main/ Electron main: window, sidecar + stdout demuxer, python env, updater, reports
69
+ preload/ the contextBridge surface (exposeShellBridge)
70
+ renderer/ React: figure bridge, FigureFrame, the chrome slice of state
71
+ testing/ the Playwright harness (launchApp)
72
+ tests/ the Python suite (incl. the boundary test)
73
+ package.json DEV ONLY: typechecks and unit-tests de_shell/js; nothing is published to npm
74
+ ```
75
+
76
+ The JavaScript that speaks the sidecar protocol ships in the same artifact
77
+ as the Python that speaks it. One `pip install -U de-shell` moves both, and
78
+ an app cannot end up with the two halves at different versions. The
79
+ TypeScript is shipped as **source** and compiled by the consuming app's
80
+ bundler, so there is no build step here and an editable install is
81
+ live-editable from the app.
82
+
83
+ ## Consuming it
84
+
85
+ **Python** — an ordinary dependency:
86
+
87
+ ```toml
88
+ dependencies = ["de-shell>=0.2,<0.3"]
89
+ ```
90
+
91
+ For hacking on the shell and an app at once, a sibling checkout as an
92
+ editable path source (uv) or `pip install -e ../de-shell` overlays it.
93
+
94
+ **Electron** — ask the installed package where its TypeScript is and link
95
+ it into the project at a fixed path, then alias and `paths` through the link:
96
+
97
+ ```
98
+ python -m de_shell.js # prints …/de_shell/js
99
+ ```
100
+
101
+ Autopilot's `electron/scripts/shell-link.mjs` is the reference: it makes
102
+ `electron/shell` a junction (a symlink off Windows) to that folder, runs from
103
+ npm's postinstall and from the vite config on every build, and re-points a
104
+ stale link rather than trusting it. With it in place:
105
+
106
+ ```ts
107
+ // electron.vite.config.ts
108
+ const shell = ensureShellLink(__dirname)
109
+ resolve: { alias: { '@de/shell-main': resolve(shell, 'main', 'index.ts') },
110
+ dedupe: ['react', 'react-dom'] }
111
+ ```
112
+
113
+ ```json
114
+ // tsconfig.json
115
+ "noEmit": true, "allowImportingTsExtensions": true,
116
+ "paths": { "@de/shell-main": ["./shell/main/index.ts"], … }
117
+ ```
118
+
119
+ `dedupe` matters: an editable checkout carries its own `node_modules` for
120
+ its typecheck, and without it the renderer would bundle a second React. The
121
+ peer dependencies — react, electron, electron-updater, @playwright/test —
122
+ are the app's to declare; every app already does. The e2e specs take the
123
+ harness from `shell/testing/harness.cjs`.
124
+
125
+ Autopilot and SpyDE (on its `chore/de-shell-split` branch) are wired this
126
+ way; Ground Crew still carries a copy under its `packages/` and is next.
127
+
128
+ ## Developing it
129
+
130
+ ```bash
131
+ uv sync --extra tests && uv run pytest # the Python suite
132
+ ELECTRON_SKIP_BINARY_DOWNLOAD=1 npm install # types only; drop the variable to run Electron
133
+ npm run typecheck # every target, tests included, under tsconfig.json
134
+ npm run test:unit # node --test over de_shell/js
135
+ uv build # the wheel — CI checks it carries de_shell/js
136
+ ```
137
+
138
+ The unit tests run under Node's native type stripping, which resolves
139
+ relative imports literally — so shell modules import their siblings with the
140
+ `.ts` extension spelled out, and every tsconfig that compiles them (this one
141
+ and each app's) sets `allowImportingTsExtensions`.
142
+
143
+ CI (`.github/workflows/ci.yml`) runs the Python suite on Linux, Windows and
144
+ macOS at the oldest and newest supported Python, the typecheck and unit
145
+ tests, and builds the wheel and checks what it carries.
146
+
147
+ ## Releasing
148
+
149
+ The version is written once, in `de_shell/__init__.py`. To release:
150
+
151
+ 1. Bump `__version__`, move the `CHANGELOG.md` entries under the new version.
152
+ 2. Commit, tag `vX.Y.Z`, push the tag.
153
+
154
+ `.github/workflows/publish.yml` builds the distributions, refuses a tag that
155
+ does not match `__version__`, and uploads to PyPI through trusted publishing
156
+ — on pypi.org the project must list this repository, that workflow file and
157
+ the `pypi` environment as a publisher (no token lives in the repo). Semver,
158
+ with the 0.x caveat: a breaking change to the sidecar protocol bumps the
159
+ minor, and the apps pin `>=0.x,<0.(x+1)`.
160
+
161
+ ## Provenance
162
+
163
+ Merged 2026-09-02 from the three vendored copies, three-way against the
164
+ SpyDE commit the app copies were taken from:
165
+
166
+ * SpyDE `main` @ 1f3331d (v0.4.3): the problem reporter (`errorReport`,
167
+ `problemLog`, `sentryEnvelope`), `recentBackendOutput`, the workspace-member
168
+ wheels in `pythonEnv`, the update handoff that tree-kills the sidecar first,
169
+ `run_on_worker`'s in-flight count and `ComputeHandle` in `lifecycle.py`.
170
+ * Autopilot @ 7f0651e: the sidecar's close handler forgets only ITS child, the
171
+ malformed-message report, the figure/stream fixes ported from the siblings,
172
+ the renderer state and FigureFrame changes.
173
+ * Ground Crew `main` @ 26e853a: the spawn-error trap and 5 s tree-kill grace,
174
+ the resolved `uv` path, the open-directory dialog, `_pin_tile_band` (black
175
+ panes on large stills), JSON emit that never writes bare `NaN`, the harness
176
+ hardening, and the unit tests for all of it.
177
+
178
+ Not yet included: Ground Crew's `dev/instrument-actions` shell deltas
179
+ (`stdoutDemux`, `sizeReporter`, the `frameBytes` transport) — they ride a
180
+ branch that has not merged.
181
+
182
+ ## Rules
183
+
184
+ * **Nothing here mentions a detector, a signal type, or an analysis.** If
185
+ extracting something into the shell requires touching one, the boundary is
186
+ in the wrong place.
187
+ * **The Python side stays tiny.** Every dependency added is one all three
188
+ apps install: numpy, anyplotlib, pyyaml, and that is the list.
189
+ * **The protocol is the contract.** `PLOTAPP:` JSON lines and `PLOTBIN:`
190
+ binary frames over the sidecar's stdio. Both halves of it live in this one
191
+ package on purpose; keep it that way.
192
+ * **LF line endings**, enforced by `.gitattributes`.
193
+
194
+ ## License
195
+
196
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,57 @@
1
+ de_shell/__init__.py,sha256=XVlMUM-wy0M_wGn0T9vnuebiPu-SJpF7LvraZqVkwEY,1300
2
+ de_shell/app.py,sha256=XQXMeLekItBSV7QRV3ZDsWdXHHe47CX2e1T_3B2cegA,6515
3
+ de_shell/compute.py,sha256=lg2V19HDdgvfFJm-30-DkLbcqQuzm9KaJmdsfXZ1o9s,3955
4
+ de_shell/debug_flags.py,sha256=umr2gLdWoPg4OEmN6nzzfPugRPpPEJSYl_90TKp8H4s,2993
5
+ de_shell/ipc.py,sha256=FX53c2tQAQQDX3xENWLx1RFDQVlL1u06jeZ2kdyEO9I,9445
6
+ de_shell/log_stream.py,sha256=mf5hAuOzZbjjZF2i8ecjlrZ_IpHT0yyNK6JRwhZav7s,7543
7
+ de_shell/process_guard.py,sha256=-jN6pYUwTIr2MSZbZ5IaL6vs5EADg9h1OG9tj5rqYu4,8533
8
+ de_shell/session.py,sha256=oiHRshmmfqEnG6afhS5ZmC2XhSnqZUmI3Qk7a0ABIkE,9765
9
+ de_shell/timing.py,sha256=SRVf6FZvN_5TVJJLLrVMDchigUdFtY9ePQxaMn7Flig,1070
10
+ de_shell/actions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
+ de_shell/actions/context.py,sha256=xQbKMCxCM_bYJ-8-cbI7sZv3OVQYiOGWf9EDURdK7gU,2626
12
+ de_shell/actions/figure_registry.py,sha256=8j8KbLXmPARgmSiLdKEBd1wEIef-pVzN1wfTvTGvwwM,2047
13
+ de_shell/actions/lifecycle.py,sha256=KzsCbvMjjEEeuC7iXX--lllXM_XtMHsv3XGNxxeDmEA,11782
14
+ de_shell/actions/registry.py,sha256=CV3jJEecUM8Et1SGSZPlS_-XH8fD3hhXoQe_tZHKJYk,6263
15
+ de_shell/actions/wizard.py,sha256=jT_43aWLFFuRTHGgYilnGQVDuNuFJoBHD8h6vc6G4XI,5294
16
+ de_shell/js/__init__.py,sha256=A8nHUYp7wiChI88ihhEj0t6J2MF62W_vvS8Iu6ww61A,1713
17
+ de_shell/js/__main__.py,sha256=erFsK0Mnzj9td7fQUx-_QmBh9Q4HNW5JEC9JDA_0L6w,117
18
+ de_shell/js/package.json,sha256=kjMBaXcVWFx6Z5_IX8K6Zf7qWDCUIsq9lSRC-70qCno,229
19
+ de_shell/js/main/backendProcess.test.ts,sha256=xbgSNhw52jlD-OTR1NoKbCl41LQIgI8KFN8nVUJxhVM,2545
20
+ de_shell/js/main/backendProcess.ts,sha256=-FK_cH_cq6A5Enz1Yu_FzHMXwPPt5rUhFo5wMVNI5Os,14961
21
+ de_shell/js/main/config.ts,sha256=8_xfaoWuPwIT4DJEdSFWKQq0ctpsMY-SoNAe2qLt4fI,2077
22
+ de_shell/js/main/dialogs.ts,sha256=91KlIWDTiARx58_P1WIjp9y49b4iJUKuLH9iEVxd37o,2692
23
+ de_shell/js/main/envProgress.ts,sha256=rDHpSiZaBnbXOXqoy3i3IeF75UMzZCjOglK4j67bUS0,5189
24
+ de_shell/js/main/errorReport.ts,sha256=vti7YZ55VS63BXQ_bEC6rM-VrWCPWusPleu_AiHRvOA,9918
25
+ de_shell/js/main/index.ts,sha256=dqa8YK5KXnwWwZqfRbbJJ8sZHRq2iEmbUimtOWoHceM,2122
26
+ de_shell/js/main/problemLog.ts,sha256=96JMKEKBa_W9BWfUf9PVwGeMgsrMM5xJGa0SBma0-SM,1753
27
+ de_shell/js/main/pythonEnv.test.ts,sha256=UCAZ5a8jvBbPZN-dLYSmXcfjLd7R5T1AlyTcaMmQqWc,4456
28
+ de_shell/js/main/pythonEnv.ts,sha256=Bx_8MoIHLto9UIu8swXrv4YwB13I-T-5MlbGYxgXpzE,19268
29
+ de_shell/js/main/sentryEnvelope.test.ts,sha256=nfmeyQL_8awCOh57GsjHxBLUkJW29PnuevZTwsZb6K0,4204
30
+ de_shell/js/main/sentryEnvelope.ts,sha256=tAvbrm7CHcwkzIx8Vzx5-PjeXgMhXJWIKLUPRGuJT9s,3646
31
+ de_shell/js/main/updater.ts,sha256=Pc2JZjuAIn6HbCYusc-NqhhbsSOO0xOIjTlz3dLkSKE,14406
32
+ de_shell/js/main/updaterErrors.test.ts,sha256=sF0nIjl2VPunIdV35yHZuCPunAgA_0vqjP-F4abgMIA,4545
33
+ de_shell/js/main/updaterErrors.ts,sha256=Q1fdDwG-UjiZjYpVtLsaeM_PaPAoK_i2xE8yMz67ois,3558
34
+ de_shell/js/main/window.ts,sha256=d63Icr7hb71IF8bJJIV5_7-cjr278-Dhw2idXU1HigY,5904
35
+ de_shell/js/preload/index.ts,sha256=OI2DtJd5GXo676ryfabX4wyANIKzRG-arYTFLMW5Xpw,5620
36
+ de_shell/js/renderer/FigureFrame.tsx,sha256=kE3VsqTW9wAEMY7ASvFyezQlK9hK-qjI_tuMJRmHesM,3760
37
+ de_shell/js/renderer/figureBridge.react.ts,sha256=C7yHfZSqeUpg45-dP-mqqv007d9vs2rfc_4EpfoD8z0,2336
38
+ de_shell/js/renderer/figureBridge.test.ts,sha256=64qOd5Ejs7TAp-wW-2Z0Mf_D4Whi3S52qhCMzx0TDfQ,7023
39
+ de_shell/js/renderer/figureBridge.ts,sha256=ck6QSNk0b_BbHlgd0BjkAdzvN3V2N3PjcoUV29WKj9U,6954
40
+ de_shell/js/renderer/index.ts,sha256=zrySGnAQWv-1BlPRVUg447hes_KeOlfhqH1qlUhNTY4,1362
41
+ de_shell/js/renderer/protocol.ts,sha256=CBjx2QdYhnwV50Re6_3WALIgySuXSHy2mJZ64Q5jLao,4787
42
+ de_shell/js/renderer/shellState.test.ts,sha256=tNDhK9YImBGmXh58hyFcztPpGWr8pn2AbgtF-TytA6E,8124
43
+ de_shell/js/renderer/shellState.ts,sha256=gS4VYvANMqH5eCKGRwFINpF5a_uLRBzqWbUBMZnYCBk,11012
44
+ de_shell/js/testing/harness.cjs,sha256=Jc0Iu4X9S949y5liFpP7QPT-DXyKxhJ3MkDkwpt043Q,9750
45
+ de_shell/js/testing/harness.test.cjs,sha256=ClMYpMIEyE-0qOxnKDntoiLWKht8F9sjbDO_CFw-RoE,2660
46
+ de_shell/plotting/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
47
+ de_shell/plotting/colormaps.py,sha256=spjwz3Z0BuDZGZF2FSiZPx426ZSfUsB9kShLXVx07qs,1104
48
+ de_shell/plotting/figure.py,sha256=bH7LwnBQxEP8raXA59y6gsDbmYW5r7gC91xGqsn0GqQ,27229
49
+ de_shell/plotting/stream.py,sha256=dfhukXDKvCosU8kLg4WBQhLAOJPereCv9NrZ8Mi8pIE,7193
50
+ de_shell/plotting/selectors/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
51
+ de_shell/plotting/selectors/utils.py,sha256=k2jDvPvbhuxn9Fj_1j88xCxno28fcZm0xvxa-YKsiz4,825
52
+ de_shell/testing/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
53
+ de_shell-0.2.0.dist-info/licenses/LICENSE,sha256=loY7HtU18sSR16cVKwg-SThASzEYIuHBL0DqxLldkKA,1072
54
+ de_shell-0.2.0.dist-info/METADATA,sha256=Im98ebQQqEz5B6SVDsFf5GzbhJ2mwPMhSPWEk5O7Y2o,8776
55
+ de_shell-0.2.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
56
+ de_shell-0.2.0.dist-info/top_level.txt,sha256=X3wBU8swYcsGGP4_1mEaMJqTW9Ij2HjruuyOfQxwvKc,9
57
+ de_shell-0.2.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (84.0.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Direct Electron
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1 @@
1
+ de_shell