dap-mux 0.9.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.
- dap_mux-0.9.0/.envrc.sample +9 -0
- dap_mux-0.9.0/.github/workflows/ci.yml +32 -0
- dap_mux-0.9.0/.github/workflows/publish.yml +44 -0
- dap_mux-0.9.0/.gitignore +37 -0
- dap_mux-0.9.0/.pre-commit-config.yaml +37 -0
- dap_mux-0.9.0/.secrets.baseline +127 -0
- dap_mux-0.9.0/CHANGELOG.md +18 -0
- dap_mux-0.9.0/CONTRIBUTING.md +63 -0
- dap_mux-0.9.0/LICENSE.md +21 -0
- dap_mux-0.9.0/PKG-INFO +372 -0
- dap_mux-0.9.0/README.md +347 -0
- dap_mux-0.9.0/demos/README.md +45 -0
- dap_mux-0.9.0/demos/fibonacci.py +33 -0
- dap_mux-0.9.0/demos/helix/languages.toml +21 -0
- dap_mux-0.9.0/demos/vscode/launch.json +14 -0
- dap_mux-0.9.0/pyproject.toml +120 -0
- dap_mux-0.9.0/src/dap_mux/__init__.py +22 -0
- dap_mux-0.9.0/src/dap_mux/_version.py +24 -0
- dap_mux-0.9.0/src/dap_mux/adapter.py +203 -0
- dap_mux-0.9.0/src/dap_mux/cli.py +245 -0
- dap_mux-0.9.0/src/dap_mux/client.py +114 -0
- dap_mux-0.9.0/src/dap_mux/compat.py +162 -0
- dap_mux-0.9.0/src/dap_mux/ipython_ext.py +549 -0
- dap_mux-0.9.0/src/dap_mux/mux.py +316 -0
- dap_mux-0.9.0/src/dap_mux/protocol.py +222 -0
- dap_mux-0.9.0/src/dap_mux/seq.py +133 -0
- dap_mux-0.9.0/src/dap_mux/upstream.py +139 -0
- dap_mux-0.9.0/tests/conftest.py +251 -0
- dap_mux-0.9.0/tests/test_adapter.py +116 -0
- dap_mux-0.9.0/tests/test_cli.py +78 -0
- dap_mux-0.9.0/tests/test_compat.py +136 -0
- dap_mux-0.9.0/tests/test_ipython_ext.py +376 -0
- dap_mux-0.9.0/tests/test_multi_client.py +512 -0
- dap_mux-0.9.0/tests/test_mux.py +160 -0
- dap_mux-0.9.0/tests/test_protocol.py +169 -0
- dap_mux-0.9.0/tests/test_seq.py +125 -0
- dap_mux-0.9.0/tests/test_version.py +10 -0
- dap_mux-0.9.0/uv.lock +521 -0
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# .envrc — project-level direnv configuration
|
|
2
|
+
#
|
|
3
|
+
# Copy or symlink this to .envrc at the project root.
|
|
4
|
+
# .envrc is gitignored — add local overrides there.
|
|
5
|
+
#
|
|
6
|
+
# Requires layout_uv in ~/.config/direnv/direnvrc:
|
|
7
|
+
# layout_uv() { source "$(uv python find)/../../activate"; }
|
|
8
|
+
|
|
9
|
+
layout uv
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
permissions: {}
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
test:
|
|
13
|
+
name: Test (Python ${{ matrix.python-version }})
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
strategy:
|
|
16
|
+
fail-fast: false
|
|
17
|
+
matrix:
|
|
18
|
+
python-version: ["3.12", "3.13", "3.14"]
|
|
19
|
+
|
|
20
|
+
steps:
|
|
21
|
+
- uses: actions/checkout@v4
|
|
22
|
+
|
|
23
|
+
- uses: astral-sh/setup-uv@v5
|
|
24
|
+
with:
|
|
25
|
+
python-version: ${{ matrix.python-version }}
|
|
26
|
+
|
|
27
|
+
- run: uv sync --group dev
|
|
28
|
+
|
|
29
|
+
- run: uv run ruff format --check .
|
|
30
|
+
- run: uv run ruff check .
|
|
31
|
+
- run: uv run ty check
|
|
32
|
+
- run: uv run pytest
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v[0-9]*"
|
|
7
|
+
|
|
8
|
+
permissions: {}
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
build:
|
|
12
|
+
name: Build
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
with:
|
|
17
|
+
fetch-depth: 0 # hatch-vcs needs full tag history
|
|
18
|
+
|
|
19
|
+
- uses: astral-sh/setup-uv@v5
|
|
20
|
+
|
|
21
|
+
- run: uv build
|
|
22
|
+
|
|
23
|
+
- uses: actions/upload-artifact@v4
|
|
24
|
+
with:
|
|
25
|
+
name: dist
|
|
26
|
+
path: dist/
|
|
27
|
+
|
|
28
|
+
publish:
|
|
29
|
+
name: Publish to PyPI
|
|
30
|
+
needs: build
|
|
31
|
+
runs-on: ubuntu-latest
|
|
32
|
+
environment:
|
|
33
|
+
name: pypi
|
|
34
|
+
url: https://pypi.org/project/dap-mux/
|
|
35
|
+
permissions:
|
|
36
|
+
id-token: write # required for trusted publishing
|
|
37
|
+
|
|
38
|
+
steps:
|
|
39
|
+
- uses: actions/download-artifact@v4
|
|
40
|
+
with:
|
|
41
|
+
name: dist
|
|
42
|
+
path: dist/
|
|
43
|
+
|
|
44
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
dap_mux-0.9.0/.gitignore
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Python-generated files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[oc]
|
|
4
|
+
build/
|
|
5
|
+
dist/
|
|
6
|
+
wheels/
|
|
7
|
+
*.egg-info
|
|
8
|
+
|
|
9
|
+
# Virtual environments
|
|
10
|
+
.venv
|
|
11
|
+
|
|
12
|
+
# Generated by hatch-vcs
|
|
13
|
+
src/dap_mux/_version.py
|
|
14
|
+
|
|
15
|
+
# direnv (may contain credentials)
|
|
16
|
+
.envrc
|
|
17
|
+
|
|
18
|
+
# Editor files
|
|
19
|
+
*.swp
|
|
20
|
+
*.swo
|
|
21
|
+
*~
|
|
22
|
+
.idea/
|
|
23
|
+
.vscode/
|
|
24
|
+
|
|
25
|
+
# OS files
|
|
26
|
+
.DS_Store
|
|
27
|
+
Thumbs.db
|
|
28
|
+
|
|
29
|
+
# Local-only files (not tracked)
|
|
30
|
+
*.local-only.*
|
|
31
|
+
|
|
32
|
+
# Test coverage artifacts
|
|
33
|
+
.coverage
|
|
34
|
+
htmlcov/
|
|
35
|
+
|
|
36
|
+
# Spike artifacts (not part of the project)
|
|
37
|
+
SPIKE-CONCLUSIONS.md
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# .pre-commit-config.yaml — standard hook sequence
|
|
2
|
+
#
|
|
3
|
+
# Managed by prek (not pre-commit). Install: prek install
|
|
4
|
+
# Run manually: prek run --all-files
|
|
5
|
+
#
|
|
6
|
+
# Hook order matters: format first, then lint, then type-check, then test.
|
|
7
|
+
# Each stage must pass before code enters history.
|
|
8
|
+
|
|
9
|
+
repos:
|
|
10
|
+
- repo: https://github.com/Yelp/detect-secrets
|
|
11
|
+
rev: v1.5.0
|
|
12
|
+
hooks:
|
|
13
|
+
- id: detect-secrets
|
|
14
|
+
args: ['--baseline', '.secrets.baseline']
|
|
15
|
+
|
|
16
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
17
|
+
rev: v0.15.10
|
|
18
|
+
hooks:
|
|
19
|
+
- id: ruff-format
|
|
20
|
+
- id: ruff
|
|
21
|
+
args: [--fix, --exit-non-zero-on-fix]
|
|
22
|
+
|
|
23
|
+
- repo: local
|
|
24
|
+
hooks:
|
|
25
|
+
- id: ty
|
|
26
|
+
name: ty
|
|
27
|
+
entry: uv run ty check
|
|
28
|
+
language: system
|
|
29
|
+
pass_filenames: false
|
|
30
|
+
always_run: true
|
|
31
|
+
|
|
32
|
+
- id: pytest
|
|
33
|
+
name: pytest
|
|
34
|
+
entry: uv run pytest --doctest-modules
|
|
35
|
+
language: system
|
|
36
|
+
pass_filenames: false
|
|
37
|
+
always_run: true
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "1.5.0",
|
|
3
|
+
"plugins_used": [
|
|
4
|
+
{
|
|
5
|
+
"name": "ArtifactoryDetector"
|
|
6
|
+
},
|
|
7
|
+
{
|
|
8
|
+
"name": "AWSKeyDetector"
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"name": "AzureStorageKeyDetector"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"name": "Base64HighEntropyString",
|
|
15
|
+
"limit": 4.5
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"name": "BasicAuthDetector"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"name": "CloudantDetector"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"name": "DiscordBotTokenDetector"
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"name": "GitHubTokenDetector"
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"name": "GitLabTokenDetector"
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"name": "HexHighEntropyString",
|
|
34
|
+
"limit": 3.0
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"name": "IbmCloudIamDetector"
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"name": "IbmCosHmacDetector"
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"name": "IPPublicDetector"
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"name": "JwtTokenDetector"
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"name": "KeywordDetector",
|
|
50
|
+
"keyword_exclude": ""
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"name": "MailchimpDetector"
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"name": "NpmDetector"
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"name": "OpenAIDetector"
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"name": "PrivateKeyDetector"
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"name": "PypiTokenDetector"
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"name": "SendGridDetector"
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"name": "SlackDetector"
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
"name": "SoftlayerDetector"
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"name": "SquareOAuthDetector"
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"name": "StripeDetector"
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"name": "TelegramBotTokenDetector"
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
"name": "TwilioKeyDetector"
|
|
87
|
+
}
|
|
88
|
+
],
|
|
89
|
+
"filters_used": [
|
|
90
|
+
{
|
|
91
|
+
"path": "detect_secrets.filters.allowlist.is_line_allowlisted"
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"path": "detect_secrets.filters.common.is_ignored_due_to_verification_policies",
|
|
95
|
+
"min_level": 2
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
"path": "detect_secrets.filters.heuristic.is_indirect_reference"
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
"path": "detect_secrets.filters.heuristic.is_likely_id_string"
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
"path": "detect_secrets.filters.heuristic.is_lock_file"
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
"path": "detect_secrets.filters.heuristic.is_not_alphanumeric_string"
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
"path": "detect_secrets.filters.heuristic.is_potential_uuid"
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
"path": "detect_secrets.filters.heuristic.is_prefixed_with_dollar_sign"
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
"path": "detect_secrets.filters.heuristic.is_sequential_string"
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
"path": "detect_secrets.filters.heuristic.is_swagger_file"
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
"path": "detect_secrets.filters.heuristic.is_templated_secret"
|
|
123
|
+
}
|
|
124
|
+
],
|
|
125
|
+
"results": {},
|
|
126
|
+
"generated_at": "2026-05-29T20:16:27Z"
|
|
127
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## v0.9.0 (2026-05-30)
|
|
4
|
+
|
|
5
|
+
First release. The core multiplexer is complete and live-tested: connect Helix or VS Code and an IPython REPL to the same debugpy session and debug from both simultaneously.
|
|
6
|
+
|
|
7
|
+
**Features:**
|
|
8
|
+
* DAP multiplexer with full protocol support — framing, sequence rewriting, multi-client routing, event broadcasting
|
|
9
|
+
* Late-join state replay — a client connecting to an already-running session receives the initialized handshake and current stop position immediately
|
|
10
|
+
* Launch mode (`dmux script.py`) spawns debugpy and opens the IPython REPL in one command
|
|
11
|
+
* Attach mode (`dmux --attach host:port`) connects to an already-running debug adapter
|
|
12
|
+
* IPython extension with debug magics: `%step`, `%next`, `%continue_`, `%finish`, `%bt`, `%frame`, `%eval`, `%break`, `%clear`, `%sync`, `%connect`, `%disconnect`
|
|
13
|
+
* Headless mode (`--no-repl`) for scripted setups or external REPL frontends
|
|
14
|
+
* Configurable mux port (`-p`), log level (`-l`), and log file
|
|
15
|
+
|
|
16
|
+
**Internal:**
|
|
17
|
+
* CI/CD via GitHub Actions: Python 3.14 test matrix, trusted publisher workflow for PyPI releases
|
|
18
|
+
* 114 tests covering protocol framing, sequence rewriting, multi-client routing, late-join state replay, and the IPython extension
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
dap-mux is a small, focused tool. Contributions that help it do its one thing better are welcome.
|
|
4
|
+
|
|
5
|
+
## Ways to contribute
|
|
6
|
+
|
|
7
|
+
Not all contributions are code. Bug reports, documentation improvements, and notes on editors or debug adapters you've tested against are all genuinely useful — especially for a project whose compatibility surface is larger than its test suite.
|
|
8
|
+
|
|
9
|
+
## Start with an issue
|
|
10
|
+
|
|
11
|
+
Before writing code, open an issue. Describe the problem you're trying to solve or the use case you want to support. Good things happen in issues: the problem gets refined, edge cases surface, and you learn whether the project will accept a solution before you spend time building one.
|
|
12
|
+
|
|
13
|
+
A pull request with no linked issue gives us nothing to evaluate it against. We can't know if it solves the right problem, if this is the right solution, or if the problem is something this project should solve at all. We'll close it and ask you to open an issue first.
|
|
14
|
+
|
|
15
|
+
Exception: if you're fixing a clear, unambiguous bug, you can open the PR directly — just describe the behavior you observed and what you changed.
|
|
16
|
+
|
|
17
|
+
## Scope
|
|
18
|
+
|
|
19
|
+
dap-mux is a router. It connects debug clients to debug adapters. It is not a platform, and it's not trying to become one.
|
|
20
|
+
|
|
21
|
+
The right question to ask before proposing a feature: *does this help connect things, or does it add capability that belongs in the client or adapter?* The project will grow, but slowly and deliberately. Proposals that significantly expand scope need to clear a higher bar — start with an issue and make the case.
|
|
22
|
+
|
|
23
|
+
## What makes a good PR
|
|
24
|
+
|
|
25
|
+
**It addresses the issue and nothing more.** Small incidental cleanups are fine; sweeping refactors bundled with a feature are not. Focused changes are easier to review, easier to revert, and easier to understand six months later.
|
|
26
|
+
|
|
27
|
+
**It is good code.** Clear names, no dead code, no commented-out experiments. Code that requires a long explanation to justify is usually code that needs to be changed.
|
|
28
|
+
|
|
29
|
+
**It comes with tests.** Behavior changes need test coverage. Tests should verify promises — what the code is supposed to do — not implementation details.
|
|
30
|
+
|
|
31
|
+
**You can defend it.** If AI helped you write the code, that's fine. But you are responsible for it. You should be able to explain every line, debug a failure in it, and adapt it when requirements change. If you can't, the PR can't be proven safe to merge — regardless of how it was written.
|
|
32
|
+
|
|
33
|
+
## Development setup
|
|
34
|
+
|
|
35
|
+
You need [uv](https://docs.astral.sh/uv/) and [prek](https://github.com/drmikehenry/prek).
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
git clone https://github.com/dap-mux/dap-mux
|
|
39
|
+
cd dap-mux
|
|
40
|
+
uv sync --group dev
|
|
41
|
+
prek install
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
If you use [direnv](https://direnv.net/), a `.envrc.sample` is committed. Copy or symlink it to `.envrc` and direnv will activate the virtualenv automatically whenever you enter the project directory.
|
|
45
|
+
|
|
46
|
+
`prek install` sets up the pre-commit hooks. After that, every commit automatically runs secret scanning, linting, formatting, type checking, and the test suite. If any of them fail, the commit doesn't happen.
|
|
47
|
+
|
|
48
|
+
## Tests and code quality
|
|
49
|
+
|
|
50
|
+
The pre-commit hooks run everything automatically. To run tools individually:
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
uv run pytest # test suite
|
|
54
|
+
uv run ruff check . # lint
|
|
55
|
+
uv run ruff format . # format
|
|
56
|
+
uv run ty check # type check
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
All four must pass before a PR is ready to review.
|
|
60
|
+
|
|
61
|
+
## License
|
|
62
|
+
|
|
63
|
+
By submitting a pull request, you agree that your contribution will be licensed under the [MIT License](LICENSE.md) that covers this project, and that you have the right to grant that license.
|
dap_mux-0.9.0/LICENSE.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Wolf
|
|
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.
|