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.
Files changed (38) hide show
  1. dap_mux-0.9.0/.envrc.sample +9 -0
  2. dap_mux-0.9.0/.github/workflows/ci.yml +32 -0
  3. dap_mux-0.9.0/.github/workflows/publish.yml +44 -0
  4. dap_mux-0.9.0/.gitignore +37 -0
  5. dap_mux-0.9.0/.pre-commit-config.yaml +37 -0
  6. dap_mux-0.9.0/.secrets.baseline +127 -0
  7. dap_mux-0.9.0/CHANGELOG.md +18 -0
  8. dap_mux-0.9.0/CONTRIBUTING.md +63 -0
  9. dap_mux-0.9.0/LICENSE.md +21 -0
  10. dap_mux-0.9.0/PKG-INFO +372 -0
  11. dap_mux-0.9.0/README.md +347 -0
  12. dap_mux-0.9.0/demos/README.md +45 -0
  13. dap_mux-0.9.0/demos/fibonacci.py +33 -0
  14. dap_mux-0.9.0/demos/helix/languages.toml +21 -0
  15. dap_mux-0.9.0/demos/vscode/launch.json +14 -0
  16. dap_mux-0.9.0/pyproject.toml +120 -0
  17. dap_mux-0.9.0/src/dap_mux/__init__.py +22 -0
  18. dap_mux-0.9.0/src/dap_mux/_version.py +24 -0
  19. dap_mux-0.9.0/src/dap_mux/adapter.py +203 -0
  20. dap_mux-0.9.0/src/dap_mux/cli.py +245 -0
  21. dap_mux-0.9.0/src/dap_mux/client.py +114 -0
  22. dap_mux-0.9.0/src/dap_mux/compat.py +162 -0
  23. dap_mux-0.9.0/src/dap_mux/ipython_ext.py +549 -0
  24. dap_mux-0.9.0/src/dap_mux/mux.py +316 -0
  25. dap_mux-0.9.0/src/dap_mux/protocol.py +222 -0
  26. dap_mux-0.9.0/src/dap_mux/seq.py +133 -0
  27. dap_mux-0.9.0/src/dap_mux/upstream.py +139 -0
  28. dap_mux-0.9.0/tests/conftest.py +251 -0
  29. dap_mux-0.9.0/tests/test_adapter.py +116 -0
  30. dap_mux-0.9.0/tests/test_cli.py +78 -0
  31. dap_mux-0.9.0/tests/test_compat.py +136 -0
  32. dap_mux-0.9.0/tests/test_ipython_ext.py +376 -0
  33. dap_mux-0.9.0/tests/test_multi_client.py +512 -0
  34. dap_mux-0.9.0/tests/test_mux.py +160 -0
  35. dap_mux-0.9.0/tests/test_protocol.py +169 -0
  36. dap_mux-0.9.0/tests/test_seq.py +125 -0
  37. dap_mux-0.9.0/tests/test_version.py +10 -0
  38. 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
@@ -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.
@@ -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.