How to Fix Deprecation Warnings in FreeCAD Python Macros

Updating legacy FreeCAD macros often triggers deprecation warnings caused by transitions between major Python versions, shifts across Qt toolkits (PySide to PySide2/PySide6), and internal FreeCAD API refactoring. This guide outlines how to identify the source of these warnings using built-in diagnostic tools, update outdated syntax to current FreeCAD standards, replace deprecated Qt bindings, and maintain clean, future-proof scripts without breaking backward compatibility.

1. Identify Warnings Using Built-in Tools

Before modifying code, capture the exact warnings and their stack traces to know which module or method is flagged.

  • Enable the Report View: Go to View → Panels → Report View. Ensure this panel is visible, as FreeCAD prints internal API warnings and Python standard library deprecations directly here.
  • Configure Output Levels: Navigate to Edit → Preferences → General → Output window. Enable Redirect Python output to report view and Redirect Python errors to report view.
  • Trace Warnings with Python: If a warning appears without a line number, run your macro with the Python warnings module configured to raise errors on deprecations. Add this to the top of your macro temporarily:
import warnings
warnings.simplefilter('error', DeprecationWarning)

This forces the macro to stop and output a full traceback pointing directly to the offending line.

2. Update Deprecated FreeCAD Core Methods

FreeCAD has gradually standardized its naming conventions and object handling methods. Common updates include:

  • Document Access:
    • Old: FreeCAD.activeDocument()
    • Current: FreeCAD.ActiveDocument or App.ActiveDocument
  • Object Retrieval:
    • Old: doc.getObject("Box").Shape.Faces
    • Current: Check validity using doc.getObject("Box") is not None before accessing properties. Avoid using hardcoded internal strings that may have changed across workbenches.
  • Vector and Placement Operations:
    • Old: Mathematical operations directly modifying tuple positions or obsolete vector properties.

    • Current: Use App.Vector and App.Placement explicitly. For example:

      import FreeCAD as App
      placement = App.Placement(App.Vector(0, 0, 10), App.Rotation(App.Vector(0, 0, 1), 45))
  • Workbench-Specific Imports (Draft, Part, TechDraw):
    • Many standalone functions in the Draft module have moved to sub-namespaces. For example, legacy calls like Draft.makeWire() are often redirected to draftmake.make_wire() in modern releases. Import modern submodules directly or rely on the unified Draft.make_wire aliases.

3. Migrate PySide and GUI Components

Older macros often rely on Python-Qt bindings that are no longer standard in modern FreeCAD builds (which use PySide2 or PySide6 depending on the build).

  • Use Universal Imports: Avoid importing directly from PyQt4, PyQt5, or unversioned PySide. Use FreeCAD's built-in PySide wrappers to ensure compatibility:
from PySide import QtGui, QtCore, QtWidgets

Note: In modern FreeCAD builds, FreeCAD maps the correct active PySide implementation automatically under the PySide namespace.

  • Class Relocations (Qt4/5 to Qt5/6):
    • Widgets previously in QtGui (like QPushButton, QDialog, QVBoxLayout) now belong to QtWidgets.

    • Update your references:

      # Legacy
      button = QtGui.QPushButton("Click")
      
      # Modern
      button = QtWidgets.QPushButton("Click")

4. Resolve Python 2 to Python 3 Incompatibilities

If an older macro hasn't been touched in several years, general Python deprecations may be mixed with FreeCAD-specific warnings:

  • Dictionary Methods: Replace .iteritems(), .iterkeys(), and .itervalues() with .items(), .keys(), and .values().
  • String Encodings: FreeCAD objects return standard UTF-8 strings in Python 3. Remove calls to unicode() and replace them with standard str().
  • Integer Division: Replace standard single slash / integer assumptions with // to prevent unwanted floating-point values when calculating coordinate indices.

5. Final Verification and Cleanup

Once legacy calls are refactored:

  1. Remove any temporary warnings.simplefilter('error', DeprecationWarning) statements added during testing.
  2. Re-run the macro from the Macro execution dialog (Macro → Macros...).
  3. Confirm that the macro executes without outputting yellow warning text to the Report View.
  4. Test the macro on a freshly created empty document to ensure it creates and updates geometry properly without relying on cached session states.