Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions .github/workflows/test_freecad.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
name: Test FreeCAD

on: [push, pull_request]

jobs:
tests:
runs-on: ubuntu-latest
steps:
- name: Checkout project
uses: actions/checkout@v4

- name: Install and Test
run: |
conda create -y -n freecad -c conda-forge python=3.11 freecad=0.21.2
conda init bash
source /usr/share/miniconda/bin/activate
conda activate freecad
python -m pip install --upgrade pip
pip install -e .
pip install -e .[dev]
python -m pytest -v tests/test_freecad.py
2 changes: 1 addition & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,4 @@ jobs:
pip3 install -e .[dev]
- name: Run tests
run: |
python3 -m pytest -v
python3 -m pytest -v --ignore=tests/test_freecad.py
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -127,3 +127,6 @@ dmypy.json

# Pyre type checker
.pyre/

# FreeCAD related files
updated_part*
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ dependencies = [
"typish",
"casadi",
"path",
"cadquery-freecad-import-plugin @ git+https://github.com/jmwright/cadquery-freecad-import-plugin.git"
]

[project.scripts]
Expand Down
50 changes: 45 additions & 5 deletions src/cq_cli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,55 @@
from cq_cli.cqcodecs import loader


def handle_freecad_file(file_path, params=None):
"""
Wrapper method that takes care of importing a FreeCAD file and applying parameters to it.
"""
from cadquery_freecad_import_plugin.plugin import import_freecad_part

# Construct a build result so that the rest of the code can handle it
build_result = cq.cqgi.BuildResult()

# Only apply parameters if there are any
if params != None and len(params) > 0:
# Assemble the FreeCAD params
freecad_params = {}
for key in params:
freecad_params[key] = {"value": params[key], "units": "mm"}

# Import the FreeCAD file using the parametric method
result = import_freecad_part(file_path, freecad_params)
shape_result = cq.cqgi.ShapeResult()
shape_result.shape = result
build_result.results.append(shape_result)
build_result.success = True
else:
# Import the FreeCAD file without applying parameters
result = import_freecad_part(file_path)
shape_result = cq.cqgi.ShapeResult()
shape_result.shape = result
build_result.results.append(shape_result)
build_result.success = True

return build_result


def build_and_parse(script_str, params, errfile, expression):
"""
Uses CQGI to parse and build a script, substituting in parameters if any were supplied.
"""

# We need to do a broad try/catch to let the user know if something higher-level fails
try:
# Do the CQGI handling of the script here and, if successful, pass the build result to the codec
if expression != None:
script_str += "\nshow_object({expr})".format(expr=expression)
cqModel = cqgi.parse(script_str)
build_result = cqModel.build(params)
# If we have a freecad file, handle it differently
if script_str.lower().endswith(".fcstd"):
build_result = handle_freecad_file(script_str, params)
else:
# Do the CQGI handling of the script here and, if successful, pass the build result to the codec
if expression != None:
script_str += "\nshow_object({expr})".format(expr=expression)
cqModel = cqgi.parse(script_str)
build_result = cqModel.build(params)

# Handle the case of the build not being successful, otherwise pass the codec the build result
if not build_result.success:
Expand Down Expand Up @@ -81,6 +119,8 @@ def get_script_from_infile(infile, outfile, errfile):
if infile == None:
# Grab the string from stdin
script_str = sys.stdin.read()
elif infile.lower().endswith(".fcstd"):
script_str = infile
else:
with open(infile, "r") as file:
script_str = file.read()
Expand Down
41 changes: 41 additions & 0 deletions tests/test_freecad.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import tests.test_helpers as helpers


def test_static_freecad_file():
"""
Basic test of the FreeCAD (FCStd) codec plugin.
"""
test_file = helpers.get_test_file_location("shelf.FCStd")

command = [
"python",
"src/cq_cli/main.py",
"--codec",
"step",
"--infile",
test_file,
]
out, err, exitcode = helpers.cli_call(command)

assert "ISO-10303-21;" in out.decode()


def test_parametric_freecad_file():
"""
Basic test of the FreeCAD (FCStd) codec plugin.
"""
test_file = helpers.get_test_file_location("shelf.FCStd")

command = [
"python",
"src/cq_cli/main.py",
"--codec",
"step",
"--params",
"internal_rail_spacing:152.4;",
"--infile",
test_file,
]
out, err, exitcode = helpers.cli_call(command)

assert "ISO-10303-21;" in out.decode()
Binary file added tests/testdata/shelf.FCStd
Binary file not shown.