mirror of
https://github.com/jdegenstein/jmwright-CQ-Editor.git
synced 2025-12-20 14:37:04 +01:00
Compare commits
67 Commits
dev
...
mactrackpa
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
524a8dd6fd | ||
|
|
bd12503e81 | ||
|
|
2ba23c4659 | ||
|
|
ee6a60705c | ||
|
|
a144b2e60a | ||
|
|
7b49f25f94 | ||
|
|
2b3620b759 | ||
|
|
afa20cd715 | ||
|
|
2d7fbeb08d | ||
|
|
ecaf68edac | ||
|
|
69d6bc368e | ||
|
|
dbc90c2724 | ||
|
|
fbbb1fd7b6 | ||
|
|
73a5825f3f | ||
|
|
fefb57c2b9 | ||
|
|
5e0d68e2ad | ||
|
|
7c8fa2b100 | ||
|
|
925aded53c | ||
|
|
973448697a | ||
|
|
c5e0d73422 | ||
|
|
a7a376f9f5 | ||
|
|
e436bd3d7e | ||
|
|
26b64607a5 | ||
|
|
000fe986e0 | ||
|
|
acf5639e76 | ||
|
|
ebcb831ca9 | ||
|
|
fd47eadcdc | ||
|
|
67fa19704e | ||
|
|
272bede28f | ||
|
|
9f4fa50c7c | ||
|
|
03e8575210 | ||
|
|
0087803ee4 | ||
|
|
72e814db3b | ||
|
|
466d1e7534 | ||
|
|
3f3e22c2f1 | ||
|
|
aa90e48968 | ||
|
|
0e29e3091b | ||
|
|
66e620a877 | ||
|
|
14535ec7a4 | ||
|
|
ee09398909 | ||
|
|
10a81d4e12 | ||
|
|
ca706045ba | ||
|
|
ce68e6e120 | ||
|
|
839d514f66 | ||
|
|
36f2896652 | ||
|
|
36f23a4d7e | ||
|
|
c85c8358f5 | ||
|
|
de73e88033 | ||
|
|
be62509ba7 | ||
|
|
b0284ac80c | ||
|
|
2d7cb64247 | ||
|
|
5b474bb493 | ||
|
|
0818537f34 | ||
|
|
cf7253ebe7 | ||
|
|
4a6e9a1cc3 | ||
|
|
22c3d3a37b | ||
|
|
dfb79aa306 | ||
|
|
3ac6e93a5e | ||
|
|
621e0dc86b | ||
|
|
3764233ed7 | ||
|
|
6e26bdb7fc | ||
|
|
5fd737ab50 | ||
|
|
cfb952047f | ||
|
|
974fd51f88 | ||
|
|
6bd2148257 | ||
|
|
39bb40289f | ||
|
|
02453f7823 |
126
.github/workflows/pyinstaller-builds-actions-PIP-TAR.yml
vendored
Normal file
126
.github/workflows/pyinstaller-builds-actions-PIP-TAR.yml
vendored
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
name: build-PIP-TAR
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 0 * * 1'
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
type:
|
||||||
|
description: 'Whether to build a single file (onefile) or directory (dir) dist'
|
||||||
|
required: true
|
||||||
|
default: 'dir'
|
||||||
|
jobs:
|
||||||
|
build-linux:
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: mamba-org/provision-with-micromamba@main
|
||||||
|
with:
|
||||||
|
#miniconda-version: "latest"
|
||||||
|
#auto-update-conda: true
|
||||||
|
environment-name: test
|
||||||
|
environment-file: environment.yml
|
||||||
|
extra-specs:
|
||||||
|
python=3.9
|
||||||
|
- name: Mamba install CadQuery and pyinstaller
|
||||||
|
shell: bash --login {0}
|
||||||
|
run: |
|
||||||
|
sudo apt install -y libblas-dev libblas3 libblas64-3 libblas64-dev
|
||||||
|
sudo apt install -y libxkbcommon0
|
||||||
|
sudo apt install -y libxkbcommon-x11-0
|
||||||
|
sudo apt install -y libxcb-xinerama0
|
||||||
|
micromamba info
|
||||||
|
pip install git+https://github.com/jdegenstein/jmwright-CQ-Editor
|
||||||
|
pip install -vvv --pre git+https://github.com/cadquery/cadquery casadi==3.5.5
|
||||||
|
pip install pyinstaller==4.10
|
||||||
|
pip install path
|
||||||
|
pip install git+https://github.com/gumyr/cq_warehouse.git#egg=cq_warehouse
|
||||||
|
pip install git+https://github.com/meadiode/cq_gears.git@main
|
||||||
|
pip install -e "git+https://github.com/CadQuery/cadquery-plugins.git#egg=cq_cache&subdirectory=plugins/cq_cache"
|
||||||
|
pip install git+https://github.com/gumyr/build123d.git#egg=build123d
|
||||||
|
pip install git+https://github.com/JustinSDK/cqMore
|
||||||
|
pip list
|
||||||
|
- name: Run build
|
||||||
|
shell: bash --login {0}
|
||||||
|
run: |
|
||||||
|
micromamba info
|
||||||
|
pyinstaller pyinstaller_pip.spec ${{ github.event.inputs.type }}
|
||||||
|
cp /home/runner/work/jmwright-CQ-Editor/jmwright-CQ-Editor/pyinstaller/CQ-editor.sh /home/runner/work/jmwright-CQ-Editor/jmwright-CQ-Editor/dist/
|
||||||
|
- uses: alehechka/upload-tartifact@v1
|
||||||
|
with:
|
||||||
|
name: CQ-editor-Linux-x86_64
|
||||||
|
path: dist
|
||||||
|
build-macos:
|
||||||
|
runs-on: macos-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: mamba-org/provision-with-micromamba@main
|
||||||
|
with:
|
||||||
|
#miniconda-version: "latest"
|
||||||
|
#auto-update-conda: true
|
||||||
|
environment-name: test
|
||||||
|
environment-file: environment.yml
|
||||||
|
extra-specs:
|
||||||
|
python=3.9
|
||||||
|
- name: Mamba install CadQuery and pyinstaller
|
||||||
|
shell: bash --login {0}
|
||||||
|
run: |
|
||||||
|
micromamba info
|
||||||
|
pip install git+https://github.com/jdegenstein/jmwright-CQ-Editor
|
||||||
|
pip install --pre git+https://github.com/cadquery/cadquery casadi==3.5.5
|
||||||
|
pip install pyinstaller==4.10
|
||||||
|
pip install path
|
||||||
|
pip uninstall -y PyQt5
|
||||||
|
pip install PyQt5==5.15.7
|
||||||
|
pip install PyQtWebEngine==5.15.6
|
||||||
|
pip install git+https://github.com/gumyr/cq_warehouse.git#egg=cq_warehouse
|
||||||
|
pip install git+https://github.com/meadiode/cq_gears.git@main
|
||||||
|
pip install -e "git+https://github.com/CadQuery/cadquery-plugins.git#egg=cq_cache&subdirectory=plugins/cq_cache"
|
||||||
|
pip install git+https://github.com/gumyr/build123d.git#egg=build123d
|
||||||
|
pip install git+https://github.com/JustinSDK/cqMore
|
||||||
|
pip list
|
||||||
|
- name: Run build
|
||||||
|
shell: bash --login {0}
|
||||||
|
run: |
|
||||||
|
micromamba info
|
||||||
|
pyinstaller pyinstaller_pip.spec ${{ github.event.inputs.type }}
|
||||||
|
cp /Users/runner/work/jmwright-CQ-Editor/jmwright-CQ-Editor/pyinstaller/CQ-editor.sh /Users/runner/work/jmwright-CQ-Editor/jmwright-CQ-Editor/dist/
|
||||||
|
- uses: alehechka/upload-tartifact@v1
|
||||||
|
with:
|
||||||
|
name: CQ-editor-MacOS
|
||||||
|
path: dist
|
||||||
|
build-windows:
|
||||||
|
runs-on: windows-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: mamba-org/provision-with-micromamba@main
|
||||||
|
with:
|
||||||
|
#miniconda-version: "latest"
|
||||||
|
#auto-update-conda: true
|
||||||
|
environment-name: test
|
||||||
|
environment-file: environment.yml
|
||||||
|
extra-specs:
|
||||||
|
python=3.9
|
||||||
|
- name: pip install cadquery CQ-editor ... etc
|
||||||
|
shell: powershell
|
||||||
|
run: |
|
||||||
|
micromamba info
|
||||||
|
pip install git+https://github.com/jdegenstein/jmwright-CQ-Editor
|
||||||
|
pip install --pre git+https://github.com/cadquery/cadquery casadi==3.5.5
|
||||||
|
pip install pyinstaller==4.10
|
||||||
|
pip install path
|
||||||
|
pip install git+https://github.com/gumyr/cq_warehouse.git#egg=cq_warehouse
|
||||||
|
pip install git+https://github.com/meadiode/cq_gears.git@main
|
||||||
|
pip install -e "git+https://github.com/CadQuery/cadquery-plugins.git#egg=cq_cache&subdirectory=plugins/cq_cache"
|
||||||
|
pip install git+https://github.com/gumyr/build123d.git#egg=build123d
|
||||||
|
pip install git+https://github.com/JustinSDK/cqMore
|
||||||
|
pip list
|
||||||
|
- name: Run build
|
||||||
|
shell: powershell
|
||||||
|
run: |
|
||||||
|
micromamba info
|
||||||
|
pyinstaller --debug all pyinstaller_pip.spec ${{ github.event.inputs.type }}
|
||||||
|
Copy-Item D:\a\jmwright-CQ-Editor\jmwright-CQ-Editor\pyinstaller\CQ-editor.cmd D:\a\jmwright-CQ-Editor\jmwright-CQ-Editor\dist\
|
||||||
|
- uses: alehechka/upload-tartifact@v1
|
||||||
|
with:
|
||||||
|
name: CQ-editor-Windows
|
||||||
|
path: dist
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
name: build-micromamba-TAR
|
name: build-micromamba-DEV
|
||||||
on:
|
on:
|
||||||
schedule:
|
schedule:
|
||||||
- cron: '0 0 * * 1'
|
- cron: '0 0 * * 1'
|
||||||
@@ -31,20 +31,19 @@ jobs:
|
|||||||
# micromamba info
|
# micromamba info
|
||||||
# micromamba install -c cadquery -c conda-forge cq-editor=master cadquery=master debugpy ipython=8.4.0 jedi=0.17.2 python=3.9
|
# micromamba install -c cadquery -c conda-forge cq-editor=master cadquery=master debugpy ipython=8.4.0 jedi=0.17.2 python=3.9
|
||||||
# micromamba install -c conda-forge pyinstaller=4.10
|
# micromamba install -c conda-forge pyinstaller=4.10
|
||||||
# micromamba uninstall --force -y importlib_resources
|
|
||||||
# pip install path
|
# pip install path
|
||||||
# pip install git+https://github.com/gumyr/cq_warehouse.git#egg=cq_warehouse
|
# pip install git+https://github.com/gumyr/cq_warehouse.git#egg=cq_warehouse
|
||||||
# pip install git+https://github.com/meadiode/cq_gears.git@main
|
# pip install git+https://github.com/meadiode/cq_gears.git@main
|
||||||
# pip install -e "git+https://github.com/CadQuery/cadquery-plugins.git#egg=cq_cache&subdirectory=plugins/cq_cache"
|
# pip install -e "git+https://github.com/CadQuery/cadquery-plugins.git#egg=cq_cache&subdirectory=plugins/cq_cache"
|
||||||
# pip install git+https://github.com/gumyr/build123d.git#egg=build123d
|
# pip install git+https://github.com/gumyr/build123d.git#egg=build123d
|
||||||
|
# pip install git+https://github.com/JustinSDK/cqMore
|
||||||
# - name: Run build
|
# - name: Run build
|
||||||
# shell: bash --login {0}
|
# shell: bash --login {0}
|
||||||
# run: |
|
# run: |
|
||||||
# micromamba info
|
# micromamba info
|
||||||
# pyinstaller pyinstaller.spec ${{ github.event.inputs.type }}
|
# pyinstaller pyinstaller.spec ${{ github.event.inputs.type }}
|
||||||
# cp /home/runner/work/jmwright-CQ-Editor/jmwright-CQ-Editor/pyinstaller/CQ-editor.sh /home/runner/work/jmwright-CQ-Editor/jmwright-CQ-Editor/dist/
|
# cp /home/runner/work/jmwright-CQ-Editor/jmwright-CQ-Editor/pyinstaller/CQ-editor.sh /home/runner/work/jmwright-CQ-Editor/jmwright-CQ-Editor/dist/
|
||||||
# rm /home/runner/work/jmwright-CQ-Editor/jmwright-CQ-Editor/dist/CQ-editor/libstdc++.so.6
|
# - uses: actions/upload-artifact@v2
|
||||||
# - uses: actions/upload-tartifact@main
|
|
||||||
# with:
|
# with:
|
||||||
# name: CQ-editor-Linux-x86_64
|
# name: CQ-editor-Linux-x86_64
|
||||||
# path: dist
|
# path: dist
|
||||||
@@ -66,7 +65,6 @@ jobs:
|
|||||||
# micromamba info
|
# micromamba info
|
||||||
# micromamba install -c cadquery -c conda-forge cq-editor=master cadquery=master debugpy ipython=8.4.0 jedi=0.17.2 python=3.9
|
# micromamba install -c cadquery -c conda-forge cq-editor=master cadquery=master debugpy ipython=8.4.0 jedi=0.17.2 python=3.9
|
||||||
# micromamba install -c conda-forge pyinstaller
|
# micromamba install -c conda-forge pyinstaller
|
||||||
# micromamba uninstall --force -y importlib_resources
|
|
||||||
# pip install path
|
# pip install path
|
||||||
# pip uninstall -y PyQt5
|
# pip uninstall -y PyQt5
|
||||||
# pip install PyQt5==5.15.7
|
# pip install PyQt5==5.15.7
|
||||||
@@ -75,13 +73,14 @@ jobs:
|
|||||||
# pip install git+https://github.com/meadiode/cq_gears.git@main
|
# pip install git+https://github.com/meadiode/cq_gears.git@main
|
||||||
# pip install -e "git+https://github.com/CadQuery/cadquery-plugins.git#egg=cq_cache&subdirectory=plugins/cq_cache"
|
# pip install -e "git+https://github.com/CadQuery/cadquery-plugins.git#egg=cq_cache&subdirectory=plugins/cq_cache"
|
||||||
# pip install git+https://github.com/gumyr/build123d.git#egg=build123d
|
# pip install git+https://github.com/gumyr/build123d.git#egg=build123d
|
||||||
|
# pip install git+https://github.com/JustinSDK/cqMore
|
||||||
# - name: Run build
|
# - name: Run build
|
||||||
# shell: bash --login {0}
|
# shell: bash --login {0}
|
||||||
# run: |
|
# run: |
|
||||||
# micromamba info
|
# micromamba info
|
||||||
# pyinstaller pyinstaller.spec ${{ github.event.inputs.type }}
|
# pyinstaller pyinstaller.spec ${{ github.event.inputs.type }}
|
||||||
# cp /Users/runner/work/jmwright-CQ-Editor/jmwright-CQ-Editor/pyinstaller/CQ-editor.sh /Users/runner/work/jmwright-CQ-Editor/jmwright-CQ-Editor/dist/
|
# cp /Users/runner/work/jmwright-CQ-Editor/jmwright-CQ-Editor/pyinstaller/CQ-editor.sh /Users/runner/work/jmwright-CQ-Editor/jmwright-CQ-Editor/dist/
|
||||||
# - uses: actions/upload-tartifact@main
|
# - uses: actions/upload-artifact@v2
|
||||||
# with:
|
# with:
|
||||||
# name: CQ-editor-MacOS
|
# name: CQ-editor-MacOS
|
||||||
# path: dist
|
# path: dist
|
||||||
@@ -101,7 +100,7 @@ jobs:
|
|||||||
shell: powershell
|
shell: powershell
|
||||||
run: |
|
run: |
|
||||||
micromamba install -c cadquery -c conda-forge cq-editor=master cadquery=master debugpy ipython=8.4.0 jedi=0.17.2 python=3.9
|
micromamba install -c cadquery -c conda-forge cq-editor=master cadquery=master debugpy ipython=8.4.0 jedi=0.17.2 python=3.9
|
||||||
micromamba install -c conda-forge pyinstaller=4.10
|
micromamba install -c conda-forge pyinstaller=4.10 casadi ipopt
|
||||||
pip install path
|
pip install path
|
||||||
pip install pipwin
|
pip install pipwin
|
||||||
pipwin install numpy
|
pipwin install numpy
|
||||||
@@ -109,17 +108,15 @@ jobs:
|
|||||||
pip install git+https://github.com/meadiode/cq_gears.git@main
|
pip install git+https://github.com/meadiode/cq_gears.git@main
|
||||||
pip install -e "git+https://github.com/CadQuery/cadquery-plugins.git#egg=cq_cache&subdirectory=plugins/cq_cache"
|
pip install -e "git+https://github.com/CadQuery/cadquery-plugins.git#egg=cq_cache&subdirectory=plugins/cq_cache"
|
||||||
pip install git+https://github.com/gumyr/build123d.git#egg=build123d
|
pip install git+https://github.com/gumyr/build123d.git#egg=build123d
|
||||||
|
pip install git+https://github.com/JustinSDK/cqMore
|
||||||
- name: Run build
|
- name: Run build
|
||||||
shell: powershell
|
shell: powershell
|
||||||
run: |
|
run: |
|
||||||
micromamba info
|
micromamba info
|
||||||
pyinstaller --debug all pyinstaller.spec ${{ github.event.inputs.type }}
|
pyinstaller --debug all pyinstaller.spec ${{ github.event.inputs.type }}
|
||||||
|
Copy-Item C:\Users\runneradmin\micromamba-root\envs\test\Library\bin\casadi_nlpsol_ipopt.dll D:\a\jmwright-CQ-Editor\jmwright-CQ-Editor\dist\CQ-editor\
|
||||||
Copy-Item D:\a\jmwright-CQ-Editor\jmwright-CQ-Editor\pyinstaller\CQ-editor.cmd D:\a\jmwright-CQ-Editor\jmwright-CQ-Editor\dist\
|
Copy-Item D:\a\jmwright-CQ-Editor\jmwright-CQ-Editor\pyinstaller\CQ-editor.cmd D:\a\jmwright-CQ-Editor\jmwright-CQ-Editor\dist\
|
||||||
- uses: alehechka/upload-tartifact@v1
|
- uses: alehechka/upload-tartifact@v1
|
||||||
with:
|
with:
|
||||||
name: CQ-editor-Windows
|
name: CQ-editor-Windows
|
||||||
path: dist
|
path: dist
|
||||||
#- uses: alehechka/download-tartifact@v1
|
|
||||||
# with:
|
|
||||||
# name: CQ-editor-Windows
|
|
||||||
# path: dist
|
|
||||||
|
|||||||
32
README.md
32
README.md
@@ -1,10 +1,11 @@
|
|||||||
# CadQuery editor
|
# CadQuery editor
|
||||||
|
|
||||||
This is a fork of jmwright's fork of CadQuery/CQ-editor. This fork includes changes that enable dark mode for CQ-editor (see screenshot below). Under the GitHub Actions menu this fork also contains static builds of CQ-editor for Linux/MacOS/Windows that include the cq_gears, cq_cache, cq_warehouse, and build123d libraries. Note you need to change color preferences to enable dark mode for all panes (see Edit -> Preferences).
|
This is a fork of [jmwright's fork](https://github.com/jmwright/CQ-editor) of [CadQuery/CQ-editor](https://github.com/CadQuery/CQ-editor). This fork includes changes that enable dark mode for CQ-editor (see screenshot below). Under the GitHub Actions menu this fork also contains static builds of CQ-editor for Linux/MacOS/Windows that include the [cq_gears](https://github.com/meadiode/cq_gears), [cq_cache](https://github.com/CadQuery/cadquery-plugins/tree/main/plugins/cq_cache), [cq_more](https://github.com/JustinSDK/cqMore), [cq_warehouse](https://github.com/gumyr/cq_warehouse), and [build123d](https://github.com/gumyr/build123d) libraries. Note you need to change color preferences to enable dark mode for all panes (see Edit -> Preferences).
|
||||||
|
|
||||||
|
This fork also contains additional changes to the `show_object` function in CQ-editor that make it easier to display and export build123d objects and object lists.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
|
||||||
[](https://ci.appveyor.com/project/adam-urbanczyk/cq-editor/branch/master)
|
[](https://ci.appveyor.com/project/adam-urbanczyk/cq-editor/branch/master)
|
||||||
[](https://codecov.io/gh/CadQuery/CQ-editor)
|
[](https://codecov.io/gh/CadQuery/CQ-editor)
|
||||||
[](https://dev.azure.com/cadquery/CQ-editor/_build/latest?definitionId=3&branchName=master)
|
[](https://dev.azure.com/cadquery/CQ-editor/_build/latest?definitionId=3&branchName=master)
|
||||||
@@ -32,34 +33,17 @@ CadQuery GUI editor based on PyQT supports Linux, Windows and Mac.
|
|||||||
|
|
||||||
### Release Packages
|
### Release Packages
|
||||||
|
|
||||||
Stable release builds which do not require Anaconda are attached to the [latest release](https://github.com/CadQuery/CQ-editor/releases). Download the zip file for your operating system, extract it, and run the CQ-editor script for your OS (CQ-editor.cmd for Windows, CQ-editor.sh for Linux and MacOS). On Windows you should be able to simply double-click on CQ-editor.cmd. On Linux and MacOS you may need to make the script executable with `chmod +x CQ-editor.sh` and run the script from the command line. The script contains an environment variable export that may be required to get CQ-editor to launch correctly on MacOS Big Sur, so it is better to use the script than to launch CQ-editor directly.
|
TBD
|
||||||
|
|
||||||
### Development Packages
|
### Development Packages
|
||||||
|
|
||||||
Development builds are also available, but can be unstable and should be used at your own risk. Click on the newest build with a green checkmark [here](https://github.com/jmwright/CQ-editor/actions?query=workflow%3Abuild), wait for the _Artifacts_ section at the bottom of the page to load, and then click on the appropriate download for your operating system. Extract the archive file and run the shell (Linux/MacOS) or cmd (Windows) script in the root CQ-editor directory. The CQ-editor window should launch.
|
Development builds are also available, but can be unstable and should be used at your own risk. Click on the newest build with a green checkmark [here](https://github.com/jdegenstein/jmwright-CQ-editor/actions), wait for the _Artifacts_ section at the bottom of the page to load, and then click on the appropriate download for your operating system. Extract the archive file and run the shell (Linux/MacOS) or cmd (Windows) script in the root CQ-editor directory. The CQ-editor window should launch.
|
||||||
|
|
||||||
## Installation (Anaconda)
|
## Installation (pip)
|
||||||
|
|
||||||
Use conda to install:
|
|
||||||
```
|
```
|
||||||
conda install -c cadquery -c conda-forge cq-editor=master
|
pip install git+https://github.com/jdegenstein/jmwright-CQ-Editor
|
||||||
```
|
pip install --pre git+https://github.com/cadquery/cadquery
|
||||||
and then simply type `cq-editor` to run it. This installs the latest version built directly from the HEAD of this repository.
|
|
||||||
|
|
||||||
Alternatively clone this git repository and set up the following conda environment:
|
|
||||||
```
|
|
||||||
conda env create -f cqgui_env.yml -n cqgui
|
|
||||||
conda activate cqgui
|
|
||||||
python run.py
|
|
||||||
```
|
|
||||||
|
|
||||||
On some linux distributions (e.g. `Ubuntu 18.04`) it might be necessary to install additonal packages:
|
|
||||||
```
|
|
||||||
sudo apt install libglu1-mesa libgl1-mesa-dri mesa-common-dev libglu1-mesa-dev
|
|
||||||
```
|
|
||||||
On Fedora 29 the packages can be installed as follows:
|
|
||||||
```
|
|
||||||
dnf install -y mesa-libGLU mesa-libGL mesa-libGLU-devel
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|||||||
@@ -1,162 +1,233 @@
|
|||||||
import cadquery as cq
|
import cadquery as cq
|
||||||
from cadquery.occ_impl.assembly import toCAF
|
from cadquery.occ_impl.assembly import toCAF
|
||||||
|
|
||||||
from typing import List, Union
|
from typing import List, Union
|
||||||
from imp import reload
|
from imp import reload
|
||||||
from types import SimpleNamespace
|
from types import SimpleNamespace
|
||||||
|
|
||||||
from OCP.XCAFPrs import XCAFPrs_AISObject
|
from OCP.XCAFPrs import XCAFPrs_AISObject
|
||||||
from OCP.TopoDS import TopoDS_Shape
|
from OCP.TopoDS import TopoDS_Shape
|
||||||
from OCP.AIS import AIS_InteractiveObject, AIS_Shape
|
from OCP.AIS import AIS_InteractiveObject, AIS_Shape
|
||||||
from OCP.Quantity import \
|
from OCP.Quantity import (
|
||||||
Quantity_TOC_RGB as TOC_RGB, Quantity_Color
|
Quantity_TOC_RGB as TOC_RGB,
|
||||||
|
Quantity_Color,
|
||||||
from PyQt5.QtGui import QColor
|
Quantity_NOC_GOLD as GOLD,
|
||||||
|
)
|
||||||
def find_cq_objects(results : dict):
|
from OCP.Graphic3d import Graphic3d_NOM_JADE, Graphic3d_MaterialAspect
|
||||||
|
|
||||||
return {k:SimpleNamespace(shape=v,options={}) for k,v in results.items() if isinstance(v,cq.Workplane)}
|
from PyQt5.QtGui import QColor
|
||||||
|
|
||||||
def to_compound(obj : Union[cq.Workplane, List[cq.Workplane], cq.Shape, List[cq.Shape], cq.Sketch]):
|
DEFAULT_FACE_COLOR = Quantity_Color(GOLD)
|
||||||
|
DEFAULT_MATERIAL = Graphic3d_MaterialAspect(Graphic3d_NOM_JADE)
|
||||||
vals = []
|
|
||||||
|
|
||||||
if isinstance(obj,cq.Workplane):
|
def find_cq_objects(results: dict):
|
||||||
vals.extend(obj.vals())
|
|
||||||
elif isinstance(obj,cq.Shape):
|
return {
|
||||||
vals.append(obj)
|
k: SimpleNamespace(shape=v, options={})
|
||||||
elif isinstance(obj,list) and isinstance(obj[0],cq.Workplane):
|
for k, v in results.items()
|
||||||
for o in obj: vals.extend(o.vals())
|
if isinstance(v, cq.Workplane)
|
||||||
elif isinstance(obj,list) and isinstance(obj[0],cq.Shape):
|
}
|
||||||
vals.extend(obj)
|
|
||||||
elif isinstance(obj, TopoDS_Shape):
|
|
||||||
vals.append(cq.Shape.cast(obj))
|
def to_compound(
|
||||||
elif isinstance(obj,list) and isinstance(obj[0],TopoDS_Shape):
|
obj: Union[cq.Workplane, List[cq.Workplane], cq.Shape, List[cq.Shape], cq.Sketch]
|
||||||
vals.extend(cq.Shape.cast(o) for o in obj)
|
):
|
||||||
elif hasattr(obj, "wrapped") and isinstance(obj.wrapped, TopoDS_Shape):
|
|
||||||
vals.append(cq.Shape.cast(obj.wrapped))
|
vals = []
|
||||||
elif hasattr(obj, "_obj") and hasattr(obj._obj, "wrapped") and isinstance(obj._obj.wrapped, TopoDS_Shape):
|
|
||||||
vals.append(cq.Shape.cast(obj._obj.wrapped))
|
if isinstance(obj, cq.Workplane):
|
||||||
elif isinstance(obj, cq.Sketch):
|
vals.extend(obj.vals())
|
||||||
if obj._faces:
|
elif isinstance(obj, cq.Shape):
|
||||||
vals.append(obj._faces)
|
vals.append(obj)
|
||||||
else:
|
elif isinstance(obj, list) and isinstance(obj[0], cq.Workplane):
|
||||||
vals.extend(obj._edges)
|
for o in obj:
|
||||||
else:
|
vals.extend(o.vals())
|
||||||
raise ValueError(f'Invalid type {type(obj)}')
|
elif isinstance(obj, list) and isinstance(obj[0], cq.Shape):
|
||||||
|
vals.extend(obj)
|
||||||
return cq.Compound.makeCompound(vals)
|
elif isinstance(obj, TopoDS_Shape):
|
||||||
|
vals.append(cq.Shape.cast(obj))
|
||||||
def to_workplane(obj : cq.Shape):
|
elif isinstance(obj, list) and isinstance(obj[0], TopoDS_Shape):
|
||||||
|
vals.extend(cq.Shape.cast(o) for o in obj)
|
||||||
rv = cq.Workplane('XY')
|
elif hasattr(obj, "wrapped") and isinstance(obj.wrapped, TopoDS_Shape):
|
||||||
rv.objects = [obj,]
|
vals.append(cq.Shape.cast(obj.wrapped))
|
||||||
|
elif (
|
||||||
return rv
|
isinstance(obj, list)
|
||||||
|
and hasattr(obj[0], "wrapped")
|
||||||
def make_AIS(obj : Union[cq.Workplane, List[cq.Workplane], cq.Shape, List[cq.Shape], cq.Assembly, AIS_InteractiveObject],
|
and isinstance(obj[0].wrapped, TopoDS_Shape)
|
||||||
options={}):
|
):
|
||||||
|
vals.extend(o for o in obj)
|
||||||
shape = None
|
elif (
|
||||||
|
hasattr(obj, "_obj")
|
||||||
if isinstance(obj, cq.Assembly):
|
and hasattr(obj._obj, "wrapped")
|
||||||
label, shape = toCAF(obj)
|
and isinstance(obj._obj.wrapped, TopoDS_Shape)
|
||||||
ais = XCAFPrs_AISObject(label)
|
):
|
||||||
elif isinstance(obj, AIS_InteractiveObject):
|
vals.append(cq.Shape.cast(obj._obj.wrapped))
|
||||||
ais = obj
|
elif (
|
||||||
else:
|
isinstance(obj, list)
|
||||||
shape = to_compound(obj)
|
and hasattr(obj[0], "_obj")
|
||||||
ais = AIS_Shape(shape.wrapped)
|
and hasattr(obj[0]._obj, "wrapped")
|
||||||
|
and isinstance(obj[0]._obj.wrapped, TopoDS_Shape)
|
||||||
if 'alpha' in options:
|
):
|
||||||
ais.SetTransparency(options['alpha'])
|
vals.append(o for o in obj)
|
||||||
if 'color' in options:
|
elif isinstance(obj, cq.Sketch):
|
||||||
ais.SetColor(to_occ_color(options['color']))
|
if obj._faces:
|
||||||
if 'rgba' in options:
|
vals.append(obj._faces)
|
||||||
r,g,b,a = options['rgba']
|
else:
|
||||||
ais.SetColor(to_occ_color((r,g,b)))
|
vals.extend(obj._edges)
|
||||||
ais.SetTransparency(a)
|
else:
|
||||||
|
raise ValueError(f"Invalid type {type(obj)}")
|
||||||
return ais,shape
|
|
||||||
|
return cq.Compound.makeCompound(vals)
|
||||||
def export(obj : Union[cq.Workplane, List[cq.Workplane]], type : str,
|
|
||||||
file, precision=1e-1):
|
|
||||||
|
def to_workplane(obj: cq.Shape):
|
||||||
comp = to_compound(obj)
|
|
||||||
|
rv = cq.Workplane("XY")
|
||||||
if type == 'stl':
|
rv.objects = [
|
||||||
comp.exportStl(file, tolerance=precision)
|
obj,
|
||||||
elif type == 'step':
|
]
|
||||||
comp.exportStep(file)
|
|
||||||
elif type == 'brep':
|
return rv
|
||||||
comp.exportBrep(file)
|
|
||||||
|
|
||||||
def to_occ_color(color) -> Quantity_Color:
|
def make_AIS(
|
||||||
|
obj: Union[
|
||||||
if not isinstance(color, QColor):
|
cq.Workplane,
|
||||||
if isinstance(color, tuple):
|
List[cq.Workplane],
|
||||||
if isinstance(color[0], int):
|
cq.Shape,
|
||||||
color = QColor(*color)
|
List[cq.Shape],
|
||||||
elif isinstance(color[0], float):
|
cq.Assembly,
|
||||||
color = QColor.fromRgbF(*color)
|
AIS_InteractiveObject,
|
||||||
else:
|
],
|
||||||
raise ValueError('Unknown color format')
|
options={},
|
||||||
else:
|
):
|
||||||
color = QColor(color)
|
|
||||||
|
shape = None
|
||||||
return Quantity_Color(color.redF(),
|
|
||||||
color.greenF(),
|
if isinstance(obj, cq.Assembly):
|
||||||
color.blueF(),
|
label, shape = toCAF(obj)
|
||||||
TOC_RGB)
|
ais = XCAFPrs_AISObject(label)
|
||||||
|
elif isinstance(obj, AIS_InteractiveObject):
|
||||||
def get_occ_color(obj : Union[AIS_InteractiveObject, Quantity_Color]) -> QColor:
|
ais = obj
|
||||||
|
else:
|
||||||
if isinstance(obj, AIS_InteractiveObject):
|
shape = to_compound(obj)
|
||||||
color = Quantity_Color()
|
ais = AIS_Shape(shape.wrapped)
|
||||||
obj.Color(color)
|
|
||||||
else:
|
set_material(ais, DEFAULT_MATERIAL)
|
||||||
color = obj
|
set_color(ais, DEFAULT_FACE_COLOR)
|
||||||
|
|
||||||
return QColor.fromRgbF(color.Red(), color.Green(), color.Blue())
|
if "alpha" in options:
|
||||||
|
set_transparency(ais, options["alpha"])
|
||||||
def set_color(ais : AIS_Shape, color : Quantity_Color) -> AIS_Shape:
|
if "color" in options:
|
||||||
|
set_color(ais, to_occ_color(options["color"]))
|
||||||
drawer = ais.Attributes()
|
if "rgba" in options:
|
||||||
drawer.ShadingAspect().SetColor(color)
|
r, g, b, a = options["rgba"]
|
||||||
|
set_color(ais, to_occ_color((r, g, b)))
|
||||||
return ais
|
set_transparency(ais, a)
|
||||||
|
|
||||||
def reload_cq():
|
return ais, shape
|
||||||
|
|
||||||
# NB: order of reloads is important
|
|
||||||
reload(cq.types)
|
def export(
|
||||||
reload(cq.occ_impl.geom)
|
obj: Union[cq.Workplane, List[cq.Workplane]], type: str, file, precision=1e-1
|
||||||
reload(cq.occ_impl.shapes)
|
):
|
||||||
reload(cq.occ_impl.importers.dxf)
|
|
||||||
reload(cq.occ_impl.importers)
|
comp = to_compound(obj)
|
||||||
reload(cq.occ_impl.solver)
|
|
||||||
reload(cq.occ_impl.assembly)
|
if type == "stl":
|
||||||
reload(cq.occ_impl.sketch_solver)
|
comp.exportStl(file, tolerance=precision)
|
||||||
reload(cq.hull)
|
elif type == "step":
|
||||||
reload(cq.selectors)
|
comp.exportStep(file)
|
||||||
reload(cq.sketch)
|
elif type == "brep":
|
||||||
reload(cq.occ_impl.exporters.svg)
|
comp.exportBrep(file)
|
||||||
reload(cq.cq)
|
|
||||||
reload(cq.occ_impl.exporters.utils)
|
|
||||||
reload(cq.occ_impl.exporters.dxf)
|
def to_occ_color(color) -> Quantity_Color:
|
||||||
reload(cq.occ_impl.exporters.amf)
|
|
||||||
reload(cq.occ_impl.exporters.json)
|
if not isinstance(color, QColor):
|
||||||
#reload(cq.occ_impl.exporters.assembly)
|
if isinstance(color, tuple):
|
||||||
reload(cq.occ_impl.exporters)
|
if isinstance(color[0], int):
|
||||||
reload(cq.assembly)
|
color = QColor(*color)
|
||||||
reload(cq)
|
elif isinstance(color[0], float):
|
||||||
|
color = QColor.fromRgbF(*color)
|
||||||
|
else:
|
||||||
def is_obj_empty(obj : Union[cq.Workplane,cq.Shape]) -> bool:
|
raise ValueError("Unknown color format")
|
||||||
|
else:
|
||||||
rv = False
|
color = QColor(color)
|
||||||
|
|
||||||
if isinstance(obj, cq.Workplane):
|
return Quantity_Color(color.redF(), color.greenF(), color.blueF(), TOC_RGB)
|
||||||
rv = True if isinstance(obj.val(), cq.Vector) else False
|
|
||||||
|
|
||||||
return rv
|
def get_occ_color(obj: Union[AIS_InteractiveObject, Quantity_Color]) -> QColor:
|
||||||
|
|
||||||
|
if isinstance(obj, AIS_InteractiveObject):
|
||||||
|
color = Quantity_Color()
|
||||||
|
obj.Color(color)
|
||||||
|
else:
|
||||||
|
color = obj
|
||||||
|
|
||||||
|
return QColor.fromRgbF(color.Red(), color.Green(), color.Blue())
|
||||||
|
|
||||||
|
|
||||||
|
def set_color(ais: AIS_Shape, color: Quantity_Color) -> AIS_Shape:
|
||||||
|
|
||||||
|
drawer = ais.Attributes()
|
||||||
|
drawer.SetupOwnShadingAspect()
|
||||||
|
drawer.ShadingAspect().SetColor(color)
|
||||||
|
|
||||||
|
return ais
|
||||||
|
|
||||||
|
|
||||||
|
def set_material(ais: AIS_Shape, material: Graphic3d_MaterialAspect) -> AIS_Shape:
|
||||||
|
|
||||||
|
drawer = ais.Attributes()
|
||||||
|
drawer.SetupOwnShadingAspect()
|
||||||
|
drawer.ShadingAspect().SetMaterial(material)
|
||||||
|
|
||||||
|
return ais
|
||||||
|
|
||||||
|
|
||||||
|
def set_transparency(ais: AIS_Shape, alpha: float) -> AIS_Shape:
|
||||||
|
|
||||||
|
drawer = ais.Attributes()
|
||||||
|
drawer.SetupOwnShadingAspect()
|
||||||
|
drawer.ShadingAspect().SetTransparency(alpha)
|
||||||
|
|
||||||
|
return ais
|
||||||
|
|
||||||
|
|
||||||
|
def reload_cq():
|
||||||
|
|
||||||
|
# NB: order of reloads is important
|
||||||
|
reload(cq.types)
|
||||||
|
reload(cq.occ_impl.geom)
|
||||||
|
reload(cq.occ_impl.shapes)
|
||||||
|
reload(cq.occ_impl.importers.dxf)
|
||||||
|
reload(cq.occ_impl.importers)
|
||||||
|
reload(cq.occ_impl.solver)
|
||||||
|
reload(cq.occ_impl.assembly)
|
||||||
|
reload(cq.occ_impl.sketch_solver)
|
||||||
|
reload(cq.hull)
|
||||||
|
reload(cq.selectors)
|
||||||
|
reload(cq.sketch)
|
||||||
|
reload(cq.occ_impl.exporters.svg)
|
||||||
|
reload(cq.cq)
|
||||||
|
reload(cq.occ_impl.exporters.utils)
|
||||||
|
reload(cq.occ_impl.exporters.dxf)
|
||||||
|
reload(cq.occ_impl.exporters.amf)
|
||||||
|
reload(cq.occ_impl.exporters.json)
|
||||||
|
# reload(cq.occ_impl.exporters.assembly)
|
||||||
|
reload(cq.occ_impl.exporters)
|
||||||
|
reload(cq.assembly)
|
||||||
|
reload(cq)
|
||||||
|
|
||||||
|
|
||||||
|
def is_obj_empty(obj: Union[cq.Workplane, cq.Shape]) -> bool:
|
||||||
|
|
||||||
|
rv = False
|
||||||
|
|
||||||
|
if isinstance(obj, cq.Workplane):
|
||||||
|
rv = True if isinstance(obj.val(), cq.Vector) else False
|
||||||
|
|
||||||
|
return rv
|
||||||
|
|||||||
@@ -299,6 +299,7 @@ class MainWindow(QMainWindow,MainMixin):
|
|||||||
#CQ related items
|
#CQ related items
|
||||||
console.push_vars({'show' : obj_tree.addObject,
|
console.push_vars({'show' : obj_tree.addObject,
|
||||||
'show_object' : obj_tree.addObject,
|
'show_object' : obj_tree.addObject,
|
||||||
|
'rand_color' : self.components['debugger']._rand_color,
|
||||||
'cq' : cq,
|
'cq' : cq,
|
||||||
'log' : Logger(self.name).info})
|
'log' : Logger(self.name).info})
|
||||||
|
|
||||||
|
|||||||
@@ -1,365 +1,386 @@
|
|||||||
import sys
|
import sys
|
||||||
from contextlib import ExitStack, contextmanager
|
from contextlib import ExitStack, contextmanager
|
||||||
from enum import Enum, auto
|
from enum import Enum, auto
|
||||||
from types import SimpleNamespace, FrameType, ModuleType
|
from types import SimpleNamespace, FrameType, ModuleType
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
import cadquery as cq
|
import cadquery as cq
|
||||||
from PyQt5 import QtCore
|
from PyQt5 import QtCore
|
||||||
from PyQt5.QtCore import Qt, QObject, pyqtSlot, pyqtSignal, QEventLoop, QAbstractTableModel
|
from PyQt5.QtCore import Qt, QObject, pyqtSlot, pyqtSignal, QEventLoop, QAbstractTableModel
|
||||||
from PyQt5.QtWidgets import (QAction,
|
from PyQt5.QtWidgets import (QAction,
|
||||||
QTableView)
|
QTableView)
|
||||||
from logbook import info
|
from logbook import info
|
||||||
from path import Path
|
from path import Path
|
||||||
from pyqtgraph.parametertree import Parameter
|
from pyqtgraph.parametertree import Parameter
|
||||||
from spyder.utils.icon_manager import icon
|
from spyder.utils.icon_manager import icon
|
||||||
|
from random import randrange as rrr, seed
|
||||||
from ..cq_utils import find_cq_objects, reload_cq
|
|
||||||
from ..mixins import ComponentMixin
|
from ..cq_utils import find_cq_objects, reload_cq
|
||||||
|
from ..mixins import ComponentMixin
|
||||||
DUMMY_FILE = '<string>'
|
|
||||||
|
DUMMY_FILE = '<string>'
|
||||||
|
|
||||||
class DbgState(Enum):
|
|
||||||
|
class DbgState(Enum):
|
||||||
STEP = auto()
|
|
||||||
CONT = auto()
|
STEP = auto()
|
||||||
STEP_IN = auto()
|
CONT = auto()
|
||||||
RETURN = auto()
|
STEP_IN = auto()
|
||||||
|
RETURN = auto()
|
||||||
class DbgEevent(object):
|
|
||||||
|
class DbgEevent(object):
|
||||||
LINE = 'line'
|
|
||||||
CALL = 'call'
|
LINE = 'line'
|
||||||
RETURN = 'return'
|
CALL = 'call'
|
||||||
|
RETURN = 'return'
|
||||||
class LocalsModel(QAbstractTableModel):
|
|
||||||
|
class LocalsModel(QAbstractTableModel):
|
||||||
HEADER = ('Name','Type', 'Value')
|
|
||||||
|
HEADER = ('Name','Type', 'Value')
|
||||||
def __init__(self,parent):
|
|
||||||
|
def __init__(self,parent):
|
||||||
super(LocalsModel,self).__init__(parent)
|
|
||||||
self.frame = None
|
super(LocalsModel,self).__init__(parent)
|
||||||
|
self.frame = None
|
||||||
def update_frame(self,frame):
|
|
||||||
|
def update_frame(self,frame):
|
||||||
self.frame = \
|
|
||||||
[(k,type(v).__name__, str(v)) for k,v in frame.items() if not k.startswith('_')]
|
self.frame = \
|
||||||
|
[(k,type(v).__name__, str(v)) for k,v in frame.items() if not k.startswith('_')]
|
||||||
|
|
||||||
def rowCount(self,parent=QtCore.QModelIndex()):
|
|
||||||
|
def rowCount(self,parent=QtCore.QModelIndex()):
|
||||||
if self.frame:
|
|
||||||
return len(self.frame)
|
if self.frame:
|
||||||
else:
|
return len(self.frame)
|
||||||
return 0
|
else:
|
||||||
|
return 0
|
||||||
def columnCount(self,parent=QtCore.QModelIndex()):
|
|
||||||
|
def columnCount(self,parent=QtCore.QModelIndex()):
|
||||||
return 3
|
|
||||||
|
return 3
|
||||||
def headerData(self, section, orientation, role=Qt.DisplayRole):
|
|
||||||
if role == Qt.DisplayRole and orientation == Qt.Horizontal:
|
def headerData(self, section, orientation, role=Qt.DisplayRole):
|
||||||
return self.HEADER[section]
|
if role == Qt.DisplayRole and orientation == Qt.Horizontal:
|
||||||
return QAbstractTableModel.headerData(self, section, orientation, role)
|
return self.HEADER[section]
|
||||||
|
return QAbstractTableModel.headerData(self, section, orientation, role)
|
||||||
def data(self, index, role):
|
|
||||||
if role == QtCore.Qt.DisplayRole:
|
def data(self, index, role):
|
||||||
i = index.row()
|
if role == QtCore.Qt.DisplayRole:
|
||||||
j = index.column()
|
i = index.row()
|
||||||
return self.frame[i][j]
|
j = index.column()
|
||||||
else:
|
return self.frame[i][j]
|
||||||
return QtCore.QVariant()
|
else:
|
||||||
|
return QtCore.QVariant()
|
||||||
|
|
||||||
class LocalsView(QTableView,ComponentMixin):
|
|
||||||
|
class LocalsView(QTableView,ComponentMixin):
|
||||||
name = 'Variables'
|
|
||||||
|
name = 'Variables'
|
||||||
def __init__(self,parent):
|
|
||||||
|
def __init__(self,parent):
|
||||||
super(LocalsView,self).__init__(parent)
|
|
||||||
ComponentMixin.__init__(self)
|
super(LocalsView,self).__init__(parent)
|
||||||
|
ComponentMixin.__init__(self)
|
||||||
header = self.horizontalHeader()
|
|
||||||
header.setStretchLastSection(True)
|
header = self.horizontalHeader()
|
||||||
|
header.setStretchLastSection(True)
|
||||||
vheader = self.verticalHeader()
|
|
||||||
vheader.setVisible(False)
|
vheader = self.verticalHeader()
|
||||||
|
vheader.setVisible(False)
|
||||||
@pyqtSlot(dict)
|
|
||||||
def update_frame(self,frame):
|
@pyqtSlot(dict)
|
||||||
|
def update_frame(self,frame):
|
||||||
model = LocalsModel(self)
|
|
||||||
model.update_frame(frame)
|
model = LocalsModel(self)
|
||||||
|
model.update_frame(frame)
|
||||||
self.setModel(model)
|
|
||||||
|
self.setModel(model)
|
||||||
class Debugger(QObject,ComponentMixin):
|
|
||||||
|
class Debugger(QObject,ComponentMixin):
|
||||||
name = 'Debugger'
|
|
||||||
|
name = 'Debugger'
|
||||||
preferences = Parameter.create(name='Preferences',children=[
|
|
||||||
{'name': 'Reload CQ', 'type': 'bool', 'value': False},
|
preferences = Parameter.create(name='Preferences',children=[
|
||||||
{'name': 'Add script dir to path','type': 'bool', 'value': True},
|
{'name': 'Reload CQ', 'type': 'bool', 'value': False},
|
||||||
{'name': 'Change working dir to script dir','type': 'bool', 'value': True},
|
{'name': 'Add script dir to path','type': 'bool', 'value': True},
|
||||||
{'name': 'Reload imported modules', 'type': 'bool', 'value': True},
|
{'name': 'Change working dir to script dir','type': 'bool', 'value': True},
|
||||||
])
|
{'name': 'Reload imported modules', 'type': 'bool', 'value': True},
|
||||||
|
])
|
||||||
|
|
||||||
sigRendered = pyqtSignal(dict)
|
|
||||||
sigLocals = pyqtSignal(dict)
|
sigRendered = pyqtSignal(dict)
|
||||||
sigTraceback = pyqtSignal(object,str)
|
sigLocals = pyqtSignal(dict)
|
||||||
|
sigTraceback = pyqtSignal(object,str)
|
||||||
sigFrameChanged = pyqtSignal(object)
|
|
||||||
sigLineChanged = pyqtSignal(int)
|
sigFrameChanged = pyqtSignal(object)
|
||||||
sigLocalsChanged = pyqtSignal(dict)
|
sigLineChanged = pyqtSignal(int)
|
||||||
sigCQChanged = pyqtSignal(dict,bool)
|
sigLocalsChanged = pyqtSignal(dict)
|
||||||
sigDebugging = pyqtSignal(bool)
|
sigCQChanged = pyqtSignal(dict,bool)
|
||||||
|
sigDebugging = pyqtSignal(bool)
|
||||||
_frames : List[FrameType]
|
|
||||||
|
_frames : List[FrameType]
|
||||||
def __init__(self,parent):
|
|
||||||
|
def __init__(self,parent):
|
||||||
super(Debugger,self).__init__(parent)
|
|
||||||
ComponentMixin.__init__(self)
|
super(Debugger,self).__init__(parent)
|
||||||
|
ComponentMixin.__init__(self)
|
||||||
self.inner_event_loop = QEventLoop(self)
|
|
||||||
|
self.inner_event_loop = QEventLoop(self)
|
||||||
self._actions = \
|
|
||||||
{'Run' : [QAction(icon('run'),
|
self._actions = \
|
||||||
'Render',
|
{'Run' : [QAction(icon('run'),
|
||||||
self,
|
'Render',
|
||||||
shortcut='F5',
|
self,
|
||||||
triggered=self.render),
|
shortcut='F5',
|
||||||
QAction(icon('debug'),
|
triggered=self.render),
|
||||||
'Debug',
|
QAction(icon('debug'),
|
||||||
self,
|
'Debug',
|
||||||
checkable=True,
|
self,
|
||||||
shortcut='ctrl+F5',
|
checkable=True,
|
||||||
triggered=self.debug),
|
shortcut='ctrl+F5',
|
||||||
QAction(icon('arrow-step-over'),
|
triggered=self.debug),
|
||||||
'Step',
|
QAction(icon('arrow-step-over'),
|
||||||
self,
|
'Step',
|
||||||
shortcut='ctrl+F10',
|
self,
|
||||||
triggered=lambda: self.debug_cmd(DbgState.STEP)),
|
shortcut='ctrl+F10',
|
||||||
QAction(icon('arrow-step-in'),
|
triggered=lambda: self.debug_cmd(DbgState.STEP)),
|
||||||
'Step in',
|
QAction(icon('arrow-step-in'),
|
||||||
self,
|
'Step in',
|
||||||
shortcut='ctrl+F11',
|
self,
|
||||||
triggered=lambda: self.debug_cmd(DbgState.STEP_IN)),
|
shortcut='ctrl+F11',
|
||||||
QAction(icon('arrow-continue'),
|
triggered=lambda: self.debug_cmd(DbgState.STEP_IN)),
|
||||||
'Continue',
|
QAction(icon('arrow-continue'),
|
||||||
self,
|
'Continue',
|
||||||
shortcut='ctrl+F12',
|
self,
|
||||||
triggered=lambda: self.debug_cmd(DbgState.CONT))
|
shortcut='ctrl+F12',
|
||||||
]}
|
triggered=lambda: self.debug_cmd(DbgState.CONT))
|
||||||
|
]}
|
||||||
self._frames = []
|
|
||||||
|
self._frames = []
|
||||||
def get_current_script(self):
|
|
||||||
|
def get_current_script(self):
|
||||||
return self.parent().components['editor'].get_text_with_eol()
|
|
||||||
|
return self.parent().components['editor'].get_text_with_eol()
|
||||||
def get_breakpoints(self):
|
|
||||||
|
def get_breakpoints(self):
|
||||||
return self.parent().components['editor'].debugger.get_breakpoints()
|
|
||||||
|
return self.parent().components['editor'].debugger.get_breakpoints()
|
||||||
def compile_code(self, cq_script):
|
|
||||||
|
def compile_code(self, cq_script):
|
||||||
try:
|
|
||||||
module = ModuleType('temp')
|
try:
|
||||||
cq_code = compile(cq_script, '<string>', 'exec')
|
module = ModuleType('temp')
|
||||||
return cq_code, module
|
cq_code = compile(cq_script, '<string>', 'exec')
|
||||||
except Exception:
|
return cq_code, module
|
||||||
self.sigTraceback.emit(sys.exc_info(), cq_script)
|
except Exception:
|
||||||
return None, None
|
self.sigTraceback.emit(sys.exc_info(), cq_script)
|
||||||
|
return None, None
|
||||||
def _exec(self, code, locals_dict, globals_dict):
|
|
||||||
|
def _exec(self, code, locals_dict, globals_dict):
|
||||||
with ExitStack() as stack:
|
|
||||||
fname = self.parent().components['editor'].filename
|
with ExitStack() as stack:
|
||||||
p = Path(fname if fname else '').abspath().dirname()
|
fname = self.parent().components['editor'].filename
|
||||||
|
p = Path(fname if fname else '').abspath().dirname()
|
||||||
if self.preferences['Add script dir to path'] and p.exists():
|
|
||||||
sys.path.insert(0,p)
|
if self.preferences['Add script dir to path'] and p.exists():
|
||||||
stack.callback(sys.path.remove, p)
|
sys.path.insert(0,p)
|
||||||
if self.preferences['Change working dir to script dir'] and p.exists():
|
stack.callback(sys.path.remove, p)
|
||||||
stack.enter_context(p)
|
if self.preferences['Change working dir to script dir'] and p.exists():
|
||||||
if self.preferences['Reload imported modules']:
|
stack.enter_context(p)
|
||||||
stack.enter_context(module_manager())
|
if self.preferences['Reload imported modules']:
|
||||||
|
stack.enter_context(module_manager())
|
||||||
exec(code, locals_dict, globals_dict)
|
|
||||||
|
exec(code, locals_dict, globals_dict)
|
||||||
def _inject_locals(self,module):
|
|
||||||
|
def _rand_color(self, alpha = 0., cfloat=False):
|
||||||
cq_objects = {}
|
#helper function to generate a random color dict
|
||||||
|
#for CQ-editor's show_object function
|
||||||
def _show_object(obj,name=None, options={}):
|
lower = 10
|
||||||
|
upper = 100 #not too high to keep color brightness in check
|
||||||
if name:
|
if cfloat: #for two output types depending on need
|
||||||
cq_objects.update({name : SimpleNamespace(shape=obj,options=options)})
|
return (
|
||||||
else:
|
(rrr(lower,upper)/255),
|
||||||
cq_objects.update({str(id(obj)) : SimpleNamespace(shape=obj,options=options)})
|
(rrr(lower,upper)/255),
|
||||||
|
(rrr(lower,upper)/255),
|
||||||
def _debug(obj,name=None):
|
alpha,
|
||||||
|
)
|
||||||
_show_object(obj,name,options=dict(color='red',alpha=0.2))
|
return {"alpha": alpha,
|
||||||
|
"color": (
|
||||||
module.__dict__['show_object'] = _show_object
|
rrr(lower,upper),
|
||||||
module.__dict__['debug'] = _debug
|
rrr(lower,upper),
|
||||||
module.__dict__['log'] = lambda x: info(str(x))
|
rrr(lower,upper),
|
||||||
module.__dict__['cq'] = cq
|
)}
|
||||||
|
|
||||||
return cq_objects, set(module.__dict__)-{'cq'}
|
def _inject_locals(self,module):
|
||||||
|
|
||||||
def _cleanup_locals(self,module,injected_names):
|
cq_objects = {}
|
||||||
|
|
||||||
for name in injected_names: module.__dict__.pop(name)
|
def _show_object(obj,name=None, options={}):
|
||||||
|
|
||||||
@pyqtSlot(bool)
|
if name:
|
||||||
def render(self):
|
cq_objects.update({name : SimpleNamespace(shape=obj,options=options)})
|
||||||
|
else:
|
||||||
if self.preferences['Reload CQ']:
|
cq_objects.update({str(id(obj)) : SimpleNamespace(shape=obj,options=options)})
|
||||||
reload_cq()
|
|
||||||
|
def _debug(obj,name=None):
|
||||||
cq_script = self.get_current_script()
|
|
||||||
cq_code,module = self.compile_code(cq_script)
|
_show_object(obj,name,options=dict(color='red',alpha=0.2))
|
||||||
|
|
||||||
if cq_code is None: return
|
module.__dict__['show_object'] = _show_object
|
||||||
|
module.__dict__['debug'] = _debug
|
||||||
cq_objects,injected_names = self._inject_locals(module)
|
module.__dict__['rand_color'] = self._rand_color
|
||||||
|
module.__dict__['log'] = lambda x: info(str(x))
|
||||||
try:
|
module.__dict__['cq'] = cq
|
||||||
self._exec(cq_code, module.__dict__, module.__dict__)
|
|
||||||
|
return cq_objects, set(module.__dict__)-{'cq'}
|
||||||
#remove the special methods
|
|
||||||
self._cleanup_locals(module,injected_names)
|
def _cleanup_locals(self,module,injected_names):
|
||||||
|
|
||||||
#collect all CQ objects if no explicit show_object was called
|
for name in injected_names: module.__dict__.pop(name)
|
||||||
if len(cq_objects) == 0:
|
|
||||||
cq_objects = find_cq_objects(module.__dict__)
|
@pyqtSlot(bool)
|
||||||
self.sigRendered.emit(cq_objects)
|
def render(self):
|
||||||
self.sigTraceback.emit(None,
|
seed(371353) #reset the seed every time render is called (preserves colors run to run)
|
||||||
cq_script)
|
if self.preferences['Reload CQ']:
|
||||||
self.sigLocals.emit(module.__dict__)
|
reload_cq()
|
||||||
except Exception:
|
|
||||||
exc_info = sys.exc_info()
|
cq_script = self.get_current_script()
|
||||||
sys.last_traceback = exc_info[-1]
|
cq_code,module = self.compile_code(cq_script)
|
||||||
self.sigTraceback.emit(exc_info, cq_script)
|
|
||||||
|
if cq_code is None: return
|
||||||
@property
|
|
||||||
def breakpoints(self):
|
cq_objects,injected_names = self._inject_locals(module)
|
||||||
return [ el[0] for el in self.get_breakpoints()]
|
|
||||||
|
try:
|
||||||
@pyqtSlot(bool)
|
self._exec(cq_code, module.__dict__, module.__dict__)
|
||||||
def debug(self,value):
|
|
||||||
|
#remove the special methods
|
||||||
previous_trace = sys.gettrace()
|
self._cleanup_locals(module,injected_names)
|
||||||
|
|
||||||
if value:
|
#collect all CQ objects if no explicit show_object was called
|
||||||
self.sigDebugging.emit(True)
|
if len(cq_objects) == 0:
|
||||||
self.state = DbgState.STEP
|
cq_objects = find_cq_objects(module.__dict__)
|
||||||
|
self.sigRendered.emit(cq_objects)
|
||||||
self.script = self.get_current_script()
|
self.sigTraceback.emit(None,
|
||||||
code,module = self.compile_code(self.script)
|
cq_script)
|
||||||
|
self.sigLocals.emit(module.__dict__)
|
||||||
if code is None:
|
except Exception:
|
||||||
self.sigDebugging.emit(False)
|
exc_info = sys.exc_info()
|
||||||
self._actions['Run'][1].setChecked(False)
|
sys.last_traceback = exc_info[-1]
|
||||||
return
|
self.sigTraceback.emit(exc_info, cq_script)
|
||||||
|
|
||||||
cq_objects,injected_names = self._inject_locals(module)
|
@property
|
||||||
|
def breakpoints(self):
|
||||||
#clear possible traceback
|
return [ el[0] for el in self.get_breakpoints()]
|
||||||
self.sigTraceback.emit(None,
|
|
||||||
self.script)
|
@pyqtSlot(bool)
|
||||||
|
def debug(self,value):
|
||||||
try:
|
|
||||||
sys.settrace(self.trace_callback)
|
previous_trace = sys.gettrace()
|
||||||
exec(code,module.__dict__,module.__dict__)
|
|
||||||
except Exception:
|
if value:
|
||||||
exc_info = sys.exc_info()
|
self.sigDebugging.emit(True)
|
||||||
sys.last_traceback = exc_info[-1]
|
self.state = DbgState.STEP
|
||||||
self.sigTraceback.emit(exc_info,
|
|
||||||
self.script)
|
self.script = self.get_current_script()
|
||||||
finally:
|
code,module = self.compile_code(self.script)
|
||||||
sys.settrace(previous_trace)
|
|
||||||
self.sigDebugging.emit(False)
|
if code is None:
|
||||||
self._actions['Run'][1].setChecked(False)
|
self.sigDebugging.emit(False)
|
||||||
|
self._actions['Run'][1].setChecked(False)
|
||||||
if len(cq_objects) == 0:
|
return
|
||||||
cq_objects = find_cq_objects(module.__dict__)
|
|
||||||
self.sigRendered.emit(cq_objects)
|
cq_objects,injected_names = self._inject_locals(module)
|
||||||
|
|
||||||
self._cleanup_locals(module,injected_names)
|
#clear possible traceback
|
||||||
self.sigLocals.emit(module.__dict__)
|
self.sigTraceback.emit(None,
|
||||||
|
self.script)
|
||||||
self._frames = []
|
|
||||||
else:
|
try:
|
||||||
sys.settrace(previous_trace)
|
sys.settrace(self.trace_callback)
|
||||||
self.inner_event_loop.exit(0)
|
exec(code,module.__dict__,module.__dict__)
|
||||||
|
except Exception:
|
||||||
|
exc_info = sys.exc_info()
|
||||||
def debug_cmd(self,state=DbgState.STEP):
|
sys.last_traceback = exc_info[-1]
|
||||||
|
self.sigTraceback.emit(exc_info,
|
||||||
self.state = state
|
self.script)
|
||||||
self.inner_event_loop.exit(0)
|
finally:
|
||||||
|
sys.settrace(previous_trace)
|
||||||
|
self.sigDebugging.emit(False)
|
||||||
def trace_callback(self,frame,event,arg):
|
self._actions['Run'][1].setChecked(False)
|
||||||
|
|
||||||
filename = frame.f_code.co_filename
|
if len(cq_objects) == 0:
|
||||||
|
cq_objects = find_cq_objects(module.__dict__)
|
||||||
if filename==DUMMY_FILE:
|
self.sigRendered.emit(cq_objects)
|
||||||
if not self._frames:
|
|
||||||
self._frames.append(frame)
|
self._cleanup_locals(module,injected_names)
|
||||||
self.trace_local(frame,event,arg)
|
self.sigLocals.emit(module.__dict__)
|
||||||
return self.trace_callback
|
|
||||||
|
self._frames = []
|
||||||
else:
|
else:
|
||||||
return None
|
sys.settrace(previous_trace)
|
||||||
|
self.inner_event_loop.exit(0)
|
||||||
def trace_local(self,frame,event,arg):
|
|
||||||
|
|
||||||
lineno = frame.f_lineno
|
def debug_cmd(self,state=DbgState.STEP):
|
||||||
|
|
||||||
if event in (DbgEevent.LINE,):
|
self.state = state
|
||||||
if (self.state in (DbgState.STEP, DbgState.STEP_IN) and frame is self._frames[-1]) \
|
self.inner_event_loop.exit(0)
|
||||||
or (lineno in self.breakpoints):
|
|
||||||
|
|
||||||
if lineno in self.breakpoints:
|
def trace_callback(self,frame,event,arg):
|
||||||
self._frames.append(frame)
|
|
||||||
|
filename = frame.f_code.co_filename
|
||||||
self.sigLineChanged.emit(lineno)
|
|
||||||
self.sigFrameChanged.emit(frame)
|
if filename==DUMMY_FILE:
|
||||||
self.sigLocalsChanged.emit(frame.f_locals)
|
if not self._frames:
|
||||||
self.sigCQChanged.emit(find_cq_objects(frame.f_locals),True)
|
self._frames.append(frame)
|
||||||
|
self.trace_local(frame,event,arg)
|
||||||
self.inner_event_loop.exec_()
|
return self.trace_callback
|
||||||
|
|
||||||
elif event in (DbgEevent.RETURN):
|
else:
|
||||||
self.sigLocalsChanged.emit(frame.f_locals)
|
return None
|
||||||
self._frames.pop()
|
|
||||||
|
def trace_local(self,frame,event,arg):
|
||||||
elif event == DbgEevent.CALL:
|
|
||||||
func_filename = frame.f_code.co_filename
|
lineno = frame.f_lineno
|
||||||
if self.state == DbgState.STEP_IN and func_filename == DUMMY_FILE:
|
|
||||||
self.sigLineChanged.emit(lineno)
|
if event in (DbgEevent.LINE,):
|
||||||
self.sigFrameChanged.emit(frame)
|
if (self.state in (DbgState.STEP, DbgState.STEP_IN) and frame is self._frames[-1]) \
|
||||||
self.state = DbgState.STEP
|
or (lineno in self.breakpoints):
|
||||||
self._frames.append(frame)
|
|
||||||
|
if lineno in self.breakpoints:
|
||||||
|
self._frames.append(frame)
|
||||||
@contextmanager
|
|
||||||
def module_manager():
|
self.sigLineChanged.emit(lineno)
|
||||||
""" unloads any modules loaded while the context manager is active """
|
self.sigFrameChanged.emit(frame)
|
||||||
loaded_modules = set(sys.modules.keys())
|
self.sigLocalsChanged.emit(frame.f_locals)
|
||||||
|
self.sigCQChanged.emit(find_cq_objects(frame.f_locals),True)
|
||||||
try:
|
|
||||||
yield
|
self.inner_event_loop.exec_()
|
||||||
finally:
|
|
||||||
new_modules = set(sys.modules.keys()) - loaded_modules
|
elif event in (DbgEevent.RETURN):
|
||||||
for module_name in new_modules:
|
self.sigLocalsChanged.emit(frame.f_locals)
|
||||||
del sys.modules[module_name]
|
self._frames.pop()
|
||||||
|
|
||||||
|
elif event == DbgEevent.CALL:
|
||||||
|
func_filename = frame.f_code.co_filename
|
||||||
|
if self.state == DbgState.STEP_IN and func_filename == DUMMY_FILE:
|
||||||
|
self.sigLineChanged.emit(lineno)
|
||||||
|
self.sigFrameChanged.emit(frame)
|
||||||
|
self.state = DbgState.STEP
|
||||||
|
self._frames.append(frame)
|
||||||
|
|
||||||
|
|
||||||
|
@contextmanager
|
||||||
|
def module_manager():
|
||||||
|
""" unloads any modules loaded while the context manager is active """
|
||||||
|
loaded_modules = set(sys.modules.keys())
|
||||||
|
|
||||||
|
try:
|
||||||
|
yield
|
||||||
|
finally:
|
||||||
|
new_modules = set(sys.modules.keys()) - loaded_modules
|
||||||
|
for module_name in new_modules:
|
||||||
|
del sys.modules[module_name]
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
from PyQt5.QtWidgets import QTreeWidget, QTreeWidgetItem, QAction, QMenu, QWidget, QAbstractItemView
|
from PyQt5.QtWidgets import QTreeWidget, QTreeWidgetItem, QAction, QMenu, QWidget, QAbstractItemView
|
||||||
from PyQt5.QtCore import Qt, pyqtSlot, pyqtSignal
|
from PyQt5.QtCore import Qt, pyqtSlot, pyqtSignal
|
||||||
|
|
||||||
from pyqtgraph.parametertree import Parameter, ParameterTree
|
from pyqtgraph.parametertree import Parameter, ParameterTree
|
||||||
|
|
||||||
from OCP.AIS import AIS_Line
|
from OCP.AIS import AIS_Line
|
||||||
@@ -390,6 +389,3 @@ class ObjectTree(QWidget,ComponentMixin):
|
|||||||
item.properties['Visible'] = True
|
item.properties['Visible'] = True
|
||||||
else:
|
else:
|
||||||
item.properties['Visible'] = False
|
item.properties['Visible'] = False
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -95,8 +95,8 @@ class OCCTWidget(QWidget):
|
|||||||
self.old_pos.y() - y, theToStart=True)
|
self.old_pos.y() - y, theToStart=True)
|
||||||
|
|
||||||
elif event.buttons() == Qt.RightButton:
|
elif event.buttons() == Qt.RightButton:
|
||||||
self.view.ZoomAtPoint(self.old_pos.x(), y,
|
self.view.Pan(x - self.old_pos.x(),
|
||||||
x, self.old_pos.y())
|
self.old_pos.y() - y, theToStart=True)
|
||||||
|
|
||||||
self.old_pos = pos
|
self.old_pos = pos
|
||||||
|
|
||||||
|
|||||||
@@ -7,21 +7,21 @@ from OCP.Graphic3d import Graphic3d_Camera, Graphic3d_StereoMode, Graphic3d_NOM_
|
|||||||
Graphic3d_MaterialAspect
|
Graphic3d_MaterialAspect
|
||||||
from OCP.AIS import AIS_Shaded,AIS_WireFrame, AIS_ColoredShape, AIS_Axis
|
from OCP.AIS import AIS_Shaded,AIS_WireFrame, AIS_ColoredShape, AIS_Axis
|
||||||
from OCP.Aspect import Aspect_GDM_Lines, Aspect_GT_Rectangular
|
from OCP.Aspect import Aspect_GDM_Lines, Aspect_GT_Rectangular
|
||||||
from OCP.Quantity import Quantity_NOC_BLACK as BLACK, Quantity_NOC_GOLD as GOLD,\
|
from OCP.Quantity import Quantity_NOC_BLACK as BLACK, Quantity_TOC_RGB as TOC_RGB,\
|
||||||
Quantity_TOC_RGB as TOC_RGB, Quantity_Color
|
Quantity_Color
|
||||||
from OCP.Geom import Geom_Axis1Placement
|
from OCP.Geom import Geom_Axis1Placement
|
||||||
from OCP.gp import gp_Ax3, gp_Dir, gp_Pnt, gp_Ax1
|
from OCP.gp import gp_Ax3, gp_Dir, gp_Pnt, gp_Ax1
|
||||||
|
|
||||||
from ..utils import layout, get_save_filename
|
from ..utils import layout, get_save_filename
|
||||||
from ..mixins import ComponentMixin
|
from ..mixins import ComponentMixin
|
||||||
from ..icons import icon
|
from ..icons import icon
|
||||||
from ..cq_utils import to_occ_color, make_AIS
|
from ..cq_utils import to_occ_color, make_AIS, DEFAULT_FACE_COLOR
|
||||||
|
|
||||||
from .occt_widget import OCCTWidget
|
from .occt_widget import OCCTWidget
|
||||||
|
|
||||||
from pyqtgraph.parametertree import Parameter
|
from pyqtgraph.parametertree import Parameter
|
||||||
import qtawesome as qta
|
import qtawesome as qta
|
||||||
DEFAULT_FACE_COLOR = Quantity_Color(GOLD)
|
|
||||||
DEFAULT_EDGE_COLOR = Quantity_Color(BLACK)
|
DEFAULT_EDGE_COLOR = Quantity_Color(BLACK)
|
||||||
DEFAULT_EDGE_WIDTH = 2
|
DEFAULT_EDGE_WIDTH = 2
|
||||||
|
|
||||||
|
|||||||
@@ -19,14 +19,25 @@ elif sys.platform == 'darwin':
|
|||||||
ocp_path = (os.path.join(HOMEPATH, 'OCP.cpython-39-darwin.so'), '.')
|
ocp_path = (os.path.join(HOMEPATH, 'OCP.cpython-39-darwin.so'), '.')
|
||||||
elif sys.platform == 'win32':
|
elif sys.platform == 'win32':
|
||||||
occt_dir = os.path.join(Path(sys.prefix), 'Library', 'share', 'opencascade')
|
occt_dir = os.path.join(Path(sys.prefix), 'Library', 'share', 'opencascade')
|
||||||
ocp_path = (os.path.join(HOMEPATH, 'OCP.cp39-win_amd64.pyd'), '.')
|
ocp_path = [(os.path.join(HOMEPATH, 'OCP.cp39-win_amd64.pyd'), '.')]
|
||||||
|
cas_DLL = [(os.path.join(Path(sys.prefix), 'Library', 'bin', 'casadi_nlpsol_ipopt.dll'), '.')]
|
||||||
|
ipo_DLL = [(os.path.join(Path(sys.prefix), 'Library', 'bin', 'ipopt-3.dll'), '.')]
|
||||||
|
bla_DLL = [(os.path.join(Path(sys.prefix), 'Library', 'bin', 'libblas.dll'), '.')]
|
||||||
|
lap_DLL = [(os.path.join(Path(sys.prefix), 'Library', 'bin', 'liblapack.dll'), '.')]
|
||||||
|
mum_DLL = [(os.path.join(Path(sys.prefix), 'Library', 'bin', 'dmumps.dll'), '.')]
|
||||||
|
fla_DLL = [(os.path.join(Path(sys.prefix), 'Library', 'bin', 'flang.dll'), '.')]
|
||||||
|
flr_DLL = [(os.path.join(Path(sys.prefix), 'Library', 'bin', 'flangrti.dll'), '.')]
|
||||||
|
omp_DLL = [(os.path.join(Path(sys.prefix), 'Library', 'bin', 'libomp.dll'), '.')]
|
||||||
|
mkl_DLLs = [(os.path.join(Path(sys.prefix), 'Library', 'bin', 'mkl*.dll'), '.')]
|
||||||
|
#cas_dllA = os.path.join(HOMEPATH, 'casadi', 'libcasadi.dll')
|
||||||
|
#cas_dllB = os.path.join(HOMEPATH, 'casadi', 'libcasadi_nlpsol_ipopt.dll')
|
||||||
|
|
||||||
datas1, binaries1, hiddenimports1 = collect_all('debugpy')
|
datas1, binaries1, hiddenimports1 = collect_all('debugpy')
|
||||||
hiddenimports2 = collect_submodules('xmlrpc')
|
hiddenimports2 = collect_submodules('xmlrpc')
|
||||||
|
|
||||||
a = Analysis(['run.py'],
|
a = Analysis(['run.py'],
|
||||||
pathex=['.'],
|
pathex=['.'],
|
||||||
binaries=[ocp_path] + binaries1,
|
binaries=ocp_path + cas_DLL + ipo_DLL + bla_DLL + lap_DLL + mum_DLL + fla_DLL + flr_DLL + omp_DLL + mkl_DLLs + binaries1,
|
||||||
datas=[(spyder_data, 'spyder'),
|
datas=[(spyder_data, 'spyder'),
|
||||||
(occt_dir, 'opencascade'),
|
(occt_dir, 'opencascade'),
|
||||||
(cqw_path, 'cq_warehouse'),
|
(cqw_path, 'cq_warehouse'),
|
||||||
@@ -35,10 +46,11 @@ a = Analysis(['run.py'],
|
|||||||
hiddenimports=['ipykernel.datapub', 'debugpy', 'vtkmodules', 'vtkmodules.all',
|
hiddenimports=['ipykernel.datapub', 'debugpy', 'vtkmodules', 'vtkmodules.all',
|
||||||
'pyqtgraph.graphicsItems.ViewBox.axisCtrlTemplate_pyqt5',
|
'pyqtgraph.graphicsItems.ViewBox.axisCtrlTemplate_pyqt5',
|
||||||
'pyqtgraph.graphicsItems.PlotItem.plotConfigTemplate_pyqt5',
|
'pyqtgraph.graphicsItems.PlotItem.plotConfigTemplate_pyqt5',
|
||||||
'pyqtgraph.imageview.ImageViewTemplate_pyqt5', 'xmlrpc',
|
'pyqtgraph.imageview.ImageViewTemplate_pyqt5', 'xmlrpc', 'ipopt', 'casadi',
|
||||||
'zmq.backend', 'cq_warehouse', 'cq_warehouse.bearing', 'cq_warehouse.chain',
|
'zmq.backend', 'cq_warehouse', 'cq_warehouse.bearing', 'cq_warehouse.chain',
|
||||||
'cq_warehouse.drafting', 'cq_warehouse.extensions', 'cq_warehouse.fastener',
|
'cq_warehouse.drafting', 'cq_warehouse.extensions', 'cq_warehouse.fastener',
|
||||||
'cq_warehouse.sprocket', 'cq_warehouse.thread', 'cq_gears', 'cq_cache', 'build123d', 'cqmore'] + hiddenimports1 + hiddenimports2,
|
'cq_warehouse.sprocket', 'cq_warehouse.thread', 'cq_gears', 'cq_cache',
|
||||||
|
'build123d', 'cqmore'] + hiddenimports1 + hiddenimports2,
|
||||||
hookspath=[],
|
hookspath=[],
|
||||||
runtime_hooks=['pyinstaller/pyi_rth_occ.py',
|
runtime_hooks=['pyinstaller/pyi_rth_occ.py',
|
||||||
'pyinstaller/pyi_rth_fontconfig.py'],
|
'pyinstaller/pyi_rth_fontconfig.py'],
|
||||||
|
|||||||
9
pyinstaller/extrahooks/hook-casadi.py
Normal file
9
pyinstaller/extrahooks/hook-casadi.py
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
# hook-casadi.py
|
||||||
|
from PyInstaller.utils.hooks import collect_dynamic_libs
|
||||||
|
|
||||||
|
binaries = collect_dynamic_libs('casadi')
|
||||||
|
|
||||||
|
# Something about legacy import codepaths in casadi.casadi causes PyInstaller's analysis to pick up
|
||||||
|
# casadi._casadi as a top-level _casadi module, which is wrong.
|
||||||
|
hiddenimports = ['casadi._casadi']
|
||||||
|
excludedimports = ['_casadi']
|
||||||
86
pyinstaller_pip.spec
Normal file
86
pyinstaller_pip.spec
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
# -*- mode: python -*-
|
||||||
|
|
||||||
|
import sys, site, os
|
||||||
|
from path import Path
|
||||||
|
from PyInstaller.utils.hooks import collect_all, collect_submodules
|
||||||
|
|
||||||
|
block_cipher = None
|
||||||
|
|
||||||
|
spyder_data = Path(site.getsitepackages()[-1]) / 'spyder'
|
||||||
|
parso_grammar = (Path(site.getsitepackages()[-1]) / 'parso/python').glob('grammar*')
|
||||||
|
cqw_path = Path(site.getsitepackages()[-1]) / 'cq_warehouse'
|
||||||
|
cq_path = Path(site.getsitepackages()[-1]) / 'cadquery'
|
||||||
|
|
||||||
|
if sys.platform == 'linux':
|
||||||
|
occt_dir = os.path.join(Path(sys.prefix), 'share', 'opencascade')
|
||||||
|
ocp_path = [(os.path.join(HOMEPATH, 'OCP.cpython-39-x86_64-linux-gnu.so'), '.')]
|
||||||
|
elif sys.platform == 'darwin':
|
||||||
|
occt_dir = os.path.join(Path(sys.prefix), 'share', 'opencascade')
|
||||||
|
ocp_path = [(os.path.join(HOMEPATH, 'OCP.cpython-39-darwin.so'), '.')]
|
||||||
|
elif sys.platform == 'win32':
|
||||||
|
occt_dir = os.path.join(Path(sys.prefix), 'Library', 'share', 'opencascade')
|
||||||
|
ocp_path = [(os.path.join(HOMEPATH, 'OCP.cp39-win_amd64.pyd'), '.')]
|
||||||
|
|
||||||
|
datas1, binaries1, hiddenimports1 = collect_all('debugpy')
|
||||||
|
hiddenimports2 = collect_submodules('xmlrpc')
|
||||||
|
|
||||||
|
a = Analysis(['run.py'],
|
||||||
|
pathex=['.'],
|
||||||
|
binaries=ocp_path + binaries1,
|
||||||
|
datas=[(spyder_data, 'spyder'),
|
||||||
|
(cqw_path, 'cq_warehouse'),
|
||||||
|
(cq_path, 'cadquery')] +
|
||||||
|
[(p, 'parso/python') for p in parso_grammar] + datas1,
|
||||||
|
hiddenimports=['ipykernel.datapub', 'debugpy', 'vtkmodules', 'vtkmodules.all',
|
||||||
|
'pyqtgraph.graphicsItems.ViewBox.axisCtrlTemplate_pyqt5',
|
||||||
|
'pyqtgraph.graphicsItems.PlotItem.plotConfigTemplate_pyqt5',
|
||||||
|
'pyqtgraph.imageview.ImageViewTemplate_pyqt5', 'xmlrpc',
|
||||||
|
'zmq.backend', 'cq_warehouse', 'cq_warehouse.bearing', 'cq_warehouse.chain',
|
||||||
|
'cq_warehouse.drafting', 'cq_warehouse.extensions', 'cq_warehouse.fastener',
|
||||||
|
'cq_warehouse.sprocket', 'cq_warehouse.thread', 'cq_gears', 'cq_cache',
|
||||||
|
'build123d', 'cqmore'] + hiddenimports1 + hiddenimports2,
|
||||||
|
hookspath=['pyinstaller/extrahooks/'],
|
||||||
|
runtime_hooks=['pyinstaller/pyi_rth_occ.py',
|
||||||
|
'pyinstaller/pyi_rth_fontconfig.py'],
|
||||||
|
excludes=['_tkinter'],
|
||||||
|
win_no_prefer_redirects=False,
|
||||||
|
win_private_assemblies=False,
|
||||||
|
cipher=block_cipher,
|
||||||
|
noarchive=False)
|
||||||
|
|
||||||
|
# There is an issue that keeps the OpenSSL libraries from being copied to the output directory.
|
||||||
|
# This should work if nothing else, but does not with GitHub Actions
|
||||||
|
if sys.platform == 'win32':
|
||||||
|
from PyInstaller.depend.bindepend import getfullnameof
|
||||||
|
rel_data_path = ['PyQt5', 'Qt', 'bin']
|
||||||
|
a.datas += [
|
||||||
|
(getfullnameof('libssl-1_1-x64.dll'), os.path.join(*rel_data_path), 'DATA'),
|
||||||
|
(getfullnameof('libcrypto-1_1-x64.dll'), os.path.join(*rel_data_path), 'DATA'),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
pyz = PYZ(a.pure, a.zipped_data,
|
||||||
|
cipher=block_cipher)
|
||||||
|
exe = EXE(pyz,
|
||||||
|
a.scripts,
|
||||||
|
[],
|
||||||
|
exclude_binaries=True,
|
||||||
|
name='CQ-editor',
|
||||||
|
debug=False,
|
||||||
|
bootloader_ignore_signals=False,
|
||||||
|
strip=False,
|
||||||
|
upx=True,
|
||||||
|
console=True,
|
||||||
|
icon='icons/cadquery_logo_dark.ico')
|
||||||
|
|
||||||
|
exclude = ()
|
||||||
|
#exclude = ('libGL','libEGL','libbsd')
|
||||||
|
a.binaries = TOC([x for x in a.binaries if not x[0].startswith(exclude)])
|
||||||
|
|
||||||
|
coll = COLLECT(exe,
|
||||||
|
a.binaries,
|
||||||
|
a.zipfiles,
|
||||||
|
a.datas,
|
||||||
|
strip=False,
|
||||||
|
upx=True,
|
||||||
|
name='CQ-editor')
|
||||||
31
setup.py
31
setup.py
@@ -16,12 +16,25 @@ def get_version(rel_path):
|
|||||||
else:
|
else:
|
||||||
raise RuntimeError("Unable to find version string.")
|
raise RuntimeError("Unable to find version string.")
|
||||||
|
|
||||||
setup(name='CQ-editor',
|
setup(
|
||||||
version=get_version('cq_editor/_version.py'),
|
name="CQ-editor",
|
||||||
packages=find_packages(),
|
version=get_version("cq_editor/_version.py"),
|
||||||
entry_points={
|
packages=find_packages(),
|
||||||
'gui_scripts': [
|
entry_points={
|
||||||
'cq-editor = cq_editor.__main__:main',
|
"gui_scripts": [
|
||||||
'CQ-editor = cq_editor.__main__:main'
|
"cq-editor = cq_editor.__main__:main",
|
||||||
]}
|
"CQ-editor = cq_editor.__main__:main",
|
||||||
)
|
]
|
||||||
|
},
|
||||||
|
python_requires=">=3.8,<3.11",
|
||||||
|
install_requires=[
|
||||||
|
"logbook>=1",
|
||||||
|
"ipython==8.4.0",
|
||||||
|
"jedi==0.17.2",
|
||||||
|
"path>=16",
|
||||||
|
"PyQt5>=5",
|
||||||
|
"requests>=2,<3",
|
||||||
|
"spyder>=5,<6",
|
||||||
|
"pyqtgraph==0.12.4",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|||||||
@@ -1018,13 +1018,13 @@ def test_render_colors(main_clean):
|
|||||||
|
|
||||||
# object 1 (defualt color)
|
# object 1 (defualt color)
|
||||||
assert not CQ.child(0).ais.HasColor()
|
assert not CQ.child(0).ais.HasColor()
|
||||||
|
|
||||||
# object 2
|
# object 2
|
||||||
r,g,b,a = get_rgba(CQ.child(1).ais)
|
r,g,b,a = get_rgba(CQ.child(1).ais)
|
||||||
assert( a == 0.5 )
|
assert( a == 0.5 )
|
||||||
assert( r == 1.0 )
|
assert( r == 1.0 )
|
||||||
assert( g == 0.0 )
|
assert( g == 0.0 )
|
||||||
|
|
||||||
# object 3
|
# object 3
|
||||||
r,g,b,a = get_rgba(CQ.child(2).ais)
|
r,g,b,a = get_rgba(CQ.child(2).ais)
|
||||||
assert( a == 0.5)
|
assert( a == 0.5)
|
||||||
@@ -1058,7 +1058,7 @@ def test_render_colors_console(main_clean):
|
|||||||
console = win.components['console']
|
console = win.components['console']
|
||||||
|
|
||||||
console.execute_command(code_color)
|
console.execute_command(code_color)
|
||||||
|
|
||||||
CQ = obj_tree.CQ
|
CQ = obj_tree.CQ
|
||||||
|
|
||||||
# object 1 (defualt color)
|
# object 1 (defualt color)
|
||||||
@@ -1092,7 +1092,37 @@ def test_render_colors_console(main_clean):
|
|||||||
# check if error occured
|
# check if error occured
|
||||||
qtbot.wait(100)
|
qtbot.wait(100)
|
||||||
assert('Unknown color format' in log.toPlainText().splitlines()[-1])
|
assert('Unknown color format' in log.toPlainText().splitlines()[-1])
|
||||||
|
|
||||||
|
code_shading = \
|
||||||
|
'''
|
||||||
|
import cadquery as cq
|
||||||
|
|
||||||
|
res1 = cq.Workplane('XY').box(5, 7, 5)
|
||||||
|
res2 = cq.Workplane('XY').box(8, 5, 4)
|
||||||
|
show_object(res1)
|
||||||
|
show_object(res2,options={"alpha":0})
|
||||||
|
'''
|
||||||
|
|
||||||
|
def test_shading_aspect(main_clean):
|
||||||
|
|
||||||
|
qtbot, win = main_clean
|
||||||
|
|
||||||
|
obj_tree = win.components['object_tree']
|
||||||
|
editor = win.components['editor']
|
||||||
|
debugger = win.components['debugger']
|
||||||
|
|
||||||
|
editor.set_text(code_shading)
|
||||||
|
debugger._actions['Run'][0].triggered.emit()
|
||||||
|
|
||||||
|
CQ = obj_tree.CQ
|
||||||
|
|
||||||
|
# get material aspects
|
||||||
|
ma1 = CQ.child(0).ais.Attributes().ShadingAspect().Material()
|
||||||
|
ma2 = CQ.child(1).ais.Attributes().ShadingAspect().Material()
|
||||||
|
|
||||||
|
# verify that they are the same
|
||||||
|
assert ma1.Shininess() == ma2.Shininess()
|
||||||
|
|
||||||
def test_confirm_new(monkeypatch,editor):
|
def test_confirm_new(monkeypatch,editor):
|
||||||
|
|
||||||
qtbot, editor = editor
|
qtbot, editor = editor
|
||||||
@@ -1433,4 +1463,3 @@ def test_modulefinder(tmp_path, main):
|
|||||||
|
|
||||||
qtbot.wait(100)
|
qtbot.wait(100)
|
||||||
assert("Cannot determine imported modules" in log.toPlainText().splitlines()[-1])
|
assert("Cannot determine imported modules" in log.toPlainText().splitlines()[-1])
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user