caland 0.5.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.
- caland-0.5.0/.github/ISSUE_TEMPLATE/bug_report.yml +41 -0
- caland-0.5.0/.github/ISSUE_TEMPLATE/config.yml +5 -0
- caland-0.5.0/.github/PULL_REQUEST_TEMPLATE.md +13 -0
- caland-0.5.0/.github/workflows/ci.yml +74 -0
- caland-0.5.0/.github/workflows/docs.yml +54 -0
- caland-0.5.0/.github/workflows/release.yml +95 -0
- caland-0.5.0/.gitignore +15 -0
- caland-0.5.0/.pre-commit-config.yaml +8 -0
- caland-0.5.0/.zed/settings.json +36 -0
- caland-0.5.0/CHANGELOG.md +343 -0
- caland-0.5.0/CLAUDE.md +115 -0
- caland-0.5.0/CONTRIBUTING.md +91 -0
- caland-0.5.0/LICENSE +202 -0
- caland-0.5.0/PKG-INFO +219 -0
- caland-0.5.0/README.md +187 -0
- caland-0.5.0/SECURITY.md +32 -0
- caland-0.5.0/docs/USER_STORIES.md +70 -0
- caland-0.5.0/docs/architecture.md +28 -0
- caland-0.5.0/docs/browsing.md +103 -0
- caland-0.5.0/docs/connecting.md +64 -0
- caland-0.5.0/docs/contributing.md +65 -0
- caland-0.5.0/docs/img/audit.svg +211 -0
- caland-0.5.0/docs/img/auth.svg +209 -0
- caland-0.5.0/docs/img/browse.svg +206 -0
- caland-0.5.0/docs/img/confirm.svg +211 -0
- caland-0.5.0/docs/img/login-empty.svg +200 -0
- caland-0.5.0/docs/img/login.svg +199 -0
- caland-0.5.0/docs/img/perms.svg +209 -0
- caland-0.5.0/docs/img/search.svg +208 -0
- caland-0.5.0/docs/index.md +51 -0
- caland-0.5.0/docs/installation.md +88 -0
- caland-0.5.0/docs/keyboard.md +45 -0
- caland-0.5.0/docs/page.md +82 -0
- caland-0.5.0/docs/redesign/capture.py +101 -0
- caland-0.5.0/docs/security.md +28 -0
- caland-0.5.0/docs/stylesheets/extra.css +67 -0
- caland-0.5.0/docs/themes.md +24 -0
- caland-0.5.0/examples/databricks.yml +23 -0
- caland-0.5.0/mise.toml +60 -0
- caland-0.5.0/mkdocs.yml +99 -0
- caland-0.5.0/pyproject.toml +104 -0
- caland-0.5.0/spec/000-what-caland-is.md +92 -0
- caland-0.5.0/spec/001-connecting.md +47 -0
- caland-0.5.0/spec/002-browsing.md +51 -0
- caland-0.5.0/spec/003-secrets.md +74 -0
- caland-0.5.0/spec/004-scopes-and-permissions.md +55 -0
- caland-0.5.0/spec/005-bulk-and-audit.md +45 -0
- caland-0.5.0/spec/006-safety.md +65 -0
- caland-0.5.0/spec/007-name-and-release.md +79 -0
- caland-0.5.0/spec/008-the-page.md +231 -0
- caland-0.5.0/spec/009-who-reads-a-secret.md +71 -0
- caland-0.5.0/spec/README.md +73 -0
- caland-0.5.0/spec/mock/page.html +581 -0
- caland-0.5.0/src/caland/__init__.py +0 -0
- caland-0.5.0/src/caland/__main__.py +4 -0
- caland-0.5.0/src/caland/app.py +183 -0
- caland-0.5.0/src/caland/application/__init__.py +22 -0
- caland-0.5.0/src/caland/application/dotenv.py +52 -0
- caland-0.5.0/src/caland/application/loading.py +138 -0
- caland-0.5.0/src/caland/application/onboarding.py +106 -0
- caland-0.5.0/src/caland/application/read_model.py +76 -0
- caland-0.5.0/src/caland/application/workspace.py +177 -0
- caland-0.5.0/src/caland/domain/__init__.py +55 -0
- caland-0.5.0/src/caland/domain/errors.py +12 -0
- caland-0.5.0/src/caland/domain/host.py +15 -0
- caland-0.5.0/src/caland/domain/models.py +120 -0
- caland-0.5.0/src/caland/domain/permissions.py +72 -0
- caland-0.5.0/src/caland/domain/ports.py +55 -0
- caland-0.5.0/src/caland/domain/secret_store.py +30 -0
- caland-0.5.0/src/caland/formerly.py +50 -0
- caland-0.5.0/src/caland/infrastructure/__init__.py +23 -0
- caland-0.5.0/src/caland/infrastructure/bundle.py +84 -0
- caland-0.5.0/src/caland/infrastructure/config.py +13 -0
- caland-0.5.0/src/caland/infrastructure/connector.py +47 -0
- caland-0.5.0/src/caland/infrastructure/databricks.py +159 -0
- caland-0.5.0/src/caland/infrastructure/profiles.py +66 -0
- caland-0.5.0/src/caland/infrastructure/settings.py +76 -0
- caland-0.5.0/src/caland/interface/__init__.py +0 -0
- caland-0.5.0/src/caland/interface/modals.py +932 -0
- caland-0.5.0/src/caland/interface/screens/__init__.py +0 -0
- caland-0.5.0/src/caland/interface/screens/login.py +245 -0
- caland-0.5.0/src/caland/interface/screens/main.py +1107 -0
- caland-0.5.0/src/caland/interface/sorting.py +59 -0
- caland-0.5.0/src/caland/interface/theme.py +137 -0
- caland-0.5.0/src/caland/interface/web/__init__.py +134 -0
- caland-0.5.0/src/caland/interface/web/gate.py +107 -0
- caland-0.5.0/src/caland/interface/web/opening.py +54 -0
- caland-0.5.0/src/caland/interface/web/server.py +328 -0
- caland-0.5.0/src/caland/interface/web/static/page.css +110 -0
- caland-0.5.0/src/caland/interface/web/static/page.html +94 -0
- caland-0.5.0/src/caland/interface/web/static/page.js +425 -0
- caland-0.5.0/src/caland/interface/web/views.py +86 -0
- caland-0.5.0/src/caland/interface/widgets.py +473 -0
- caland-0.5.0/src/caland/styles.tcss +371 -0
- caland-0.5.0/tests/__snapshots__/test_snapshots/test_audit_screen.raw +195 -0
- caland-0.5.0/tests/__snapshots__/test_snapshots/test_browse_screen.raw +189 -0
- caland-0.5.0/tests/__snapshots__/test_snapshots/test_login_empty_state.raw +184 -0
- caland-0.5.0/tests/chrome.py +224 -0
- caland-0.5.0/tests/conftest.py +24 -0
- caland-0.5.0/tests/fakes.py +179 -0
- caland-0.5.0/tests/test_bundle.py +121 -0
- caland-0.5.0/tests/test_cache.py +35 -0
- caland-0.5.0/tests/test_choose.py +47 -0
- caland-0.5.0/tests/test_databricks.py +107 -0
- caland-0.5.0/tests/test_dotenv.py +33 -0
- caland-0.5.0/tests/test_formerly.py +173 -0
- caland-0.5.0/tests/test_help.py +41 -0
- caland-0.5.0/tests/test_host.py +22 -0
- caland-0.5.0/tests/test_loading.py +137 -0
- caland-0.5.0/tests/test_models.py +72 -0
- caland-0.5.0/tests/test_page_in_a_browser.py +425 -0
- caland-0.5.0/tests/test_permissions.py +67 -0
- caland-0.5.0/tests/test_profiles.py +76 -0
- caland-0.5.0/tests/test_session.py +112 -0
- caland-0.5.0/tests/test_settings.py +79 -0
- caland-0.5.0/tests/test_snapshots.py +54 -0
- caland-0.5.0/tests/test_sorting.py +45 -0
- caland-0.5.0/tests/test_ui_browse.py +476 -0
- caland-0.5.0/tests/test_ui_login.py +54 -0
- caland-0.5.0/tests/test_ui_modals.py +197 -0
- caland-0.5.0/tests/test_ui_permissions.py +100 -0
- caland-0.5.0/tests/test_ui_scope_filter.py +63 -0
- caland-0.5.0/tests/test_ui_small_terminal.py +90 -0
- caland-0.5.0/tests/test_ui_tools.py +186 -0
- caland-0.5.0/tests/test_web_gate.py +169 -0
- caland-0.5.0/tests/test_web_opening.py +81 -0
- caland-0.5.0/tests/test_web_run.py +115 -0
- caland-0.5.0/tests/test_web_server.py +582 -0
- caland-0.5.0/uv.lock +1699 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
name: Bug report
|
|
2
|
+
description: Something isn't working
|
|
3
|
+
labels: [bug]
|
|
4
|
+
body:
|
|
5
|
+
- type: textarea
|
|
6
|
+
id: what
|
|
7
|
+
attributes:
|
|
8
|
+
label: What happened?
|
|
9
|
+
description: What did you do, what did you expect, and what happened instead?
|
|
10
|
+
validations:
|
|
11
|
+
required: true
|
|
12
|
+
- type: textarea
|
|
13
|
+
id: repro
|
|
14
|
+
attributes:
|
|
15
|
+
label: Steps to reproduce
|
|
16
|
+
placeholder: |
|
|
17
|
+
1. Run `caland`
|
|
18
|
+
2. ...
|
|
19
|
+
- type: input
|
|
20
|
+
id: version
|
|
21
|
+
attributes:
|
|
22
|
+
label: Caland version
|
|
23
|
+
placeholder: "0.1.0 (uvx caland --version, or `uv tool list`)"
|
|
24
|
+
- type: input
|
|
25
|
+
id: python
|
|
26
|
+
attributes:
|
|
27
|
+
label: Python version
|
|
28
|
+
placeholder: "3.12"
|
|
29
|
+
- type: input
|
|
30
|
+
id: os
|
|
31
|
+
attributes:
|
|
32
|
+
label: OS / terminal
|
|
33
|
+
placeholder: "macOS 15 · iTerm2"
|
|
34
|
+
- type: textarea
|
|
35
|
+
id: logs
|
|
36
|
+
attributes:
|
|
37
|
+
label: Error output
|
|
38
|
+
description: >
|
|
39
|
+
The TUI takes over the screen, so capture stderr with
|
|
40
|
+
`caland 2>err.log` and paste `err.log` here.
|
|
41
|
+
render: text
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<!-- Thanks for contributing to Caland! -->
|
|
2
|
+
|
|
3
|
+
## What & why
|
|
4
|
+
|
|
5
|
+
<!-- What does this change, and why? Link any related issue (#123). -->
|
|
6
|
+
|
|
7
|
+
## Checklist
|
|
8
|
+
|
|
9
|
+
- [ ] `uv run pytest` passes
|
|
10
|
+
- [ ] `uv run ruff check .` and `uv run ruff format .` are clean
|
|
11
|
+
- [ ] `uv run ty check` passes
|
|
12
|
+
- [ ] New behaviour has a test
|
|
13
|
+
- [ ] Business logic stays out of `interface/`; the SDK stays in `infrastructure/`
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
name: ci
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
lint:
|
|
10
|
+
name: lint + types
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@v4
|
|
14
|
+
- uses: astral-sh/setup-uv@v6
|
|
15
|
+
with:
|
|
16
|
+
enable-cache: true
|
|
17
|
+
- run: uv sync
|
|
18
|
+
- name: Lint (ruff)
|
|
19
|
+
run: uv run ruff check .
|
|
20
|
+
- name: Format check (ruff)
|
|
21
|
+
run: uv run ruff format --check .
|
|
22
|
+
- name: Type check (ty)
|
|
23
|
+
run: uv run ty check
|
|
24
|
+
|
|
25
|
+
test:
|
|
26
|
+
name: test (py${{ matrix.python-version }} · ${{ matrix.os }})
|
|
27
|
+
runs-on: ${{ matrix.os }}
|
|
28
|
+
strategy:
|
|
29
|
+
fail-fast: false
|
|
30
|
+
matrix:
|
|
31
|
+
os: [ubuntu-latest]
|
|
32
|
+
python-version: ["3.11", "3.12", "3.13", "3.14"]
|
|
33
|
+
include:
|
|
34
|
+
- os: macos-latest
|
|
35
|
+
python-version: "3.14"
|
|
36
|
+
steps:
|
|
37
|
+
- uses: actions/checkout@v4
|
|
38
|
+
- uses: astral-sh/setup-uv@v6
|
|
39
|
+
with:
|
|
40
|
+
enable-cache: true
|
|
41
|
+
- name: Tests (pytest)
|
|
42
|
+
run: uv run --python ${{ matrix.python-version }} pytest
|
|
43
|
+
|
|
44
|
+
docs:
|
|
45
|
+
name: docs (strict build + screenshots)
|
|
46
|
+
runs-on: ubuntu-latest
|
|
47
|
+
steps:
|
|
48
|
+
- uses: actions/checkout@v4
|
|
49
|
+
- uses: astral-sh/setup-uv@v6
|
|
50
|
+
with:
|
|
51
|
+
enable-cache: true
|
|
52
|
+
# mkdocs lives in the `docs` dependency group, which a plain sync skips
|
|
53
|
+
- run: uv sync --group docs
|
|
54
|
+
- name: Build the docs site (strict — broken links/nav fail)
|
|
55
|
+
run: uv run --group docs mkdocs build --strict
|
|
56
|
+
- name: Screenshot pipeline still runs
|
|
57
|
+
run: uv run --group docs python docs/redesign/capture.py
|
|
58
|
+
|
|
59
|
+
build:
|
|
60
|
+
name: build (wheel + sdist)
|
|
61
|
+
runs-on: ubuntu-latest
|
|
62
|
+
steps:
|
|
63
|
+
- uses: actions/checkout@v4
|
|
64
|
+
- uses: astral-sh/setup-uv@v6
|
|
65
|
+
- run: uv build
|
|
66
|
+
- name: Smoke-test the built wheel on 3.11
|
|
67
|
+
run: |
|
|
68
|
+
uv venv /tmp/smoke -p 3.11
|
|
69
|
+
uv pip install --python /tmp/smoke/bin/python dist/*.whl
|
|
70
|
+
/tmp/smoke/bin/python -c "import caland.app; print('import OK')"
|
|
71
|
+
- uses: actions/upload-artifact@v4
|
|
72
|
+
with:
|
|
73
|
+
name: dist
|
|
74
|
+
path: dist/*
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
name: docs
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
paths:
|
|
7
|
+
- "docs/**"
|
|
8
|
+
- "mkdocs.yml"
|
|
9
|
+
- ".github/workflows/docs.yml"
|
|
10
|
+
pull_request:
|
|
11
|
+
paths:
|
|
12
|
+
- "docs/**"
|
|
13
|
+
- "mkdocs.yml"
|
|
14
|
+
- ".github/workflows/docs.yml"
|
|
15
|
+
workflow_dispatch:
|
|
16
|
+
|
|
17
|
+
# allow the GITHUB_TOKEN to deploy to Pages, and serialise deploys
|
|
18
|
+
permissions:
|
|
19
|
+
contents: read
|
|
20
|
+
pages: write
|
|
21
|
+
id-token: write
|
|
22
|
+
|
|
23
|
+
concurrency:
|
|
24
|
+
group: pages
|
|
25
|
+
cancel-in-progress: false
|
|
26
|
+
|
|
27
|
+
jobs:
|
|
28
|
+
build:
|
|
29
|
+
name: build site
|
|
30
|
+
runs-on: ubuntu-latest
|
|
31
|
+
env:
|
|
32
|
+
NO_MKDOCS_2_WARNING: "1" # we pin mkdocs < 2; suppress the advisory banner
|
|
33
|
+
steps:
|
|
34
|
+
- uses: actions/checkout@v4
|
|
35
|
+
- uses: astral-sh/setup-uv@v6
|
|
36
|
+
with:
|
|
37
|
+
enable-cache: true
|
|
38
|
+
- name: Build (mkdocs)
|
|
39
|
+
run: uv run --group docs mkdocs build --strict
|
|
40
|
+
- uses: actions/upload-pages-artifact@v3
|
|
41
|
+
with:
|
|
42
|
+
path: site
|
|
43
|
+
|
|
44
|
+
deploy:
|
|
45
|
+
name: deploy to Pages
|
|
46
|
+
needs: build
|
|
47
|
+
if: github.event_name != 'pull_request' # build-only on PRs; deploy from main
|
|
48
|
+
runs-on: ubuntu-latest
|
|
49
|
+
environment:
|
|
50
|
+
name: github-pages
|
|
51
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
52
|
+
steps:
|
|
53
|
+
- id: deployment
|
|
54
|
+
uses: actions/deploy-pages@v4
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
name: release
|
|
2
|
+
|
|
3
|
+
# Version-driven releases — the package version is the single source of truth.
|
|
4
|
+
# To cut a release:
|
|
5
|
+
# 1. uv version --bump {patch|minor|major} # edits pyproject.toml + uv.lock
|
|
6
|
+
# 2. move the CHANGELOG "[Unreleased]" notes under a "## [x.y.z]" heading
|
|
7
|
+
# 3. open a PR and merge to main
|
|
8
|
+
# On that merge this workflow checks whether the version is already released; if
|
|
9
|
+
# not, it builds the wheel + sdist, publishes to PyPI, and creates the matching
|
|
10
|
+
# `vX.Y.Z` git tag + GitHub release (notes pulled from the CHANGELOG). A push that
|
|
11
|
+
# doesn't change the version is a no-op.
|
|
12
|
+
#
|
|
13
|
+
# One-time setup — configure a PyPI Trusted Publisher (no API token needed) for
|
|
14
|
+
# repo: kostavo-oss/caland · workflow: release.yml · environment: pypi
|
|
15
|
+
# at https://pypi.org/manage/account/publishing/
|
|
16
|
+
|
|
17
|
+
on:
|
|
18
|
+
push:
|
|
19
|
+
branches: [main]
|
|
20
|
+
workflow_dispatch:
|
|
21
|
+
|
|
22
|
+
concurrency:
|
|
23
|
+
group: release
|
|
24
|
+
cancel-in-progress: false
|
|
25
|
+
|
|
26
|
+
jobs:
|
|
27
|
+
check:
|
|
28
|
+
name: detect version bump
|
|
29
|
+
runs-on: ubuntu-latest
|
|
30
|
+
outputs:
|
|
31
|
+
should_release: ${{ steps.decide.outputs.should_release }}
|
|
32
|
+
version: ${{ steps.read.outputs.version }}
|
|
33
|
+
steps:
|
|
34
|
+
- uses: actions/checkout@v4
|
|
35
|
+
with:
|
|
36
|
+
fetch-depth: 0 # need the tags to tell whether this version shipped
|
|
37
|
+
- id: read
|
|
38
|
+
name: Read the project version
|
|
39
|
+
run: |
|
|
40
|
+
v=$(python3 -c "import tomllib; print(tomllib.load(open('pyproject.toml','rb'))['project']['version'])")
|
|
41
|
+
echo "version=$v" >> "$GITHUB_OUTPUT"
|
|
42
|
+
echo "Project version: $v"
|
|
43
|
+
- id: decide
|
|
44
|
+
name: Already released?
|
|
45
|
+
run: |
|
|
46
|
+
version="${{ steps.read.outputs.version }}"
|
|
47
|
+
released=false
|
|
48
|
+
if git rev-parse "v$version" >/dev/null 2>&1; then
|
|
49
|
+
echo "git tag v$version already exists"; released=true
|
|
50
|
+
fi
|
|
51
|
+
code=$(curl -fsS -o /dev/null -w "%{http_code}" \
|
|
52
|
+
"https://pypi.org/pypi/caland/$version/json" || echo 000)
|
|
53
|
+
if [ "$code" = "200" ]; then
|
|
54
|
+
echo "caland $version is already on PyPI"; released=true
|
|
55
|
+
fi
|
|
56
|
+
if [ "$released" = "true" ]; then
|
|
57
|
+
echo "Nothing to release for $version."
|
|
58
|
+
echo "should_release=false" >> "$GITHUB_OUTPUT"
|
|
59
|
+
else
|
|
60
|
+
echo "Will release $version."
|
|
61
|
+
echo "should_release=true" >> "$GITHUB_OUTPUT"
|
|
62
|
+
fi
|
|
63
|
+
|
|
64
|
+
release:
|
|
65
|
+
name: publish v${{ needs.check.outputs.version }}
|
|
66
|
+
needs: check
|
|
67
|
+
if: needs.check.outputs.should_release == 'true'
|
|
68
|
+
runs-on: ubuntu-latest
|
|
69
|
+
environment: pypi
|
|
70
|
+
permissions:
|
|
71
|
+
contents: write # create the tag + GitHub release
|
|
72
|
+
id-token: write # PyPI Trusted Publishing (OIDC)
|
|
73
|
+
steps:
|
|
74
|
+
- uses: actions/checkout@v4
|
|
75
|
+
- uses: astral-sh/setup-uv@v6
|
|
76
|
+
- name: Build
|
|
77
|
+
run: uv build
|
|
78
|
+
- name: Publish to PyPI
|
|
79
|
+
run: uv publish --trusted-publishing always --check-url https://pypi.org/simple/
|
|
80
|
+
- name: Release notes from CHANGELOG
|
|
81
|
+
run: |
|
|
82
|
+
version="${{ needs.check.outputs.version }}"
|
|
83
|
+
awk -v v="$version" '
|
|
84
|
+
index($0, "## [" v "]") == 1 { f=1; next }
|
|
85
|
+
f && index($0, "## [") == 1 { exit }
|
|
86
|
+
f { print }
|
|
87
|
+
' CHANGELOG.md > notes.md || true
|
|
88
|
+
- name: Create the tag + GitHub release
|
|
89
|
+
env:
|
|
90
|
+
GH_TOKEN: ${{ github.token }}
|
|
91
|
+
run: |
|
|
92
|
+
version="${{ needs.check.outputs.version }}"
|
|
93
|
+
args=(--title "v$version" --target "$GITHUB_SHA")
|
|
94
|
+
if [ -s notes.md ]; then args+=(--notes-file notes.md); else args+=(--generate-notes); fi
|
|
95
|
+
gh release create "v$version" dist/* "${args[@]}"
|
caland-0.5.0/.gitignore
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# `uvx pre-commit install` once, and ruff runs on every commit.
|
|
2
|
+
repos:
|
|
3
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
4
|
+
rev: v0.15.20 # the ruff uv.lock has, so a commit is checked as ci checks it
|
|
5
|
+
hooks:
|
|
6
|
+
- id: ruff-check
|
|
7
|
+
args: [--fix]
|
|
8
|
+
- id: ruff-format
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"languages": {
|
|
3
|
+
"Python": {
|
|
4
|
+
"language_servers": ["ty", "ruff"],
|
|
5
|
+
"format_on_save": "on",
|
|
6
|
+
"code_actions_on_format": {
|
|
7
|
+
"source.organizeImports.ruff": true
|
|
8
|
+
},
|
|
9
|
+
"formatter": {
|
|
10
|
+
"language_server": { "name": "ruff" }
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"lsp": {
|
|
15
|
+
"ruff": {
|
|
16
|
+
"binary": {
|
|
17
|
+
"path": ".venv/bin/ruff",
|
|
18
|
+
"arguments": ["server"]
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"ty": {
|
|
22
|
+
"binary": {
|
|
23
|
+
"path": ".venv/bin/ty",
|
|
24
|
+
"arguments": ["server"]
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"terminal": {
|
|
29
|
+
"detect_venv": {
|
|
30
|
+
"on": {
|
|
31
|
+
"directories": [".venv"],
|
|
32
|
+
"activate_script": "default"
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|