entangled-cli 2.4.3__tar.gz → 2.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.
Files changed (74) hide show
  1. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/PKG-INFO +25 -14
  2. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/README.md +19 -8
  3. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/commands/__init__.py +2 -1
  4. entangled_cli-2.5.0/entangled/commands/serve.py +57 -0
  5. entangled_cli-2.5.0/entangled/server/__init__.py +0 -0
  6. entangled_cli-2.5.0/entangled/server/server.py +86 -0
  7. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/pyproject.toml +12 -9
  8. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/.gitignore +0 -0
  9. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/LICENSE +0 -0
  10. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/__init__.py +0 -0
  11. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/commands/brei.py +0 -0
  12. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/commands/main.py +0 -0
  13. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/commands/new.py +0 -0
  14. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/commands/reset.py +0 -0
  15. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/commands/status.py +0 -0
  16. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/commands/stitch.py +0 -0
  17. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/commands/sync.py +0 -0
  18. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/commands/tangle.py +0 -0
  19. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/commands/watch.py +0 -0
  20. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/config/__init__.py +0 -0
  21. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/config/annotation_method.py +0 -0
  22. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/config/config_data.py +0 -0
  23. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/config/config_update.py +0 -0
  24. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/config/document_style.py +0 -0
  25. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/config/language.py +0 -0
  26. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/config/markers.py +0 -0
  27. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/config/namespace_default.py +0 -0
  28. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/config/templates.py +0 -0
  29. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/config/version.py +0 -0
  30. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/errors/__init__.py +0 -0
  31. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/errors/internal.py +0 -0
  32. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/errors/user.py +0 -0
  33. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/hooks/__init__.py +0 -0
  34. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/hooks/base.py +0 -0
  35. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/hooks/build.py +0 -0
  36. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/hooks/quarto_attributes.py +0 -0
  37. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/hooks/repl.py +0 -0
  38. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/hooks/shebang.py +0 -0
  39. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/hooks/spdx_license.py +0 -0
  40. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/hooks/task.py +0 -0
  41. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/interface/__init__.py +0 -0
  42. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/interface/context.py +0 -0
  43. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/interface/document.py +0 -0
  44. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/io/__init__.py +0 -0
  45. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/io/filedb.py +0 -0
  46. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/io/stat.py +0 -0
  47. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/io/transaction.py +0 -0
  48. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/io/virtual.py +0 -0
  49. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/iterators/__init__.py +0 -0
  50. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/iterators/lines.py +0 -0
  51. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/iterators/peekable.py +0 -0
  52. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/iterators/run_generator.py +0 -0
  53. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/logging.py +0 -0
  54. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/main.py +0 -0
  55. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/model/__init__.py +0 -0
  56. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/model/code_block.py +0 -0
  57. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/model/content.py +0 -0
  58. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/model/properties.py +0 -0
  59. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/model/reference_id.py +0 -0
  60. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/model/reference_map.py +0 -0
  61. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/model/reference_name.py +0 -0
  62. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/model/tangle.py +0 -0
  63. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/parsing.py +0 -0
  64. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/py.typed +0 -0
  65. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/readers/__init__.py +0 -0
  66. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/readers/code.py +0 -0
  67. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/readers/delimiters.py +0 -0
  68. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/readers/markdown.py +0 -0
  69. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/readers/types.py +0 -0
  70. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/readers/yaml_header.py +0 -0
  71. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/status.py +0 -0
  72. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/text_location.py +0 -0
  73. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/utility.py +0 -0
  74. {entangled_cli-2.4.3 → entangled_cli-2.5.0}/entangled/version.py +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: entangled-cli
3
- Version: 2.4.3
3
+ Version: 2.5.0
4
4
  Summary: Literate Programming toolbox
5
5
  Project-URL: Homepage, https://entangled.github.io/
6
6
  Project-URL: Repository, https://github.com/entangled/entangled.py
@@ -11,16 +11,16 @@ Requires-Python: <4,>=3.13
11
11
  Requires-Dist: brei<0.3,>=0.2.3
12
12
  Requires-Dist: click>=8.3.0
13
13
  Requires-Dist: copier<10,>=9
14
- Requires-Dist: filelock<4,>=3.12.0
14
+ Requires-Dist: filelock<5,>=3.12.0
15
15
  Requires-Dist: msgspec>=0.20.0
16
16
  Requires-Dist: pyyaml<7,>=6.0.1
17
17
  Requires-Dist: repl-session>=0.2.0
18
18
  Requires-Dist: rich-argparse<2,>=1.4.0
19
19
  Requires-Dist: rich-click>=1.9.4
20
- Requires-Dist: rich<15,>=13
21
- Requires-Dist: tomlkit<0.13,>=0.12.1
20
+ Requires-Dist: rich<16,>=13
21
+ Requires-Dist: tomlkit<0.16,>=0.12.1
22
22
  Requires-Dist: typeguard>=4.4.4
23
- Requires-Dist: watchfiles>=1.1.1
23
+ Requires-Dist: watchfiles>=1.3
24
24
  Description-Content-Type: text/markdown
25
25
 
26
26
  # Entangled
@@ -38,26 +38,28 @@ Literate programming was introduced by Donald Knuth in 1984 and has since then f
38
38
  We’re trying to increase the visibility of Entangled. If you like Entangled, please consider adding this badge [![Entangled badge](https://img.shields.io/badge/entangled-Use%20the%20source!-%2300aeff)](https://entangled.github.io/) to the appropriate location in your project:
39
39
 
40
40
  ```markdown
41
- [![Entangled badge](https://img.shields.io/badge/entangled-Use%20the%20source!-%2300aeff)](https://entangled.github.io/)
41
+ [![Entangled badge](https://img.shields.io/badge/entangled-Use%19the%20source!-%2300aeff)](https://entangled.github.io/)
42
42
  ```
43
43
 
44
44
  ## Get started
45
45
 
46
- To install Entangled, all you need is a Python (version &ge;3.11) installation. If you use [`poetry`](https://python-poetry.org), and you start a new project,
46
+ To install Entangled, all you need is a Python (version &ge;3.11) installation. If you use UV, and you start a new project,
47
47
 
48
48
  ```
49
- poetry init
50
- poetry add entangled-cli
49
+ uv init --bare
50
+ uv add entangled-cli
51
51
  ```
52
52
 
53
- The `poetry init` command will create a `pyproject.toml` file and a virtual environment to install Python dependencies in. To activate the virtual environment, run `poetry shell` inside the project directory.
53
+ The `uv init --bare` command will create a `pyproject.toml` file and a virtual environment to install Python dependencies in. To activate the virtual environment, run `. ./.venv/bin/activate` inside the project directory, or you can prepend commands with `uv run` to run them in the venv.
54
54
 
55
- Or, if you prefer plain old `pip`,
55
+ Or, if you prefer plain old `pip`, or `pipx`,
56
56
 
57
57
  ```
58
- pip install entangled-cli
58
+ pipx install entangled-cli
59
59
  ```
60
60
 
61
+ Here, `pipx` creates a virtual environment for just the `entangled-cli` package.
62
+
61
63
  Or, if you prefer the nix package manager:
62
64
 
63
65
  ```
@@ -185,6 +187,13 @@ identifiers = ["java"]
185
187
  comment = { open = "//" }
186
188
  ```
187
189
 
190
+ ## Serving Rendered Pages
191
+ Entangled v2.5 includes a auto-reloading web server. Suppose your documents are in `docs` and they are rendered to `site` with `make site`, you can run the live server like so:
192
+
193
+ ```shell
194
+ entangled serve --watch docs --build 'entangled sync && make site' site
195
+ ```
196
+
188
197
  ## Working in VSCode
189
198
  The [EntangleD-VSCode](https://github.com/deephbz/entangled-vscode) extension provides code block navigation, reference&symbol search, NOWEB high-lighting functionalities.
190
199
 
@@ -521,7 +530,9 @@ This is a rewrite of Entangled in Python. Older versions were written in Haskell
521
530
 
522
531
  ## Contributing
523
532
 
524
- If you have an idea for improving Entangled, please file an issue before creating a pull request. Code in this repository is formatted using `black` and type checked using `mypy`.
533
+ If you have an idea for improving Entangled, please file an issue before creating a pull request. Code in this repository is type checked using `mypy`. Within reasonable limits we adhere to PEP-8 code standards.
534
+
535
+ Some parts of Entangled were developed with AI assistance. When you submit a PR, in interest of careful review, please make sure that you've pruned for needles changes.
525
536
 
526
537
  ## License
527
538
 
@@ -13,26 +13,28 @@ Literate programming was introduced by Donald Knuth in 1984 and has since then f
13
13
  We’re trying to increase the visibility of Entangled. If you like Entangled, please consider adding this badge [![Entangled badge](https://img.shields.io/badge/entangled-Use%20the%20source!-%2300aeff)](https://entangled.github.io/) to the appropriate location in your project:
14
14
 
15
15
  ```markdown
16
- [![Entangled badge](https://img.shields.io/badge/entangled-Use%20the%20source!-%2300aeff)](https://entangled.github.io/)
16
+ [![Entangled badge](https://img.shields.io/badge/entangled-Use%19the%20source!-%2300aeff)](https://entangled.github.io/)
17
17
  ```
18
18
 
19
19
  ## Get started
20
20
 
21
- To install Entangled, all you need is a Python (version &ge;3.11) installation. If you use [`poetry`](https://python-poetry.org), and you start a new project,
21
+ To install Entangled, all you need is a Python (version &ge;3.11) installation. If you use UV, and you start a new project,
22
22
 
23
23
  ```
24
- poetry init
25
- poetry add entangled-cli
24
+ uv init --bare
25
+ uv add entangled-cli
26
26
  ```
27
27
 
28
- The `poetry init` command will create a `pyproject.toml` file and a virtual environment to install Python dependencies in. To activate the virtual environment, run `poetry shell` inside the project directory.
28
+ The `uv init --bare` command will create a `pyproject.toml` file and a virtual environment to install Python dependencies in. To activate the virtual environment, run `. ./.venv/bin/activate` inside the project directory, or you can prepend commands with `uv run` to run them in the venv.
29
29
 
30
- Or, if you prefer plain old `pip`,
30
+ Or, if you prefer plain old `pip`, or `pipx`,
31
31
 
32
32
  ```
33
- pip install entangled-cli
33
+ pipx install entangled-cli
34
34
  ```
35
35
 
36
+ Here, `pipx` creates a virtual environment for just the `entangled-cli` package.
37
+
36
38
  Or, if you prefer the nix package manager:
37
39
 
38
40
  ```
@@ -160,6 +162,13 @@ identifiers = ["java"]
160
162
  comment = { open = "//" }
161
163
  ```
162
164
 
165
+ ## Serving Rendered Pages
166
+ Entangled v2.5 includes a auto-reloading web server. Suppose your documents are in `docs` and they are rendered to `site` with `make site`, you can run the live server like so:
167
+
168
+ ```shell
169
+ entangled serve --watch docs --build 'entangled sync && make site' site
170
+ ```
171
+
163
172
  ## Working in VSCode
164
173
  The [EntangleD-VSCode](https://github.com/deephbz/entangled-vscode) extension provides code block navigation, reference&symbol search, NOWEB high-lighting functionalities.
165
174
 
@@ -496,7 +505,9 @@ This is a rewrite of Entangled in Python. Older versions were written in Haskell
496
505
 
497
506
  ## Contributing
498
507
 
499
- If you have an idea for improving Entangled, please file an issue before creating a pull request. Code in this repository is formatted using `black` and type checked using `mypy`.
508
+ If you have an idea for improving Entangled, please file an issue before creating a pull request. Code in this repository is type checked using `mypy`. Within reasonable limits we adhere to PEP-8 code standards.
509
+
510
+ Some parts of Entangled were developed with AI assistance. When you submit a PR, in interest of careful review, please make sure that you've pruned for needles changes.
500
511
 
501
512
  ## License
502
513
 
@@ -7,7 +7,8 @@ from .sync import sync
7
7
  from .watch import watch
8
8
  from .status import status
9
9
  from .brei import brei
10
+ from .serve import serve
10
11
 
11
12
  __all__ = [
12
- "main", "stitch", "tangle", "new", "reset", "sync", "watch", "status", "brei"
13
+ "main", "stitch", "tangle", "new", "reset", "sync", "watch", "status", "brei", "serve"
13
14
  ]
@@ -0,0 +1,57 @@
1
+ from ..server.server import Reloader, Handler
2
+ from .main import main
3
+ from ..logging import logger
4
+
5
+ from functools import partial
6
+ from pathlib import Path
7
+ import subprocess
8
+ import threading
9
+ from http.server import ThreadingHTTPServer
10
+
11
+ from watchfiles import watch
12
+ import click
13
+
14
+
15
+ def watch_site(site: Path, reloader: Reloader):
16
+ for changes in watch(site):
17
+ logger().info(f"[livereload] {len(changes)} change(s) in {site}, reloading")
18
+ reloader.trigger()
19
+
20
+
21
+ def watch_sources(paths: list[Path], site: Path, build: str):
22
+ def is_source(_change, path: str) -> bool:
23
+ return not Path(path).resolve().is_relative_to(site.resolve())
24
+
25
+ for _ in watch(*paths, watch_filter=is_source):
26
+ logger().info(f"[livereload] sources changed, running: {build}")
27
+ subprocess.run(build, shell=True, check=False)
28
+
29
+
30
+ @main.command()
31
+ @click.argument("directory", type=Path, help="directory to serve")
32
+ @click.option("-p", "--port", type=int, default=8000)
33
+ @click.option("-b", "--bind", default="127.0.0.1")
34
+ @click.option("--build", help="shell command to run when sources change")
35
+ @click.option("-w", "--watch", type=Path, multiple=True, help="source paths for --build")
36
+ def serve(directory: Path, port: int, bind: str, build: str | None = None, watch: list[Path] | None = None) -> None:
37
+ """Stand-alone webserver with browser auto-reloading."""
38
+ reloader = Reloader()
39
+ threading.Thread(
40
+ target=watch_site, args=(directory, reloader), daemon=True
41
+ ).start()
42
+ if build:
43
+ threading.Thread(
44
+ target=watch_sources,
45
+ args=(watch or [Path(".")], directory, build),
46
+ daemon=True,
47
+ ).start()
48
+
49
+ handler = partial(Handler, directory=str(directory))
50
+ Handler.reloader = reloader
51
+ with ThreadingHTTPServer((bind, port), handler) as server:
52
+ server.daemon_threads = True
53
+ logger().info(f"[livereload] serving {directory} at http://{bind}:{port}/")
54
+ try:
55
+ server.serve_forever()
56
+ except KeyboardInterrupt:
57
+ pass
File without changes
@@ -0,0 +1,86 @@
1
+ """Minimal live-reloading static file server.
2
+
3
+ Serves a directory over HTTP, injects a tiny script into every HTML page,
4
+ and tells connected browsers to reload (via Server-Sent Events) whenever
5
+ something in the served directory changes. Optionally runs a build command
6
+ whenever source files change.
7
+
8
+ Mostly generated by Claude Opus 5.5.
9
+ """
10
+
11
+ import threading
12
+ from pathlib import Path
13
+ from http import HTTPStatus
14
+ from http.server import SimpleHTTPRequestHandler
15
+
16
+
17
+ EVENT_PATH = "/__livereload"
18
+ SNIPPET = (
19
+ f'<script>new EventSource("{EVENT_PATH}")'
20
+ '.addEventListener("reload", () => location.reload());</script>'
21
+ ).encode()
22
+
23
+
24
+ class Reloader:
25
+ """Generation counter that SSE handlers block on."""
26
+
27
+ def __init__(self):
28
+ self.generation = 0
29
+ self.cond = threading.Condition()
30
+
31
+ def trigger(self):
32
+ with self.cond:
33
+ self.generation += 1
34
+ self.cond.notify_all()
35
+
36
+ def wait(self, generation: int, timeout: float) -> int:
37
+ with self.cond:
38
+ self.cond.wait_for(lambda: self.generation != generation, timeout)
39
+ return self.generation
40
+
41
+
42
+ class Handler(SimpleHTTPRequestHandler):
43
+ reloader: Reloader
44
+
45
+ def do_GET(self):
46
+ if self.path == EVENT_PATH:
47
+ return self.serve_events()
48
+ path = Path(self.translate_path(self.path))
49
+ if path.is_dir():
50
+ path = path / "index.html"
51
+ if path.suffix == ".html" and path.is_file():
52
+ return self.serve_html(path)
53
+ return super().do_GET()
54
+
55
+ def serve_html(self, path: Path):
56
+ body = path.read_bytes()
57
+ i = body.rfind(b"</body>")
58
+ body = body[:i] + SNIPPET + body[i:] if i >= 0 else body + SNIPPET
59
+ self.send_response(HTTPStatus.OK)
60
+ self.send_header("Content-Type", "text/html; charset=utf-8")
61
+ self.send_header("Content-Length", str(len(body)))
62
+ self.send_header("Cache-Control", "no-store")
63
+ self.end_headers()
64
+ self.wfile.write(body)
65
+
66
+ def serve_events(self):
67
+ self.send_response(HTTPStatus.OK)
68
+ self.send_header("Content-Type", "text/event-stream")
69
+ self.send_header("Cache-Control", "no-store")
70
+ self.end_headers()
71
+ generation = self.reloader.generation
72
+ try:
73
+ while True:
74
+ new = self.reloader.wait(generation, timeout=15)
75
+ if new != generation:
76
+ generation = new
77
+ self.wfile.write(b"event: reload\ndata: \n\n")
78
+ else:
79
+ self.wfile.write(b": keepalive\n\n") # detects closed tabs
80
+ self.wfile.flush()
81
+ except (BrokenPipeError, ConnectionResetError):
82
+ pass
83
+
84
+ def log_message(self, format, *args):
85
+ if self.path != EVENT_PATH:
86
+ super().log_message(format, *args)
@@ -1,15 +1,15 @@
1
1
  [project]
2
2
  name = "entangled-cli"
3
- version = "2.4.3"
3
+ version = "2.5.0"
4
4
  description = "Literate Programming toolbox"
5
5
  authors = [{ name = "Johan Hidding", email = "j.hidding@esciencecenter.nl" }]
6
6
  requires-python = ">=3.13,<4"
7
7
  readme = "README.md"
8
8
  license = "Apache-2.0"
9
9
  dependencies = [
10
- "filelock>=3.12.0,<4",
11
- "rich>=13,<15",
12
- "tomlkit>=0.12.1,<0.13",
10
+ "filelock>=3.12.0,<5",
11
+ "rich>=13,<16",
12
+ "tomlkit>=0.12.1,<0.16",
13
13
  "copier>=9,<10",
14
14
  "brei>=0.2.3,<0.3",
15
15
  "rich-argparse>=1.4.0,<2",
@@ -19,7 +19,7 @@ dependencies = [
19
19
  "click>=8.3.0",
20
20
  "rich-click>=1.9.4",
21
21
  "typeguard>=4.4.4",
22
- "watchfiles>=1.1.1",
22
+ "watchfiles>=1.3",
23
23
  ]
24
24
 
25
25
  [project.urls]
@@ -32,8 +32,7 @@ entangled = "entangled.main:cli"
32
32
  [dependency-groups]
33
33
  dev = [
34
34
  "pytest>=9.0,<10",
35
- "mypy>=1.18,<2",
36
- "black>=23.3.0,<24",
35
+ "mypy>=2.4.0",
37
36
  "pytest-cov>=4.0.0,<5",
38
37
  "mkdocs>=1.4.3,<2",
39
38
  "mkdocs-material>=9.7,<10",
@@ -48,7 +47,6 @@ dev = [
48
47
  "types-pexpect>=4.9.0.20250916",
49
48
  "types-PyYAML>=6.0.1,<7",
50
49
  "pytest-timeout>=2.4.0",
51
- "ty>=0.0.1a24",
52
50
  ]
53
51
 
54
52
  [tool.hatch.build.targets.sdist]
@@ -70,5 +68,10 @@ testpaths = ["test"]
70
68
  [tool.mypy]
71
69
  packages = ["entangled"]
72
70
 
71
+ [tool.uv.workspace]
72
+ members = [
73
+ ".",
74
+ ]
75
+
73
76
  [tool.uv.sources]
74
- watchdog = { git = "https://github.com/gorakhargosh/watchdog" }
77
+ entangled-cli = { workspace = true, editable = true }
File without changes
File without changes