pycodecad 1.0.0__tar.gz → 1.0.1__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 (54) hide show
  1. pycodecad-1.0.1/CHANGELOG.md +10 -0
  2. {pycodecad-1.0.0 → pycodecad-1.0.1}/PKG-INFO +1 -1
  3. {pycodecad-1.0.0 → pycodecad-1.0.1}/src/pycodecad/__init__.py +1 -1
  4. {pycodecad-1.0.0 → pycodecad-1.0.1}/src/pycodecad/ui.py +5 -0
  5. {pycodecad-1.0.0 → pycodecad-1.0.1}/src/pycodecad/workspace.py +6 -2
  6. {pycodecad-1.0.0 → pycodecad-1.0.1}/tests/test_workspace.py +13 -0
  7. pycodecad-1.0.0/CHANGELOG.md +0 -5
  8. {pycodecad-1.0.0 → pycodecad-1.0.1}/.gitignore +0 -0
  9. {pycodecad-1.0.0 → pycodecad-1.0.1}/LICENSE +0 -0
  10. {pycodecad-1.0.0 → pycodecad-1.0.1}/README.md +0 -0
  11. {pycodecad-1.0.0 → pycodecad-1.0.1}/examples/assembly.py +0 -0
  12. {pycodecad-1.0.0 → pycodecad-1.0.1}/examples/assets/logo.svg +0 -0
  13. {pycodecad-1.0.0 → pycodecad-1.0.1}/examples/assets/pyramid.stl +0 -0
  14. {pycodecad-1.0.0 → pycodecad-1.0.1}/examples/embedded_app.py +0 -0
  15. {pycodecad-1.0.0 → pycodecad-1.0.1}/examples/gear.py +0 -0
  16. {pycodecad-1.0.0 → pycodecad-1.0.1}/examples/gearbox.py +0 -0
  17. {pycodecad-1.0.0 → pycodecad-1.0.1}/examples/gears_turning.py +0 -0
  18. {pycodecad-1.0.0 → pycodecad-1.0.1}/examples/import_files.py +0 -0
  19. {pycodecad-1.0.0 → pycodecad-1.0.1}/examples/parts.py +0 -0
  20. {pycodecad-1.0.0 → pycodecad-1.0.1}/examples/tray.py +0 -0
  21. {pycodecad-1.0.0 → pycodecad-1.0.1}/pyproject.toml +0 -0
  22. {pycodecad-1.0.0 → pycodecad-1.0.1}/src/pycodecad/__main__.py +0 -0
  23. {pycodecad-1.0.0 → pycodecad-1.0.1}/src/pycodecad/api.py +0 -0
  24. {pycodecad-1.0.0 → pycodecad-1.0.1}/src/pycodecad/app.py +0 -0
  25. {pycodecad-1.0.0 → pycodecad-1.0.1}/src/pycodecad/cad.py +0 -0
  26. {pycodecad-1.0.0 → pycodecad-1.0.1}/src/pycodecad/camera.py +0 -0
  27. {pycodecad-1.0.0 → pycodecad-1.0.1}/src/pycodecad/cli.py +0 -0
  28. {pycodecad-1.0.0 → pycodecad-1.0.1}/src/pycodecad/context.py +0 -0
  29. {pycodecad-1.0.0 → pycodecad-1.0.1}/src/pycodecad/editor.py +0 -0
  30. {pycodecad-1.0.0 → pycodecad-1.0.1}/src/pycodecad/embed.py +0 -0
  31. {pycodecad-1.0.0 → pycodecad-1.0.1}/src/pycodecad/files.py +0 -0
  32. {pycodecad-1.0.0 → pycodecad-1.0.1}/src/pycodecad/icons/LICENSE +0 -0
  33. {pycodecad-1.0.0 → pycodecad-1.0.1}/src/pycodecad/icons/__init__.py +0 -0
  34. {pycodecad-1.0.0 → pycodecad-1.0.1}/src/pycodecad/icons/lucide.ttf +0 -0
  35. {pycodecad-1.0.0 → pycodecad-1.0.1}/src/pycodecad/imgui_backend.py +0 -0
  36. {pycodecad-1.0.0 → pycodecad-1.0.1}/src/pycodecad/params.py +0 -0
  37. {pycodecad-1.0.0 → pycodecad-1.0.1}/src/pycodecad/renderer.py +0 -0
  38. {pycodecad-1.0.0 → pycodecad-1.0.1}/src/pycodecad/runner.py +0 -0
  39. {pycodecad-1.0.0 → pycodecad-1.0.1}/src/pycodecad/sidecar.py +0 -0
  40. {pycodecad-1.0.0 → pycodecad-1.0.1}/src/pycodecad/textedit.py +0 -0
  41. {pycodecad-1.0.0 → pycodecad-1.0.1}/src/pycodecad/viewcube.py +0 -0
  42. {pycodecad-1.0.0 → pycodecad-1.0.1}/src/pycodecad/viewer.py +0 -0
  43. {pycodecad-1.0.0 → pycodecad-1.0.1}/src/pycodecad/window.py +0 -0
  44. {pycodecad-1.0.0 → pycodecad-1.0.1}/tests/conftest.py +0 -0
  45. {pycodecad-1.0.0 → pycodecad-1.0.1}/tests/test_camera.py +0 -0
  46. {pycodecad-1.0.0 → pycodecad-1.0.1}/tests/test_cli.py +0 -0
  47. {pycodecad-1.0.0 → pycodecad-1.0.1}/tests/test_embed.py +0 -0
  48. {pycodecad-1.0.0 → pycodecad-1.0.1}/tests/test_export_consistency.py +0 -0
  49. {pycodecad-1.0.0 → pycodecad-1.0.1}/tests/test_files.py +0 -0
  50. {pycodecad-1.0.0 → pycodecad-1.0.1}/tests/test_frames.py +0 -0
  51. {pycodecad-1.0.0 → pycodecad-1.0.1}/tests/test_params.py +0 -0
  52. {pycodecad-1.0.0 → pycodecad-1.0.1}/tests/test_runner.py +0 -0
  53. {pycodecad-1.0.0 → pycodecad-1.0.1}/tests/test_textedit.py +0 -0
  54. {pycodecad-1.0.0 → pycodecad-1.0.1}/tests/test_viewcube.py +0 -0
@@ -0,0 +1,10 @@
1
+ # Changelog
2
+
3
+ ## 1.0.1
4
+
5
+ - The window says when a file the part reads (a helper module, an asset) changes on disk after a
6
+ run, for example edited by an AI assistant: "helper.py changed on disk: Run to see it".
7
+
8
+ ## 1.0.0
9
+
10
+ First release.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: pycodecad
3
- Version: 1.0.0
3
+ Version: 1.0.1
4
4
  Summary: Code-CAD with build123d: a desktop window that shows and exports what your Python script builds.
5
5
  Project-URL: Repository, https://github.com/offerrall/pycodecad
6
6
  License-Expression: MIT
@@ -1,7 +1,7 @@
1
1
  """Code-CAD with build123d: write a Python script, see the part, export it."""
2
2
  from typing import TYPE_CHECKING
3
3
 
4
- __version__ = "1.0.0"
4
+ __version__ = "1.0.1"
5
5
 
6
6
  __all__ = ["show", "clear", "frame", "import_mesh", "expose"]
7
7
 
@@ -293,6 +293,11 @@ def topbar(ws: Workspace) -> None:
293
293
  imgui.set_cursor_pos_y(top + (TOOL_SIDE - imgui.get_frame_height()) / 2)
294
294
  if button(f"{icon('refresh-cw')} Reload", "Load the file from disk; then Run to see it"):
295
295
  ws.reload()
296
+ if ws.inputs_changed: # a helper module or asset changed (e.g. by an AI assistant): Run shows it
297
+ imgui.same_line(spacing=16.0)
298
+ imgui.set_cursor_pos_y(text_y)
299
+ more = f" and {len(ws.inputs_changed) - 1} more" if len(ws.inputs_changed) > 1 else ""
300
+ imgui.text_colored(WARNING, f"{Path(ws.inputs_changed[0]).name}{more} changed on disk: Run to see it")
296
301
  name = ws.path.name
297
302
  runs = f" · Run: {ws.main.name}" if ws.path != ws.main else "" # the main, when another file is edited
298
303
  width = imgui.calc_text_size(name + runs)[0]
@@ -141,6 +141,7 @@ class Workspace:
141
141
  self.shown_job: tuple[Job, dict[str, object], dict[str, tuple[int, int]]] | None = None
142
142
  self.child_stamp: dict[str, tuple[int, int]] = {} # input_stamp at the start of the child
143
143
  self.written: dict[str, tuple[int, int]] = {} # file_signature of the exports and pictures written
144
+ self.inputs_changed: list[str] = [] # files the part reads that changed since the run on screen
144
145
  self.exports: list[runner.Run] = []
145
146
  self.stopped: list[runner.Run] = [] # killed runs still writing their final last-run file
146
147
  self.message = "" # last status message
@@ -298,6 +299,7 @@ class Workspace:
298
299
  if result.error is None: # on errors the last good objects (and parameters) stay on screen
299
300
  used = {f"{e.function}.{p.name}": p.value for e in result.parameters for p in e.params}
300
301
  self.shown_job = (self.child_job, used, self.child_stamp)
302
+ self.inputs_changed = []
301
303
  self.set_parameters(result.parameters, used, self.child_values)
302
304
  self.shown = result.shown
303
305
  self.frames, self.clock, self.playing = result.frames, 0.0, True
@@ -497,9 +499,11 @@ class Workspace:
497
499
  return True
498
500
 
499
501
  def watch_file(self) -> None:
500
- """Notice (never apply) changes made to the edited file by someone else, and files that
501
- appear in or disappear from the folder."""
502
+ """Notice (never apply) changes made to the edited file by someone else, to the other files
503
+ the part reads (helper modules, assets: Run shows them), and files that appear in or
504
+ disappear from the folder."""
502
505
  self.file_list = python_files(self.folder)
506
+ self.inputs_changed = self.changed_inputs(self.shown_job[2]) if self.shown_job else []
503
507
  mtime = self._mtime(self.path)
504
508
  if mtime is None or mtime == self.file_mtime:
505
509
  return
@@ -511,6 +511,19 @@ def helped_part(folder):
511
511
  return folder
512
512
 
513
513
 
514
+ def test_a_helper_changed_on_disk_is_noticed_until_the_next_run(tmp_path):
515
+ helped_part(tmp_path)
516
+ ws = Workspace(tmp_path, run=False)
517
+ finish_run(ws)
518
+ ws.watch_file()
519
+ assert ws.error is None and ws.inputs_changed == []
520
+ (tmp_path / "helper.py").write_text("SIZE = 30\n") # e.g. an AI assistant, with part.py in the editor
521
+ ws.watch_file()
522
+ assert ws.inputs_changed == [str(tmp_path / "helper.py")] and not ws.disk_changed
523
+ finish_run(ws)
524
+ assert ws.inputs_changed == [] and "30" in ws.stdout
525
+
526
+
514
527
  def test_the_main_file_of_a_folder(tmp_path):
515
528
  (tmp_path / "a_notes.py").write_text("x = 1\n")
516
529
  (tmp_path / "b_part.py").write_text("show(1)\n")
@@ -1,5 +0,0 @@
1
- # Changelog
2
-
3
- ## 1.0.0
4
-
5
- First release.
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes