---
title: freecad-scripting-cheatsheet
tags: freecad, ose
---
# `freecad-scripting-cheatsheet`
In the spirit of a cheatsheet, little explanaton is given. Instead you see mostly code snippets along with the result.
## Docs
- Doxygen https://freecad.github.io/SourceDoc/modules.html
- Wiki
- https://wiki.freecadweb.org/Python_scripting_tutorial
- https://wiki.freecadweb.org/FreeCAD_Scripting_Basics
- https://wiki.freecadweb.org/Macros_recipes
- https://wiki.freecadweb.org/Scripts
- https://yorikvanhavre.gitbooks.io/a-freecad-manual/content/python_scripting/creating_and_manipulating_geometry.html
- http://staff.ltam.lu/feljc/software/freecad/fc_scripting_summary.pdf
## Scripting setup
- PAW macro https://wiki.freecadweb.org/Macro_Python_Assistant_Window
- https://wiki.freecadweb.org/Python_Development_Environment
## Querying (meta information)
```python=
obj.TypeId # FreeCAD-specific method
obj.isDerivedFrom("Part::Feature") # FreeCAD-specific method
```
```python=
>>> type(App.ActiveDocument)
<class 'App.Document'>
>>> type(App)
<class 'module'>
```
```python=
>>> print(dir()) # shows loaded modules
['App', 'Draft', 'Err', 'FCADLogger', 'FreeCAD', 'FreeCADGui', 'Gui', 'IntEnum', 'Log', 'MRU', 'MWB_wb_version', 'Msg', 'Part', 'PartGui', 'PathCommandGroup', 'Scheme', 'Sketcher', 'Start', 'StartPage', 'WebGui', 'WebPage', 'WebView', 'Workbench', 'Wrn', '_SoGroup_init', '_SoGroup_init_orig', '__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', '__warningregistry__', '_objs_', 'arc', 'c0', 'circle', 'cmake', 'coin', 'datetime', 'file', 'inspect', 'io', 'j', 'main_MWB_Icon', 'mycommitsMWB', 'myurlMWB', 'os', 'pl', 'rec', 'removeFromPath', 'rf', 's', 'setupSearchPaths', 'sys', 'traceback', 'webView']
>>> print(dir(FreeCAD)) # shows what's inside the FreeCAD module
['ActiveDocument', 'Axis', 'Base', 'BoundBox', 'ConfigDump', 'ConfigGet', 'ConfigSet', 'Console', 'Document', 'DocumentObject', 'DocumentObjectExtension', 'DocumentObjectGroup', 'DraftWorkingPlane', 'EndingAdd', 'EndingGet', 'Extension', 'ExtensionContainer', 'GeoFeature', 'GeoFeatureGroupExtension', 'GroupExtension', 'Gui', 'GuiUp', 'LinkBaseExtension', 'Logger', 'Material', 'Matrix', 'OriginGroupExtension', 'ParamGet', 'Part', 'Placement', 'PropertyContainer', 'Qt', 'Rotation', 'Units', 'Vector', 'Version', '__ModDirs__', '__cmake__', '__doc__', '__loader__', '__name__', '__package__', '__path__', '__spec__', '__unit_test__', '_importFromFreeCAD', 'activeDocument', 'activeDraftCommand', 'addDocumentObserver', 'addExportType', 'addImportType', 'changeExportModule', 'changeImportModule', 'checkAbort', 'checkLinkDepth', 'closeActiveTransaction', 'closeDocument', 'getActiveTransaction', 'getDependentObjects', 'getDocument', 'getExportType', 'getHelpDir', 'getHomePath', 'getImportType', 'getLinksTo', 'getLogLevel', 'getResourceDir', 'getUserAppDataDir', 'getUserMacroDir', 'isRestoring', 'listDocuments', 'loadFile', 'newDocument', 'open', 'openDocument', 'removeDocumentObserver', 'saveParameter', 'setActiveDocument', 'setActiveTransaction', 'setLogLevel', 'svgpatterns']
```
```python=
obj.__class_
>>> edge.__class__
<class 'Part.Edge'>
```
```python=
clazz.__base__
>>> Part.Edge.__base__
<class 'Part.Shape'>
```
```python=
import inspect
clazz.mro() # method resolution order
inspect.getmro(type(obj))
>>> Part.Edge.mro()
[<class 'Part.Edge'>, <class 'Part.Shape'>, <class 'Data.ComplexGeoData'>, <class 'Base.Persistence'>, <class 'Base.BaseClass'>, <class 'PyObjectBase'>, <class 'object'>]
>>> inspect.getmro(type(line))
(<class 'FeaturePython'>, <class 'Part.Part2DObject'>, <class 'Part.Feature'>, <class 'App.GeoFeature'>, <class 'App.DocumentObject'>, <class 'App.ExtensionContainer'>, <class 'App.PropertyContainer'>, <class 'Base.Persistence'>, <class 'Base.BaseClass'>, <class 'PyObjectBase'>, <class 'object'>)
```
### Imports: App vs. Gui
https://wiki.freecadweb.org/Object_API
https://wiki.freecadweb.org/ViewObject_API
```python=
import FreeCAD # App
import FreeCADGui # Gui
import FreeCAD as App
import FreeCADGui as Gui
import Part # Part workbench (Parts have Shape property)
import Mesh # Mesh workbench (Meshes have Mesh property)
# each App object has a correspondng Gui object
>>> App.ActiveDocument
<Document object at 0x5585f32d4a40>
>>> Gui.ActiveDocument
<GUI Document object at 0x5585f37a76e0>
>>> box.ViewObject ## corresponds to GUI's View tab
<View provider object at 0x5585f3978860>
```
### Document
https://wiki.freecadweb.org/FreeCADGui_API
https://wiki.freecadweb.org/FreeCAD_API
```python=
>>> App.ActiveDocument
<Document object at 0x5585f32d4a40>
>>> FreeCAD.ActiveDocument.supportedTypes() # types that can be instantiated
['App::DocumentObject', 'App::GeoFeature', 'App::FeatureTest', 'App::FeatureTestException', 'App::FeaturePython', 'App::GeometryPython', 'App::DocumentObjectGroup', 'App::DocumentObjectGroupPython', 'App::DocumentObjectFileIncluded', 'App::InventorObject', 'App::VRMLObject', 'App::Annotation', 'App::AnnotationLabel', 'App::MeasureDistance', 'App::MaterialObject', 'App::MaterialObjectPython', 'App::TextDocument', 'App::Placement', 'App::PlacementPython', 'App::OriginFeature', 'App::Plane', 'App::Line', 'App::Part', 'App::Origin', 'App::Link', 'App::LinkPython', 'App::LinkElement', 'App::LinkElementPython', 'App::LinkGroup', 'App::LinkGroupPython', 'Part::Feature', 'Part::FeatureExt', 'Part::BodyBase', 'Part::FeaturePython', 'Part::FeatureGeometrySet', 'Part::CustomFeature', 'Part::CustomFeaturePython', 'Part::Primitive', 'Part::Box', 'Part::Spline', 'Part::Boolean', 'Part::Common', 'Part::MultiCommon', 'Part::Cut', 'Part::Fuse', 'Part::MultiFuse', 'Part::Section', 'Part::FilletBase', 'Part::Fillet', 'Part::Chamfer', 'Part::Compound', 'Part::Compound2', 'Part::Extrusion', 'Part::Revolution', 'Part::Mirroring', 'Part::ImportStep', 'Part::ImportIges', 'Part::ImportBrep', 'Part::CurveNet', 'Part::Polygon', 'Part::Circle', 'Part::Ellipse', 'Part::Vertex', 'Part::Line', 'Part::Ellipsoid', 'Part::Plane', 'Part::Sphere', 'Part::Cylinder', 'Part::Prism', 'Part::RegularPolygon', 'Part::Cone', 'Part::Torus', 'Part::Helix', 'Part::Spiral', 'Part::Wedge', 'Part::Part2DObject', 'Part::Part2DObjectPython', 'Part::Face', 'Part::RuledSurface', 'Part::Loft', 'Part::Sweep', 'Part::Offset', 'Part::Offset2D', 'Part::Thickness', 'Part::Refine', 'Part::Reverse', 'Part::Datum', 'Drawing::FeaturePage', 'Drawing::FeatureView', 'Drawing::FeatureViewPart', 'Drawing::PageGroup', 'Drawing::FeatureProjection', 'Drawing::FeatureViewPartPython', 'Drawing::FeatureViewPython', 'Drawing::FeatureViewAnnotation', 'Drawing::FeatureViewSymbol', 'Drawing::FeatureClip', 'Drawing::FeatureViewSpreadsheet', 'Sketcher::SketchObjectSF', 'Sketcher::SketchObject', 'Sketcher::SketchObjectPython']
>>> App.ActiveDocument.Name # name does not change, this is not the file name
'Unnamed'
App.ActiveDocument.addObject('Part::Box','Box') # instantiate object and give it a name
App.ActiveDocument.ActiveObject.Label = "Cube"
App.ActiveDocument.recompute()
>>> App.ActiveDocument.getObject('Box').Label # transitive query by name, not label
'Cube'
>>> App.ActiveDocument.Box001.Label # shortform of the above
'Cube001'
```
### Base and Vectors (FreeCAD.Base.Vector)
https://wiki.freecadweb.org/Base_API
https://wiki.freecadweb.org/Vector_API
```python=
import FreeCAD
vec = FreeCAD.Vector(1, 2, 3)
>>> vec.z
3.0
```
### Draft
https://wiki.freecadweb.org/Topological_data_scripting
Most Draft objects are derived from [Part2DObject](https://wiki.freecadweb.org/Part_Part2DObject): "This basic Part::Part2DObject doesn't have a Proxy object so it can't be fully used for sub-classing. Therefore, for Python subclassing, you should create the Part::Part2DObjectPython object."
See [API reference](https://wiki.freecadweb.org/Draft_API).

```python=
>>> edge = Part.makeLine((0, 0, 0), (10, 0, 0)) # not a Draft Line: not editable, not upgradable
>>> edge
<Edge object at 0x557b0581a770>
>>> edge.ShapeType
'Edge'
>>> edge.TypeId # topological shape
'Part::TopoShape'
>>> edge.Vertexes
[<Vertex object at 0x5585f270e3d0>, <Vertex object at 0x5585f2c863e0>]
>>> edge.Vertex2.Point # Vertex2 is shortcut for Vertexes[1]
Vector (10.0, 0.0, 0.0)
>>> edge.Length # result is (always?) in mm
355.6
>>> edge.Faces # an edge has no face
[]
>>> Draft.draftify(edge) # cannot upgrade to a Draft Line
[]
```
```python=
>>> line = Draft.makeWire([(1,2,3),(4,5,6)]) # Draft Line
>>> line.Shape.Content # not a Shape (empty)
''
>>> line.TypeId
'Part::Part2DObjectPython'
>>> line.Start # and line.End
Vector (1.0, 2.0, 3.0)
```
### Units
https://wiki.freecadweb.org/Quantity#Python_scripting
* imperial: in - fo - yd
```python=
>>> from FreeCAD import Units
>>> edge.Length # edge with 2 vertices, result in internal system (mm/kg/s)
355.6
>>> Units.Quantity( str(edge.Length)+'mm' ) # make unit explicit
355.6 mm
>>> Units.Quantity( str(edge.Length)+'mm' ).getValueAs('in') # mm to inch
14.000000000000002
>>> Units.Quantity( str(edge.Length)+'mm' ).getValueAs(Units.Inch) # mm to inch
14.000000000000002
```
### Part
https://wiki.freecadweb.org/Part_API
Most Draft objects are derived from [TopoShape](https://wiki.freecadweb.org/Part_TopoShape). See [API reference](https://wiki.freecadweb.org/TopoShape_API).
A `Shape` has `Vertexes`, `Edges`, `Faces`, `Shells` and `Solids`.
The Part module has its own `'Part::Line'`, `'Part::Circle'`, etc. (TypeId strings).
Examples creating primitive shapes https://wiki.freecadweb.org/Part_Primitives#Scripting
```python=
>>> print(dir(Part.Shape))
['Area', 'BoundBox', 'CompSolids', 'Compounds', 'Content', 'Edges', 'Faces', 'Length', 'Matrix', 'MemSize', 'Module', 'Orientation', 'Placement', 'ShapeType', 'Shells', 'Solids', 'SubShapes', 'Tag', 'TypeId', 'Vertexes', 'Volume', 'Wires', '__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__', 'ancestorsOfType', 'check', 'childShapes', 'cleaned', 'common', 'complement', 'copy', 'countElement', 'cut', 'defeaturing', 'distToShape', 'dumpContent', 'dumpToString', 'exportBinary', 'exportBrep', 'exportBrepToString', 'exportIges', 'exportStep', 'exportStl', 'extrude', 'findPlane', 'fix', 'fixTolerance', 'fuse', 'generalFuse', 'getAllDerivedFrom', 'getElement', 'getFacesFromSubelement', 'getTolerance', 'globalTolerance', 'hashCode', 'importBinary', 'importBrep', 'importBrepFromString', 'inTolerance', 'isClosed', 'isCoplanar', 'isDerivedFrom', 'isEqual', 'isInfinite', 'isInside', 'isNull', 'isPartner', 'isSame', 'isValid', 'limitTolerance', 'makeChamfer', 'makeFillet', 'makeOffset2D', 'makeOffsetShape', 'makeParallelProjection', 'makePerspectiveProjection', 'makeShapeFromMesh', 'makeThickness', 'makeWires', 'mirror', 'multiFuse', 'nullify', 'oldFuse', 'optimalBoundingBox', 'overTolerance', 'project', 'proximity', 'read', 'reflectLines', 'removeInternalWires', 'removeShape', 'removeSplitter', 'replaceShape', 'restoreContent', 'reverse', 'reversed', 'revolve', 'rotate', 'rotated', 'scale', 'scaled', 'section', 'sewShape', 'slice', 'slices', 'tessellate', 'toNurbs', 'transformGeometry', 'transformShape', 'transformed', 'translate', 'translated', 'writeInventor']
```
```python=
>>> box.Shape.ShapeType
'Solid'
```
#### Template to create geometry
```python=
shp = Part.makeSphere(10)
obj = doc.addObject("Part::Feature", "MySphere") # or use shortform, see below
obj.Shape = shp ## "attach"
doc.recompute()
shp = Part.makeSphere(10)
Part.show(myshape) # shortform for above 3 lines
```
[:link:](https://wiki.freecadweb.org/Python_scripting_tutorial#Part)
### Selection (GUI)
```python=
>>> Gui.Selection.getSelection()[0].Name
'Box'
```
```python=
>>> Gui.Selection.getSelectionEx()[0]
<SelectionObject>
>>> Gui.Selection.getSelectionEx()[0].Object.Name
'Box'
```
### Scripted objects
https://wiki.freecadweb.org/Scripted_objects
https://wiki.freecadweb.org/FeaturePython_Objects
https://wiki.freecadweb.org/FeaturePython_methods
https://wiki.freecadweb.org/Creating_a_FeaturePython_Box,_Part_II