meshwire 0.5.0a1__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 (137) hide show
  1. meshwire-0.5.0a1/.editorconfig +24 -0
  2. meshwire-0.5.0a1/.github/ISSUE_TEMPLATE/bug_report.yml +77 -0
  3. meshwire-0.5.0a1/.github/ISSUE_TEMPLATE/feature_request.yml +54 -0
  4. meshwire-0.5.0a1/.github/PULL_REQUEST_TEMPLATE.md +31 -0
  5. meshwire-0.5.0a1/.github/dependabot.yml +19 -0
  6. meshwire-0.5.0a1/.github/workflows/blender.yml +162 -0
  7. meshwire-0.5.0a1/.github/workflows/ci.yml +71 -0
  8. meshwire-0.5.0a1/.github/workflows/codeql.yml +33 -0
  9. meshwire-0.5.0a1/.github/workflows/release.yml +119 -0
  10. meshwire-0.5.0a1/.gitignore +99 -0
  11. meshwire-0.5.0a1/CHANGELOG.md +239 -0
  12. meshwire-0.5.0a1/CLA.md +82 -0
  13. meshwire-0.5.0a1/CONTRIBUTING.md +314 -0
  14. meshwire-0.5.0a1/LICENSE +661 -0
  15. meshwire-0.5.0a1/PKG-INFO +379 -0
  16. meshwire-0.5.0a1/README.md +350 -0
  17. meshwire-0.5.0a1/addon/blender_mcp_addon/__init__.py +152 -0
  18. meshwire-0.5.0a1/addon/blender_mcp_addon/compat.py +262 -0
  19. meshwire-0.5.0a1/addon/blender_mcp_addon/external/__init__.py +1 -0
  20. meshwire-0.5.0a1/addon/blender_mcp_addon/external/ai_backends/__init__.py +580 -0
  21. meshwire-0.5.0a1/addon/blender_mcp_addon/external/ai_backends/base.py +274 -0
  22. meshwire-0.5.0a1/addon/blender_mcp_addon/external/ai_backends/comfyui.py +672 -0
  23. meshwire-0.5.0a1/addon/blender_mcp_addon/external/ai_backends/hunyuan3d.py +543 -0
  24. meshwire-0.5.0a1/addon/blender_mcp_addon/external/ai_backends/meshy.py +272 -0
  25. meshwire-0.5.0a1/addon/blender_mcp_addon/external/ai_backends/multiview.py +151 -0
  26. meshwire-0.5.0a1/addon/blender_mcp_addon/external/ai_backends/ollama_vision.py +486 -0
  27. meshwire-0.5.0a1/addon/blender_mcp_addon/external/ai_backends/rodin.py +540 -0
  28. meshwire-0.5.0a1/addon/blender_mcp_addon/external/ai_backends/stable_fast_3d.py +151 -0
  29. meshwire-0.5.0a1/addon/blender_mcp_addon/external/ai_backends/tripo_ai.py +186 -0
  30. meshwire-0.5.0a1/addon/blender_mcp_addon/external/ai_backends/triposg.py +145 -0
  31. meshwire-0.5.0a1/addon/blender_mcp_addon/external/ai_backends/triposr.py +541 -0
  32. meshwire-0.5.0a1/addon/blender_mcp_addon/external/ai_backends/workflows/controlnet_texture.json +92 -0
  33. meshwire-0.5.0a1/addon/blender_mcp_addon/external/ai_backends/workflows/inpaint.json +87 -0
  34. meshwire-0.5.0a1/addon/blender_mcp_addon/external/ai_backends/workflows/multiview_to_3d.json +110 -0
  35. meshwire-0.5.0a1/addon/blender_mcp_addon/external/ai_backends/workflows/pbr_texture.json +97 -0
  36. meshwire-0.5.0a1/addon/blender_mcp_addon/external/ai_backends/workflows/reference_image.json +68 -0
  37. meshwire-0.5.0a1/addon/blender_mcp_addon/external/ai_backends/workflows/stable_fast_3d.json +32 -0
  38. meshwire-0.5.0a1/addon/blender_mcp_addon/external/ai_backends/workflows/triposg.json +84 -0
  39. meshwire-0.5.0a1/addon/blender_mcp_addon/external/ai_models.py +911 -0
  40. meshwire-0.5.0a1/addon/blender_mcp_addon/external/cache.py +356 -0
  41. meshwire-0.5.0a1/addon/blender_mcp_addon/external/job_queue.py +553 -0
  42. meshwire-0.5.0a1/addon/blender_mcp_addon/external/mesh_processing.py +781 -0
  43. meshwire-0.5.0a1/addon/blender_mcp_addon/external/pipeline.py +393 -0
  44. meshwire-0.5.0a1/addon/blender_mcp_addon/external/polyhaven.py +598 -0
  45. meshwire-0.5.0a1/addon/blender_mcp_addon/external/refinement.py +107 -0
  46. meshwire-0.5.0a1/addon/blender_mcp_addon/external/texture_applicator.py +136 -0
  47. meshwire-0.5.0a1/addon/blender_mcp_addon/handlers/__init__.py +377 -0
  48. meshwire-0.5.0a1/addon/blender_mcp_addon/handlers/_helpers.py +1050 -0
  49. meshwire-0.5.0a1/addon/blender_mcp_addon/handlers/ai.py +943 -0
  50. meshwire-0.5.0a1/addon/blender_mcp_addon/handlers/animation.py +134 -0
  51. meshwire-0.5.0a1/addon/blender_mcp_addon/handlers/annotations.py +453 -0
  52. meshwire-0.5.0a1/addon/blender_mcp_addon/handlers/armature.py +1253 -0
  53. meshwire-0.5.0a1/addon/blender_mcp_addon/handlers/baking.py +949 -0
  54. meshwire-0.5.0a1/addon/blender_mcp_addon/handlers/collections.py +368 -0
  55. meshwire-0.5.0a1/addon/blender_mcp_addon/handlers/export_import.py +215 -0
  56. meshwire-0.5.0a1/addon/blender_mcp_addon/handlers/geonodes.py +807 -0
  57. meshwire-0.5.0a1/addon/blender_mcp_addon/handlers/materials.py +697 -0
  58. meshwire-0.5.0a1/addon/blender_mcp_addon/handlers/measurement.py +966 -0
  59. meshwire-0.5.0a1/addon/blender_mcp_addon/handlers/mesh_editing.py +2632 -0
  60. meshwire-0.5.0a1/addon/blender_mcp_addon/handlers/modifiers.py +163 -0
  61. meshwire-0.5.0a1/addon/blender_mcp_addon/handlers/msfs.py +397 -0
  62. meshwire-0.5.0a1/addon/blender_mcp_addon/handlers/objects.py +277 -0
  63. meshwire-0.5.0a1/addon/blender_mcp_addon/handlers/physics.py +490 -0
  64. meshwire-0.5.0a1/addon/blender_mcp_addon/handlers/render.py +251 -0
  65. meshwire-0.5.0a1/addon/blender_mcp_addon/handlers/scene.py +59 -0
  66. meshwire-0.5.0a1/addon/blender_mcp_addon/handlers/sculpt.py +712 -0
  67. meshwire-0.5.0a1/addon/blender_mcp_addon/msfs/__init__.py +108 -0
  68. meshwire-0.5.0a1/addon/blender_mcp_addon/msfs/animation.py +397 -0
  69. meshwire-0.5.0a1/addon/blender_mcp_addon/msfs/collision.py +328 -0
  70. meshwire-0.5.0a1/addon/blender_mcp_addon/msfs/export.py +418 -0
  71. meshwire-0.5.0a1/addon/blender_mcp_addon/msfs/livery/__init__.py +53 -0
  72. meshwire-0.5.0a1/addon/blender_mcp_addon/msfs/livery/export.py +536 -0
  73. meshwire-0.5.0a1/addon/blender_mcp_addon/msfs/livery/painting.py +537 -0
  74. meshwire-0.5.0a1/addon/blender_mcp_addon/msfs/livery/templates.py +325 -0
  75. meshwire-0.5.0a1/addon/blender_mcp_addon/msfs/livery/transfer.py +599 -0
  76. meshwire-0.5.0a1/addon/blender_mcp_addon/msfs/lod.py +282 -0
  77. meshwire-0.5.0a1/addon/blender_mcp_addon/msfs/materials.py +383 -0
  78. meshwire-0.5.0a1/addon/blender_mcp_addon/socket_server.py +223 -0
  79. meshwire-0.5.0a1/addon/blender_mcp_addon/utils.py +175 -0
  80. meshwire-0.5.0a1/addon/blender_mcp_addon/validation.py +200 -0
  81. meshwire-0.5.0a1/assets/logo.svg +19 -0
  82. meshwire-0.5.0a1/build-constraints.txt +93 -0
  83. meshwire-0.5.0a1/deploy/comfyui/custom_nodes.txt +11 -0
  84. meshwire-0.5.0a1/deploy/comfyui/docker-compose.yml +44 -0
  85. meshwire-0.5.0a1/deploy/comfyui/download_models.sh +105 -0
  86. meshwire-0.5.0a1/docs/MSFS_ROADMAP.md +498 -0
  87. meshwire-0.5.0a1/docs/architecture.md +82 -0
  88. meshwire-0.5.0a1/docs/index.md +55 -0
  89. meshwire-0.5.0a1/docs/tools.md +253 -0
  90. meshwire-0.5.0a1/docs/usage.md +163 -0
  91. meshwire-0.5.0a1/pyproject.toml +71 -0
  92. meshwire-0.5.0a1/scripts/fetch_blender.py +100 -0
  93. meshwire-0.5.0a1/scripts/package_addon.py +105 -0
  94. meshwire-0.5.0a1/src/mcp_blender/__init__.py +3 -0
  95. meshwire-0.5.0a1/src/mcp_blender/blender_client.py +248 -0
  96. meshwire-0.5.0a1/src/mcp_blender/py.typed +0 -0
  97. meshwire-0.5.0a1/src/mcp_blender/server.py +5766 -0
  98. meshwire-0.5.0a1/src/mcp_blender/tools/__init__.py +21 -0
  99. meshwire-0.5.0a1/src/mcp_blender/tools/animation.py +75 -0
  100. meshwire-0.5.0a1/src/mcp_blender/tools/export.py +80 -0
  101. meshwire-0.5.0a1/src/mcp_blender/tools/external.py +550 -0
  102. meshwire-0.5.0a1/src/mcp_blender/tools/materials.py +96 -0
  103. meshwire-0.5.0a1/src/mcp_blender/tools/modifiers.py +66 -0
  104. meshwire-0.5.0a1/src/mcp_blender/tools/objects.py +136 -0
  105. meshwire-0.5.0a1/src/mcp_blender/tools/render.py +74 -0
  106. meshwire-0.5.0a1/src/mcp_blender/tools/scene.py +56 -0
  107. meshwire-0.5.0a1/src/mcp_blender/types.py +106 -0
  108. meshwire-0.5.0a1/tests/__init__.py +1 -0
  109. meshwire-0.5.0a1/tests/blender_integration_test.py +544 -0
  110. meshwire-0.5.0a1/tests/harness/__init__.py +0 -0
  111. meshwire-0.5.0a1/tests/harness/assets.py +88 -0
  112. meshwire-0.5.0a1/tests/harness/baselines/blender-4.2.json +831 -0
  113. meshwire-0.5.0a1/tests/harness/baselines/blender-4.5.json +831 -0
  114. meshwire-0.5.0a1/tests/harness/baselines/blender-5.2.json +831 -0
  115. meshwire-0.5.0a1/tests/harness/baselines/socket-lane.json +20 -0
  116. meshwire-0.5.0a1/tests/harness/cases.py +64 -0
  117. meshwire-0.5.0a1/tests/harness/catalog.py +15 -0
  118. meshwire-0.5.0a1/tests/harness/classify.py +39 -0
  119. meshwire-0.5.0a1/tests/harness/driver.py +252 -0
  120. meshwire-0.5.0a1/tests/harness/fixtures.py +200 -0
  121. meshwire-0.5.0a1/tests/harness/runner.py +110 -0
  122. meshwire-0.5.0a1/tests/harness/scene.py +114 -0
  123. meshwire-0.5.0a1/tests/harness/socket_boot.py +75 -0
  124. meshwire-0.5.0a1/tests/harness/socket_lane.py +645 -0
  125. meshwire-0.5.0a1/tests/static_gate_baseline.json +121 -0
  126. meshwire-0.5.0a1/tests/test_client.py +192 -0
  127. meshwire-0.5.0a1/tests/test_comfyui_workflows.py +171 -0
  128. meshwire-0.5.0a1/tests/test_compat.py +79 -0
  129. meshwire-0.5.0a1/tests/test_harness_driver.py +236 -0
  130. meshwire-0.5.0a1/tests/test_harness_socket_lane.py +333 -0
  131. meshwire-0.5.0a1/tests/test_harness_unit.py +357 -0
  132. meshwire-0.5.0a1/tests/test_readme.py +12 -0
  133. meshwire-0.5.0a1/tests/test_server.py +209 -0
  134. meshwire-0.5.0a1/tests/test_static_gates.py +694 -0
  135. meshwire-0.5.0a1/tests/test_tools.py +271 -0
  136. meshwire-0.5.0a1/tests/test_version.py +51 -0
  137. meshwire-0.5.0a1/uv.lock +962 -0
@@ -0,0 +1,24 @@
1
+ # EditorConfig helps maintain consistent coding styles
2
+ # https://editorconfig.org
3
+
4
+ root = true
5
+
6
+ [*]
7
+ indent_style = space
8
+ indent_size = 4
9
+ end_of_line = lf
10
+ charset = utf-8
11
+ trim_trailing_whitespace = true
12
+ insert_final_newline = true
13
+
14
+ [*.py]
15
+ max_line_length = 100
16
+
17
+ [*.md]
18
+ trim_trailing_whitespace = false
19
+
20
+ [*.{json,yaml,yml,toml}]
21
+ indent_size = 2
22
+
23
+ [Makefile]
24
+ indent_style = tab
@@ -0,0 +1,77 @@
1
+ name: Bug Report
2
+ description: Report a bug or unexpected behavior
3
+ title: "[Bug]: "
4
+ labels: ["bug"]
5
+ body:
6
+ - type: markdown
7
+ attributes:
8
+ value: |
9
+ Thanks for reporting! Please fill out the details below.
10
+ - type: input
11
+ id: blender-version
12
+ attributes:
13
+ label: Blender Version
14
+ description: "e.g., 4.2.19 LTS, 5.0"
15
+ placeholder: "4.2.19"
16
+ validations:
17
+ required: true
18
+ - type: input
19
+ id: mcp-version
20
+ attributes:
21
+ label: MCP Server Version
22
+ description: "e.g., 0.2.0"
23
+ placeholder: "0.2.0"
24
+ validations:
25
+ required: true
26
+ - type: input
27
+ id: tool-name
28
+ attributes:
29
+ label: Tool Name
30
+ description: "Which MCP tool is affected? e.g., blender_object_create"
31
+ placeholder: "blender_"
32
+ - type: textarea
33
+ id: description
34
+ attributes:
35
+ label: Description
36
+ description: What happened? What did you expect to happen?
37
+ validations:
38
+ required: true
39
+ - type: textarea
40
+ id: steps
41
+ attributes:
42
+ label: Steps to Reproduce
43
+ description: Minimal steps to reproduce the issue
44
+ value: |
45
+ 1.
46
+ 2.
47
+ 3.
48
+ validations:
49
+ required: true
50
+ - type: textarea
51
+ id: error
52
+ attributes:
53
+ label: Error Output
54
+ description: Paste any error messages or logs
55
+ render: shell
56
+ - type: dropdown
57
+ id: os
58
+ attributes:
59
+ label: Operating System
60
+ options:
61
+ - Windows
62
+ - macOS
63
+ - Linux
64
+ validations:
65
+ required: true
66
+ - type: dropdown
67
+ id: mcp-client
68
+ attributes:
69
+ label: MCP Client
70
+ options:
71
+ - Claude Desktop
72
+ - Claude Code
73
+ - Cursor
74
+ - VS Code + Continue
75
+ - Other
76
+ validations:
77
+ required: true
@@ -0,0 +1,54 @@
1
+ name: Feature Request
2
+ description: Suggest a new tool or enhancement
3
+ title: "[Feature]: "
4
+ labels: ["enhancement"]
5
+ body:
6
+ - type: markdown
7
+ attributes:
8
+ value: |
9
+ Thanks for suggesting an improvement! Please describe what you'd like.
10
+ - type: dropdown
11
+ id: category
12
+ attributes:
13
+ label: Tool Category
14
+ description: Which area does this feature relate to?
15
+ options:
16
+ - Scene / Object Management
17
+ - Modeling / Mesh Editing
18
+ - Materials / Shaders
19
+ - Sculpting
20
+ - Rigging / Armature
21
+ - Animation
22
+ - Rendering
23
+ - Baking
24
+ - Geometry Nodes
25
+ - Physics Simulation
26
+ - Export / Import
27
+ - AI Generation Pipeline
28
+ - MSFS Content Creation
29
+ - Livery System
30
+ - Measurement / Validation
31
+ - Collections / System
32
+ - Annotations
33
+ - Other
34
+ validations:
35
+ required: true
36
+ - type: textarea
37
+ id: description
38
+ attributes:
39
+ label: Description
40
+ description: Describe the feature or tool you'd like to see
41
+ validations:
42
+ required: true
43
+ - type: textarea
44
+ id: use-case
45
+ attributes:
46
+ label: Use Case
47
+ description: How would you use this? What workflow does it enable?
48
+ validations:
49
+ required: true
50
+ - type: textarea
51
+ id: alternatives
52
+ attributes:
53
+ label: Alternatives Considered
54
+ description: Any workarounds you've tried (e.g., using execute_script)
@@ -0,0 +1,31 @@
1
+ ## Summary
2
+
3
+ Brief description of what this PR does.
4
+
5
+ ## Changes
6
+
7
+ -
8
+
9
+ ## Tool Changes
10
+
11
+ - [ ] New tools added (update tool count in test_server.py)
12
+ - [ ] Existing tools modified
13
+ - [ ] Handler registrations added in `addon/blender_mcp_addon/handlers/`
14
+ - [ ] Handler implementations added
15
+
16
+ ## Testing
17
+
18
+ - [ ] `pytest tests/ --ignore=tests/blender_integration_test.py` passes
19
+ - [ ] Truth harness baselines updated if any tool result class changed (see CONTRIBUTING.md)
20
+ - [ ] `ruff check .` passes
21
+ - [ ] Tested with Blender (version: )
22
+ - [ ] Tested via MCP client (client: )
23
+
24
+ ## Checklist
25
+
26
+ - [ ] Tool definitions use `"type": "number"` (not `"integer"`) for numeric params
27
+ - [ ] Handler returns `{"success": True, ...}` or `{"error": "..."}`
28
+ - [ ] README updated if new tools added
29
+ - [ ] CHANGELOG updated
30
+
31
+ - [ ] I have read and agree to [CLA.md](../CLA.md) for this contribution.
@@ -0,0 +1,19 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: uv
4
+ directory: /
5
+ schedule:
6
+ interval: weekly
7
+ open-pull-requests-limit: 2
8
+ groups:
9
+ python-minor-patch:
10
+ update-types: [minor, patch]
11
+
12
+ - package-ecosystem: github-actions
13
+ directory: /
14
+ schedule:
15
+ interval: weekly
16
+ open-pull-requests-limit: 2
17
+ groups:
18
+ actions-minor-patch:
19
+ update-types: [minor, patch]
@@ -0,0 +1,162 @@
1
+ name: Blender harness
2
+
3
+ on:
4
+ pull_request:
5
+ branches: [main]
6
+ push:
7
+ branches: [main]
8
+ schedule:
9
+ - cron: "17 4 * * *"
10
+ workflow_dispatch:
11
+
12
+ permissions:
13
+ contents: read
14
+
15
+ concurrency:
16
+ group: blender-${{ github.event_name }}-${{ github.event_name == 'pull_request' && github.ref || github.run_id }}
17
+ cancel-in-progress: ${{ github.event_name == 'pull_request' }}
18
+
19
+ env:
20
+ BLENDER_DEPS: >-
21
+ xvfb xauth libgl1 libegl1 libglx-mesa0 libgl1-mesa-dri libxi6 libxxf86vm1
22
+ libxfixes3 libxrender1 libxkbcommon0 libsm6 libice6 libxkbcommon-x11-0 libdbus-1-3
23
+
24
+ jobs:
25
+ # Gated: an unrecorded behavior change on a supported Blender fails the run.
26
+ gated:
27
+ name: Blender ${{ matrix.version }}
28
+ runs-on: ubuntu-24.04
29
+ timeout-minutes: 45
30
+ strategy:
31
+ fail-fast: false
32
+ matrix:
33
+ include:
34
+ - version: "4.5.15"
35
+ series: "4.5"
36
+ - version: "5.2.3"
37
+ series: "5.2"
38
+ steps:
39
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
40
+ with:
41
+ persist-credentials: false
42
+
43
+ - uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
44
+
45
+ - name: Install system libraries
46
+ run: |
47
+ sudo apt-get update
48
+ # shellcheck disable=SC2086
49
+ sudo apt-get install -y --no-install-recommends $BLENDER_DEPS
50
+
51
+ # Only the tarball is cached. fetch_blender.py re-checks its sha256 on
52
+ # every use, so a poisoned cache entry is rejected.
53
+ - name: Cache Blender tarball
54
+ uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
55
+ with:
56
+ path: ~/.cache/meshwire/*.tar.xz
57
+ key: blender-${{ matrix.version }}-${{ hashFiles('scripts/fetch_blender.py') }}
58
+
59
+ - name: Install test dependencies
60
+ run: uv sync --locked --extra dev --python 3.12
61
+
62
+ - name: Fetch Blender
63
+ id: fetch
64
+ run: |
65
+ set -e
66
+ bin="$(uv run --locked --python 3.12 python scripts/fetch_blender.py ${{ matrix.version }} --dest "$RUNNER_TEMP/blender")"
67
+ test -x "$bin"
68
+ echo "bin=$bin" >> "$GITHUB_OUTPUT"
69
+
70
+ - name: Run harness driver
71
+ env:
72
+ BLENDER_BIN: ${{ steps.fetch.outputs.bin }}
73
+ run: >-
74
+ xvfb-run -a uv run --locked --python 3.12 python -m tests.harness.driver
75
+ --blender "$BLENDER_BIN"
76
+ --out "$RUNNER_TEMP/runs/driver-${{ matrix.series }}"
77
+ --check-baseline tests/harness/baselines/blender-${{ matrix.series }}.json
78
+
79
+ # Runs even when the driver step failed so one failure does not hide the
80
+ # other. The failed driver step still fails the job.
81
+ - name: Run socket lane
82
+ if: ${{ !cancelled() && steps.fetch.outcome == 'success' }}
83
+ env:
84
+ BLENDER_BIN: ${{ steps.fetch.outputs.bin }}
85
+ run: >-
86
+ xvfb-run -a uv run --locked --python 3.12 python -m tests.harness.socket_lane
87
+ --blender "$BLENDER_BIN"
88
+ --out "$RUNNER_TEMP/runs/socket-${{ matrix.series }}"
89
+ --check-baseline tests/harness/baselines/socket-lane.json
90
+
91
+ - name: Upload results
92
+ if: always()
93
+ uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
94
+ with:
95
+ name: harness-${{ matrix.version }}
96
+ path: |
97
+ ${{ runner.temp }}/runs
98
+ !${{ runner.temp }}/runs/**/*.blend
99
+ !${{ runner.temp }}/runs/**/*.blend1
100
+ !${{ runner.temp }}/runs/**/tmp/**
101
+ if-no-files-found: ignore
102
+ retention-days: 14
103
+
104
+ # Best effort: 4.2 segfaults at random inside Blender in two cases. Its
105
+ # result never gates anything and nothing may depend on this job.
106
+ nightly-4-2:
107
+ name: Blender 4.2.23 (best effort)
108
+ if: ${{ github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' }}
109
+ runs-on: ubuntu-24.04
110
+ timeout-minutes: 60
111
+ continue-on-error: true
112
+ steps:
113
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
114
+ with:
115
+ persist-credentials: false
116
+
117
+ - uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
118
+
119
+ - name: Install system libraries
120
+ run: |
121
+ sudo apt-get update
122
+ # shellcheck disable=SC2086
123
+ sudo apt-get install -y --no-install-recommends $BLENDER_DEPS
124
+
125
+ - name: Cache Blender tarball
126
+ uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
127
+ with:
128
+ path: ~/.cache/meshwire/*.tar.xz
129
+ key: blender-4.2.23-${{ hashFiles('scripts/fetch_blender.py') }}
130
+
131
+ - name: Install test dependencies
132
+ run: uv sync --locked --extra dev --python 3.12
133
+
134
+ - name: Fetch Blender
135
+ id: fetch
136
+ run: |
137
+ set -e
138
+ bin="$(uv run --locked --python 3.12 python scripts/fetch_blender.py 4.2.23 --dest "$RUNNER_TEMP/blender")"
139
+ test -x "$bin"
140
+ echo "bin=$bin" >> "$GITHUB_OUTPUT"
141
+
142
+ - name: Run harness driver
143
+ env:
144
+ BLENDER_BIN: ${{ steps.fetch.outputs.bin }}
145
+ run: >-
146
+ xvfb-run -a uv run --locked --python 3.12 python -m tests.harness.driver
147
+ --blender "$BLENDER_BIN"
148
+ --out "$RUNNER_TEMP/runs/driver-4.2"
149
+ --check-baseline tests/harness/baselines/blender-4.2.json
150
+
151
+ - name: Upload results
152
+ if: always()
153
+ uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
154
+ with:
155
+ name: harness-4.2.23
156
+ path: |
157
+ ${{ runner.temp }}/runs
158
+ !${{ runner.temp }}/runs/**/*.blend
159
+ !${{ runner.temp }}/runs/**/*.blend1
160
+ !${{ runner.temp }}/runs/**/tmp/**
161
+ if-no-files-found: ignore
162
+ retention-days: 14
@@ -0,0 +1,71 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ permissions:
10
+ contents: read
11
+
12
+ concurrency:
13
+ group: ci-${{ github.event_name }}-${{ github.event_name == 'pull_request' && github.ref || github.run_id }}
14
+ cancel-in-progress: ${{ github.event_name == 'pull_request' }}
15
+
16
+ jobs:
17
+ lint:
18
+ runs-on: ubuntu-latest
19
+ steps:
20
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
21
+ with:
22
+ persist-credentials: false
23
+
24
+ - uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
25
+
26
+ - name: Run Ruff
27
+ run: uv run --locked --extra dev --python 3.11 ruff check .
28
+
29
+ test:
30
+ runs-on: ubuntu-latest
31
+ strategy:
32
+ matrix:
33
+ python-version: ["3.10", "3.11", "3.12"]
34
+
35
+ steps:
36
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
37
+ with:
38
+ persist-credentials: false
39
+
40
+ - uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
41
+
42
+ - name: Install dependencies
43
+ run: uv sync --locked --extra dev --python ${{ matrix.python-version }}
44
+
45
+ - name: Run unit tests
46
+ run: uv run --locked --extra dev --python ${{ matrix.python-version }} pytest tests/ --ignore=tests/blender_integration_test.py -v
47
+
48
+ build:
49
+ runs-on: ubuntu-latest
50
+ needs: [lint, test]
51
+ steps:
52
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
53
+ with:
54
+ persist-credentials: false
55
+
56
+ - uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
57
+
58
+ - name: Build package
59
+ run: uv build --build-constraint build-constraints.txt --require-hashes
60
+
61
+ - name: Build addon ZIP
62
+ run: uv run --locked --python 3.11 python scripts/package_addon.py
63
+
64
+ - name: Upload artifacts
65
+ uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
66
+ with:
67
+ name: dist
68
+ path: |
69
+ dist/*.whl
70
+ dist/*.tar.gz
71
+ dist/*.zip
@@ -0,0 +1,33 @@
1
+ name: CodeQL
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+ schedule:
9
+ - cron: "31 5 * * 1"
10
+
11
+ permissions:
12
+ contents: read
13
+
14
+ jobs:
15
+ analyze:
16
+ runs-on: ubuntu-latest
17
+ timeout-minutes: 30
18
+ permissions:
19
+ contents: read
20
+ security-events: write
21
+ steps:
22
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
23
+ with:
24
+ persist-credentials: false
25
+
26
+ - uses: github/codeql-action/init@9b3254085494b55a0f7c4c2b3d2d52cc712ce370 # v4.39.1
27
+ with:
28
+ languages: python
29
+ build-mode: none
30
+
31
+ - uses: github/codeql-action/analyze@9b3254085494b55a0f7c4c2b3d2d52cc712ce370 # v4.39.1
32
+ with:
33
+ category: "/language:python"
@@ -0,0 +1,119 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+
8
+ permissions:
9
+ contents: read
10
+
11
+ jobs:
12
+ build:
13
+ runs-on: ubuntu-24.04
14
+ timeout-minutes: 15
15
+ steps:
16
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
17
+ with:
18
+ fetch-depth: 0
19
+ persist-credentials: false
20
+
21
+ - uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
22
+ with:
23
+ version: "0.13.6"
24
+
25
+ # PyPI never lets a version be reused, so catch mistakes here. This check and the version
26
+ # check below are not a security boundary, because a tagged commit can edit this file. The
27
+ # repository's tag ruleset and the pypi environment's tag policy restrict publishing.
28
+ - name: Refuse a tag that is not on main
29
+ run: git merge-base --is-ancestor "$GITHUB_SHA" origin/main
30
+
31
+ # No unlocked code runs from here to the upload: uv.lock pins dependencies with hashes,
32
+ # build-constraints.txt does the same for the build backend, and --no-build rules out any
33
+ # dependency's own build step. Keep it that way, because this job produces what gets published.
34
+ - name: Install locked dependencies
35
+ run: uv sync --locked --no-install-project --no-build --extra dev --python 3.12
36
+
37
+ - name: Run tests
38
+ env:
39
+ PYTHONPATH: src
40
+ run: .venv/bin/python -m pytest tests/ --ignore=tests/blender_integration_test.py -q
41
+
42
+ - name: Build package
43
+ run: uv build --build-constraint build-constraints.txt --require-hashes
44
+
45
+ - name: Refuse a tag that does not match the package version
46
+ run: test -f "dist/meshwire-${GITHUB_REF_NAME#v}-py3-none-any.whl"
47
+
48
+ - name: Run the built wheel
49
+ run: |
50
+ uv pip install --no-deps "dist/meshwire-${GITHUB_REF_NAME#v}-py3-none-any.whl"
51
+ actual="$(.venv/bin/meshwire --version)"
52
+ test "$actual" = "meshwire ${GITHUB_REF_NAME#v}"
53
+
54
+ # Built outside dist/: the PyPI action uploads everything in that folder.
55
+ - name: Build addon ZIP
56
+ run: |
57
+ mkdir addon-zip
58
+ .venv/bin/python scripts/package_addon.py
59
+ mv dist/*.zip addon-zip/
60
+
61
+ - name: Upload package
62
+ uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
63
+ with:
64
+ name: dist
65
+ path: dist/
66
+ if-no-files-found: error
67
+
68
+ - name: Upload addon ZIP
69
+ uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
70
+ with:
71
+ name: addon-zip
72
+ path: addon-zip/
73
+ if-no-files-found: error
74
+
75
+ publish:
76
+ needs: build
77
+ runs-on: ubuntu-24.04
78
+ timeout-minutes: 15
79
+ environment:
80
+ name: pypi
81
+ url: https://pypi.org/p/meshwire
82
+ permissions:
83
+ id-token: write
84
+ steps:
85
+ - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
86
+ with:
87
+ name: dist
88
+ path: dist
89
+
90
+ - name: Publish to PyPI
91
+ uses: pypa/gh-action-pypi-publish@7245906fb61fa33a13554f9d5fb856fe61758086 # v1.14.3
92
+
93
+ github-release:
94
+ needs: publish
95
+ runs-on: ubuntu-24.04
96
+ timeout-minutes: 15
97
+ permissions:
98
+ contents: write
99
+ steps:
100
+ - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
101
+ with:
102
+ name: dist
103
+ path: dist
104
+
105
+ - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
106
+ with:
107
+ name: addon-zip
108
+ path: addon-zip
109
+
110
+ - name: Create the GitHub release
111
+ env:
112
+ GH_TOKEN: ${{ github.token }}
113
+ GH_REPO: ${{ github.repository }}
114
+ run: |
115
+ flags=""
116
+ case "$GITHUB_REF_NAME" in
117
+ *a*|*b*|*rc*) flags="--prerelease" ;;
118
+ esac
119
+ gh release create "$GITHUB_REF_NAME" --verify-tag --generate-notes $flags dist/* addon-zip/*
@@ -0,0 +1,99 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ .Python
7
+ build/
8
+ develop-eggs/
9
+ dist/
10
+ downloads/
11
+ eggs/
12
+ .eggs/
13
+ lib/
14
+ lib64/
15
+ parts/
16
+ sdist/
17
+ var/
18
+ wheels/
19
+ *.egg-info/
20
+ .installed.cfg
21
+ *.egg
22
+ *.whl
23
+
24
+ # Virtual environments
25
+ .venv/
26
+ venv/
27
+ ENV/
28
+ env/
29
+
30
+ # IDE
31
+ .idea/
32
+ .vscode/
33
+ *.swp
34
+ *.swo
35
+ *~
36
+
37
+ # Testing
38
+ .pytest_cache/
39
+ .coverage
40
+ htmlcov/
41
+ .tox/
42
+ .nox/
43
+
44
+ # OS
45
+ .DS_Store
46
+ Thumbs.db
47
+ Desktop.ini
48
+ ._*
49
+
50
+ # Blender
51
+ *.blend1
52
+ *.blend2
53
+
54
+ # Assets: keep only banner.svg for README, ignore everything else
55
+ # (renders, screenshots, reference images, 3D models, blend files)
56
+ assets/*.png
57
+ assets/*.jpg
58
+ assets/*.jpeg
59
+ assets/*.glb
60
+ assets/*.gltf
61
+ assets/*.fbx
62
+ assets/*.obj
63
+ assets/*.stl
64
+ assets/*.usd
65
+ assets/*.blend
66
+ assets/*.py
67
+ assets/generated/
68
+
69
+ # Exports
70
+ exports/
71
+
72
+ # Build artifacts
73
+ *.zip
74
+ *.tar.gz
75
+
76
+ # Generated tool files (used during development)
77
+ new_tools/
78
+
79
+ # Environment and secrets
80
+ .env
81
+ .env.*
82
+ *.key
83
+ *.pem
84
+ credentials.*
85
+
86
+ # Logs
87
+ *.log
88
+
89
+ # Claude/MCP local config
90
+ .claude/
91
+ tasks/
92
+ runs/
93
+
94
+ # CAD/design files
95
+ *.kicad_pcb
96
+ *.brd
97
+ *.step
98
+ *.stp
99
+ .ip-denylist