FreeCAD external editor with Code – OSS

I’m not a big fan of M$ but Code – OSS is quite good and is the one I managed to set up with FreeCAD with a working debugger. I am very open to try another documented way if you have one to suggest !

Set up

To allow auto-completion and your linter like pylint to work partially you need to reference FreeCAD libraries. Examples below shows path for Arch/Manjaro with freecad-git installed. To get better auto-completion you can also add reference to freecad-stubs folder below I cloned it in my home git folder with git clone https://github.com/CyrilWaechter/freecad-stubs.git.

  1. Open your working folder in Code – OSS eg. :
    • macro folder : ~/.FreeCAD/Macro
    • your in progress workbench folder
  2. Create an .env file referencing FreeCAD lib folder and optionally your stubs folder :
    FREECAD_LIB=/usr/lib/freecad/lib
    FREECAD_STUBS=/home/<user>/git/freecad-stubs/out
    PYTHONPATH=${FREECAD_MOD}:${FREECAD_LIB}:${PYTHONPATH}
    (Note that on windows you need to replace : by ;)
  3. If you use git, add .vscode and .env to gitignore to avoid dirtyness

.env file concept is explained in Code – OSS help : Environment variable definitions file.

Unfortunately auto-completion and linter do not work for everything eg. Part. Shall we generate stubs like Gui Talarico did for Revit API or is there a better way ?

Update: I have generated stubs with mypy stubgen. Still unperfect but far better than before. You might want to keep an eye on Vanuan freecad-python-stubs.

Use

Once set up you have multiple options :

  1. Embedding FreeCAD
  2. Use your script as a macro or as a full workbench

Embedding FreeCAD

As explained on the wiki page FreeCAD can be embedded in another application sharing the host event loop. Let’s take a very basic example of application with PySide2 on their website :

import sys

from PySide2.QtWidgets import QApplication, QLabel
                                                    
if __name__ == "__main__":
    app = QApplication(sys.argv)
    label = QLabel("Hello World")
    label.show()
    sys.exit(app.exec_())

Let’s replace the hello world label with the two lines from FreeCAD wiki and create a box :

import FreeCAD
import FreeCADGui
import Part

import sys

from PySide2.QtWidgets import QApplication


if __name__ == "__main__":

    app = QApplication(sys.argv)

    FreeCADGui.showMainWindow()
    
    doc = FreeCAD.newDocument()
    box = Part.makeBox(100, 100, 100)
    Part.show(box)

    sys.exit(app.exec_())

That’s it, nothing more. The sad thing is that I don’t know yet how to interact with an already running application like you do with eg. Libre Office. Maybe with QProcess ? I saw multiple reference to this on Stackoverflow : Read output from python script in C++ Qt app, Communicating with QProcess Python program). I saw on FreeCAD forum that some people are doing it using a webserver : Re: Remote editor possible ?, Animate – Server. But for good reason or not it seems weird to me to use a webserver to communicate between 2 local applications.

Macro / workbench

Nothing much to say here. As you modify you macro or workbench you can then use it in FreeCAD as usual.

Debugging

Embedding FreeCAD

As you embed FreeCAD in your own application you can use your usual debugger.

Macro / workbench

To debug a script running from FreeCAD check Debugging wiki page. I described the process for Code – OSS at Visual Studio Code (VS Code) paragraph. You need ptvsd installed :

pip install ptvsd

Add a piece of code to your script :

import ptvsd
print("Waiting for debugger attach")
# 5678 is the default attach port in the VS Code debug configurations
ptvsd.enable_attach(address=('localhost', 5678), redirect_output=True)
ptvsd.wait_for_attach()

And add a new debug configuration : Debug → Add Configurations…

    "configurations": [
        {
            "name": "Python: Attacher",
            "type": "python",
            "request": "attach",
            "port": 5678,
            "host": "localhost",
            "pathMappings": [
                {
                    "localRoot": "${workspaceFolder}",
                    "remoteRoot": "."
                }
            ]
        },

Then start your script from FreeCAD which freeze waiting for the debugger to start.

Video demo

8 comments

  1. Hi,
    as lots of people in the freecad forum use Windows, maybe you should add a note telling them to use ; instead of : for the PYTHONPATH like this to help them:

    PYTHONPATH=${FREECAD_MOD};${FREECAD_LIB};${PYTHONPATH}

  2. Hello

    I tried the second method and installed ptvsd with pip, but when I launch a macro within FreeCAD, I get the message on the import line :
    No module named ‘ptvsd’

    I get not this message if I start a script from VS-Code, which proves that ptvsd exists !

    May be a problem of path for FreeCAD but where ?

    Thanks in advance

    1. Hello,
      I assume FreeCAD uses its own python interpreter. ptvsd installed from pip is in `/site-packages` while FreeCAD is looking in its own `/site-packages`. You can copy / link ptvsd folder into freecad python folder if python version is compatible. I think pip is also somewhere in packaged FreeCAD you can use this pip instead of system one to install ptvsd again.

  3. Hi, first thank you for your time! Then sorry for me being so noob… to the point..
    Regarding the .env file in Windows? I did the clone for the freecad stubs, but Im not sure if Im inserting correctly the path. I tried different ways with no luck. Also, the freecad lib path, does it has to point to freecad instalation? or do I need the download the source code?

    Thank you! traing to get started with Macros and I was just looking how to use VS Code + QT Designer, so this document is just what I needed.

  4. sorry, forgot to paste my .env file

    FREECAD_LIB=”C:/Program Files/FreeCAD_0.19.23546-Win-Conda_vc14.x-x86_64/lib”
    FREECAD_STUBS=”C:/Users/jmmartin/Documents/JM/Python/freecad-stubs”
    PYTHONPATH=${FREECAD_MOD};${FREECAD_LIB};${PYTHONPATH}

    1. Hi Juan,
      On windows, my env path looks like this :
      `FREECAD=”C:\\tools\\FreeCAD_0.19.22894_Win-LPv12.1.6_vc14.x-x86-64\\bin”
      FREECADMOD=”C:\\tools\\FreeCAD_0.19.22894_Win-LPv12.1.6_vc14.x-x86-64\\Mod”
      FREECADSTUBS=”C:\\git\\freecad-stubs\\out”
      PYTHONPATH=${FREECADSTUBS};${FREECADMOD};${FREECAD};${PYTHONPATH}`
      The subfolder out is missing in your .env file. It might solve your issue.

      1. Thank Cyril,

        Now it looks like this:

        FREECAD_LIB=”C:\\Program Files\\FreeCAD_0.19.23546-Win-Conda_vc14.x-x86_64\\lib”
        FREECAD_MOD=”C:\\Program Files\\FreeCAD_0.19.23546-Win-Conda_vc14.x-x86_64\\Mod”
        FREECAD_STUBS=”C:\\Users\\jmmartin\\Documents\\JM\\Python\\freecad-stubs\\out”
        PYTHONPATH=${FREECADSTUBS};${FREECADMOD};${FREECAD};${PYTHONPATH}

        But Im not sure if its working. Im not having any auto complete from FreeCAD commands. Which could be a simple test to know if its working. Again sorry for being so noob. (both python and macros in FreeCAD).

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.