naming template
This commit is contained in:
parent
31d34577e7
commit
926da63dd8
6 changed files with 314 additions and 27 deletions
|
|
@ -328,6 +328,19 @@ class SLICENODE_MeshToPdf(ExecSliceNode):
|
|||
bl_label = "Mesh to PDF"
|
||||
button_label = "Generate PDF"
|
||||
|
||||
template: str = NfStringProperty(
|
||||
name="Template",
|
||||
default="{object_name}-{size_x_mm}x{size_y_mm}-{today_date_iso}.pdf",
|
||||
)
|
||||
|
||||
@property
|
||||
def filename_template(self) -> str:
|
||||
return getattr(self, "template", "{object_name}-{size_x_mm}x{size_y_mm}-{today_date_iso}.pdf")
|
||||
|
||||
@filename_template.setter
|
||||
def filename_template(self, value: str) -> None:
|
||||
self.template = value
|
||||
|
||||
draw_wireframe: bool = NfBoolProperty(name="Wireframe", default=True)
|
||||
draw_boundary: bool = NfBoolProperty(name="Boundary (1 Face)", default=False)
|
||||
draw_contour: bool = NfBoolProperty(name="Contour", default=False)
|
||||
|
|
@ -392,6 +405,8 @@ class SLICENODE_MeshToPdf(ExecSliceNode):
|
|||
def draw_buttons(self, context, layout):
|
||||
super().draw_buttons(context, layout)
|
||||
|
||||
layout.prop(self, "template")
|
||||
|
||||
# Technical Drawing Header subpanel (collapsible, collapsed by default)
|
||||
layout.prop(self, "show_header", text="Technical Drawing Header", icon='TRIA_DOWN' if self.show_header else 'TRIA_RIGHT')
|
||||
if self.show_header:
|
||||
|
|
@ -443,7 +458,12 @@ class SLICENODE_MeshToPdf(ExecSliceNode):
|
|||
|
||||
def evaluate(self, operator=None):
|
||||
import datetime
|
||||
from ...pdf_exporter import extract_unique_top_view_edges, export_mesh_to_pdf, get_first_object_name
|
||||
from ...pdf_exporter import (
|
||||
extract_unique_top_view_edges,
|
||||
export_mesh_to_pdf,
|
||||
format_pdf_filename_template,
|
||||
get_first_object_name,
|
||||
)
|
||||
|
||||
geom = self.resolve("Geometry")
|
||||
slice_paths = self.resolve("Paths")
|
||||
|
|
@ -485,25 +505,6 @@ class SLICENODE_MeshToPdf(ExecSliceNode):
|
|||
|
||||
is_single_pdf_file = len(primary_items) == 1 and folder_path.suffix.lower() == ".pdf"
|
||||
|
||||
if is_single_pdf_file:
|
||||
os.makedirs(folder_path.parent, exist_ok=True)
|
||||
target_list = [(primary_items[0], str(folder_path))]
|
||||
else:
|
||||
out_dir = folder_path if folder_path.suffix == "" else folder_path.parent
|
||||
os.makedirs(out_dir, exist_ok=True)
|
||||
target_list = []
|
||||
for i, target_item in enumerate(primary_items):
|
||||
if isinstance(target_item, SlicingGroup) and target_item.collections:
|
||||
raw_name = "_".join(target_item.collections.keys())
|
||||
elif hasattr(target_item, 'name') and getattr(target_item, 'name'):
|
||||
raw_name = str(getattr(target_item, 'name'))
|
||||
else:
|
||||
raw_name = f"object_{i}"
|
||||
|
||||
name_part = raw_name.split('.')[0] if raw_name else f"object_{i}"
|
||||
filename = f"{name_part}.pdf"
|
||||
target_list.append((target_item, str(out_dir / filename)))
|
||||
|
||||
# Automatic scene scale determination
|
||||
scale_str = "1:1"
|
||||
try:
|
||||
|
|
@ -530,7 +531,9 @@ class SLICENODE_MeshToPdf(ExecSliceNode):
|
|||
"scale": scale_str,
|
||||
}
|
||||
|
||||
for target_item, filepath in target_list:
|
||||
template = getattr(self, "template", None) or getattr(self, "filename_template", None) or "{object_name}-{size_x_mm}x{size_y_mm}-{today_date_iso}.pdf"
|
||||
|
||||
for i, target_item in enumerate(primary_items):
|
||||
if has_raw_geom:
|
||||
current_raw_geom = target_item
|
||||
current_slice_paths = slice_paths
|
||||
|
|
@ -558,13 +561,10 @@ class SLICENODE_MeshToPdf(ExecSliceNode):
|
|||
if len(sp_e) > 0:
|
||||
edges_2d = np.concatenate([edges_2d, sp_e], axis=0) if len(edges_2d) > 0 else sp_e
|
||||
|
||||
if len(edges_2d) == 0:
|
||||
if operator: operator.report({'WARNING'}, f"Geometry for {os.path.basename(filepath)} has no valid 2D top-view wireframe edges")
|
||||
|
||||
try:
|
||||
export_mesh_to_pdf(
|
||||
exporter = export_mesh_to_pdf(
|
||||
edges_2d=edges_2d,
|
||||
filepath=filepath,
|
||||
filepath=None,
|
||||
draw_wireframe=self.draw_wireframe,
|
||||
draw_boundary=self.draw_boundary,
|
||||
draw_contour=self.draw_contour,
|
||||
|
|
@ -585,6 +585,36 @@ class SLICENODE_MeshToPdf(ExecSliceNode):
|
|||
draw_grid_xz=getattr(self, "draw_grid_xz", False),
|
||||
draw_grid_yz=getattr(self, "draw_grid_yz", False),
|
||||
)
|
||||
|
||||
if is_single_pdf_file:
|
||||
os.makedirs(folder_path.parent, exist_ok=True)
|
||||
filepath = str(folder_path)
|
||||
else:
|
||||
out_dir = folder_path if folder_path.suffix == "" else folder_path.parent
|
||||
os.makedirs(out_dir, exist_ok=True)
|
||||
if isinstance(target_item, SlicingGroup) and target_item.collections:
|
||||
raw_name = "_".join(target_item.collections.keys())
|
||||
elif hasattr(target_item, 'name') and getattr(target_item, 'name'):
|
||||
raw_name = str(getattr(target_item, 'name'))
|
||||
else:
|
||||
raw_name = f"object_{i}"
|
||||
|
||||
object_name = raw_name.split('.')[0] if raw_name else f"object_{i}"
|
||||
filename = format_pdf_filename_template(
|
||||
template=template,
|
||||
object_name=object_name,
|
||||
size_x_mm=round(exporter.page_w_mm),
|
||||
size_y_mm=round(exporter.page_h_mm),
|
||||
today_date_iso=datetime.date.today().isoformat(),
|
||||
target_item=target_item,
|
||||
header_info=current_header_info,
|
||||
)
|
||||
filepath = str(out_dir / filename)
|
||||
|
||||
if len(edges_2d) == 0:
|
||||
if operator: operator.report({'WARNING'}, f"Geometry for {os.path.basename(filepath)} has no valid 2D top-view wireframe edges")
|
||||
|
||||
exporter.export(filepath)
|
||||
if operator: operator.report({'INFO'}, f"Mesh PDF saved to {filepath}")
|
||||
except Exception as e:
|
||||
if operator: operator.report({'ERROR'}, f"PDF Generation Error: {str(e)}")
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ from .sa2_measures import (
|
|||
from .sizing import MM_TO_PT
|
||||
from .writer import (
|
||||
export_mesh_to_pdf,
|
||||
format_pdf_filename_template,
|
||||
PDFElement,
|
||||
PDFBackgroundElement,
|
||||
PDFGridElement,
|
||||
|
|
@ -61,6 +62,7 @@ from .writer import (
|
|||
__all__ = [
|
||||
# Main exporters & element classes
|
||||
"export_mesh_to_pdf",
|
||||
"format_pdf_filename_template",
|
||||
"PDFElement",
|
||||
"PDFBackgroundElement",
|
||||
"PDFGridElement",
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ Formats vector edge arrays and renders scalable PDF files with grid overlays, te
|
|||
import datetime
|
||||
import math
|
||||
import os
|
||||
import re
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
import numpy as np
|
||||
|
|
@ -15,6 +16,7 @@ from .metadata import (
|
|||
extract_object_bounding_boxes,
|
||||
extract_settings_items,
|
||||
get_first_attribute_value,
|
||||
get_first_object_name,
|
||||
resolve_object_properties,
|
||||
)
|
||||
from .geometry import (
|
||||
|
|
@ -39,6 +41,94 @@ from .sizing import (
|
|||
from .pdf_utils import PdfStream
|
||||
|
||||
|
||||
def format_pdf_filename_template(
|
||||
template: str | None = None,
|
||||
object_name: str = "",
|
||||
size_x_mm: float = 0.0,
|
||||
size_y_mm: float = 0.0,
|
||||
today_date_iso: str | None = None,
|
||||
target_item: Any = None,
|
||||
header_info: dict[str, Any] | None = None,
|
||||
) -> str:
|
||||
"""
|
||||
Format a file naming template for PDF export.
|
||||
|
||||
Default template:
|
||||
{object_name}-{size_x_mm}x{size_y_mm}-{today_date_iso}.pdf
|
||||
|
||||
Supported placeholders:
|
||||
- {object_name}, {name}, {obj_name}, {part_name}: Name of the object
|
||||
- {size_x_mm}, {size_x}, {width_mm}, {width}: Total width in mm of the whole PDF
|
||||
- {size_y_mm}, {size_y}, {height_mm}, {height}: Total height in mm of the whole PDF
|
||||
- {today_date_iso}, {date_iso}, {today_date}, {date}, {today}: Current date in ISO format (YYYY-MM-DD)
|
||||
- Custom object attributes (via get_first_attribute_value) or header_info keys
|
||||
|
||||
Args:
|
||||
template: The template format string.
|
||||
object_name: The object name.
|
||||
size_x_mm: Whole PDF width in mm.
|
||||
size_y_mm: Whole PDF height in mm.
|
||||
today_date_iso: ISO 8601 date string.
|
||||
target_item: SlicingObject / SlicingGroup / SlicePaths item for attribute lookups.
|
||||
header_info: Optional dictionary containing technical header drawing metadata.
|
||||
|
||||
Returns:
|
||||
The formatted PDF filename ending in .pdf.
|
||||
"""
|
||||
tmpl = (template or "").strip()
|
||||
if not tmpl:
|
||||
tmpl = "{object_name}-{size_x_mm}x{size_y_mm}-{today_date_iso}.pdf"
|
||||
|
||||
if today_date_iso is None:
|
||||
today_date_iso = datetime.date.today().isoformat()
|
||||
|
||||
sx_str = f"{round(size_x_mm, 2):g}"
|
||||
sy_str = f"{round(size_y_mm, 2):g}"
|
||||
|
||||
context: dict[str, Any] = {
|
||||
"object_name": object_name,
|
||||
"name": object_name,
|
||||
"obj_name": object_name,
|
||||
"part_name": object_name,
|
||||
"size_x_mm": sx_str,
|
||||
"size_x": sx_str,
|
||||
"width_mm": sx_str,
|
||||
"width": sx_str,
|
||||
"size_y_mm": sy_str,
|
||||
"size_y": sy_str,
|
||||
"height_mm": sy_str,
|
||||
"height": sy_str,
|
||||
"today_date_iso": today_date_iso,
|
||||
"date_iso": today_date_iso,
|
||||
"today_date": today_date_iso,
|
||||
"date": today_date_iso,
|
||||
"today": today_date_iso,
|
||||
}
|
||||
|
||||
def replace_match(match: re.Match[str]) -> str:
|
||||
key = match.group(1).strip()
|
||||
if key in context:
|
||||
return str(context[key])
|
||||
if key.lower() in context:
|
||||
return str(context[key.lower()])
|
||||
if target_item is not None:
|
||||
val = get_first_attribute_value(target_item, key)
|
||||
if val is not None:
|
||||
if isinstance(val, float):
|
||||
return f"{round(val, 2):g}"
|
||||
return str(val)
|
||||
if header_info and key in header_info:
|
||||
return str(header_info[key])
|
||||
return ""
|
||||
|
||||
formatted = re.sub(r"\{([^}]+)\}", replace_match, tmpl).strip()
|
||||
if not formatted:
|
||||
formatted = f"{object_name or 'object'}.pdf"
|
||||
if not formatted.lower().endswith(".pdf"):
|
||||
formatted = f"{formatted}.pdf"
|
||||
return formatted
|
||||
|
||||
|
||||
def render_technical_header_table(
|
||||
s: PdfStream,
|
||||
page_w_pt: float,
|
||||
|
|
@ -710,6 +800,7 @@ class export_mesh_to_pdf:
|
|||
self,
|
||||
edges_2d: NDArray[np.float64] | None = None,
|
||||
filepath: str | Path | None = None,
|
||||
template: str | None = None,
|
||||
draw_wireframe: bool = True,
|
||||
draw_boundary: bool = False,
|
||||
draw_contour: bool = False,
|
||||
|
|
@ -747,6 +838,7 @@ class export_mesh_to_pdf:
|
|||
self.projection_plane = "XY" if draw_grid_xy else ("XZ" if draw_grid_xz else "YZ")
|
||||
self.edges_2d = edges_2d if edges_2d is not None else np.empty((0, 2, 2), dtype=np.float64)
|
||||
self.filepath = filepath
|
||||
self.template = template
|
||||
self.draw_wireframe = draw_wireframe
|
||||
self.draw_boundary = draw_boundary
|
||||
self.draw_contour = draw_contour
|
||||
|
|
@ -784,7 +876,29 @@ class export_mesh_to_pdf:
|
|||
]
|
||||
|
||||
if filepath is not None:
|
||||
self.export(filepath)
|
||||
target_p = Path(filepath)
|
||||
if target_p.is_dir() or target_p.suffix.lower() != ".pdf":
|
||||
out_dir = target_p if target_p.suffix == "" else target_p.parent
|
||||
tmpl = self.template or "{object_name}-{size_x_mm}x{size_y_mm}-{today_date_iso}.pdf"
|
||||
primary_obj_name = ""
|
||||
if self.slicing_objs:
|
||||
for so in self.slicing_objs:
|
||||
if hasattr(so, "name") and getattr(so, "name"):
|
||||
primary_obj_name = str(getattr(so, "name")).split('.')[0]
|
||||
break
|
||||
if not primary_obj_name:
|
||||
primary_obj_name = (get_first_object_name(self.raw_geometry) or get_first_object_name(self.slice_paths) or "object").split('.')[0]
|
||||
fname = format_pdf_filename_template(
|
||||
template=tmpl,
|
||||
object_name=primary_obj_name,
|
||||
size_x_mm=self.page_w_mm,
|
||||
size_y_mm=self.page_h_mm,
|
||||
target_item=self.raw_geometry or self.slice_paths,
|
||||
header_info=self.header_info,
|
||||
)
|
||||
self.export(out_dir / fname)
|
||||
else:
|
||||
self.export(filepath)
|
||||
|
||||
def _prepare_geometry_and_layout(self) -> None:
|
||||
objs_raw = get_all_slicing_objects(self.raw_geometry)
|
||||
|
|
@ -1026,6 +1140,10 @@ class export_mesh_to_pdf:
|
|||
w_total_mm = w_grid_mm + w_table_mm + 2.0 * self.total_margin_mm
|
||||
h_total_mm = max(h_grid_mm, h_table_col_mm) + 2.0 * self.total_margin_mm
|
||||
|
||||
self.w_total_mm = w_total_mm
|
||||
self.h_total_mm = h_total_mm
|
||||
self.page_w_mm = w_total_mm
|
||||
self.page_h_mm = h_total_mm
|
||||
self.page_w_pt = w_total_mm * MM_TO_PT
|
||||
self.page_h_pt = h_total_mm * MM_TO_PT
|
||||
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ This file provides a mapping of modules to their primary responsibilities and ke
|
|||
- `extract_slicing_object_features()`: Feature detection for circular bores (Ø), arcs (R), chamfers (C), and steps.
|
||||
- `writer.py`:
|
||||
- `export_mesh_to_pdf`: Class for building scalable 1:1 vector PDF files. Uses a modular element architecture with element subclasses (`PDFElement`, `PDFLegendElement`, `PDFHeaderTableElement`, `PDFGridElement`, `PDFGeometryElement`, `PDFBoundingBoxElement`, `PDFSA2MeasuresElement`, `PDFObjectLabelsElement`, `PDFBackgroundElement`).
|
||||
- `format_pdf_filename_template`: Formats file naming templates with placeholders for object names, whole PDF dimensions in mm (`{size_x_mm}`, `{size_y_mm}`), and ISO dates (`{today_date_iso}`).
|
||||
|
||||
## `/infra` (Blender Integration)
|
||||
|
||||
|
|
|
|||
|
|
@ -140,6 +140,7 @@ All nodes are found in the **Add (Shift+A)** menu under the **SliceNodes** categ
|
|||
- **Geometry**: Generic geometry input socket (accepts `SLICESOCK_Mesh`, `SLICESOCK_Paths`, or `SLICESOCK_Geometry`).
|
||||
- **Settings**: Input socket accepting configuration settings or property items.
|
||||
- **Mesh to PDF**: Generates a 1:1 true-scale 2D top-view (+Z orthographic) vector PDF from a `SlicingGroup` or `SlicingCollection` with a custom grid and background color. Subpanel menus are collapsed by default.
|
||||
- **Template**: File naming template string for exported PDF files when saving to a folder (default: `{object_name}-{size_x_mm}x{size_y_mm}-{today_date_iso}.pdf`). Supports placeholders `{object_name}`, `{size_x_mm}`, `{size_y_mm}` (the whole PDF page dimensions in mm), `{today_date_iso}` (current ISO date `YYYY-MM-DD`), and custom object attributes.
|
||||
- **Technical Drawing Header**: Collapsible menu containing string inputs for technical drawing info (Company, Part Name, Drawing No., Author, Revision, Material, Tolerance). If Part Name is left empty, it automatically defaults to the name of the first object being rendered. Automatically computes ISO date and scale length (`1:1`). Renders an ISO/DIN technical drawing header table on the bottom-right of the drawing.
|
||||
- **Geometry**: Input socket accepting a single geometry (`SlicingGroup`, `SlicingCollection`, or `SlicingObject`). Join multiple geometries using Join Geometry nodes.
|
||||
- **SlicePaths**: Input socket accepting `SlicePaths` (reserved for path rendering).
|
||||
|
|
|
|||
|
|
@ -1742,6 +1742,141 @@ class TestPdfExporter(unittest.TestCase):
|
|||
self.assertFalse(getattr(node, "draw_grid_xz", False))
|
||||
self.assertFalse(getattr(node, "draw_grid_yz", False))
|
||||
|
||||
def test_format_pdf_filename_template(self):
|
||||
from NodeSlicer.core.pdf_exporter import format_pdf_filename_template
|
||||
import datetime
|
||||
|
||||
today = datetime.date.today().isoformat()
|
||||
|
||||
# 1. Default template
|
||||
fname = format_pdf_filename_template(
|
||||
template="{object_name}-{size_x_mm}x{size_y_mm}-{today_date_iso}.pdf",
|
||||
object_name="PartA",
|
||||
size_x_mm=140.0,
|
||||
size_y_mm=95.0,
|
||||
today_date_iso="2026-08-31",
|
||||
)
|
||||
self.assertEqual(fname, "PartA-140x95-2026-08-31.pdf")
|
||||
|
||||
# 2. None or empty template -> defaults to {object_name}-{size_x_mm}x{size_y_mm}-{today_date_iso}.pdf
|
||||
fname_default = format_pdf_filename_template(
|
||||
template="",
|
||||
object_name="PartB",
|
||||
size_x_mm=200.5,
|
||||
size_y_mm=100.25,
|
||||
today_date_iso="2026-08-31",
|
||||
)
|
||||
self.assertEqual(fname_default, "PartB-200.5x100.25-2026-08-31.pdf")
|
||||
|
||||
# 3. Dynamic today_date_iso when not provided
|
||||
fname_today = format_pdf_filename_template(
|
||||
template="{object_name}_{today_date_iso}",
|
||||
object_name="Plate",
|
||||
size_x_mm=50.0,
|
||||
size_y_mm=50.0,
|
||||
)
|
||||
self.assertEqual(fname_today, f"Plate_{today}.pdf")
|
||||
|
||||
# 4. Aliases: {name}, {width_mm}, {height_mm}, {date}
|
||||
fname_aliases = format_pdf_filename_template(
|
||||
template="{name}_W{width_mm}_H{height_mm}_{date}.pdf",
|
||||
object_name="Bracket",
|
||||
size_x_mm=120.0,
|
||||
size_y_mm=80.0,
|
||||
today_date_iso="2026-01-15",
|
||||
)
|
||||
self.assertEqual(fname_aliases, "Bracket_W120_H80_2026-01-15.pdf")
|
||||
|
||||
# 5. Missing .pdf extension should be appended
|
||||
fname_no_ext = format_pdf_filename_template(
|
||||
template="{object_name}_spec",
|
||||
object_name="Gear",
|
||||
size_x_mm=60.0,
|
||||
size_y_mm=60.0,
|
||||
)
|
||||
self.assertEqual(fname_no_ext, "Gear_spec.pdf")
|
||||
|
||||
# 6. Target item attributes
|
||||
so = SlicingObject()
|
||||
so.attributes = {"material": {"values": np.array(["Aluminum"]), "domain": "OBJECT", "type": "STRING"}}
|
||||
fname_attr = format_pdf_filename_template(
|
||||
template="{object_name}_{material}.pdf",
|
||||
object_name="Rod",
|
||||
size_x_mm=30.0,
|
||||
size_y_mm=10.0,
|
||||
target_item=so,
|
||||
)
|
||||
self.assertEqual(fname_attr, "Rod_Aluminum.pdf")
|
||||
|
||||
def test_mesh_to_pdf_template_property_and_evaluation_to_directory(self):
|
||||
from NodeSlicer.core.nodeslicer.nodes.output import SLICENODE_MeshToPdf
|
||||
import datetime
|
||||
|
||||
# Check annotations
|
||||
self.assertIn("template", SLICENODE_MeshToPdf.__annotations__)
|
||||
node = SLICENODE_MeshToPdf()
|
||||
self.assertEqual(getattr(node, "template", ""), "{object_name}-{size_x_mm}x{size_y_mm}-{today_date_iso}.pdf")
|
||||
|
||||
# Check alias filename_template
|
||||
self.assertEqual(node.filename_template, "{object_name}-{size_x_mm}x{size_y_mm}-{today_date_iso}.pdf")
|
||||
node.filename_template = "custom_{object_name}.pdf"
|
||||
self.assertEqual(node.template, "custom_{object_name}.pdf")
|
||||
|
||||
# Test evaluation with folder destination (directory)
|
||||
node_exec = SLICENODE_MeshToPdf.__new__(SLICENODE_MeshToPdf)
|
||||
node_exec.template = "{object_name}-{size_x_mm}x{size_y_mm}-{today_date_iso}.pdf"
|
||||
node_exec.draw_wireframe = True
|
||||
node_exec.draw_boundary = False
|
||||
node_exec.draw_contour = False
|
||||
node_exec.draw_crease = False
|
||||
node_exec.crease_angle = 30.0
|
||||
node_exec.draw_bbox = False
|
||||
node_exec.draw_sa2_holes = False
|
||||
node_exec.draw_header = False
|
||||
node_exec.header_company = ""
|
||||
node_exec.header_part_name = ""
|
||||
node_exec.header_drawing_number = ""
|
||||
node_exec.header_author = ""
|
||||
node_exec.header_revision = "A"
|
||||
node_exec.header_material = ""
|
||||
node_exec.header_tolerance = ""
|
||||
node_exec.font_size = 0.0
|
||||
node_exec.margin = 10.0
|
||||
node_exec.wire_color = (0.0, 0.0, 0.0)
|
||||
node_exec.bg_color = (1.0, 1.0, 1.0)
|
||||
node_exec.bbox_color = (0.0, 0.0, 1.0)
|
||||
|
||||
class MockOperator:
|
||||
def __init__(self):
|
||||
self.reports = []
|
||||
def report(self, type_set, message):
|
||||
self.reports.append((type_set, message))
|
||||
|
||||
op = MockOperator()
|
||||
so = SlicingObject()
|
||||
so.name = "MyComponent"
|
||||
so.mesh = np.array([[[0.0, 0.0, 0.0], [50.0, 0.0, 0.0], [0.0, 50.0, 0.0]]], dtype=np.float64)
|
||||
|
||||
with tempfile.TemporaryDirectory() as tmpdir:
|
||||
resolved_inputs = {
|
||||
"Geometry": so,
|
||||
"Paths": None,
|
||||
"Folder": tmpdir,
|
||||
"Settings": None,
|
||||
}
|
||||
node_exec.resolve = lambda fieldname: resolved_inputs.get(fieldname)
|
||||
res = node_exec.evaluate(operator=op)
|
||||
self.assertEqual(res, "ok")
|
||||
|
||||
# Check exported file in directory
|
||||
files = os.listdir(tmpdir)
|
||||
self.assertEqual(len(files), 1)
|
||||
generated_name = files[0]
|
||||
today_str = datetime.date.today().isoformat()
|
||||
self.assertTrue(generated_name.startswith("MyComponent-"))
|
||||
self.assertTrue(generated_name.endswith(f"-{today_str}.pdf"))
|
||||
self.assertIn("x", generated_name)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue