Fix #3647. Fix bug where Windows .exe suffix needed to be explicit in commands. No more eval, and commands must now be provided in json form, and variables should be given as simple strings.

This commit is contained in:
Dion Moult
2023-08-31 22:28:18 +10:00
parent f1f5b7627c
commit 116ad507cf
3 changed files with 40 additions and 37 deletions
@@ -70,15 +70,6 @@ class profile:
print(self.task, timer() - self.start) print(self.task, timer() - self.start)
def open_with_user_command(user_command, path):
if user_command:
commands = eval(user_command)
for command in commands:
subprocess.Popen(command)
else:
webbrowser.open("file://" + path)
class Operator: class Operator:
def execute(self, context): def execute(self, context):
IfcStore.execute_ifc_operator(self, context) IfcStore.execute_ifc_operator(self, context)
@@ -269,7 +260,7 @@ class CreateDrawing(bpy.types.Operator):
with profile("Combine SVG layers"): with profile("Combine SVG layers"):
svg_path = self.combine_svgs(context, underlay_svg, linework_svg, annotation_svg) svg_path = self.combine_svgs(context, underlay_svg, linework_svg, annotation_svg)
open_with_user_command(context.preferences.addons["blenderbim"].preferences.svg_command, svg_path) tool.Drawing.open_with_user_command(context.preferences.addons["blenderbim"].preferences.svg_command, svg_path)
if self.print_all: if self.print_all:
bpy.ops.bim.activate_drawing(drawing=original_drawing_id, camera_view_point=False) bpy.ops.bim.activate_drawing(drawing=original_drawing_id, camera_view_point=False)
@@ -572,11 +563,13 @@ class CreateDrawing(bpy.types.Operator):
if obj and obj.type == "MESH" and len(obj.data.polygons): if obj and obj.type == "MESH" and len(obj.data.polygons):
elements_with_faces.add(element.GlobalId) elements_with_faces.add(element.GlobalId)
projections = root.xpath(".//svg:g[contains(@class, 'projection')]", namespaces={'svg': 'http://www.w3.org/2000/svg'}) projections = root.xpath(
".//svg:g[contains(@class, 'projection')]", namespaces={"svg": "http://www.w3.org/2000/svg"}
)
boundary_lines = [] boundary_lines = []
for projection in projections: for projection in projections:
global_id = projection.attrib['{http://www.ifcopenshell.org/ns}guid'] global_id = projection.attrib["{http://www.ifcopenshell.org/ns}guid"]
if global_id not in elements_with_faces: if global_id not in elements_with_faces:
continue continue
for path in projection.findall("./{http://www.w3.org/2000/svg}path"): for path in projection.findall("./{http://www.w3.org/2000/svg}path"):
@@ -616,9 +609,7 @@ class CreateDrawing(bpy.types.Operator):
path = etree.Element("path") path = etree.Element("path")
d = ( d = (
"M" "M"
+ " L".join( + " L".join([",".join([str(o) for o in co]) for co in polygon.exterior.coords[0:-1]])
[",".join([str(o) for o in co]) for co in polygon.exterior.coords[0:-1]]
)
+ " Z" + " Z"
) )
for interior in polygon.interiors: for interior in polygon.interiors:
@@ -1068,7 +1059,9 @@ class CreateDrawing(bpy.types.Operator):
# IfcConvert puts the projection afterwards which is not correct since # IfcConvert puts the projection afterwards which is not correct since
# projection should be drawn underneath the cut. # projection should be drawn underneath the cut.
group = root.find("{http://www.w3.org/2000/svg}g") group = root.find("{http://www.w3.org/2000/svg}g")
projections = root.xpath(".//svg:g[contains(@class, 'projection')]", namespaces={'svg': 'http://www.w3.org/2000/svg'}) projections = root.xpath(
".//svg:g[contains(@class, 'projection')]", namespaces={"svg": "http://www.w3.org/2000/svg"}
)
for projection in projections: for projection in projections:
projection.getparent().remove(projection) projection.getparent().remove(projection)
group.insert(0, projection) group.insert(0, projection)
@@ -1285,11 +1278,15 @@ class CreateSheets(bpy.types.Operator, Operator):
# These variables will be made available to the evaluated commands # These variables will be made available to the evaluated commands
svg = references["SHEET"] svg = references["SHEET"]
basename = os.path.basename(svg)
path = os.path.dirname(svg)
pdf = os.path.splitext(svg)[0] + ".pdf" pdf = os.path.splitext(svg)[0] + ".pdf"
eps = os.path.splitext(svg)[0] + ".eps" replacements = {
dxf = os.path.splitext(svg)[0] + ".dxf" "svg": svg,
"basename": os.path.basename(svg),
"path": os.path.dirname(svg),
"pdf": pdf,
"eps": os.path.splitext(svg)[0] + ".eps",
"dxf": os.path.splitext(svg)[0] + ".dxf",
}
has_sheet_reference = False has_sheet_reference = False
for reference in tool.Drawing.get_document_references(sheet): for reference in tool.Drawing.get_document_references(sheet):
@@ -1322,22 +1319,23 @@ class CreateSheets(bpy.types.Operator, Operator):
if svg2pdf_command: if svg2pdf_command:
# With great power comes great responsibility. Example: # With great power comes great responsibility. Example:
# [['inkscape', svg, '-o', pdf]] # [["inkscape", "svg", "-o", "pdf"]]
commands = eval(svg2pdf_command) commands = json.loads(svg2pdf_command)
for command in commands: for command in commands:
subprocess.run(command) subprocess.run([replacements.get(c, c) for c in command])
if svg2dxf_command: if svg2dxf_command:
# With great power comes great responsibility. Example: # With great power comes great responsibility. Example:
# [['inkscape', svg, '-o', eps], ['pstoedit', '-dt', '-f', 'dxf:-polyaslines -mm', eps, dxf, '-psarg', '-dNOSAFER']] # [["inkscape", "svg", "-o", "eps"], ["pstoedit", "-dt", "-f", "dxf:-polyaslines -mm", "eps", "dxf", "-psarg", "-dNOSAFER"]]
commands = eval(svg2dxf_command) commands = json.loads(svg2dxf_command)
for command in commands: for command in commands:
subprocess.run(command) command[0] = shutil.which(command[0]) or command[0]
subprocess.run([replacements.get(c, c) for c in command])
if svg2pdf_command: if svg2pdf_command:
open_with_user_command(context.preferences.addons["blenderbim"].preferences.pdf_command, pdf) tool.Drawing.open_with_user_command(context.preferences.addons["blenderbim"].preferences.pdf_command, pdf)
else: else:
open_with_user_command(context.preferences.addons["blenderbim"].preferences.svg_command, svg) tool.Drawing.open_with_user_command(context.preferences.addons["blenderbim"].preferences.svg_command, svg)
class SelectAllDrawings(bpy.types.Operator): class SelectAllDrawings(bpy.types.Operator):
@@ -1404,7 +1402,9 @@ class OpenDrawing(bpy.types.Operator):
return {"CANCELLED"} return {"CANCELLED"}
for drawing_uri in drawing_uris: for drawing_uri in drawing_uris:
open_with_user_command(context.preferences.addons["blenderbim"].preferences.svg_command, drawing_uri) tool.Drawing.open_with_user_command(
context.preferences.addons["blenderbim"].preferences.svg_command, drawing_uri
)
return {"FINISHED"} return {"FINISHED"}
+5 -5
View File
@@ -126,14 +126,14 @@ class BIM_UL_topics(bpy.types.UIList):
class BIM_ADDON_preferences(bpy.types.AddonPreferences): class BIM_ADDON_preferences(bpy.types.AddonPreferences):
bl_idname = "blenderbim" bl_idname = "blenderbim"
svg2pdf_command: StringProperty(name="SVG to PDF Command", description="E.g. [['inkscape', svg, '-o', pdf]]") svg2pdf_command: StringProperty(name="SVG to PDF Command", description='E.g. [["inkscape", "svg", "-o", pdf]]')
svg2dxf_command: StringProperty( svg2dxf_command: StringProperty(
name="SVG to DXF Command", name="SVG to DXF Command",
description="E.g. [['inkscape', svg, '-o', eps], ['pstoedit', '-dt', '-f', 'dxf:-polyaslines -mm', eps, dxf, '-psarg', '-dNOSAFER']]", description='E.g. [["inkscape", "svg", "-o", "eps"], ["pstoedit", "-dt", "-f", "dxf:-polyaslines -mm", "eps", "dxf", "-psarg", "-dNOSAFER"]]',
) )
svg_command: StringProperty(name="SVG Command", description="E.g. [['firefox', path]]") svg_command: StringProperty(name="SVG Command", description='E.g. [["firefox", "path"]]')
pdf_command: StringProperty(name="PDF Command", description="E.g. [['firefox', path]]") pdf_command: StringProperty(name="PDF Command", description='E.g. [["firefox", "path"]]')
spreadsheet_command: StringProperty(name="Spreadsheet Command", description="E.g. [['libreoffice', path]]") spreadsheet_command: StringProperty(name="Spreadsheet Command", description='E.g. [["libreoffice", "path"]]')
openlca_port: IntProperty(name="OpenLCA IPC Port", default=8080) openlca_port: IntProperty(name="OpenLCA IPC Port", default=8080)
should_hide_empty_props: BoolProperty(name="Should Hide Empty Properties", default=True) should_hide_empty_props: BoolProperty(name="Should Hide Empty Properties", default=True)
should_setup_workspace: BoolProperty(name="Should Setup Workspace Layout for BIM", default=True) should_setup_workspace: BoolProperty(name="Should Setup Workspace Layout for BIM", default=True)
+6 -3
View File
@@ -20,6 +20,7 @@ import os
import re import re
import bpy import bpy
import math import math
import json
import lark import lark
import bmesh import bmesh
import shutil import shutil
@@ -835,9 +836,11 @@ class Drawing(blenderbim.core.tool.Drawing):
@classmethod @classmethod
def open_with_user_command(cls, user_command, path): def open_with_user_command(cls, user_command, path):
if user_command: if user_command:
commands = eval(user_command) commands = json.loads(user_command)
replacements = {"path": path}
for command in commands: for command in commands:
subprocess.Popen(command) command[0] = shutil.which(command[0]) or command[0]
subprocess.Popen([replacements.get(c, c) for c in command])
else: else:
webbrowser.open("file://" + path) webbrowser.open("file://" + path)
@@ -1849,7 +1852,7 @@ class Drawing(blenderbim.core.tool.Drawing):
sheet_references.append(reference) sheet_references.append(reference)
break break
return sheet_references return sheet_references
@classmethod @classmethod
def get_camera_matrix(cls, camera): def get_camera_matrix(cls, camera):
matrix_world = camera.matrix_world.copy().normalized() matrix_world = camera.matrix_world.copy().normalized()