Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/jinja2 templates #41

Merged
merged 3 commits into from
Jan 7, 2024
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
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,6 @@
"python.terminal.executeInFileDir": true,
"python.terminal.launchArgs": [
],
"OcpCadViewer.advanced.autostart": false
"OcpCadViewer.advanced.autostart": false,
"yaml.format.bracketSpacing": false // prevent YAML formatter from breaking Jinja2 templates
}
2 changes: 1 addition & 1 deletion examples/assembly_assy/logo_embedded.assy
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ links:
package: example_part_cadquery_logo
name: head_half_2
location: [[0,0,0], [0,0,1], -90]
name: head
name: {{name}}_head
location: [[0,0,25], [1,0,0], 0]
- part: bolt
package: example_part_step
Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ progress==1.6
ruamel.yaml==0.18.5
packaging==23.1
setuptools
jinja2
1 change: 1 addition & 0 deletions src/partcad/assembly_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class AssemblyFactory:
def __init__(self, ctx, project, assembly_config, extension=""):
self.ctx = ctx
self.project = project
self.assembly_config = assembly_config
self.name = assembly_config["name"]

self.path = self.name + extension
Expand Down
22 changes: 19 additions & 3 deletions src/partcad/assembly_factory_assy.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
#

import build123d as b3d
import copy
from jinja2 import Template
import logging
import os
import yaml
Expand All @@ -26,8 +26,21 @@ def __init__(self, ctx, project, assembly_config):
def instantiate(self, assembly):
self.assy = {}
if os.path.exists(self.path):
# Read the body of the configuration file
fp = open(self.path, "r")
config = fp.read()
fp.close()

# Resolve Jinja templates
template = Template(config)
config = template.render(
name=self.assembly_config["name"],
)
self.config_text = config

# Parse the resulting config
try:
self.assy = yaml.safe_load(open(self.path))
self.assy = yaml.safe_load(config)
except Exception as e:
logging.error("ERROR: Failed to parse the assembly file %s" % self.path)
if self.assy is None:
Expand Down Expand Up @@ -72,4 +85,7 @@ def handle_node(self, assembly, node):
part_name = node["part"]
item = self.ctx.get_part(part_name, package_name)

assembly.add(item, name, location)
if not item is None:
assembly.add(item, name, location)
else:
logging.error("Part not found: %s" % name)
2 changes: 1 addition & 1 deletion src/partcad/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ class Context(project_config.Configuration):

def __init__(self, config_path="."):
"""Initializes the context and imports the root project."""
super().__init__(config_path)
super().__init__(consts.THIS, config_path)
self.runtimes_python = {}

if os.path.isdir(config_path):
Expand Down
4 changes: 2 additions & 2 deletions src/partcad/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@


class Project(project_config.Configuration):
def __init__(self, ctx, path):
super().__init__(path)
def __init__(self, ctx, import_config_name, path):
super().__init__(import_config_name, path)
self.ctx = ctx

# The 'path' parameter is the config filename or the directory
Expand Down
20 changes: 17 additions & 3 deletions src/partcad/project_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#
# Licensed under Apache License, Version 2.0.

from jinja2 import Template
import json
import logging
import os
Expand All @@ -17,7 +18,7 @@


class Configuration:
def __init__(self, config_path=DEFAULT_CONFIG_FILENAME):
def __init__(self, import_config_name, config_path=DEFAULT_CONFIG_FILENAME):
self.config_obj = {}
self.config_dir = config_path
self.config_path = config_path
Expand All @@ -33,10 +34,23 @@ def __init__(self, config_path=DEFAULT_CONFIG_FILENAME):
)
return

# Read the body of the configuration file
fp = open(self.config_path, "r")
config = fp.read()
fp.close()

# Resolve Jinja templates
template = Template(config)
config = template.render(
package_name=import_config_name,
)
self.config_text = config

# Parse the config
if self.config_path.endswith(".yaml"):
self.config_obj = yaml.safe_load(open(self.config_path, "r"))
self.config_obj = yaml.safe_load(config)
if self.config_path.endswith(".json"):
self.config_obj = json.load(open(self.config_path, "r"))
self.config_obj = json.load(config)

# option: "partcad"
# description: the version of PartCAD required to handle this package
Expand Down
2 changes: 1 addition & 1 deletion src/partcad/project_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def __init__(self, ctx, parent, import_config_obj, name):

def _create(self, config):
# TODO(clairbee): Finalize the config object if necessary
self.project = p.Project(self.ctx, self.path)
self.project = p.Project(self.ctx, self.import_config_name, self.path)

def _save(self):
self.ctx.projects[self.import_config_name] = self.project
4 changes: 4 additions & 0 deletions tests/unit/data/project_config_template.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
parts:
{{package_name}}:
type: cadquery
path: ../../../examples/part_cadquery_primitive/cube.py
17 changes: 17 additions & 0 deletions tests/unit/test_project_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,20 @@ def test_project_config_version_2():
assert False, "Invalid configuration file did not cause an exception"
except:
_ignore = True


def test_project_config_template():
ctx = pc.init("tests/partcad-examples.yaml")
this = ctx.get_project(pc.THIS)
ctx.import_project(
this,
{
"name": "that",
"type": "local",
"path": "unit/data/project_config_template.yaml",
},
)
# In this test case, the template is used to name the part the same name as
# the package is called.
part = ctx.get_part("that", "that")
assert not part is None