From dd31fb753a671d31f8b5640a2969300bd92e8794 Mon Sep 17 00:00:00 2001 From: BrandonPacewic Date: Fri, 21 Jun 2024 10:00:35 -0700 Subject: [PATCH 01/20] Formatting updates --- exporter/SynthesisFusionAddin/Synthesis.py | 35 +- exporter/SynthesisFusionAddin/proto/deps.py | 85 ++- exporter/SynthesisFusionAddin/pyproject.toml | 23 +- .../SynthesisFusionAddin/requirements.txt | 2 +- .../src/Analytics/alert.py | 2 +- .../src/Analytics/poster.py | 13 +- .../src/Analyzer/sniff.py | 13 +- .../src/Analyzer/timer.py | 6 +- .../SynthesisFusionAddin/src/GlobalManager.py | 5 +- .../src/Parser/ParseOptions.py | 6 +- .../src/Parser/SynthesisParser/Components.py | 46 +- .../Parser/SynthesisParser/JointHierarchy.py | 68 +- .../src/Parser/SynthesisParser/Joints.py | 85 +-- .../src/Parser/SynthesisParser/Materials.py | 57 +- .../src/Parser/SynthesisParser/PDMessage.py | 7 +- .../src/Parser/SynthesisParser/Parser.py | 47 +- .../SynthesisParser/PhysicalProperties.py | 12 +- .../src/Parser/SynthesisParser/RigidGroup.py | 5 +- .../src/Parser/SynthesisParser/Utilities.py | 38 +- .../SynthesisFusionAddin/src/Types/OString.py | 11 +- .../SynthesisFusionAddin/src/UI/Camera.py | 9 +- .../src/UI/ConfigCommand.py | 617 ++++++------------ .../src/UI/Configuration/SerialCommand.py | 1 + .../src/UI/CustomGraphics.py | 27 +- .../SynthesisFusionAddin/src/UI/Events.py | 10 +- .../src/UI/FileDialogConfig.py | 12 +- exporter/SynthesisFusionAddin/src/UI/HUI.py | 20 +- .../SynthesisFusionAddin/src/UI/Helper.py | 20 +- .../SynthesisFusionAddin/src/UI/IconPaths.py | 22 +- .../src/UI/MarkingMenu.py | 56 +- .../SynthesisFusionAddin/src/UI/OsHelper.py | 3 +- .../SynthesisFusionAddin/src/UI/Toolbar.py | 8 +- .../SynthesisFusionAddin/src/configure.py | 21 +- .../src/general_imports.py | 30 +- exporter/SynthesisFusionAddin/src/logging.py | 13 +- 35 files changed, 545 insertions(+), 890 deletions(-) diff --git a/exporter/SynthesisFusionAddin/Synthesis.py b/exporter/SynthesisFusionAddin/Synthesis.py index 4ed3a0fede..099cedd358 100644 --- a/exporter/SynthesisFusionAddin/Synthesis.py +++ b/exporter/SynthesisFusionAddin/Synthesis.py @@ -1,16 +1,17 @@ -from .src.general_imports import root_logger, gm, INTERNAL_ID, APP_NAME, DESCRIPTION - -from .src.UI import HUI, Handlers, Camera, Helper, ConfigCommand -from .src.UI.Toolbar import Toolbar -from .src.Types.OString import OString -from .src.configure import setAnalytics, unload_config - +import importlib.util +import logging.handlers +import os +import traceback from shutil import rmtree -import logging.handlers, traceback, importlib.util, os -from .src.UI import MarkingMenu import adsk.core +from .src.configure import setAnalytics, unload_config +from .src.general_imports import APP_NAME, DESCRIPTION, INTERNAL_ID, gm, root_logger +from .src.Types.OString import OString +from .src.UI import HUI, Camera, ConfigCommand, Handlers, Helper, MarkingMenu +from .src.UI.Toolbar import Toolbar + def run(_): """## Entry point to application from Fusion 360. @@ -32,9 +33,7 @@ def run(_): MarkingMenu.setupMarkingMenu(ui) except: - logging.getLogger(f"{INTERNAL_ID}").error( - "Failed:\n{}".format(traceback.format_exc()) - ) + logging.getLogger(f"{INTERNAL_ID}").error("Failed:\n{}".format(traceback.format_exc())) def stop(_): @@ -74,9 +73,7 @@ def stop(_): path = os.path.abspath(os.path.dirname(__file__)) - path_proto_files = os.path.abspath( - os.path.join(os.path.dirname(__file__), "..", "proto", "proto_out") - ) + path_proto_files = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "proto", "proto_out")) if path in sys.path: sys.path.remove(path) @@ -85,9 +82,7 @@ def stop(_): sys.path.remove(path_proto_files) except: - logging.getLogger(f"{INTERNAL_ID}").error( - "Failed:\n{}".format(traceback.format_exc()) - ) + logging.getLogger(f"{INTERNAL_ID}").error("Failed:\n{}".format(traceback.format_exc())) def unregister_all() -> None: @@ -105,9 +100,7 @@ def unregister_all() -> None: tab.deleteMe() except: - logging.getLogger(f"{INTERNAL_ID}").error( - "Failed:\n{}".format(traceback.format_exc()) - ) + logging.getLogger(f"{INTERNAL_ID}").error("Failed:\n{}".format(traceback.format_exc())) def register_ui() -> None: diff --git a/exporter/SynthesisFusionAddin/proto/deps.py b/exporter/SynthesisFusionAddin/proto/deps.py index 05c270302e..7504fc006a 100644 --- a/exporter/SynthesisFusionAddin/proto/deps.py +++ b/exporter/SynthesisFusionAddin/proto/deps.py @@ -1,13 +1,16 @@ import os -import platform, subprocess +import platform +import subprocess from pathlib import Path -from src.general_imports import INTERNAL_ID; +import adsk.core +import adsk.fusion -import adsk.core, adsk.fusion +from src.general_imports import INTERNAL_ID system = platform.system() + def getPythonFolder() -> str: """Retreives the folder that contains the Autodesk python executable @@ -19,21 +22,25 @@ def getPythonFolder() -> str: """ # Thank you Kris Kaplan - import sys import importlib.machinery - osPath = importlib.machinery.PathFinder.find_spec('os', sys.path).origin + import sys + + osPath = importlib.machinery.PathFinder.find_spec("os", sys.path).origin # The location of the python executable is found relative to the location of the os module in each operating system if system == "Windows": pythonFolder = Path(osPath).parents[1] elif system == "Darwin": - pythonFolder = f'{Path(osPath).parents[2]}/bin' + pythonFolder = f"{Path(osPath).parents[2]}/bin" else: - raise ImportError('Unsupported platform! This add-in only supports windows and macos') - - logging.getLogger(f'{INTERNAL_ID}').debug(f'Python Folder -> {pythonFolder}') + raise ImportError( + "Unsupported platform! This add-in only supports windows and macos" + ) + + logging.getLogger(f"{INTERNAL_ID}").debug(f"Python Folder -> {pythonFolder}") return pythonFolder + def executeCommand(command: tuple) -> int: """Abstracts the execution of commands to account for platform differences @@ -45,18 +52,16 @@ def executeCommand(command: tuple) -> int: """ if system == "Windows": executionResult = subprocess.call( - command, - bufsize=1, - creationflags=subprocess.CREATE_NO_WINDOW, - shell=False + command, bufsize=1, creationflags=subprocess.CREATE_NO_WINDOW, shell=False ) else: # Uses os.system because I was unable to get subprocess.call to work on MacOS - installComm = str.join(' ', command) + installComm = str.join(" ", command) executionResult = os.system(installComm) return executionResult + def installCross(pipDeps: list) -> bool: """Attempts to fetch pip script and resolve dependencies with less user interaction @@ -89,14 +94,23 @@ def installCross(pipDeps: list) -> bool: try: pythonFolder = getPythonFolder() except ImportError as e: - logging.getLogger(f'{INTERNAL_ID}').error(f'Failed to download dependencies: {e.msg}') + logging.getLogger(f"{INTERNAL_ID}").error( + f"Failed to download dependencies: {e.msg}" + ) return False if system == "Darwin": # macos # if nothing has previously fetched it - if (not os.path.exists(f'{pythonFolder}/get-pip.py')) : - executeCommand(['curl', 'https://bootstrap.pypa.io/get-pip.py', '-o', f'"{pythonFolder}/get-pip.py"']) + if not os.path.exists(f"{pythonFolder}/get-pip.py"): + executeCommand( + [ + "curl", + "https://bootstrap.pypa.io/get-pip.py", + "-o", + f'"{pythonFolder}/get-pip.py"', + ] + ) executeCommand([f'"{pythonFolder}/python"', f'"{pythonFolder}/get-pip.py"']) @@ -105,9 +119,19 @@ def installCross(pipDeps: list) -> bool: progressBar.message = f"Installing {depName}..." adsk.doEvents() # os.path.join needed for varying system path separators - installResult = executeCommand([f"\"{os.path.join(pythonFolder, 'python')}\"", '-m', 'pip', 'install', depName]) + installResult = executeCommand( + [ + f"\"{os.path.join(pythonFolder, 'python')}\"", + "-m", + "pip", + "install", + depName, + ] + ) if installResult != 0: - logging.getLogger(f'{INTERNAL_ID}').warn(f'Dep installation "{depName}" exited with code "{installResult}"') + logging.getLogger(f"{INTERNAL_ID}").warn( + f'Dep installation "{depName}" exited with code "{installResult}"' + ) if system == "Darwin": pipAntiDeps = ["dataclasses", "typing"] @@ -117,9 +141,20 @@ def installCross(pipDeps: list) -> bool: progressBar.message = f"Uninstalling {depName}..." progressBar.progressValue += 1 adsk.doEvents() - uninstallResult = executeCommand([f"\"{os.path.join(pythonFolder, 'python')}\"", '-m', 'pip', 'uninstall', f'{depName}', '-y']) + uninstallResult = executeCommand( + [ + f"\"{os.path.join(pythonFolder, 'python')}\"", + "-m", + "pip", + "uninstall", + f"{depName}", + "-y", + ] + ) if uninstallResult != 0: - logging.getLogger(f'{INTERNAL_ID}').warn(f'AntiDep uninstallation "{depName}" exited with code "{uninstallResult}"') + logging.getLogger(f"{INTERNAL_ID}").warn( + f'AntiDep uninstallation "{depName}" exited with code "{uninstallResult}"' + ) progressBar.hide() @@ -131,7 +166,8 @@ def installCross(pipDeps: list) -> bool: def _checkDeps() -> bool: try: - from .proto_out import joint_pb2, assembly_pb2, types_pb2, material_pb2 + from .proto_out import assembly_pb2, joint_pb2, material_pb2, types_pb2 + return True except ImportError: return False @@ -139,10 +175,11 @@ def _checkDeps() -> bool: try: import logging.handlers + import google.protobuf import pkg_resources - from .proto_out import joint_pb2, assembly_pb2, types_pb2, material_pb2 + from .proto_out import assembly_pb2, joint_pb2, material_pb2, types_pb2 except ImportError or ModuleNotFoundError: installCross(["protobuf==4.23.3"]) - from .proto_out import joint_pb2, assembly_pb2, types_pb2, material_pb2 + from .proto_out import assembly_pb2, joint_pb2, material_pb2, types_pb2 diff --git a/exporter/SynthesisFusionAddin/pyproject.toml b/exporter/SynthesisFusionAddin/pyproject.toml index b5a222b7c7..01222be485 100644 --- a/exporter/SynthesisFusionAddin/pyproject.toml +++ b/exporter/SynthesisFusionAddin/pyproject.toml @@ -1,8 +1,22 @@ [build-system] -requires = ["protobuf", "black", "pyminifier"] +requires = ["protobuf", "isort", "black", "pyminifier"] + +[tool.isort] +py_version = 39 +profile = "black" +skip = [ + "*.git/", + "*.venv", + "/build/", + "/docs/", + "/logs/", + ".vscode/", + "/dist/", + "proto/proto_out", +] [tool.black] -line-length = 90 +line-length = 120 target-version = ['py39'] include = '\.pyi?$' exclude = ''' @@ -13,10 +27,9 @@ exclude = ''' | build | docs | logs - | proto | .vscode | dist - | src/proto_out + | proto_out )/ ) -''' \ No newline at end of file +''' diff --git a/exporter/SynthesisFusionAddin/requirements.txt b/exporter/SynthesisFusionAddin/requirements.txt index cf28d6f7d4..75a3dbe98a 100644 --- a/exporter/SynthesisFusionAddin/requirements.txt +++ b/exporter/SynthesisFusionAddin/requirements.txt @@ -1,2 +1,2 @@ black -pyminifier \ No newline at end of file +pyminifier diff --git a/exporter/SynthesisFusionAddin/src/Analytics/alert.py b/exporter/SynthesisFusionAddin/src/Analytics/alert.py index 05c269dfa3..c134f1906b 100644 --- a/exporter/SynthesisFusionAddin/src/Analytics/alert.py +++ b/exporter/SynthesisFusionAddin/src/Analytics/alert.py @@ -1,5 +1,5 @@ -from ..general_imports import gm from ..configure import setAnalytics +from ..general_imports import gm def showAnalyticsAlert(): diff --git a/exporter/SynthesisFusionAddin/src/Analytics/poster.py b/exporter/SynthesisFusionAddin/src/Analytics/poster.py index 5c80138eb4..1c5056ff72 100644 --- a/exporter/SynthesisFusionAddin/src/Analytics/poster.py +++ b/exporter/SynthesisFusionAddin/src/Analytics/poster.py @@ -1,7 +1,10 @@ -from ..general_imports import * -from ..configure import CID, ANALYTICS, DEBUG +import sys +import urllib + +import adsk.core -import urllib, sys, adsk.core +from ..configure import ANALYTICS, CID, DEBUG +from ..general_imports import * # Reference https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters @@ -169,9 +172,7 @@ def __send(self, body) -> bool: if DEBUG: self.logger.debug(f"Sending request: \n {url}") - req = urllib.request.Request( - f"{self.url}/collect?{body}", data=b"", headers=headers - ) + req = urllib.request.Request(f"{self.url}/collect?{body}", data=b"", headers=headers) # makes the request response = urllib.request.urlopen(req) diff --git a/exporter/SynthesisFusionAddin/src/Analyzer/sniff.py b/exporter/SynthesisFusionAddin/src/Analyzer/sniff.py index 83200053c4..01d64dadf0 100644 --- a/exporter/SynthesisFusionAddin/src/Analyzer/sniff.py +++ b/exporter/SynthesisFusionAddin/src/Analyzer/sniff.py @@ -1,18 +1,21 @@ """ Takes in a given function call and times and tests the memory allocations to get data """ -from ..general_imports import * +import inspect +import linecache +import os +import time +import tracemalloc from time import time -import tracemalloc, time, linecache, os, inspect + +from ..general_imports import * class Sniffer: def __init__(self): self.logger = logging.getLogger(f"{INTERNAL_ID}.Analyzer.Sniffer") - (self.filename, self.line_number, _, self.lines, _) = inspect.getframeinfo( - inspect.currentframe().f_back.f_back - ) + (self.filename, self.line_number, _, self.lines, _) = inspect.getframeinfo(inspect.currentframe().f_back.f_back) self.stopped = False diff --git a/exporter/SynthesisFusionAddin/src/Analyzer/timer.py b/exporter/SynthesisFusionAddin/src/Analyzer/timer.py index b89099ee7c..41bb86135f 100644 --- a/exporter/SynthesisFusionAddin/src/Analyzer/timer.py +++ b/exporter/SynthesisFusionAddin/src/Analyzer/timer.py @@ -1,9 +1,11 @@ """ Takes in a given function call and times and tests the memory allocations to get data """ -from ..general_imports import * +import inspect +import os from time import time -import os, inspect + +from ..general_imports import * class Timer: diff --git a/exporter/SynthesisFusionAddin/src/GlobalManager.py b/exporter/SynthesisFusionAddin/src/GlobalManager.py index 33ccdbfa71..b438a2eb23 100644 --- a/exporter/SynthesisFusionAddin/src/GlobalManager.py +++ b/exporter/SynthesisFusionAddin/src/GlobalManager.py @@ -1,7 +1,10 @@ """ Initializes the global variables that are set in the run method to reduce hanging commands. """ -import adsk.core, adsk.fusion, traceback import inspect +import traceback + +import adsk.core +import adsk.fusion from .general_imports import * from .strings import * diff --git a/exporter/SynthesisFusionAddin/src/Parser/ParseOptions.py b/exporter/SynthesisFusionAddin/src/Parser/ParseOptions.py index 73394c9093..d306be9e23 100644 --- a/exporter/SynthesisFusionAddin/src/Parser/ParseOptions.py +++ b/exporter/SynthesisFusionAddin/src/Parser/ParseOptions.py @@ -7,9 +7,11 @@ - this is essentially a flat configuration file with non serializable objects """ -from typing import Union, List from dataclasses import dataclass -import adsk.core, adsk.fusion +from typing import List, Union + +import adsk.core +import adsk.fusion # from .unity import Parse from ..general_imports import A_EP diff --git a/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/Components.py b/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/Components.py index 9f50ffaea6..9a0101cc9f 100644 --- a/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/Components.py +++ b/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/Components.py @@ -1,15 +1,19 @@ # Contains all of the logic for mapping the Components / Occurrences -import adsk.core, adsk.fusion, uuid, logging, traceback -from proto.proto_out import assembly_pb2, types_pb2, material_pb2, joint_pb2 - -from .Utilities import * -from .. import ParseOptions +import logging +import traceback +import uuid from typing import * -from . import PhysicalProperties +import adsk.core +import adsk.fusion + +from proto.proto_out import assembly_pb2, joint_pb2, material_pb2, types_pb2 -from .PDMessage import PDMessage from ...Analyzer.timer import TimeThis +from .. import ParseOptions +from . import PhysicalProperties +from .PDMessage import PDMessage +from .Utilities import * # TODO: Impelement Material overrides @@ -98,9 +102,7 @@ def _ParseComponentRoot( if occur.isLightBulbOn: child_node = types_pb2.Node() - __parseChildOccurrence( - occur, progressDialog, options, partsData, material_map, child_node - ) + __parseChildOccurrence(occur, progressDialog, options, partsData, material_map, child_node) node.children.append(child_node) @@ -133,9 +135,7 @@ def __parseChildOccurrence( if occurrence.appearance: try: - part.appearance = "{}_{}".format( - occurrence.appearance.name, occurrence.appearance.id - ) + part.appearance = "{}_{}".format(occurrence.appearance.name, occurrence.appearance.id) except: part.appearance = "default" # TODO: Add phyical_material parser @@ -168,9 +168,7 @@ def __parseChildOccurrence( if occur.isLightBulbOn: child_node = types_pb2.Node() - __parseChildOccurrence( - occur, progressDialog, options, partsData, material_map, child_node - ) + __parseChildOccurrence(occur, progressDialog, options, partsData, material_map, child_node) node.children.append(child_node) @@ -186,7 +184,9 @@ def GetMatrixWorld(occurrence): def _ParseBRep( - body: adsk.fusion.BRepBody, options: ParseOptions, trimesh: assembly_pb2.TriangleMesh + body: adsk.fusion.BRepBody, + options: ParseOptions, + trimesh: assembly_pb2.TriangleMesh, ) -> any: try: meshManager = body.meshManager @@ -204,9 +204,7 @@ def _ParseBRep( plainmesh_out.indices.extend(mesh.nodeIndices) plainmesh_out.uv.extend(mesh.textureCoordinatesAsFloat) except: - logging.getLogger("{INTERNAL_ID}.Parser.BrepBody").error( - "Failed:\n{}".format(traceback.format_exc()) - ) + logging.getLogger("{INTERNAL_ID}.Parser.BrepBody").error("Failed:\n{}".format(traceback.format_exc())) def _ParseMesh( @@ -227,14 +225,10 @@ def _ParseMesh( plainmesh_out.indices.extend(mesh.nodeIndices) plainmesh_out.uv.extend(mesh.textureCoordinatesAsFloat) except: - logging.getLogger("{INTERNAL_ID}.Parser.BrepBody").error( - "Failed:\n{}".format(traceback.format_exc()) - ) + logging.getLogger("{INTERNAL_ID}.Parser.BrepBody").error("Failed:\n{}".format(traceback.format_exc())) -def _MapRigidGroups( - rootComponent: adsk.fusion.Component, joints: joint_pb2.Joints -) -> None: +def _MapRigidGroups(rootComponent: adsk.fusion.Component, joints: joint_pb2.Joints) -> None: groups = rootComponent.allRigidGroups for group in groups: mira_group = joint_pb2.RigidGroup() diff --git a/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/JointHierarchy.py b/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/JointHierarchy.py index 2af2426e39..1a2fcbb994 100644 --- a/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/JointHierarchy.py +++ b/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/JointHierarchy.py @@ -1,11 +1,17 @@ -from .Utilities import guid_component, guid_occurrence -from ...general_imports import * -import adsk.core, adsk.fusion, traceback, logging, enum +import enum +import logging +import traceback from typing import * + +import adsk.core +import adsk.fusion + +from proto.proto_out import joint_pb2, types_pb2 + +from ...general_imports import * from .. import ParseOptions from .PDMessage import PDMessage -from proto.proto_out import types_pb2, joint_pb2 - +from .Utilities import guid_component, guid_occurrence # ____________________________ DATA TYPES __________________ @@ -201,9 +207,7 @@ def __init__(self, design): self.grounded = searchForGrounded(design.rootComponent) if self.grounded is None: - gm.ui.messageBox( - "There is not currently a Grounded Component in the assembly, stopping kinematic export." - ) + gm.ui.messageBox("There is not currently a Grounded Component in the assembly, stopping kinematic export.") raise RuntimeWarning("There is no grounded component") return @@ -241,9 +245,7 @@ def __init__(self, design): # self.groundSimNode.printLink() def __getAllJoints(self): - for joint in list(self.design.rootComponent.allJoints) + list( - self.design.rootComponent.allAsBuiltJoints - ): + for joint in list(self.design.rootComponent.allJoints) + list(self.design.rootComponent.allAsBuiltJoints): try: if joint and joint.occurrenceOne and joint.occurrenceTwo: occurrenceOne = joint.occurrenceOne @@ -253,17 +255,13 @@ def __getAllJoints(self): if occurrenceOne is None: try: - occurrenceOne = ( - joint.geometryOrOriginOne.entityOne.assemblyContext - ) + occurrenceOne = joint.geometryOrOriginOne.entityOne.assemblyContext except: pass if occurrenceTwo is None: try: - occurrenceTwo = ( - joint.geometryOrOriginTwo.entityOne.assemblyContext - ) + occurrenceTwo = joint.geometryOrOriginTwo.entityOne.assemblyContext except: pass @@ -308,8 +306,7 @@ def _linkAllAxis(self): def _recurseLink(self, simNode: SimulationNode): connectedAxisNodes = [ - self.simulationNodesRef.get(componentKeys, None) - for componentKeys in simNode.data.getConnectedAxisTokens() + self.simulationNodesRef.get(componentKeys, None) for componentKeys in simNode.data.getConnectedAxisTokens() ] for connectedAxis in connectedAxisNodes: # connected is the occurrence @@ -359,9 +356,9 @@ def _populateNode( edge = DynamicEdge(relationship, node) prev.edges.append(edge) return - elif ( - (occ.entityToken in self.dynamicJoints.keys()) and (prev is not None) - ) or self.currentTraversal.get(occ.entityToken) is not None: + elif ((occ.entityToken in self.dynamicJoints.keys()) and (prev is not None)) or self.currentTraversal.get( + occ.entityToken + ) is not None: return node = DynamicOccurrenceNode(occ) @@ -369,9 +366,7 @@ def _populateNode( self.currentTraversal[occ.entityToken] = True for occurrence in occ.childOccurrences: - self._populateNode( - occurrence, node, OccurrenceRelationship.TRANSFORM, is_ground=is_ground - ) + self._populateNode(occurrence, node, OccurrenceRelationship.TRANSFORM, is_ground=is_ground) # if not is_ground: # THIS IS A BUG - OCCURRENCE ACCESS VIOLATION try: @@ -392,18 +387,11 @@ def _populateNode( connection = joint.occurrenceOne if connection is not None: - if ( - prev is None - or connection.entityToken != prev.data.entityToken - ): + if prev is None or connection.entityToken != prev.data.entityToken: self._populateNode( connection, node, - ( - OccurrenceRelationship.CONNECTION - if rigid - else OccurrenceRelationship.NEXT - ), + (OccurrenceRelationship.CONNECTION if rigid else OccurrenceRelationship.NEXT), is_ground=is_ground, ) else: @@ -419,7 +407,9 @@ def _populateNode( return node -def searchForGrounded(occ: adsk.fusion.Occurrence) -> Union[adsk.fusion.Occurrence, None]: +def searchForGrounded( + occ: adsk.fusion.Occurrence, +) -> Union[adsk.fusion.Occurrence, None]: """Search for a grounded component or occurrence in the assembly Args: @@ -483,9 +473,7 @@ def BuildJointPartHierarchy( except Warning: return False except: - logging.getLogger(f"{INTERNAL_ID}.JointHierarchy").error( - "Failed:\n{}".format(traceback.format_exc()) - ) + logging.getLogger(f"{INTERNAL_ID}.JointHierarchy").error("Failed:\n{}".format(traceback.format_exc())) def populateJoint(simNode: SimulationNode, joints: joint_pb2.Joints, progressDialog): @@ -501,9 +489,7 @@ def populateJoint(simNode: SimulationNode, joints: joint_pb2.Joints, progressDia progressDialog.update() if not proto_joint: - logging.getLogger(f"{INTERNAL_ID}.JointHierarchy").error( - f"Could not find protobuf joint for {simNode.name}" - ) + logging.getLogger(f"{INTERNAL_ID}.JointHierarchy").error(f"Could not find protobuf joint for {simNode.name}") return root = types_pb2.Node() diff --git a/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/Joints.py b/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/Joints.py index 199a9b0770..992c9d3c6e 100644 --- a/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/Joints.py +++ b/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/Joints.py @@ -22,16 +22,19 @@ """ -import adsk.fusion, adsk.core, traceback, uuid - -from proto.proto_out import types_pb2, joint_pb2, signal_pb2, motor_pb2, assembly_pb2 +import traceback +import uuid from typing import Union +import adsk.core +import adsk.fusion + +from proto.proto_out import assembly_pb2, joint_pb2, motor_pb2, signal_pb2, types_pb2 + from ...general_imports import * -from .Utilities import fill_info, construct_info, guid_occurrence -from .PDMessage import PDMessage from .. import ParseOptions - +from .PDMessage import PDMessage +from .Utilities import construct_info, fill_info, guid_occurrence # Need to take in a graphcontainer # Need to create a new base node for each Joint Instance @@ -79,9 +82,7 @@ def populateJoints( # Add the rest of the dynamic objects - for joint in list(design.rootComponent.allJoints) + list( - design.rootComponent.allAsBuiltJoints - ): + for joint in list(design.rootComponent.allJoints) + list(design.rootComponent.allAsBuiltJoints): if joint.isSuppressed: continue @@ -115,10 +116,7 @@ def populateJoints( signal.io = signal_pb2.IOType.OUTPUT # really could just map the enum to a friggin string - if ( - parse_joints.signalType != ParseOptions.SignalType.PASSIVE - and assembly.dynamic - ): + if parse_joints.signalType != ParseOptions.SignalType.PASSIVE and assembly.dynamic: if parse_joints.signalType == ParseOptions.SignalType.CAN: signal.device_type = signal_pb2.DeviceType.CANBUS elif parse_joints.signalType == ParseOptions.SignalType.PWM: @@ -136,18 +134,14 @@ def populateJoints( # else: # signals.signal_map.remove(guid) - _addJointInstance( - joint, joint_instance, joint_definition, signals, options - ) + _addJointInstance(joint, joint_instance, joint_definition, signals, options) # adds information for joint motion and limits _motionFromJoint(joint.jointMotion, joint_definition) except: err_msg = "Failed:\n{}".format(traceback.format_exc()) - logging.getLogger(f"{INTERNAL_ID}.JointParser").error( - "Failed:\n{}".format(traceback.format_exc()) - ) + logging.getLogger(f"{INTERNAL_ID}.JointParser").error("Failed:\n{}".format(traceback.format_exc())) continue @@ -244,9 +238,7 @@ def _addRigidGroup(joint: adsk.fusion.Joint, assembly: assembly_pb2.Assembly): assembly.data.joints.rigid_groups.append(mira_group) -def _motionFromJoint( - fusionMotionDefinition: adsk.fusion.JointMotion, proto_joint: joint_pb2.Joint -) -> None: +def _motionFromJoint(fusionMotionDefinition: adsk.fusion.JointMotion, proto_joint: joint_pb2.Joint) -> None: # if fusionJoint.geometryOrOriginOne.objectType == "adsk::fusion::JointGeometry" # create the DOF depending on what kind of information the joint has @@ -260,16 +252,12 @@ def _motionFromJoint( 6: noop, # TODO: Implement } - fillJointMotionFunc = fillJointMotionFuncSwitcher.get( - fusionMotionDefinition.jointType, lambda: None - ) + fillJointMotionFunc = fillJointMotionFuncSwitcher.get(fusionMotionDefinition.jointType, lambda: None) fillJointMotionFunc(fusionMotionDefinition, proto_joint) -def fillRevoluteJointMotion( - revoluteMotion: adsk.fusion.RevoluteJointMotion, proto_joint: joint_pb2.Joint -): +def fillRevoluteJointMotion(revoluteMotion: adsk.fusion.RevoluteJointMotion, proto_joint: joint_pb2.Joint): """#### Fill Protobuf revolute joint motion data Args: @@ -311,9 +299,7 @@ def fillRevoluteJointMotion( dof.axis.z = int(rotationAxis == 1) -def fillSliderJointMotion( - sliderMotion: adsk.fusion.SliderJointMotion, proto_joint: joint_pb2.Joint -) -> None: +def fillSliderJointMotion(sliderMotion: adsk.fusion.SliderJointMotion, proto_joint: joint_pb2.Joint) -> None: """#### Fill Protobuf slider joint motion data Args: @@ -384,9 +370,7 @@ def _searchForGrounded( return None -def _jointOrigin( - fusionJoint: Union[adsk.fusion.Joint, adsk.fusion.AsBuiltJoint] -) -> adsk.core.Point3D: +def _jointOrigin(fusionJoint: Union[adsk.fusion.Joint, adsk.fusion.AsBuiltJoint]) -> adsk.core.Point3D: """#### Joint Origin Internal Finder that was orignally created for Synthesis by Liam Wang Args: @@ -417,9 +401,7 @@ def _jointOrigin( newEnt = ent.createForAssemblyContext(fusionJoint.occurrenceOne) min = newEnt.boundingBox.minPoint max = newEnt.boundingBox.maxPoint - org = adsk.core.Point3D.create( - (max.x + min.x) / 2.0, (max.y + min.y) / 2.0, (max.z + min.z) / 2.0 - ) + org = adsk.core.Point3D.create((max.x + min.x) / 2.0, (max.y + min.y) / 2.0, (max.z + min.z) / 2.0) return org # ent.startVertex.geometry else: return geometryOrOrigin.origin @@ -434,19 +416,11 @@ def _jointOrigin( else: # adsk::fusion::JointOrigin origin = geometryOrOrigin.geometry.origin # todo: Is this the correct way to calculate a joint origin's true location? Why isn't this exposed in the API? - offsetX = ( - 0 if geometryOrOrigin.offsetX is None else geometryOrOrigin.offsetX.value - ) - offsetY = ( - 0 if geometryOrOrigin.offsetY is None else geometryOrOrigin.offsetY.value - ) - offsetZ = ( - 0 if geometryOrOrigin.offsetZ is None else geometryOrOrigin.offsetZ.value - ) + offsetX = 0 if geometryOrOrigin.offsetX is None else geometryOrOrigin.offsetX.value + offsetY = 0 if geometryOrOrigin.offsetY is None else geometryOrOrigin.offsetY.value + offsetZ = 0 if geometryOrOrigin.offsetZ is None else geometryOrOrigin.offsetZ.value # noinspection PyArgumentList - return adsk.core.Point3D.create( - origin.x + offsetX, origin.y + offsetY, origin.z + offsetZ - ) + return adsk.core.Point3D.create(origin.x + offsetX, origin.y + offsetY, origin.z + offsetZ) def createJointGraph( @@ -482,13 +456,8 @@ def createJointGraph( current_node = node_map[supplied_joint.joint_token] if supplied_joint.parent == 0: node_map["ground"].children.append(node_map[supplied_joint.joint_token]) - elif ( - node_map[supplied_joint.parent] is not None - and node_map[supplied_joint.joint_token] is not None - ): - node_map[supplied_joint.parent].children.append( - node_map[supplied_joint.joint_token] - ) + elif node_map[supplied_joint.parent] is not None and node_map[supplied_joint.joint_token] is not None: + node_map[supplied_joint.parent].children.append(node_map[supplied_joint.joint_token]) else: logging.getLogger("JointHierarchy").error( f"Cannot construct hierarhcy because of detached tree at : {supplied_joint.joint_token}" @@ -499,9 +468,7 @@ def createJointGraph( joint_tree.nodes.append(node) -def addWheelsToGraph( - wheels: list, rootNode: types_pb2.Node, joint_tree: types_pb2.GraphContainer -): +def addWheelsToGraph(wheels: list, rootNode: types_pb2.Node, joint_tree: types_pb2.GraphContainer): for wheel in wheels: # wheel name # wheel signal diff --git a/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/Materials.py b/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/Materials.py index 12af72d976..7d95c42c7a 100644 --- a/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/Materials.py +++ b/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/Materials.py @@ -1,13 +1,16 @@ # Should contain Physical and Apperance materials ? -import adsk, logging, traceback, math +import logging +import math +import traceback -from .Utilities import * -from .. import ParseOptions +import adsk -from ...general_imports import INTERNAL_ID +from proto.proto_out import material_pb2 +from ...general_imports import INTERNAL_ID +from .. import ParseOptions from .PDMessage import PDMessage -from proto.proto_out import material_pb2 +from .Utilities import * OPACITY_RAMPING_CONSTANT = 14.0 @@ -97,31 +100,17 @@ def getPhysicalMaterialData(fusion_material, proto_material, options): """ Mechanical Properties """ - mechanicalProperties.young_mod = materialProperties.itemById( - "structural_Young_modulus" - ).value - mechanicalProperties.poisson_ratio = materialProperties.itemById( - "structural_Poisson_ratio" - ).value - mechanicalProperties.shear_mod = materialProperties.itemById( - "structural_Shear_modulus" - ).value - mechanicalProperties.density = materialProperties.itemById( - "structural_Density" - ).value - mechanicalProperties.damping_coefficient = materialProperties.itemById( - "structural_Damping_coefficient" - ).value + mechanicalProperties.young_mod = materialProperties.itemById("structural_Young_modulus").value + mechanicalProperties.poisson_ratio = materialProperties.itemById("structural_Poisson_ratio").value + mechanicalProperties.shear_mod = materialProperties.itemById("structural_Shear_modulus").value + mechanicalProperties.density = materialProperties.itemById("structural_Density").value + mechanicalProperties.damping_coefficient = materialProperties.itemById("structural_Damping_coefficient").value """ Strength Properties """ - strengthProperties.yield_strength = materialProperties.itemById( - "structural_Minimum_yield_stress" - ).value - strengthProperties.tensile_strength = materialProperties.itemById( - "structural_Minimum_tensile_strength" - ).value + strengthProperties.yield_strength = materialProperties.itemById("structural_Minimum_yield_stress").value + strengthProperties.tensile_strength = materialProperties.itemById("structural_Minimum_tensile_strength").value """ strengthProperties.thermal_treatment = materialProperties.itemById( "structural_Thermally_treated" @@ -129,9 +118,9 @@ def getPhysicalMaterialData(fusion_material, proto_material, options): """ except: - logging.getLogger( - f"{INTERNAL_ID}.Parser.Materials.getPhysicalMaterialData" - ).error("Failed:\n{}".format(traceback.format_exc())) + logging.getLogger(f"{INTERNAL_ID}.Parser.Materials.getPhysicalMaterialData").error( + "Failed:\n{}".format(traceback.format_exc()) + ) def _MapAllAppearances( @@ -224,9 +213,7 @@ def getMaterialAppearance( baseColor = properties.itemById("transparent_color").value transparent_distance = properties.itemById("transparent_distance").value - opac = (255.0 * transparent_distance) / ( - transparent_distance + OPACITY_RAMPING_CONSTANT - ) + opac = (255.0 * transparent_distance) / (transparent_distance + OPACITY_RAMPING_CONSTANT) if opac > 255: opac = 255 elif opac < 0: @@ -242,11 +229,7 @@ def getMaterialAppearance( color.A = baseColor.opacity else: for prop in fusionAppearance.appearanceProperties: - if ( - (prop.name == "Color") - and (prop.value is not None) - and (prop.id != "surface_albedo") - ): + if (prop.name == "Color") and (prop.value is not None) and (prop.id != "surface_albedo"): baseColor = prop.value color.R = baseColor.red color.G = baseColor.green diff --git a/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/PDMessage.py b/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/PDMessage.py index d284a44f93..ad441fc901 100644 --- a/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/PDMessage.py +++ b/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/PDMessage.py @@ -28,12 +28,7 @@ def __init__( self.currentMessage = "working..." - self.finalValue = ( - self.componentCount - + self.occurrenceCount - + self.materialCount - + self.appearanceCount - ) + self.finalValue = self.componentCount + self.occurrenceCount + self.materialCount + self.appearanceCount self.currentValue = 0 self.progressDialog = progressDialog diff --git a/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/Parser.py b/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/Parser.py index bf3cae59a7..6b7fcd94e3 100644 --- a/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/Parser.py +++ b/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/Parser.py @@ -1,20 +1,19 @@ -import adsk.core, adsk.fusion -import traceback, gzip - -from ...general_imports import * +import gzip +import traceback +import adsk.core +import adsk.fusion from google.protobuf.json_format import MessageToJson from proto.proto_out import assembly_pb2, types_pb2 +from ...general_imports import * from ...UI.Camera import captureThumbnail, clearIconCache +from . import Components, JointHierarchy, Joints, Materials, PDMessage +from .Utilities import * # from . import Joints, Materials, Components, Utilities -from . import Materials, Components, Joints, JointHierarchy, PDMessage - -from .Utilities import * - class Parser: def __init__(self, options: any): @@ -55,9 +54,7 @@ def export(self) -> bool: progressDialog.title = "Exporting to Synthesis Format" progressDialog.minimumValue = 0 progressDialog.maximumValue = totalIterations - progressDialog.show( - "Synthesis Export", "Currently on %v of %m", 0, totalIterations - ) + progressDialog.show("Synthesis Export", "Currently on %v of %m", 0, totalIterations) # this is the formatter for the progress dialog now self.pdMessage = PDMessage.PDMessage( @@ -127,9 +124,7 @@ def export(self) -> bool: self.pdMessage, ) - JointHierarchy.BuildJointPartHierarchy( - design, assembly_out.data.joints, self.parseOptions, self.pdMessage - ) + JointHierarchy.BuildJointPartHierarchy(design, assembly_out.data.joints, self.parseOptions, self.pdMessage) # These don't have an effect, I forgot how this is suppose to work # progressDialog.message = "Taking Photo for thumbnail..." @@ -199,15 +194,9 @@ def export(self) -> bool: joint_hierarchy_out = f"{joint_hierarchy_out} |- ground\n" else: newnode = assembly_out.data.joints.joint_instances[node.value] - jointdefinition = assembly_out.data.joints.joint_definitions[ - newnode.joint_reference - ] + jointdefinition = assembly_out.data.joints.joint_definitions[newnode.joint_reference] - wheel_ = ( - " wheel : true" - if (jointdefinition.user_data.data["wheel"] != "") - else "" - ) + wheel_ = " wheel : true" if (jointdefinition.user_data.data["wheel"] != "") else "" joint_hierarchy_out = f"{joint_hierarchy_out} |- {jointdefinition.info.name} type: {jointdefinition.joint_motion_type} {wheel_}\n" @@ -215,17 +204,9 @@ def export(self) -> bool: if child.value == "ground": joint_hierarchy_out = f"{joint_hierarchy_out} |---> ground\n" else: - newnode = assembly_out.data.joints.joint_instances[ - child.value - ] - jointdefinition = assembly_out.data.joints.joint_definitions[ - newnode.joint_reference - ] - wheel_ = ( - " wheel : true" - if (jointdefinition.user_data.data["wheel"] != "") - else "" - ) + newnode = assembly_out.data.joints.joint_instances[child.value] + jointdefinition = assembly_out.data.joints.joint_definitions[newnode.joint_reference] + wheel_ = " wheel : true" if (jointdefinition.user_data.data["wheel"] != "") else "" joint_hierarchy_out = f"{joint_hierarchy_out} |---> {jointdefinition.info.name} type: {jointdefinition.joint_motion_type} {wheel_}\n" joint_hierarchy_out += "\n\n" diff --git a/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/PhysicalProperties.py b/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/PhysicalProperties.py index 4ff71be8b7..afd9489909 100644 --- a/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/PhysicalProperties.py +++ b/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/PhysicalProperties.py @@ -16,17 +16,19 @@ """ -import adsk, logging, traceback +import logging +import traceback +from typing import Union + +import adsk from proto.proto_out import types_pb2 -from typing import Union + from ...general_imports import INTERNAL_ID def GetPhysicalProperties( - fusionObject: Union[ - adsk.fusion.BRepBody, adsk.fusion.Occurrence, adsk.fusion.Component - ], + fusionObject: Union[adsk.fusion.BRepBody, adsk.fusion.Occurrence, adsk.fusion.Component], physicalProperties: types_pb2.PhysicalProperties, level=1, ): diff --git a/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/RigidGroup.py b/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/RigidGroup.py index be14c4a4e0..725ad6e650 100644 --- a/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/RigidGroup.py +++ b/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/RigidGroup.py @@ -12,9 +12,12 @@ - Success """ -import adsk.core, adsk.fusion, logging +import logging from typing import * +import adsk.core +import adsk.fusion + from proto.proto_out import assembly_pb2 diff --git a/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/Utilities.py b/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/Utilities.py index 4cff7f0655..7169cd4085 100644 --- a/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/Utilities.py +++ b/exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/Utilities.py @@ -1,5 +1,7 @@ -import math, uuid -from adsk.core import Vector3D, Base +import math +import uuid + +from adsk.core import Base, Vector3D from adsk.fusion import Component, Occurrence # from proto.proto_out import types_pb2 @@ -60,18 +62,18 @@ def construct_info(name: str, proto_obj, version=5, fus_object=None, GUID=None) # My previous function was alot more optimized however now I realize the bug was this doesn't work well with degrees def euler_to_quaternion(r): (yaw, pitch, roll) = (r[0], r[1], r[2]) - qx = math.sin(roll / 2) * math.cos(pitch / 2) * math.cos(yaw / 2) - math.cos( - roll / 2 - ) * math.sin(pitch / 2) * math.sin(yaw / 2) - qy = math.cos(roll / 2) * math.sin(pitch / 2) * math.cos(yaw / 2) + math.sin( - roll / 2 - ) * math.cos(pitch / 2) * math.sin(yaw / 2) - qz = math.cos(roll / 2) * math.cos(pitch / 2) * math.sin(yaw / 2) - math.sin( - roll / 2 - ) * math.sin(pitch / 2) * math.cos(yaw / 2) - qw = math.cos(roll / 2) * math.cos(pitch / 2) * math.cos(yaw / 2) + math.sin( - roll / 2 - ) * math.sin(pitch / 2) * math.sin(yaw / 2) + qx = math.sin(roll / 2) * math.cos(pitch / 2) * math.cos(yaw / 2) - math.cos(roll / 2) * math.sin( + pitch / 2 + ) * math.sin(yaw / 2) + qy = math.cos(roll / 2) * math.sin(pitch / 2) * math.cos(yaw / 2) + math.sin(roll / 2) * math.cos( + pitch / 2 + ) * math.sin(yaw / 2) + qz = math.cos(roll / 2) * math.cos(pitch / 2) * math.sin(yaw / 2) - math.sin(roll / 2) * math.sin( + pitch / 2 + ) * math.cos(yaw / 2) + qw = math.cos(roll / 2) * math.cos(pitch / 2) * math.cos(yaw / 2) + math.sin(roll / 2) * math.sin( + pitch / 2 + ) * math.sin(yaw / 2) return [qx, qy, qz, qw] @@ -133,9 +135,7 @@ def throwZero(): Raises: RuntimeError: Error describing the issue """ - raise RuntimeError( - "While computing the quaternion the trace was reported as 0 which is invalid" - ) + raise RuntimeError("While computing the quaternion the trace was reported as 0 which is invalid") def spatial_to_quaternion(mat): @@ -193,9 +193,7 @@ def spatial_to_quaternion(mat): return round(qx, 13), round(-qy, 13), round(-qz, 13), round(qw, 13) else: - raise RuntimeError( - "Supplied matrix to spatial_to_quaternion is not a 1D spatial matrix in size." - ) + raise RuntimeError("Supplied matrix to spatial_to_quaternion is not a 1D spatial matrix in size.") def normalize_quaternion(x, y, z, w): diff --git a/exporter/SynthesisFusionAddin/src/Types/OString.py b/exporter/SynthesisFusionAddin/src/Types/OString.py index 47cdcdeb48..ba547fe953 100644 --- a/exporter/SynthesisFusionAddin/src/Types/OString.py +++ b/exporter/SynthesisFusionAddin/src/Types/OString.py @@ -1,6 +1,7 @@ -from typing import Union -import os, platform +import os import pathlib +import platform +from typing import Union class OString: @@ -37,11 +38,7 @@ def __eq__(self, value: object) -> bool: bool: Did the OString objects match? """ if isinstance(value, OString): - if ( - self.path == value.path - and self.fileName == value.fileName - and self.platform == value.platform - ): + if self.path == value.path and self.fileName == value.fileName and self.platform == value.platform: return True return False diff --git a/exporter/SynthesisFusionAddin/src/UI/Camera.py b/exporter/SynthesisFusionAddin/src/UI/Camera.py index 33c84eb319..a7076fdfd2 100644 --- a/exporter/SynthesisFusionAddin/src/UI/Camera.py +++ b/exporter/SynthesisFusionAddin/src/UI/Camera.py @@ -1,12 +1,11 @@ -from ..general_imports import * - -from . import Helper import os -from ..Types.OString import OString - from adsk.core import SaveImageFileOptions +from ..general_imports import * +from ..Types.OString import OString +from . import Helper + def captureThumbnail(size=250): """ diff --git a/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py b/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py index 4c540f5bd5..1ff50078af 100644 --- a/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py +++ b/exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py @@ -2,27 +2,31 @@ links the Configuration Command seen when pressing the Synthesis button in the Addins Panel """ -from enum import Enum +import logging +import os import platform +import traceback +from enum import Enum +from types import SimpleNamespace + +import adsk.core +import adsk.fusion -from ..Parser.SynthesisParser.Utilities import guid_occurrence -from ..general_imports import * -from ..configure import NOTIFIED, write_configuration from ..Analytics.alert import showAnalyticsAlert -from . import Helper, FileDialogConfig, OsHelper, CustomGraphics, IconPaths +from ..configure import NOTIFIED, write_configuration +from ..general_imports import * from ..Parser.ParseOptions import ( Gamepiece, + JointParentType, Mode, ParseOptions, _Joint, _Wheel, - JointParentType, ) +from ..Parser.SynthesisParser.Utilities import guid_occurrence +from . import CustomGraphics, FileDialogConfig, Helper, IconPaths, OsHelper from .Configuration.SerialCommand import SerialCommand -import adsk.core, adsk.fusion, traceback, logging, os -from types import SimpleNamespace - # ====================================== CONFIG COMMAND ====================================== """ @@ -115,9 +119,7 @@ def bRepMassInRoot(self): for body in gm.app.activeDocument.design.rootComponent.bRepBodies: if not body.isLightBulbOn: continue - physical = body.getPhysicalProperties( - adsk.fusion.CalculationAccuracy.LowCalculationAccuracy - ) + physical = body.getPhysicalProperties(adsk.fusion.CalculationAccuracy.LowCalculationAccuracy) self.totalMass += physical.mass except: if gm.ui: @@ -132,9 +134,7 @@ def traverseOccurrenceHierarchy(self): for body in occ.component.bRepBodies: if not body.isLightBulbOn: continue - physical = body.getPhysicalProperties( - adsk.fusion.CalculationAccuracy.LowCalculationAccuracy - ) + physical = body.getPhysicalProperties(adsk.fusion.CalculationAccuracy.LowCalculationAccuracy) self.totalMass += physical.mass except: pass @@ -177,14 +177,10 @@ def notify(self, args): if type(saved) == str: try: # probably need some way to validate for each usage below - previous = json.loads( - saved, object_hook=lambda d: SimpleNamespace(**d) - ) + previous = json.loads(saved, object_hook=lambda d: SimpleNamespace(**d)) except: self.log.error("Failed:\n{}".format(traceback.format_exc())) - gm.ui.messageBox( - "Failed to read previous Unity Configuration\n - Using default configuration" - ) + gm.ui.messageBox("Failed to read previous Unity Configuration\n - Using default configuration") previous = SerialCommand() else: # new file configuration @@ -211,9 +207,7 @@ def notify(self, args): Creates the general tab. - Parent container for all the command inputs in the tab. """ - inputs = INPUTS_ROOT.addTabCommandInput( - "general_settings", "General" - ).children + inputs = INPUTS_ROOT.addTabCommandInput("general_settings", "General").children # ~~~~~~~~~~~~~~~~ HELP FILE ~~~~~~~~~~~~~~~~ """ @@ -235,9 +229,7 @@ def notify(self, args): dropdownExportMode.listItems.add("Static", False) dropdownExportMode.tooltip = "Export Mode" - dropdownExportMode.tooltipDescription = ( - "
Does this object move dynamically?" - ) + dropdownExportMode.tooltipDescription = "
Does this object move dynamically?" # ~~~~~~~~~~~~~~~~ WEIGHT CONFIGURATION ~~~~~~~~~~~~~~~~ """ @@ -252,9 +244,7 @@ def notify(self, args): "3:2:2:1", 1, ) - weightTableInput.tablePresentationStyle = ( - 2 # set transparent background for table - ) + weightTableInput.tablePresentationStyle = 2 # set transparent background for table weight_name = inputs.addStringValueInput("weight_name", "Weight") weight_name.value = "Weight" @@ -280,50 +270,34 @@ def notify(self, args): adsk.core.ValueInput.createByString("0.0"), ) weight_input.tooltip = "Robot weight" - weight_input.tooltipDescription = """(in pounds)
This is the weight of the entire robot assembly.""" + weight_input.tooltipDescription = ( + """(in pounds)
This is the weight of the entire robot assembly.""" + ) weight_unit = inputs.addDropDownCommandInput( "weight_unit", "Weight Unit", adsk.core.DropDownStyles.LabeledIconDropDownStyle, ) - weight_unit.listItems.add( - "‎", True, IconPaths.massIcons["LBS"] - ) # add listdropdown mass options - weight_unit.listItems.add( - "‎", False, IconPaths.massIcons["KG"] - ) # add listdropdown mass options + weight_unit.listItems.add("‎", True, IconPaths.massIcons["LBS"]) # add listdropdown mass options + weight_unit.listItems.add("‎", False, IconPaths.massIcons["KG"]) # add listdropdown mass options weight_unit.tooltip = "Unit of mass" - weight_unit.tooltipDescription = ( - "
Configure the unit of mass for the weight calculation." - ) - - weightTableInput.addCommandInput( - weight_name, 0, 0 - ) # add command inputs to table - weightTableInput.addCommandInput( - auto_calc_weight, 0, 1 - ) # add command inputs to table - weightTableInput.addCommandInput( - weight_input, 0, 2 - ) # add command inputs to table - weightTableInput.addCommandInput( - weight_unit, 0, 3 - ) # add command inputs to table + weight_unit.tooltipDescription = "
Configure the unit of mass for the weight calculation." + + weightTableInput.addCommandInput(weight_name, 0, 0) # add command inputs to table + weightTableInput.addCommandInput(auto_calc_weight, 0, 1) # add command inputs to table + weightTableInput.addCommandInput(weight_input, 0, 2) # add command inputs to table + weightTableInput.addCommandInput(weight_unit, 0, 3) # add command inputs to table # ~~~~~~~~~~~~~~~~ WHEEL CONFIGURATION ~~~~~~~~~~~~~~~~ """ Wheel configuration command input group - Container for wheel selection Table """ - wheelConfig = inputs.addGroupCommandInput( - "wheel_config", "Wheel Configuration" - ) + wheelConfig = inputs.addGroupCommandInput("wheel_config", "Wheel Configuration") wheelConfig.isExpanded = True wheelConfig.isEnabled = True - wheelConfig.tooltip = ( - "Select and define the drive-train wheels in your assembly." - ) + wheelConfig.tooltip = "Select and define the drive-train wheels in your assembly." wheel_inputs = wheelConfig.children @@ -340,13 +314,9 @@ def notify(self, args): 50, ) - addWheelInput = wheel_inputs.addBoolValueInput( - "wheel_add", "Add", False - ) # add button + addWheelInput = wheel_inputs.addBoolValueInput("wheel_add", "Add", False) # add button - removeWheelInput = wheel_inputs.addBoolValueInput( # remove button - "wheel_delete", "Remove", False - ) + removeWheelInput = wheel_inputs.addBoolValueInput("wheel_delete", "Remove", False) # remove button addWheelInput.tooltip = "Add a wheel joint" # tooltips removeWheelInput.tooltip = "Remove a wheel joint" @@ -356,20 +326,14 @@ def notify(self, args): "Selection", "Select the wheels joints in your drive-train assembly.", ) - wheelSelectInput.addSelectionFilter( - "Joints" - ) # filter selection to only occurrences + wheelSelectInput.addSelectionFilter("Joints") # filter selection to only occurrences wheelSelectInput.setSelectionLimits(0) # no selection count limit wheelSelectInput.isEnabled = False wheelSelectInput.isVisible = False - wheelTableInput.addToolbarCommandInput( - addWheelInput - ) # add buttons to the toolbar - wheelTableInput.addToolbarCommandInput( - removeWheelInput - ) # add buttons to the toolbar + wheelTableInput.addToolbarCommandInput(addWheelInput) # add buttons to the toolbar + wheelTableInput.addToolbarCommandInput(removeWheelInput) # add buttons to the toolbar """ Algorithmic Wheel Selection Indicator @@ -406,9 +370,7 @@ def notify(self, args): """ wheelTableInput.addCommandInput( # create textbox input using helper (component name) - self.createTextBoxInput( - "name_header", "Name", wheel_inputs, "Joint name", bold=False - ), + self.createTextBoxInput("name_header", "Name", wheel_inputs, "Joint name", bold=False), 0, 1, ) @@ -457,9 +419,7 @@ def notify(self, args): """ Joint configuration group. Container for joint selection table """ - jointConfig = inputs.addGroupCommandInput( - "joint_config", "Joint Configuration" - ) + jointConfig = inputs.addGroupCommandInput("joint_config", "Joint Configuration") jointConfig.isExpanded = False jointConfig.isVisible = True jointConfig.tooltip = "Select and define joint occurrences in your assembly." @@ -470,24 +430,18 @@ def notify(self, args): """ All selection joints appear here. """ - jointTableInput = ( - self.createTableInput( # create tablecommandinput using helper - "joint_table", - "Joint Table", - joint_inputs, - 6, - "1:2:2:2:2:2", - 50, - ) + jointTableInput = self.createTableInput( # create tablecommandinput using helper + "joint_table", + "Joint Table", + joint_inputs, + 6, + "1:2:2:2:2:2", + 50, ) - addJointInput = joint_inputs.addBoolValueInput( - "joint_add", "Add", False - ) # add button + addJointInput = joint_inputs.addBoolValueInput("joint_add", "Add", False) # add button - removeJointInput = joint_inputs.addBoolValueInput( # remove button - "joint_delete", "Remove", False - ) + removeJointInput = joint_inputs.addBoolValueInput("joint_delete", "Remove", False) # remove button addJointInput.isEnabled = removeJointInput.isEnabled = True @@ -505,12 +459,8 @@ def notify(self, args): jointSelectInput.isEnabled = False jointSelectInput.isVisible = False # make selection box invisible - jointTableInput.addToolbarCommandInput( - addJointInput - ) # add bool inputs to the toolbar - jointTableInput.addToolbarCommandInput( - removeJointInput - ) # add bool inputs to the toolbar + jointTableInput.addToolbarCommandInput(addJointInput) # add bool inputs to the toolbar + jointTableInput.addToolbarCommandInput(removeJointInput) # add bool inputs to the toolbar jointTableInput.addCommandInput( self.createTextBoxInput( # create a textBoxCommandInput for the table header (Joint Motion), using helper @@ -580,9 +530,9 @@ def notify(self, args): 5, ) - for joint in list( - gm.app.activeDocument.design.rootComponent.allJoints - ) + list(gm.app.activeDocument.design.rootComponent.allAsBuiltJoints): + for joint in list(gm.app.activeDocument.design.rootComponent.allJoints) + list( + gm.app.activeDocument.design.rootComponent.allAsBuiltJoints + ): if ( joint.jointMotion.jointType == JointMotions.REVOLUTE.value or joint.jointMotion.jointType == JointMotions.SLIDER.value @@ -594,9 +544,7 @@ def notify(self, args): Gamepiece group command input, isVisible=False by default - Container for gamepiece selection table """ - gamepieceConfig = inputs.addGroupCommandInput( - "gamepiece_config", "Gamepiece Configuration" - ) + gamepieceConfig = inputs.addGroupCommandInput("gamepiece_config", "Gamepiece Configuration") gamepieceConfig.isExpanded = True gamepieceConfig.isVisible = False gamepieceConfig.tooltip = "Select and define the gamepieces in your field." @@ -632,26 +580,14 @@ def notify(self, args): "Unit of Mass", adsk.core.DropDownStyles.LabeledIconDropDownStyle, ) - weight_unit_f.listItems.add( - "‎", True, IconPaths.massIcons["LBS"] - ) # add listdropdown mass options - weight_unit_f.listItems.add( - "‎", False, IconPaths.massIcons["KG"] - ) # add listdropdown mass options + weight_unit_f.listItems.add("‎", True, IconPaths.massIcons["LBS"]) # add listdropdown mass options + weight_unit_f.listItems.add("‎", False, IconPaths.massIcons["KG"]) # add listdropdown mass options weight_unit_f.tooltip = "Unit of mass" - weight_unit_f.tooltipDescription = ( - "
Configure the unit of mass for for the weight calculation." - ) + weight_unit_f.tooltipDescription = "
Configure the unit of mass for for the weight calculation." - weightTableInput_f.addCommandInput( - weight_name_f, 0, 0 - ) # add command inputs to table - weightTableInput_f.addCommandInput( - auto_calc_weight_f, 0, 1 - ) # add command inputs to table - weightTableInput_f.addCommandInput( - weight_unit_f, 0, 2 - ) # add command inputs to table + weightTableInput_f.addCommandInput(weight_name_f, 0, 0) # add command inputs to table + weightTableInput_f.addCommandInput(auto_calc_weight_f, 0, 1) # add command inputs to table + weightTableInput_f.addCommandInput(weight_unit_f, 0, 2) # add command inputs to table # GAMEPIECE SELECTION TABLE """ @@ -668,9 +604,7 @@ def notify(self, args): addFieldInput = gamepiece_inputs.addBoolValueInput("field_add", "Add", False) - removeFieldInput = gamepiece_inputs.addBoolValueInput( - "field_delete", "Remove", False - ) + removeFieldInput = gamepiece_inputs.addBoolValueInput("field_delete", "Remove", False) addFieldInput.isEnabled = removeFieldInput.isEnabled = True removeFieldInput.tooltip = "Remove a field element" @@ -732,19 +666,17 @@ def notify(self, args): """ Creates the advanced tab, which is the parent container for internal command inputs """ - advancedSettings = INPUTS_ROOT.addTabCommandInput( - "advanced_settings", "Advanced" + advancedSettings = INPUTS_ROOT.addTabCommandInput("advanced_settings", "Advanced") + advancedSettings.tooltip = ( + "Additional Advanced Settings to change how your model will be translated into Unity." ) - advancedSettings.tooltip = "Additional Advanced Settings to change how your model will be translated into Unity." a_input = advancedSettings.children # ~~~~~~~~~~~~~~~~ EXPORTER SETTINGS ~~~~~~~~~~~~~~~~ """ Exporter settings group command """ - exporterSetings = a_input.addGroupCommandInput( - "exporter_settings", "Exporter Settings" - ) + exporterSetings = a_input.addGroupCommandInput("exporter_settings", "Exporter Settings") exporterSetings.isExpanded = True exporterSetings.isEnabled = True exporterSetings.tooltip = "tooltip" # TODO: update tooltip @@ -800,9 +732,7 @@ def notify(self, args): """ Physics settings group command """ - physicsSettings = a_input.addGroupCommandInput( - "physics_settings", "Physics Settings" - ) + physicsSettings = a_input.addGroupCommandInput("physics_settings", "Physics Settings") physicsSettings.isExpanded = False physicsSettings.isEnabled = True @@ -857,9 +787,7 @@ def notify(self, args): enabled=True, isCheckBox=False, ) - frictionOverride.resourceFolder = IconPaths.stringIcons[ - "friction_override-enabled" - ] + frictionOverride.resourceFolder = IconPaths.stringIcons["friction_override-enabled"] frictionOverride.isFullWidth = True valueList = [1] @@ -872,9 +800,7 @@ def notify(self, args): frictionCoeff.isVisible = False frictionCoeff.valueOne = 0.5 frictionCoeff.tooltip = "Friction coefficient of field element." - frictionCoeff.tooltipDescription = ( - "Friction coefficients range from 0 (ice) to 1 (rubber)." - ) + frictionCoeff.tooltipDescription = "Friction coefficients range from 0 (ice) to 1 (rubber)." frictionOverrideTable.addCommandInput(frictionOverride, 0, 0) frictionOverrideTable.addCommandInput(frictionCoeff, 0, 1) @@ -883,9 +809,7 @@ def notify(self, args): """ Joint settings group command """ - jointsSettings = a_input.addGroupCommandInput( - "joints_settings", "Joints Settings" - ) + jointsSettings = a_input.addGroupCommandInput("joints_settings", "Joints Settings") jointsSettings.isExpanded = False jointsSettings.isEnabled = True jointsSettings.tooltip = "tooltip" # TODO: update tooltip @@ -922,9 +846,7 @@ def notify(self, args): """ Controller settings group command """ - controllerSettings = a_input.addGroupCommandInput( - "controller_settings", "Controller Settings" - ) + controllerSettings = a_input.addGroupCommandInput("controller_settings", "Controller Settings") controllerSettings.isExpanded = False controllerSettings.isEnabled = True @@ -949,9 +871,7 @@ def notify(self, args): """ onExecute = ConfigureCommandExecuteHandler( - json.dumps( - previous, default=lambda o: o.__dict__, sort_keys=True, indent=1 - ), + json.dumps(previous, default=lambda o: o.__dict__, sort_keys=True, indent=1), previous.filePath, ) cmd.execute.add(onExecute) @@ -992,9 +912,9 @@ def notify(self, args): except: if gm.ui: gm.ui.messageBox("Failed:\n{}".format(traceback.format_exc())) - logging.getLogger( - "{INTERNAL_ID}.UI.ConfigCommand.{self.__class__.__name__}" - ).error("Failed:\n{}".format(traceback.format_exc())) + logging.getLogger("{INTERNAL_ID}.UI.ConfigCommand.{self.__class__.__name__}").error( + "Failed:\n{}".format(traceback.format_exc()) + ) def createBooleanInput( self, @@ -1028,9 +948,9 @@ def createBooleanInput( _input.tooltipDescription = tooltipadvanced return _input except: - logging.getLogger( - "{INTERNAL_ID}.UI.ConfigCommand.{self.__class__.__name__}.createBooleanInput()" - ).error("Failed:\n{}".format(traceback.format_exc())) + logging.getLogger("{INTERNAL_ID}.UI.ConfigCommand.{self.__class__.__name__}.createBooleanInput()").error( + "Failed:\n{}".format(traceback.format_exc()) + ) def createTableInput( self, @@ -1068,9 +988,9 @@ def createTableInput( _input.rowSpacing = rowSpacing return _input except: - logging.getLogger( - "{INTERNAL_ID}.UI.ConfigCommand.{self.__class__.__name__}.createTableInput()" - ).error("Failed:\n{}".format(traceback.format_exc())) + logging.getLogger("{INTERNAL_ID}.UI.ConfigCommand.{self.__class__.__name__}.createTableInput()").error( + "Failed:\n{}".format(traceback.format_exc()) + ) def createTextBoxInput( self, @@ -1134,9 +1054,9 @@ def createTextBoxInput( _input.tooltipDescription = advanced_tooltip return _input except: - logging.getLogger( - "{INTERNAL_ID}.UI.ConfigCommand.createTextBoxInput()" - ).error("Failed:\n{}".format(traceback.format_exc())) + logging.getLogger("{INTERNAL_ID}.UI.ConfigCommand.createTextBoxInput()").error( + "Failed:\n{}".format(traceback.format_exc()) + ) class ConfigureCommandExecuteHandler(adsk.core.CommandEventHandler): @@ -1173,9 +1093,7 @@ def notify(self, args): self.log.error("Could not execute configuration due to failure") return - mode_dropdown = eventArgs.command.commandInputs.itemById( - "general_settings" - ).children.itemById("mode") + mode_dropdown = eventArgs.command.commandInputs.itemById("general_settings").children.itemById("mode") mode_dropdown = adsk.core.DropDownCommandInput.cast(mode_dropdown) mode = 5 @@ -1216,18 +1134,10 @@ def notify(self, args): + ".mira" ) else: - savepath = ( - os.getenv("APPDATA") - + "\\Autodesk\\Synthesis\\Mira\\" - + processedFileName - + ".mira" - ) + savepath = os.getenv("APPDATA") + "\\Autodesk\\Synthesis\\Mira\\" + processedFileName + ".mira" else: savepath = ( - os.getenv("APPDATA") - + "\\Autodesk\\Synthesis\\Mira\\Fields\\" - + processedFileName - + ".mira" + os.getenv("APPDATA") + "\\Autodesk\\Synthesis\\Mira\\Fields\\" + processedFileName + ".mira" ) else: from os.path import expanduser @@ -1235,26 +1145,11 @@ def notify(self, args): home = expanduser("~") if isRobot: if export_as_part_boolean.value: - savepath = ( - home - + "/.config/Autodesk/Synthesis/MixAndMatch/Mira/" - + processedFileName - + ".mira" - ) + savepath = home + "/.config/Autodesk/Synthesis/MixAndMatch/Mira/" + processedFileName + ".mira" else: - savepath = ( - home - + "/.config/Autodesk/Synthesis/Mira/" - + processedFileName - + ".mira" - ) + savepath = home + "/.config/Autodesk/Synthesis/Mira/" + processedFileName + ".mira" else: - savepath = ( - home - + "/.config/Autodesk/Synthesis/Mira/Fields/" - + processedFileName - + ".mira" - ) + savepath = home + "/.config/Autodesk/Synthesis/Mira/Fields/" + processedFileName + ".mira" if savepath == False: # save was canceled @@ -1292,9 +1187,7 @@ def notify(self, args): row, 2 ).selectedItem.index # This must be either 0 or 1 for standard or omni - signalTypeIndex = wheelTableInput.getInputAtPosition( - row, 3 - ).selectedItem.index + signalTypeIndex = wheelTableInput.getInputAtPosition(row, 3).selectedItem.index _exportWheels.append( _Wheel( @@ -1343,13 +1236,9 @@ def notify(self, args): ) continue elif parentJointIndex < row: - parentJointToken = JointListGlobal[ - parentJointIndex - 1 - ].entityToken # parent joint GUID, str + parentJointToken = JointListGlobal[parentJointIndex - 1].entityToken # parent joint GUID, str else: - parentJointToken = JointListGlobal[ - parentJointIndex + 1 - ].entityToken # parent joint GUID, str + parentJointToken = JointListGlobal[parentJointIndex + 1].entityToken # parent joint GUID, str # for wheel in _exportWheels: # find some way to get joint @@ -1375,16 +1264,12 @@ def notify(self, args): if row == 0: continue - weightValue = gamepieceTableInput.getInputAtPosition( - row, 2 - ).value # weight/mass input, float + weightValue = gamepieceTableInput.getInputAtPosition(row, 2).value # weight/mass input, float if weight_unit_f.selectedItem.index == 0: weightValue /= 2.2046226218 - frictionValue = gamepieceTableInput.getInputAtPosition( - row, 3 - ).valueOne # friction value, float + frictionValue = gamepieceTableInput.getInputAtPosition(row, 3).valueOne # friction value, float _exportGamepieces.append( Gamepiece( @@ -1433,9 +1318,7 @@ def notify(self, args): # success return else: - self.log.error( - f"Error: \n\t{name} could not be written to \n {savepath}" - ) + self.log.error(f"Error: \n\t{name} could not be written to \n {savepath}") except: if gm.ui: gm.ui.messageBox("Failed:\n{}".format(traceback.format_exc())) @@ -1503,14 +1386,10 @@ def notify(self, args): gm.app.activeViewport.refresh() else: gm.app.activeDocument.design.rootComponent.opacity = 1 - for ( - group - ) in gm.app.activeDocument.design.rootComponent.customGraphicsGroups: + for group in gm.app.activeDocument.design.rootComponent.customGraphicsGroups: group.deleteMe() - if ( - not addJointInput.isEnabled or not removeJointInput - ): # TODO: improve joint highlighting + if not addJointInput.isEnabled or not removeJointInput: # TODO: improve joint highlighting # for joint in JointListGlobal: # CustomGraphics.highlightJointedOccurrences(joint) @@ -1532,9 +1411,9 @@ def notify(self, args): except: if gm.ui: gm.ui.messageBox("Failed:\n{}".format(traceback.format_exc())) - logging.getLogger( - "{INTERNAL_ID}.UI.ConfigCommand.{self.__class__.__name__}" - ).error("Failed:\n{}".format(traceback.format_exc())) + logging.getLogger("{INTERNAL_ID}.UI.ConfigCommand.{self.__class__.__name__}").error( + "Failed:\n{}".format(traceback.format_exc()) + ) class MySelectHandler(adsk.core.SelectionEventHandler): @@ -1551,9 +1430,7 @@ def __init__(self, cmd): self.cmd = cmd self.allWheelPreselections = [] # all child occurrences of selections - self.allGamepiecePreselections = ( - [] - ) # all child gamepiece occurrences of selections + self.allGamepiecePreselections = [] # all child gamepiece occurrences of selections self.selectedOcc = None # selected occurrence (if there is one) self.selectedJoint = None # selected joint (if there is one) @@ -1585,9 +1462,9 @@ def traverseAssembly( except: if gm.ui: gm.ui.messageBox("Failed:\n{}".format(traceback.format_exc())) - logging.getLogger( - "{INTERNAL_ID}.UI.ConfigCommand.{self.__class__.__name__}.traverseAssembly()" - ).error("Failed:\n{}".format(traceback.format_exc())) + logging.getLogger("{INTERNAL_ID}.UI.ConfigCommand.{self.__class__.__name__}.traverseAssembly()").error( + "Failed:\n{}".format(traceback.format_exc()) + ) def wheelParent(self, occ: adsk.fusion.Occurrence): """### Identify an occurrence that encompasses the entire wheel component. @@ -1616,18 +1493,12 @@ def wheelParent(self, occ: adsk.fusion.Occurrence): try: for joint in occ.joints: - if ( - joint.jointMotion.jointType - == adsk.fusion.JointTypes.RevoluteJointType - ): + if joint.jointMotion.jointType == adsk.fusion.JointTypes.RevoluteJointType: # gm.ui.messageBox("Selection is directly jointed.\nReturning selection.\n\n" + "Occurrence:\n--> " + occ.name + "\nJoint:\n--> " + joint.name) return [joint.entityToken, occ] except: for joint in occ.component.joints: - if ( - joint.jointMotion.jointType - == adsk.fusion.JointTypes.RevoluteJointType - ): + if joint.jointMotion.jointType == adsk.fusion.JointTypes.RevoluteJointType: # gm.ui.messageBox("Selection is directly jointed.\nReturning selection.\n\n" + "Occurrence:\n--> " + occ.name + "\nJoint:\n--> " + joint.name) return [joint.entityToken, occ] @@ -1636,12 +1507,12 @@ def wheelParent(self, occ: adsk.fusion.Occurrence): return [None, occ] # return what is selected for joint in gm.app.activeDocument.design.rootComponent.allJoints: - if ( - joint.jointMotion.jointType - != adsk.fusion.JointTypes.RevoluteJointType - ): + if joint.jointMotion.jointType != adsk.fusion.JointTypes.RevoluteJointType: continue - jointedOcc[joint.entityToken] = [joint.occurrenceOne, joint.occurrenceTwo] + jointedOcc[joint.entityToken] = [ + joint.occurrenceOne, + joint.occurrenceTwo, + ] parentLevel = 1 # the number of nodes above the one selected returned = None # the returned value of traverseAssembly() @@ -1665,9 +1536,9 @@ def wheelParent(self, occ: adsk.fusion.Occurrence): except: if gm.ui: gm.ui.messageBox("Failed:\n{}".format(traceback.format_exc())) - logging.getLogger( - "{INTERNAL_ID}.UI.ConfigCommand.{self.__class__.__name__}.wheelParent()" - ).error("Failed:\n{}".format(traceback.format_exc())) + logging.getLogger("{INTERNAL_ID}.UI.ConfigCommand.{self.__class__.__name__}.wheelParent()").error( + "Failed:\n{}".format(traceback.format_exc()) + ) # gm.ui.messageBox("Selection's component has no referenced joints.\nReturning selection.\n\n" + "Occurrence:\n--> " + occ.name + "\nJoint:\n--> NONE") return [None, occ] @@ -1707,23 +1578,12 @@ def notify(self, args: adsk.core.SelectionEventArgs): elif self.selectedJoint: self.cmd.setCursor("", 0, 0) jointType = self.selectedJoint.jointMotion.jointType - if ( - jointType == JointMotions.REVOLUTE.value - or jointType == JointMotions.SLIDER.value - ): - if ( - jointType == JointMotions.REVOLUTE.value - and MySelectHandler.lastInputCmd.id == "wheel_select" - ): + if jointType == JointMotions.REVOLUTE.value or jointType == JointMotions.SLIDER.value: + if jointType == JointMotions.REVOLUTE.value and MySelectHandler.lastInputCmd.id == "wheel_select": addWheelToTable(self.selectedJoint) - elif ( - jointType == JointMotions.REVOLUTE.value - and MySelectHandler.lastInputCmd.id == "wheel_remove" - ): + elif jointType == JointMotions.REVOLUTE.value and MySelectHandler.lastInputCmd.id == "wheel_remove": if self.selectedJoint in WheelListGlobal: - removeWheelFromTable( - WheelListGlobal.index(self.selectedJoint) - ) + removeWheelFromTable(WheelListGlobal.index(self.selectedJoint)) else: if self.selectedJoint not in JointListGlobal: addJointToTable(self.selectedJoint) @@ -1735,9 +1595,9 @@ def notify(self, args: adsk.core.SelectionEventArgs): except: if gm.ui: gm.ui.messageBox("Failed:\n{}".format(traceback.format_exc())) - logging.getLogger( - "{INTERNAL_ID}.UI.ConfigCommand.{self.__class__.__name__}" - ).error("Failed:\n{}".format(traceback.format_exc())) + logging.getLogger("{INTERNAL_ID}.UI.ConfigCommand.{self.__class__.__name__}").error( + "Failed:\n{}".format(traceback.format_exc()) + ) class MyPreSelectHandler(adsk.core.SelectionEventHandler): @@ -1799,9 +1659,9 @@ def notify(self, args): except: if gm.ui: gm.ui.messageBox("Failed:\n{}".format(traceback.format_exc())) - logging.getLogger( - "{INTERNAL_ID}.UI.ConfigCommand.{self.__class__.__name__}" - ).error("Failed:\n{}".format(traceback.format_exc())) + logging.getLogger("{INTERNAL_ID}.UI.ConfigCommand.{self.__class__.__name__}").error( + "Failed:\n{}".format(traceback.format_exc()) + ) class MyPreselectEndHandler(adsk.core.SelectionEventHandler): @@ -1827,9 +1687,9 @@ def notify(self, args): except: if gm.ui: gm.ui.messageBox("Failed:\n{}".format(traceback.format_exc())) - logging.getLogger( - "{INTERNAL_ID}.UI.ConfigCommand.{self.__class__.__name__}" - ).error("Failed:\n{}".format(traceback.format_exc())) + logging.getLogger("{INTERNAL_ID}.UI.ConfigCommand.{self.__class__.__name__}").error( + "Failed:\n{}".format(traceback.format_exc()) + ) class ConfigureCommandInputChanged(adsk.core.InputChangedEventHandler): @@ -1841,9 +1701,7 @@ class ConfigureCommandInputChanged(adsk.core.InputChangedEventHandler): def __init__(self, cmd): super().__init__() - self.log = logging.getLogger( - f"{INTERNAL_ID}.UI.ConfigCommand.{self.__class__.__name__}" - ) + self.log = logging.getLogger(f"{INTERNAL_ID}.UI.ConfigCommand.{self.__class__.__name__}") self.cmd = cmd self.allWeights = [None, None] # [lbs, kg] self.isLbs = True @@ -1858,9 +1716,9 @@ def reset(self): self.cmd.setCursor("", 0, 0) gm.ui.activeSelections.clear() except: - logging.getLogger( - "{INTERNAL_ID}.UI.ConfigCommand.{self.__class__.__name__}.reset()" - ).error("Failed:\n{}".format(traceback.format_exc())) + logging.getLogger("{INTERNAL_ID}.UI.ConfigCommand.{self.__class__.__name__}.reset()").error( + "Failed:\n{}".format(traceback.format_exc()) + ) def weight(self, isLbs=True): # maybe add a progress dialog?? """### Get the total design weight using the predetermined units. @@ -1890,9 +1748,9 @@ def weight(self, isLbs=True): # maybe add a progress dialog?? value = round(value, 2) # round weight to 2 decimals places return value except: - logging.getLogger( - "{INTERNAL_ID}.UI.ConfigCommand.{self.__class__.__name__}.weight()" - ).error("Failed:\n{}".format(traceback.format_exc())) + logging.getLogger("{INTERNAL_ID}.UI.ConfigCommand.{self.__class__.__name__}.weight()").error( + "Failed:\n{}".format(traceback.format_exc()) + ) def notify(self, args): try: @@ -1940,31 +1798,21 @@ def notify(self, args): gamepieceConfig.isVisible = False weightTableInput.isVisible = True - addFieldInput.isEnabled = wheelConfig.isVisible = ( - jointConfig.isVisible - ) = True + addFieldInput.isEnabled = wheelConfig.isVisible = jointConfig.isVisible = True elif modeDropdown.selectedItem.index == 1: if gamepieceConfig: gm.ui.activeSelections.clear() gm.app.activeDocument.design.rootComponent.opacity = 1 - addWheelInput.isEnabled = addJointInput.isEnabled = ( - gamepieceConfig.isVisible - ) = True + addWheelInput.isEnabled = addJointInput.isEnabled = gamepieceConfig.isVisible = True - jointConfig.isVisible = wheelConfig.isVisible = ( - weightTableInput.isVisible - ) = False + jointConfig.isVisible = wheelConfig.isVisible = weightTableInput.isVisible = False elif cmdInput.id == "joint_config": gm.app.activeDocument.design.rootComponent.opacity = 1 - elif ( - cmdInput.id == "placeholder_w" - or cmdInput.id == "name_w" - or cmdInput.id == "signal_type_w" - ): + elif cmdInput.id == "placeholder_w" or cmdInput.id == "name_w" or cmdInput.id == "signal_type_w": self.reset() wheelSelect.isEnabled = False @@ -1973,26 +1821,11 @@ def notify(self, args): cmdInput_str = cmdInput.id if cmdInput_str == "placeholder_w": - position = ( - wheelTableInput.getPosition( - adsk.core.ImageCommandInput.cast(cmdInput) - )[1] - - 1 - ) + position = wheelTableInput.getPosition(adsk.core.ImageCommandInput.cast(cmdInput))[1] - 1 elif cmdInput_str == "name_w": - position = ( - wheelTableInput.getPosition( - adsk.core.TextBoxCommandInput.cast(cmdInput) - )[1] - - 1 - ) + position = wheelTableInput.getPosition(adsk.core.TextBoxCommandInput.cast(cmdInput))[1] - 1 elif cmdInput_str == "signal_type_w": - position = ( - wheelTableInput.getPosition( - adsk.core.DropDownCommandInput.cast(cmdInput) - )[1] - - 1 - ) + position = wheelTableInput.getPosition(adsk.core.DropDownCommandInput.cast(cmdInput))[1] - 1 gm.ui.activeSelections.add(WheelListGlobal[position]) @@ -2006,11 +1839,7 @@ def notify(self, args): jointSelect.isEnabled = False addJointInput.isEnabled = True - elif ( - cmdInput.id == "blank_gp" - or cmdInput.id == "name_gp" - or cmdInput.id == "weight_gp" - ): + elif cmdInput.id == "blank_gp" or cmdInput.id == "name_gp" or cmdInput.id == "weight_gp": self.reset() gamepieceSelect.isEnabled = False @@ -2019,33 +1848,13 @@ def notify(self, args): cmdInput_str = cmdInput.id if cmdInput_str == "name_gp": - position = ( - gamepieceTableInput.getPosition( - adsk.core.TextBoxCommandInput.cast(cmdInput) - )[1] - - 1 - ) + position = gamepieceTableInput.getPosition(adsk.core.TextBoxCommandInput.cast(cmdInput))[1] - 1 elif cmdInput_str == "weight_gp": - position = ( - gamepieceTableInput.getPosition( - adsk.core.ValueCommandInput.cast(cmdInput) - )[1] - - 1 - ) + position = gamepieceTableInput.getPosition(adsk.core.ValueCommandInput.cast(cmdInput))[1] - 1 elif cmdInput_str == "blank_gp": - position = ( - gamepieceTableInput.getPosition( - adsk.core.ImageCommandInput.cast(cmdInput) - )[1] - - 1 - ) + position = gamepieceTableInput.getPosition(adsk.core.ImageCommandInput.cast(cmdInput))[1] - 1 else: - position = ( - gamepieceTableInput.getPosition( - adsk.core.FloatSliderCommandInput.cast(cmdInput) - )[1] - - 1 - ) + position = gamepieceTableInput.getPosition(adsk.core.FloatSliderCommandInput.cast(cmdInput))[1] - 1 gm.ui.activeSelections.add(GamepieceListGlobal[position]) @@ -2056,34 +1865,23 @@ def notify(self, args): addWheelInput.isEnabled = True cmdInput_str = cmdInput.id - position = ( - wheelTableInput.getPosition( - adsk.core.DropDownCommandInput.cast(cmdInput) - )[1] - - 1 - ) + position = wheelTableInput.getPosition(adsk.core.DropDownCommandInput.cast(cmdInput))[1] - 1 wheelDropdown = adsk.core.DropDownCommandInput.cast(cmdInput) if wheelDropdown.selectedItem.index == 0: - getPosition = wheelTableInput.getPosition( - adsk.core.DropDownCommandInput.cast(cmdInput) - ) + getPosition = wheelTableInput.getPosition(adsk.core.DropDownCommandInput.cast(cmdInput)) iconInput = wheelTableInput.getInputAtPosition(getPosition[1], 0) iconInput.imageFile = IconPaths.wheelIcons["standard"] iconInput.tooltip = "Standard wheel" elif wheelDropdown.selectedItem.index == 1: - getPosition = wheelTableInput.getPosition( - adsk.core.DropDownCommandInput.cast(cmdInput) - ) + getPosition = wheelTableInput.getPosition(adsk.core.DropDownCommandInput.cast(cmdInput)) iconInput = wheelTableInput.getInputAtPosition(getPosition[1], 0) iconInput.imageFile = IconPaths.wheelIcons["omni"] iconInput.tooltip = "Omni wheel" elif wheelDropdown.selectedItem.index == 2: - getPosition = wheelTableInput.getPosition( - adsk.core.DropDownCommandInput.cast(cmdInput) - ) + getPosition = wheelTableInput.getPosition(adsk.core.DropDownCommandInput.cast(cmdInput)) iconInput = wheelTableInput.getInputAtPosition(getPosition[1], 0) iconInput.imageFile = IconPaths.wheelIcons["mecanum"] iconInput.tooltip = "Mecanum wheel" @@ -2146,10 +1944,7 @@ def notify(self, args): addFieldInput.isEnabled = True - if ( - gamepieceTableInput.selectedRow == -1 - or gamepieceTableInput.selectedRow == 0 - ): + if gamepieceTableInput.selectedRow == -1 or gamepieceTableInput.selectedRow == 0: gamepieceTableInput.selectedRow = gamepieceTableInput.rowCount - 1 gm.ui.messageBox("Select a row to delete.") else: @@ -2179,11 +1974,15 @@ def notify(self, args): if unitDropdown.selectedItem.index == 0: self.isLbs = True - weightInput.tooltipDescription = """(in pounds)
This is the weight of the entire robot assembly.""" + weightInput.tooltipDescription = ( + """(in pounds)
This is the weight of the entire robot assembly.""" + ) elif unitDropdown.selectedItem.index == 1: self.isLbs = False - weightInput.tooltipDescription = """(in kilograms)
This is the weight of the entire robot assembly.""" + weightInput.tooltipDescription = ( + """(in kilograms)
This is the weight of the entire robot assembly.""" + ) elif cmdInput.id == "weight_unit_f": unitDropdown = adsk.core.DropDownCommandInput.cast(cmdInput) @@ -2208,9 +2007,7 @@ def notify(self, args): button = adsk.core.BoolValueCommandInput.cast(cmdInput) if button.value == True: # CALCULATE button pressed - if ( - self.allWeights.count(None) == 2 - ): # if button is pressed for the first time + if self.allWeights.count(None) == 2: # if button is pressed for the first time if self.isLbs: # if pounds unit selected self.allWeights[0] = self.weight() weight_input.value = self.allWeights[0] @@ -2237,9 +2034,7 @@ def notify(self, args): if row == 0: continue weightInput = gamepieceTableInput.getInputAtPosition(row, 2) - physical = GamepieceListGlobal[ - row - 1 - ].component.getPhysicalProperties( + physical = GamepieceListGlobal[row - 1].component.getPhysicalProperties( adsk.fusion.CalculationAccuracy.LowCalculationAccuracy ) value = round(physical.mass * 2.2046226218, 2) @@ -2250,9 +2045,7 @@ def notify(self, args): if row == 0: continue weightInput = gamepieceTableInput.getInputAtPosition(row, 2) - physical = GamepieceListGlobal[ - row - 1 - ].component.getPhysicalProperties( + physical = GamepieceListGlobal[row - 1].component.getPhysicalProperties( adsk.fusion.CalculationAccuracy.LowCalculationAccuracy ) value = round(physical.mass, 2) @@ -2297,9 +2090,9 @@ def notify(self, args): except: if gm.ui: gm.ui.messageBox("Failed:\n{}".format(traceback.format_exc())) - logging.getLogger( - "{INTERNAL_ID}.UI.ConfigCommand.{self.__class__.__name__}" - ).error("Failed:\n{}".format(traceback.format_exc())) + logging.getLogger("{INTERNAL_ID}.UI.ConfigCommand.{self.__class__.__name__}").error( + "Failed:\n{}".format(traceback.format_exc()) + ) class MyKeyDownHandler(adsk.core.KeyboardEventHandler): @@ -2428,9 +2221,9 @@ def notify(self, args): except: if gm.ui: gm.ui.messageBox("Failed:\n{}".format(traceback.format_exc())) - logging.getLogger( - "{INTERNAL_ID}.UI.ConfigCommand.{self.__class__.__name__}" - ).error("Failed:\n{}".format(traceback.format_exc())) + logging.getLogger("{INTERNAL_ID}.UI.ConfigCommand.{self.__class__.__name__}").error( + "Failed:\n{}".format(traceback.format_exc()) + ) def addJointToTable(joint: adsk.fusion.Joint) -> None: @@ -2446,45 +2239,31 @@ def addJointToTable(joint: adsk.fusion.Joint) -> None: # joint type icons if joint.jointMotion.jointType == adsk.fusion.JointTypes.RigidJointType: - icon = cmdInputs.addImageCommandInput( - "placeholder", "Rigid", IconPaths.jointIcons["rigid"] - ) + icon = cmdInputs.addImageCommandInput("placeholder", "Rigid", IconPaths.jointIcons["rigid"]) icon.tooltip = "Rigid joint" elif joint.jointMotion.jointType == adsk.fusion.JointTypes.RevoluteJointType: - icon = cmdInputs.addImageCommandInput( - "placeholder", "Revolute", IconPaths.jointIcons["revolute"] - ) + icon = cmdInputs.addImageCommandInput("placeholder", "Revolute", IconPaths.jointIcons["revolute"]) icon.tooltip = "Revolute joint" elif joint.jointMotion.jointType == adsk.fusion.JointTypes.SliderJointType: - icon = cmdInputs.addImageCommandInput( - "placeholder", "Slider", IconPaths.jointIcons["slider"] - ) + icon = cmdInputs.addImageCommandInput("placeholder", "Slider", IconPaths.jointIcons["slider"]) icon.tooltip = "Slider joint" elif joint.jointMotion.jointType == adsk.fusion.JointTypes.PlanarJointType: - icon = cmdInputs.addImageCommandInput( - "placeholder", "Planar", IconPaths.jointIcons["planar"] - ) + icon = cmdInputs.addImageCommandInput("placeholder", "Planar", IconPaths.jointIcons["planar"]) icon.tooltip = "Planar joint" elif joint.jointMotion.jointType == adsk.fusion.JointTypes.PinSlotJointType: - icon = cmdInputs.addImageCommandInput( - "placeholder", "Pin Slot", IconPaths.jointIcons["pin_slot"] - ) + icon = cmdInputs.addImageCommandInput("placeholder", "Pin Slot", IconPaths.jointIcons["pin_slot"]) icon.tooltip = "Pin slot joint" elif joint.jointMotion.jointType == adsk.fusion.JointTypes.CylindricalJointType: - icon = cmdInputs.addImageCommandInput( - "placeholder", "Cylindrical", IconPaths.jointIcons["cylindrical"] - ) + icon = cmdInputs.addImageCommandInput("placeholder", "Cylindrical", IconPaths.jointIcons["cylindrical"]) icon.tooltip = "Cylindrical joint" elif joint.jointMotion.jointType == adsk.fusion.JointTypes.BallJointType: - icon = cmdInputs.addImageCommandInput( - "placeholder", "Ball", IconPaths.jointIcons["ball"] - ) + icon = cmdInputs.addImageCommandInput("placeholder", "Ball", IconPaths.jointIcons["ball"]) icon.tooltip = "Ball joint" # joint name @@ -2540,9 +2319,7 @@ def addJointToTable(joint: adsk.fusion.Joint) -> None: jointSpeed.tooltip = "Degrees per second" jointTableInput.addCommandInput(jointSpeed, row, 4) - jointForce = cmdInputs.addValueInput( - "joint_force", "Force", "N", adsk.core.ValueInput.createByReal(5000) - ) + jointForce = cmdInputs.addValueInput("joint_force", "Force", "N", adsk.core.ValueInput.createByReal(5000)) jointForce.tooltip = "Newton-Meters***" jointTableInput.addCommandInput(jointForce, row, 5) @@ -2556,9 +2333,7 @@ def addJointToTable(joint: adsk.fusion.Joint) -> None: jointSpeed.tooltip = "Meters per second" jointTableInput.addCommandInput(jointSpeed, row, 4) - jointForce = cmdInputs.addValueInput( - "joint_force", "Force", "N", adsk.core.ValueInput.createByReal(5000) - ) + jointForce = cmdInputs.addValueInput("joint_force", "Force", "N", adsk.core.ValueInput.createByReal(5000)) jointForce.tooltip = "Newtons" jointTableInput.addCommandInput(jointForce, row, 5) @@ -2593,13 +2368,9 @@ def addWheelToTable(wheel: adsk.fusion.Joint) -> None: WheelListGlobal.append(wheel) cmdInputs = adsk.core.CommandInputs.cast(wheelTableInput.commandInputs) - icon = cmdInputs.addImageCommandInput( - "placeholder_w", "Placeholder", IconPaths.wheelIcons["standard"] - ) + icon = cmdInputs.addImageCommandInput("placeholder_w", "Placeholder", IconPaths.wheelIcons["standard"]) - name = cmdInputs.addTextBoxCommandInput( - "name_w", "Joint name", wheel.name, 1, True - ) + name = cmdInputs.addTextBoxCommandInput("name_w", "Joint name", wheel.name, 1, True) name.tooltip = wheel.name wheelType = cmdInputs.addDropDownCommandInput( @@ -2611,9 +2382,9 @@ def addWheelToTable(wheel: adsk.fusion.Joint) -> None: wheelType.listItems.add("Omni", False, "") wheelType.tooltip = "Wheel type" wheelType.tooltipDescription = "
Omni-directional wheels can be used just like regular drive wheels but they have the advantage of being able to roll freely perpendicular to the drive direction.
" - wheelType.toolClipFilename = OsHelper.getOSPath( - ".", "src", "Resources" - ) + os.path.join("WheelIcons", "omni-wheel-preview.png") + wheelType.toolClipFilename = OsHelper.getOSPath(".", "src", "Resources") + os.path.join( + "WheelIcons", "omni-wheel-preview.png" + ) signalType = cmdInputs.addDropDownCommandInput( "signal_type_w", @@ -2663,18 +2434,12 @@ def addPreselections(child_occurrences): GamepieceListGlobal.append(gamepiece) cmdInputs = adsk.core.CommandInputs.cast(gamepieceTableInput.commandInputs) - blankIcon = cmdInputs.addImageCommandInput( - "blank_gp", "Blank", IconPaths.gamepieceIcons["blank"] - ) + blankIcon = cmdInputs.addImageCommandInput("blank_gp", "Blank", IconPaths.gamepieceIcons["blank"]) - type = cmdInputs.addTextBoxCommandInput( - "name_gp", "Occurrence name", gamepiece.name, 1, True - ) + type = cmdInputs.addTextBoxCommandInput("name_gp", "Occurrence name", gamepiece.name, 1, True) value = 0.0 - physical = gamepiece.component.getPhysicalProperties( - adsk.fusion.CalculationAccuracy.LowCalculationAccuracy - ) + physical = gamepiece.component.getPhysicalProperties(adsk.fusion.CalculationAccuracy.LowCalculationAccuracy) value = physical.mass # check if dropdown unit is kg or lbs. bool value taken from ConfigureCommandInputChanged @@ -2698,9 +2463,7 @@ def addPreselections(child_occurrences): for i in range(20): valueList.append(i / 20) - friction_coeff = cmdInputs.addFloatSliderListCommandInput( - "friction_coeff", "", "", valueList - ) + friction_coeff = cmdInputs.addFloatSliderListCommandInput("friction_coeff", "", "", valueList) friction_coeff.valueOne = 0.5 type.tooltip = gamepiece.name @@ -2709,9 +2472,7 @@ def addPreselections(child_occurrences): weight.tooltipDescription = massUnitInString friction_coeff.tooltip = "Friction coefficient of field element" - friction_coeff.tooltipDescription = ( - "Friction coefficients range from 0 (ice) to 1 (rubber)." - ) + friction_coeff.tooltipDescription = "Friction coefficients range from 0 (ice) to 1 (rubber)." row = gamepieceTableInput.rowCount gamepieceTableInput.addCommandInput(blankIcon, row, 0) @@ -2825,6 +2586,6 @@ def removePreselections(child_occurrences): except IndexError: pass except: - logging.getLogger( - "{INTERNAL_ID}.UI.ConfigCommand.removeGamePieceFromTable()" - ).error("Failed:\n{}".format(traceback.format_exc())) + logging.getLogger("{INTERNAL_ID}.UI.ConfigCommand.removeGamePieceFromTable()").error( + "Failed:\n{}".format(traceback.format_exc()) + ) diff --git a/exporter/SynthesisFusionAddin/src/UI/Configuration/SerialCommand.py b/exporter/SynthesisFusionAddin/src/UI/Configuration/SerialCommand.py index 0dd61c58e2..88e3447f26 100644 --- a/exporter/SynthesisFusionAddin/src/UI/Configuration/SerialCommand.py +++ b/exporter/SynthesisFusionAddin/src/UI/Configuration/SerialCommand.py @@ -6,6 +6,7 @@ """ import json + from ...Types.OString import OString diff --git a/exporter/SynthesisFusionAddin/src/UI/CustomGraphics.py b/exporter/SynthesisFusionAddin/src/UI/CustomGraphics.py index 9b99310657..17b63c8222 100644 --- a/exporter/SynthesisFusionAddin/src/UI/CustomGraphics.py +++ b/exporter/SynthesisFusionAddin/src/UI/CustomGraphics.py @@ -1,4 +1,9 @@ -import adsk.fusion, adsk.core, traceback, logging +import logging +import traceback + +import adsk.core +import adsk.fusion + from ..general_imports import * @@ -12,26 +17,18 @@ def createTextGraphics(wheel: adsk.fusion.Occurrence, _wheels) -> None: max = boundingBox.maxPoint.asArray() # [x, y, z] max coords if design: - graphics = ( - gm.app.activeDocument.design.rootComponent.customGraphicsGroups.add() - ) + graphics = gm.app.activeDocument.design.rootComponent.customGraphicsGroups.add() matrix = adsk.core.Matrix3D.create() matrix.translation = adsk.core.Vector3D.create(min[0], min[1] - 5, min[2]) - billBoard = adsk.fusion.CustomGraphicsBillBoard.create( - adsk.core.Point3D.create(0, 0, 0) - ) - billBoard.billBoardStyle = ( - adsk.fusion.CustomGraphicsBillBoardStyles.ScreenBillBoardStyle - ) + billBoard = adsk.fusion.CustomGraphicsBillBoard.create(adsk.core.Point3D.create(0, 0, 0)) + billBoard.billBoardStyle = adsk.fusion.CustomGraphicsBillBoardStyles.ScreenBillBoardStyle text = str(_wheels.index(wheel) + 1) graphicsText = graphics.addText(text, "Arial Black", 6, matrix) graphicsText.billBoarding = billBoard # make the text follow the camera graphicsText.isSelectable = False # make it non-selectable - graphicsText.cullMode = ( - adsk.fusion.CustomGraphicsCullModes.CustomGraphicsCullBack - ) + graphicsText.cullMode = adsk.fusion.CustomGraphicsCullModes.CustomGraphicsCullBack graphicsText.color = adsk.fusion.CustomGraphicsShowThroughColorEffect.create( adsk.core.Color.create(230, 146, 18, 255), 1 ) # orange/synthesis theme @@ -80,6 +77,4 @@ def createTextGraphics(wheel: adsk.fusion.Occurrence, _wheels) -> None: line.isSelectable = False line.depthPriority = 1 except: - logging.getLogger("{INTERNAL_ID}.UI.CreateTextGraphics").error( - "Failed:\n{}".format(traceback.format_exc()) - ) + logging.getLogger("{INTERNAL_ID}.UI.CreateTextGraphics").error("Failed:\n{}".format(traceback.format_exc())) diff --git a/exporter/SynthesisFusionAddin/src/UI/Events.py b/exporter/SynthesisFusionAddin/src/UI/Events.py index 407b71e481..60e2af032f 100644 --- a/exporter/SynthesisFusionAddin/src/UI/Events.py +++ b/exporter/SynthesisFusionAddin/src/UI/Events.py @@ -1,7 +1,7 @@ -from ..general_imports import * - -from typing import Sequence, Tuple import logging.handlers +from typing import Sequence, Tuple + +from ..general_imports import * """ # This file is Special It links all function names to command requests that palletes can make automatically @@ -51,9 +51,7 @@ def openDocument(json_data: str) -> str: """ data = json.loads(json_data) data = data["arguments"] - gm.ui.messageBox( - f"Attempting to open and focus on a given document: {data}\n TODO: Implement" - ) + gm.ui.messageBox(f"Attempting to open and focus on a given document: {data}\n TODO: Implement") logging.getLogger(f"{INTERNAL_ID}.Events.openDocument").info( f"Attempting to open and focus on a given document: {data}\n TODO: Implement" ) diff --git a/exporter/SynthesisFusionAddin/src/UI/FileDialogConfig.py b/exporter/SynthesisFusionAddin/src/UI/FileDialogConfig.py index 0dd7e9d88b..3c2989fada 100644 --- a/exporter/SynthesisFusionAddin/src/UI/FileDialogConfig.py +++ b/exporter/SynthesisFusionAddin/src/UI/FileDialogConfig.py @@ -1,15 +1,15 @@ +from typing import Union + +import adsk.core +import adsk.fusion + from ..general_imports import * # from ..proto_out import Configuration_pb2 from ..Types.OString import OString -from typing import Union -import adsk.core, adsk.fusion - -def SaveFileDialog( - defaultPath="", defaultName="", ext="MiraBuf Package (*.mira)" -) -> Union[str, bool]: +def SaveFileDialog(defaultPath="", defaultName="", ext="MiraBuf Package (*.mira)") -> Union[str, bool]: """Function to generate the Save File Dialog for the Hellion Data files Args: diff --git a/exporter/SynthesisFusionAddin/src/UI/HUI.py b/exporter/SynthesisFusionAddin/src/UI/HUI.py index f3530cc8ac..d7efb56398 100644 --- a/exporter/SynthesisFusionAddin/src/UI/HUI.py +++ b/exporter/SynthesisFusionAddin/src/UI/HUI.py @@ -1,7 +1,5 @@ -from . import OsHelper -from . import Handlers - from ..general_imports import * +from . import Handlers, OsHelper # no longer used @@ -47,9 +45,7 @@ def __init__( self.events.append(arg) if self.uid in gm.uniqueIds: - raise ValueError( - f"Cannot create two UI Elements with the same ID {self.uid}\n" - ) + raise ValueError(f"Cannot create two UI Elements with the same ID {self.uid}\n") if gm.ui.palettes is None: raise RuntimeError(f"No Palette object exists yet") @@ -57,9 +53,7 @@ def __init__( self.palette = gm.ui.palettes.itemById(self.uid) if self.palette is None: - path = OsHelper.getOSPathPalette( - "src", "Resources", "Palette", f'{self.name.replace(" ", "")}' - ) + path = OsHelper.getOSPathPalette("src", "Resources", "Palette", f'{self.name.replace(" ", "")}') self.palette = gm.ui.palettes.add( self.uid, @@ -72,9 +66,7 @@ def __init__( height, ) - self.palette.dockingState = ( - adsk.core.PaletteDockingStates.PaletteDockStateLeft - ) + self.palette.dockingState = adsk.core.PaletteDockingStates.PaletteDockStateLeft onHTML = Handlers.HPaletteHTMLEventHandler(self) self.palette.incomingFromHTML.add(onHTML) @@ -124,9 +116,7 @@ def __init__( self.uid = name.replace(" ", "") + f"_{INTERNAL_ID}" if self.uid in gm.uniqueIds: - raise ValueError( - f"Cannot create two UI Elements with the same ID {self.uid}\n" - ) + raise ValueError(f"Cannot create two UI Elements with the same ID {self.uid}\n") self.name = name diff --git a/exporter/SynthesisFusionAddin/src/UI/Helper.py b/exporter/SynthesisFusionAddin/src/UI/Helper.py index fdbb01e286..608d9e27b4 100644 --- a/exporter/SynthesisFusionAddin/src/UI/Helper.py +++ b/exporter/SynthesisFusionAddin/src/UI/Helper.py @@ -1,8 +1,8 @@ -from ..general_imports import * from inspect import getmembers, isfunction from typing import Union -from . import Events, HUI +from ..general_imports import * +from . import HUI, Events def check_solid_open() -> bool: @@ -31,9 +31,7 @@ def previouslyConfigured() -> Union[str, None]: app = adsk.core.Application.get() try: - configured = app.activeDocument.attributes.itemByName( - f"{INTERNAL_ID}", "Configuration" - ) + configured = app.activeDocument.attributes.itemByName(f"{INTERNAL_ID}", "Configuration") if configured is not None: return configured.value return False @@ -76,9 +74,7 @@ def checkAttribute() -> bool: return connected.value return False except: - app.userInterface.messageBox( - f"Could not access the attributes of the file \n -- {traceback.format_exc()}." - ) + app.userInterface.messageBox(f"Could not access the attributes of the file \n -- {traceback.format_exc()}.") return False @@ -99,9 +95,7 @@ def addUnityAttribute() -> bool or None: return None except: - app.userInterface.messageBox( - f"Could not access the attributes of the file \n -- {traceback.format_exc()}." - ) + app.userInterface.messageBox(f"Could not access the attributes of the file \n -- {traceback.format_exc()}.") return False @@ -122,9 +116,7 @@ def openPanel() -> None: gm.app.data.isDataPanelVisible = False else: func_list = [o for o in getmembers(Events, isfunction)] - palette_new = HUI.HPalette( - name, APP_TITLE, True, True, False, 400, 500, func_list - ) + palette_new = HUI.HPalette(name, APP_TITLE, True, True, False, 400, 500, func_list) gm.elements.append(palette_new) return diff --git a/exporter/SynthesisFusionAddin/src/UI/IconPaths.py b/exporter/SynthesisFusionAddin/src/UI/IconPaths.py index 9508f5e4ff..261720494c 100644 --- a/exporter/SynthesisFusionAddin/src/UI/IconPaths.py +++ b/exporter/SynthesisFusionAddin/src/UI/IconPaths.py @@ -1,17 +1,15 @@ -from . import OsHelper import os +from . import OsHelper + """ Dictionaries that store all the icon paths in ConfigCommand. All path strings are OS-independent """ -resources = OsHelper.getOSPath( - ".", "src", "Resources" -) # str shortcut with primary directories to all images in file +resources = OsHelper.getOSPath(".", "src", "Resources") # str shortcut with primary directories to all images in file wheelIcons = { "omni": resources + os.path.join("WheelIcons", "omni-wheel-preview190x24.png"), - "standard": resources - + os.path.join("WheelIcons", "standard-wheel-preview190x24.png"), + "standard": resources + os.path.join("WheelIcons", "standard-wheel-preview190x24.png"), "mecanum": resources + os.path.join("WheelIcons", "mecanum-wheel-preview190x24.png"), } @@ -19,10 +17,8 @@ "rigid": resources + os.path.join("JointIcons", "JointRigid", "rigid190x24.png"), "revolute": resources + os.path.join("JointIcons", "JointRev", "revolute190x24.png"), "slider": resources + os.path.join("JointIcons", "JointSlider", "slider190x24.png"), - "cylindrical": resources - + os.path.join("JointIcons", "JointCyl", "cylindrical190x24.png"), - "pin_slot": resources - + os.path.join("JointIcons", "JointPinSlot", "pin_slot190x24.png"), + "cylindrical": resources + os.path.join("JointIcons", "JointCyl", "cylindrical190x24.png"), + "pin_slot": resources + os.path.join("JointIcons", "JointPinSlot", "pin_slot190x24.png"), "planar": resources + os.path.join("JointIcons", "JointPlanar", "planar190x24.png"), "ball": resources + os.path.join("JointIcons", "JointBall", "ball190x24.png"), } @@ -48,8 +44,6 @@ } stringIcons = { - "calculate-enabled": resources - + os.path.join("AutoCalcWeight_icon"), # resource folder - "friction_override-enabled": resources - + os.path.join("FrictionOverride_icon"), # resource folder + "calculate-enabled": resources + os.path.join("AutoCalcWeight_icon"), # resource folder + "friction_override-enabled": resources + os.path.join("FrictionOverride_icon"), # resource folder } diff --git a/exporter/SynthesisFusionAddin/src/UI/MarkingMenu.py b/exporter/SynthesisFusionAddin/src/UI/MarkingMenu.py index 0a1fbadcbf..5c68d2c79a 100644 --- a/exporter/SynthesisFusionAddin/src/UI/MarkingMenu.py +++ b/exporter/SynthesisFusionAddin/src/UI/MarkingMenu.py @@ -1,5 +1,8 @@ -import adsk.core, adsk.fusion, traceback import logging.handlers +import traceback + +import adsk.core +import adsk.fusion # Ripped all the boiler plate from the example code: https://help.autodesk.com/view/fusion360/ENU/?guid=GUID-c90ce6a2-c282-11e6-a365-3417ebc87622 @@ -22,9 +25,7 @@ def setLinearMarkingMenu(args): linearMenu = menuArgs.linearMarkingMenu linearMenu.controls.addSeparator("LinearSeparator") - synthDropDown = linearMenu.controls.addDropDown( - "Synthesis", "", "synthesis" - ) + synthDropDown = linearMenu.controls.addDropDown("Synthesis", "", "synthesis") cmdSelectDisabled = ui.commandDefinitions.itemById("SelectDisabled") synthDropDown.controls.addCommand(cmdSelectDisabled) @@ -40,24 +41,15 @@ def setLinearMarkingMenu(args): occ = adsk.fusion.Occurrence.cast(sel0) if occ: - if ( - occ.attributes.itemByName("synthesis", "collision_off") - == None - ): - cmdDisableCollision = ui.commandDefinitions.itemById( - "DisableCollision" - ) + if occ.attributes.itemByName("synthesis", "collision_off") == None: + cmdDisableCollision = ui.commandDefinitions.itemById("DisableCollision") synthDropDown.controls.addCommand(cmdDisableCollision) else: - cmdEnableCollision = ui.commandDefinitions.itemById( - "EnableCollision" - ) + cmdEnableCollision = ui.commandDefinitions.itemById("EnableCollision") synthDropDown.controls.addCommand(cmdEnableCollision) except: if ui: - ui.messageBox("setting linear menu failed: {}").format( - traceback.format_exc() - ) + ui.messageBox("setting linear menu failed: {}").format(traceback.format_exc()) def setCollisionAttribute(occ: adsk.fusion.Occurrence, isEnabled: bool = True): attr = occ.attributes.itemByName("synthesis", "collision_off") @@ -90,9 +82,7 @@ def notify(self, args): handlers.append(onCommandExcute) command.execute.add(onCommandExcute) except: - ui.messageBox("command created failed: {}").format( - traceback.format_exc() - ) + ui.messageBox("command created failed: {}").format(traceback.format_exc()) class MyCommandExecuteHandler(adsk.core.CommandEventHandler): def __init__(self): @@ -125,34 +115,24 @@ def notify(self, args): design = adsk.fusion.Design.cast(product) ui.activeSelections.clear() if design: - attrs = design.findAttributes( - "synthesis", "collision_off" - ) + attrs = design.findAttributes("synthesis", "collision_off") for attr in attrs: - for b in adsk.fusion.Occurrence.cast( - attr.parent - ).bRepBodies: + for b in adsk.fusion.Occurrence.cast(attr.parent).bRepBodies: ui.activeSelections.add(b) elif cmdDef.id == "EnableAllCollision": app = adsk.core.Application.get() product = app.activeProduct design = adsk.fusion.Design.cast(product) if design: - for attr in design.findAttributes( - "synthesis", "collision_off" - ): + for attr in design.findAttributes("synthesis", "collision_off"): attr.deleteMe() else: ui.messageBox("command {} triggered.".format(cmdDef.id)) else: ui.messageBox("No CommandDefinition") except: - ui.messageBox("command executed failed: {}").format( - traceback.format_exc() - ) - logging.getLogger(f"{INTERNAL_ID}").error( - "Failed:\n{}".format(traceback.format_exc()) - ) + ui.messageBox("command executed failed: {}").format(traceback.format_exc()) + logging.getLogger(f"{INTERNAL_ID}").error("Failed:\n{}".format(traceback.format_exc())) class MyMarkingMenuHandler(adsk.core.MarkingMenuEventHandler): def __init__(self): @@ -170,11 +150,7 @@ def notify(self, args): entities = args.selectedEntities except: if ui: - ui.messageBox( - "Marking Menu Displaying event failed: {}".format( - traceback.format_exc() - ) - ) + ui.messageBox("Marking Menu Displaying event failed: {}".format(traceback.format_exc())) # Add customized handler for marking menu displaying onMarkingMenuDisplaying = MyMarkingMenuHandler() diff --git a/exporter/SynthesisFusionAddin/src/UI/OsHelper.py b/exporter/SynthesisFusionAddin/src/UI/OsHelper.py index 956c9f6fd1..e338be5815 100644 --- a/exporter/SynthesisFusionAddin/src/UI/OsHelper.py +++ b/exporter/SynthesisFusionAddin/src/UI/OsHelper.py @@ -1,4 +1,5 @@ -import os, platform +import os +import platform def getOSPath(*argv) -> str: diff --git a/exporter/SynthesisFusionAddin/src/UI/Toolbar.py b/exporter/SynthesisFusionAddin/src/UI/Toolbar.py index 8044c46e7d..e0b8f26f19 100644 --- a/exporter/SynthesisFusionAddin/src/UI/Toolbar.py +++ b/exporter/SynthesisFusionAddin/src/UI/Toolbar.py @@ -36,9 +36,7 @@ def __init__(self, name: str): except: error = traceback.format_exc() - self.logger.error( - f"Failed at creating toolbar with {self.uid} due to {error}" - ) + self.logger.error(f"Failed at creating toolbar with {self.uid} due to {error}") def getPanel(self, name: str, visibility: bool = True) -> str or None: """# Gets a control for a panel to the tabbed toolbar @@ -61,9 +59,7 @@ def getPanel(self, name: str, visibility: bool = True) -> str or None: return None @staticmethod - def getNewPanel( - name: str, tab_id: str, toolbar_id: str, visibility: bool = True - ) -> str or None: + def getNewPanel(name: str, tab_id: str, toolbar_id: str, visibility: bool = True) -> str or None: """# Gets a control for a panel to the tabbed toolbar visibility""" logger = logging.getLogger(f"{INTERNAL_ID}.Toolbar.getNewPanel") diff --git a/exporter/SynthesisFusionAddin/src/configure.py b/exporter/SynthesisFusionAddin/src/configure.py index 5226a2acce..e121e7ae6e 100644 --- a/exporter/SynthesisFusionAddin/src/configure.py +++ b/exporter/SynthesisFusionAddin/src/configure.py @@ -1,11 +1,12 @@ """ Stores data and fields from config.ini """ -from configparser import ConfigParser -from .Types.OString import OString -from .strings import INTERNAL_ID -import uuid, traceback import logging.handlers +import traceback +import uuid +from configparser import ConfigParser +from .strings import INTERNAL_ID +from .Types.OString import OString try: config = ConfigParser() @@ -35,19 +36,13 @@ else: # in here we need to ask for analytics CID = uuid.uuid4() - config.set( - "analytics", "c_id", str(CID) - ) # default values - add exception handling + config.set("analytics", "c_id", str(CID)) # default values - add exception handling except: - logging.getLogger(f"{INTERNAL_ID}.import_manager").error( - "Failed\n{}".format(traceback.format_exc()) - ) + logging.getLogger(f"{INTERNAL_ID}.import_manager").error("Failed\n{}".format(traceback.format_exc())) def setAnalytics(enabled: bool): - logging.getLogger(f"{INTERNAL_ID}.configure.setAnalytics").info( - f"First run , Analytics set to {enabled}" - ) + logging.getLogger(f"{INTERNAL_ID}.configure.setAnalytics").info(f"First run , Analytics set to {enabled}") ANALYTICS = enabled ans = "yes" if ANALYTICS else "no" write_configuration("analytics", "analytics", ans) diff --git a/exporter/SynthesisFusionAddin/src/general_imports.py b/exporter/SynthesisFusionAddin/src/general_imports.py index 7c2711ee77..7921a5e367 100644 --- a/exporter/SynthesisFusionAddin/src/general_imports.py +++ b/exporter/SynthesisFusionAddin/src/general_imports.py @@ -1,19 +1,25 @@ -import os, sys, uuid, json -import adsk.core, adsk.fusion, traceback -import logging.handlers, pathlib - -from time import time +import json +import logging.handlers +import os +import pathlib +import sys +import traceback +import uuid from datetime import datetime +from time import time from types import FunctionType +import adsk.core +import adsk.fusion + # hard coded to bypass errors for now PROTOBUF = True DEBUG = True try: - from .strings import * from .GlobalManager import * from .logging import setupLogger + from .strings import * (root_logger, log_handler) = setupLogger() except ImportError as e: @@ -23,9 +29,7 @@ try: path = os.path.abspath(os.path.join(os.path.dirname(__file__), "..")) - path_proto_files = os.path.abspath( - os.path.join(os.path.dirname(__file__), "..", "proto", "proto_out") - ) + path_proto_files = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "proto", "proto_out")) if not path in sys.path: sys.path.insert(1, path) @@ -36,9 +40,7 @@ from proto import deps except: - logging.getLogger(f"{INTERNAL_ID}.import_manager").error( - "Failed\n{}".format(traceback.format_exc()) - ) + logging.getLogger(f"{INTERNAL_ID}.import_manager").error("Failed\n{}".format(traceback.format_exc())) try: # simple analytics endpoint @@ -50,6 +52,4 @@ my_addin_path = os.path.dirname(os.path.realpath(__file__)) except: # should also log this - logging.getLogger(f"{INTERNAL_ID}.import_manager").error( - "Failed\n{}".format(traceback.format_exc()) - ) + logging.getLogger(f"{INTERNAL_ID}.import_manager").error("Failed\n{}".format(traceback.format_exc())) diff --git a/exporter/SynthesisFusionAddin/src/logging.py b/exporter/SynthesisFusionAddin/src/logging.py index 00b9fcfe4f..2a0233ae5a 100644 --- a/exporter/SynthesisFusionAddin/src/logging.py +++ b/exporter/SynthesisFusionAddin/src/logging.py @@ -2,11 +2,12 @@ """ import logging.handlers +import os +import pathlib from datetime import datetime -import os, pathlib -from .UI.OsHelper import getOSPath from .strings import * +from .UI.OsHelper import getOSPath def setupLogger(): @@ -19,14 +20,10 @@ def setupLogger(): loc = pathlib.Path(__file__).parent.parent path = getOSPath(f"{loc}", "logs") - _log_handler = logging.handlers.WatchedFileHandler( - os.environ.get("LOGFILE", f"{path}{INTERNAL_ID}.log"), mode="w" - ) + _log_handler = logging.handlers.WatchedFileHandler(os.environ.get("LOGFILE", f"{path}{INTERNAL_ID}.log"), mode="w") # This will make it so I can see the auxiliary logging levels of each of the subclasses - _log_handler.setFormatter( - logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s") - ) + _log_handler.setFormatter(logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")) log = logging.getLogger(f"{INTERNAL_ID}") log.setLevel(os.environ.get("LOGLEVEL", "DEBUG")) From d3a9b993e64b24738bba7afd0f70ff74605eae0d Mon Sep 17 00:00:00 2001 From: BrandonPacewic Date: Fri, 21 Jun 2024 10:16:09 -0700 Subject: [PATCH 02/20] Workflow update to include `isort` --- .github/workflows/BlackFormat.yml | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/.github/workflows/BlackFormat.yml b/.github/workflows/BlackFormat.yml index 2f258aab79..049067165b 100644 --- a/.github/workflows/BlackFormat.yml +++ b/.github/workflows/BlackFormat.yml @@ -9,11 +9,21 @@ on: jobs: blackFormatChecker: - name: Black Formatter for Python Exporter + name: Validate Black and isort Formatting for Python Exporter runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: psf/black@stable + - name: Checkout Code + uses: actions/checkout@v2 + - name: Python Setup + uses: actions/setup-python@v2 + with: + python-version: '3.9' + - name: Setup isort + run: python3 -m pip3 install isort + - name: Run isort + run: isort ./exporter/SynthesisFusionAddin/ + - name: Validate Black/isort Formatting + uses: psf/black@stable with: options: "--check" src: "./exporter/SynthesisFusionAddin/" From d05e3512ad70756a62414abe2e88e9ad35f8eed1 Mon Sep 17 00:00:00 2001 From: BrandonPacewic Date: Fri, 21 Jun 2024 10:17:13 -0700 Subject: [PATCH 03/20] Simply run with `pip` --- .github/workflows/BlackFormat.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/BlackFormat.yml b/.github/workflows/BlackFormat.yml index 049067165b..b5b94abf79 100644 --- a/.github/workflows/BlackFormat.yml +++ b/.github/workflows/BlackFormat.yml @@ -19,7 +19,7 @@ jobs: with: python-version: '3.9' - name: Setup isort - run: python3 -m pip3 install isort + run: python3 -m pip install isort - name: Run isort run: isort ./exporter/SynthesisFusionAddin/ - name: Validate Black/isort Formatting From 97d817b300907413ae4df1bce1bb8265890c5f26 Mon Sep 17 00:00:00 2001 From: BrandonPacewic Date: Fri, 21 Jun 2024 10:22:29 -0700 Subject: [PATCH 04/20] `deps.py` formatting --- exporter/SynthesisFusionAddin/proto/deps.py | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/exporter/SynthesisFusionAddin/proto/deps.py b/exporter/SynthesisFusionAddin/proto/deps.py index 7504fc006a..ea1363ff75 100644 --- a/exporter/SynthesisFusionAddin/proto/deps.py +++ b/exporter/SynthesisFusionAddin/proto/deps.py @@ -33,9 +33,7 @@ def getPythonFolder() -> str: elif system == "Darwin": pythonFolder = f"{Path(osPath).parents[2]}/bin" else: - raise ImportError( - "Unsupported platform! This add-in only supports windows and macos" - ) + raise ImportError("Unsupported platform! This add-in only supports windows and macos") logging.getLogger(f"{INTERNAL_ID}").debug(f"Python Folder -> {pythonFolder}") return pythonFolder @@ -51,9 +49,7 @@ def executeCommand(command: tuple) -> int: int: Exit code of the process """ if system == "Windows": - executionResult = subprocess.call( - command, bufsize=1, creationflags=subprocess.CREATE_NO_WINDOW, shell=False - ) + executionResult = subprocess.call(command, bufsize=1, creationflags=subprocess.CREATE_NO_WINDOW, shell=False) else: # Uses os.system because I was unable to get subprocess.call to work on MacOS installComm = str.join(" ", command) @@ -94,9 +90,7 @@ def installCross(pipDeps: list) -> bool: try: pythonFolder = getPythonFolder() except ImportError as e: - logging.getLogger(f"{INTERNAL_ID}").error( - f"Failed to download dependencies: {e.msg}" - ) + logging.getLogger(f"{INTERNAL_ID}").error(f"Failed to download dependencies: {e.msg}") return False if system == "Darwin": # macos @@ -129,9 +123,7 @@ def installCross(pipDeps: list) -> bool: ] ) if installResult != 0: - logging.getLogger(f"{INTERNAL_ID}").warn( - f'Dep installation "{depName}" exited with code "{installResult}"' - ) + logging.getLogger(f"{INTERNAL_ID}").warn(f'Dep installation "{depName}" exited with code "{installResult}"') if system == "Darwin": pipAntiDeps = ["dataclasses", "typing"] From 1754e2bc6f714cbfec03594be0f881062a62d0c9 Mon Sep 17 00:00:00 2001 From: BrandonPacewic Date: Fri, 21 Jun 2024 11:01:44 -0700 Subject: [PATCH 05/20] isort formatting check --- .github/workflows/BlackFormat.yml | 13 ++++++-- scripts/format/isort_format_validation.py | 40 +++++++++++++++++++++++ 2 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 scripts/format/isort_format_validation.py diff --git a/.github/workflows/BlackFormat.yml b/.github/workflows/BlackFormat.yml index b5b94abf79..2799130d70 100644 --- a/.github/workflows/BlackFormat.yml +++ b/.github/workflows/BlackFormat.yml @@ -20,8 +20,17 @@ jobs: python-version: '3.9' - name: Setup isort run: python3 -m pip install isort - - name: Run isort - run: isort ./exporter/SynthesisFusionAddin/ + - name: Run isort Validation + run: python3 scripts/format/isort_format_validation.py + id: isort-validation + - name: Check isort Validation Success + run: | + if [ ${{ steps.isort-validation.outcome }} == "success" ]; then + echo " Validation Passed" + else + echo "Format Validation Failed" + exit 1 + fi - name: Validate Black/isort Formatting uses: psf/black@stable with: diff --git a/scripts/format/isort_format_validation.py b/scripts/format/isort_format_validation.py new file mode 100644 index 0000000000..9e61b43a38 --- /dev/null +++ b/scripts/format/isort_format_validation.py @@ -0,0 +1,40 @@ +import os +import subprocess +import sys + +FILES_DIRS = ["exporter/SynthesisFusionAddin"] +FILE_TARGETS = [".py", ".pyi"] + +def main(): + if sys.platform != "linux": + print("Warning: This script was designed to be run by github action linux machines") + + files = [] + for dir in FILES_DIRS: + for root, _, filenames in os.walk(dir): + for filename in filenames: + if os.path.splitext(filename)[1] in FILE_TARGETS: + files.append(os.path.abspath(os.path.join(root, filename))) + + file_states = [open(file, "r").readlines() for file in files] + subprocess.call(["isort", "."], bufsize=1, shell=False,) + new_file_states = [open(file, "r").readlines() for file in files] + + exit_code = 0 + + for i, (previous_file_state, new_file_state) in enumerate(zip(file_states, new_file_states)): + for i, (previous_line, new_line) in enumerate(zip(previous_file_state, new_file_state)): + if previous_line != new_line: + print(f"File {files[i]} is not formatted correctly!") + print(f"Line: {i + 1}") + exit_code = 1 + break + + if exit_code == 0: + print("All files are formatted correctly!") + + sys.exit(exit_code) + + +if __name__ == '__main__': + main() From 11d4b504703552d13916443bbad553340de84144 Mon Sep 17 00:00:00 2001 From: BrandonPacewic Date: Fri, 21 Jun 2024 11:03:58 -0700 Subject: [PATCH 06/20] isort individual directories --- scripts/format/isort_format_validation.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/format/isort_format_validation.py b/scripts/format/isort_format_validation.py index 9e61b43a38..475a045f49 100644 --- a/scripts/format/isort_format_validation.py +++ b/scripts/format/isort_format_validation.py @@ -17,11 +17,11 @@ def main(): files.append(os.path.abspath(os.path.join(root, filename))) file_states = [open(file, "r").readlines() for file in files] - subprocess.call(["isort", "."], bufsize=1, shell=False,) - new_file_states = [open(file, "r").readlines() for file in files] + for dir in FILES_DIRS: + subprocess.call(["isort", dir], bufsize=1, shell=False,) + new_file_states = [open(file, "r").readlines() for file in files] exit_code = 0 - for i, (previous_file_state, new_file_state) in enumerate(zip(file_states, new_file_states)): for i, (previous_line, new_line) in enumerate(zip(previous_file_state, new_file_state)): if previous_line != new_line: From 2d29e5eceacd7c139455e344dee4cb941f93470c Mon Sep 17 00:00:00 2001 From: BrandonPacewic Date: Fri, 21 Jun 2024 11:05:42 -0700 Subject: [PATCH 07/20] Force workflow fail --- exporter/SynthesisFusionAddin/src/Parser/ParseOptions.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/exporter/SynthesisFusionAddin/src/Parser/ParseOptions.py b/exporter/SynthesisFusionAddin/src/Parser/ParseOptions.py index d306be9e23..642e668c22 100644 --- a/exporter/SynthesisFusionAddin/src/Parser/ParseOptions.py +++ b/exporter/SynthesisFusionAddin/src/Parser/ParseOptions.py @@ -7,8 +7,8 @@ - this is essentially a flat configuration file with non serializable objects """ -from dataclasses import dataclass from typing import List, Union +from dataclasses import dataclass import adsk.core import adsk.fusion @@ -20,8 +20,8 @@ # Contains enums for parents of joints that have special cases class JointParentType: # validate for unique key and value - ROOT = 0 # grounded root object - END = 1 + ROOT= 0 # grounded root object + END= 1 class WheelType: From 814422c33311d7253cefc43f8c6fbeed1ede10ea Mon Sep 17 00:00:00 2001 From: BrandonPacewic Date: Fri, 21 Jun 2024 11:08:44 -0700 Subject: [PATCH 08/20] Fix isort formatting --- exporter/SynthesisFusionAddin/src/Parser/ParseOptions.py | 2 +- scripts/format/isort_format_validation.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/exporter/SynthesisFusionAddin/src/Parser/ParseOptions.py b/exporter/SynthesisFusionAddin/src/Parser/ParseOptions.py index 642e668c22..50b3fbcf41 100644 --- a/exporter/SynthesisFusionAddin/src/Parser/ParseOptions.py +++ b/exporter/SynthesisFusionAddin/src/Parser/ParseOptions.py @@ -7,8 +7,8 @@ - this is essentially a flat configuration file with non serializable objects """ -from typing import List, Union from dataclasses import dataclass +from typing import List, Union import adsk.core import adsk.fusion diff --git a/scripts/format/isort_format_validation.py b/scripts/format/isort_format_validation.py index 475a045f49..0d065d9ddf 100644 --- a/scripts/format/isort_format_validation.py +++ b/scripts/format/isort_format_validation.py @@ -23,10 +23,10 @@ def main(): new_file_states = [open(file, "r").readlines() for file in files] exit_code = 0 for i, (previous_file_state, new_file_state) in enumerate(zip(file_states, new_file_states)): - for i, (previous_line, new_line) in enumerate(zip(previous_file_state, new_file_state)): + for j, (previous_line, new_line) in enumerate(zip(previous_file_state, new_file_state)): if previous_line != new_line: print(f"File {files[i]} is not formatted correctly!") - print(f"Line: {i + 1}") + print(f"Line: {j + 1}") exit_code = 1 break From 3ed887e4833cac41139298451f45f4493006ed86 Mon Sep 17 00:00:00 2001 From: BrandonPacewic Date: Fri, 21 Jun 2024 11:19:50 -0700 Subject: [PATCH 09/20] Embedded python this time around --- .github/workflows/BlackFormat.yml | 38 +++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/.github/workflows/BlackFormat.yml b/.github/workflows/BlackFormat.yml index 2799130d70..e0c5b748db 100644 --- a/.github/workflows/BlackFormat.yml +++ b/.github/workflows/BlackFormat.yml @@ -21,8 +21,42 @@ jobs: - name: Setup isort run: python3 -m pip install isort - name: Run isort Validation - run: python3 scripts/format/isort_format_validation.py - id: isort-validation + run: | + python - <<'EOF' + import os + import subprocess + import sys + + FILES_DIRS = ["exporter/SynthesisFusionAddin"] + FILE_TARGETS = [".py", ".pyi"] + + files = [] + for dir in FILES_DIRS: + for root, _, filenames in os.walk(dir): + for filename in filenames: + if os.path.splitext(filename)[1] in FILE_TARGETS: + print(f"Adding {filename}") + files.append(os.path.abspath(os.path.join(root, filename))) + + oldFileStates = [open(file, "r").readlines() for file in files] + for dir in FILES_DIRS: + subprocess.call(["isort", dir], bufsize=1, shell=False,) + + newFileStates = [open(file, "r").readlines() for file in files] + exitCode = 0 + for i, (oldFileState, newFileState) in enumerate(zip(oldFileStates, newFileStates)): + for j, (previous_line, new_line) in enumerate(zip(oldFileState, newFileState)): + if previous_line != new_line: + print(f"File {files[i]} is not formatted correctly!") + print(f"Line: {j + 1}") + exitCode = 1 + break + + if not exitCode: + print("All files are formatted correctly!") + + sys.exit(exitCode) + EOF - name: Check isort Validation Success run: | if [ ${{ steps.isort-validation.outcome }} == "success" ]; then From 0687a7a6c709a6cd3701db6d38053878c4d85148 Mon Sep 17 00:00:00 2001 From: BrandonPacewic Date: Fri, 21 Jun 2024 11:21:28 -0700 Subject: [PATCH 10/20] Workflow enbedded cleanups --- .github/workflows/BlackFormat.yml | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/.github/workflows/BlackFormat.yml b/.github/workflows/BlackFormat.yml index e0c5b748db..cbff818146 100644 --- a/.github/workflows/BlackFormat.yml +++ b/.github/workflows/BlackFormat.yml @@ -9,7 +9,7 @@ on: jobs: blackFormatChecker: - name: Validate Black and isort Formatting for Python Exporter + name: Validate Black and Isort Formatting for Python Exporter runs-on: ubuntu-latest steps: - name: Checkout Code @@ -18,9 +18,9 @@ jobs: uses: actions/setup-python@v2 with: python-version: '3.9' - - name: Setup isort + - name: Setup Isort run: python3 -m pip install isort - - name: Run isort Validation + - name: Validate Isort Formatting run: | python - <<'EOF' import os @@ -57,15 +57,7 @@ jobs: sys.exit(exitCode) EOF - - name: Check isort Validation Success - run: | - if [ ${{ steps.isort-validation.outcome }} == "success" ]; then - echo " Validation Passed" - else - echo "Format Validation Failed" - exit 1 - fi - - name: Validate Black/isort Formatting + - name: Validate Black Formatting uses: psf/black@stable with: options: "--check" From 9571656de834ba6269c488bbe46f98d64a78a260 Mon Sep 17 00:00:00 2001 From: BrandonPacewic Date: Fri, 21 Jun 2024 11:38:57 -0700 Subject: [PATCH 11/20] Shorter embedded python --- .github/workflows/BlackFormat.yml | 34 ++++--------- .../src/Parser/ParseOptions.py | 4 +- scripts/format/isort_format_validation.py | 51 ++++++------------- 3 files changed, 26 insertions(+), 63 deletions(-) diff --git a/.github/workflows/BlackFormat.yml b/.github/workflows/BlackFormat.yml index cbff818146..bcda2db365 100644 --- a/.github/workflows/BlackFormat.yml +++ b/.github/workflows/BlackFormat.yml @@ -23,38 +23,22 @@ jobs: - name: Validate Isort Formatting run: | python - <<'EOF' - import os - import subprocess - import sys - - FILES_DIRS = ["exporter/SynthesisFusionAddin"] - FILE_TARGETS = [".py", ".pyi"] - - files = [] - for dir in FILES_DIRS: - for root, _, filenames in os.walk(dir): - for filename in filenames: - if os.path.splitext(filename)[1] in FILE_TARGETS: - print(f"Adding {filename}") - files.append(os.path.abspath(os.path.join(root, filename))) + import os, subprocess, sys + EXPORTER_DIR = "exporter/SynthesisFusionAddin" + files = (lambda d: [os.path.abspath(os.path.join(root, filename)) for root, _, filenames in os.walk(d) + for filename in filenames if filename.endswith(".py")])(EXPORTER_DIR) oldFileStates = [open(file, "r").readlines() for file in files] - for dir in FILES_DIRS: - subprocess.call(["isort", dir], bufsize=1, shell=False,) - + subprocess.call(["isort", EXPORTER_DIR], bufsize=1, shell=False) newFileStates = [open(file, "r").readlines() for file in files] exitCode = 0 for i, (oldFileState, newFileState) in enumerate(zip(oldFileStates, newFileStates)): - for j, (previous_line, new_line) in enumerate(zip(oldFileState, newFileState)): - if previous_line != new_line: - print(f"File {files[i]} is not formatted correctly!") - print(f"Line: {j + 1}") + for j, (previousLine, newLine) in enumerate(zip(oldFileState, newFileState)): + if previousLine != newLine: + print(f"File {files[i]} is not formatted correctly!\nLine: {j + 1}") exitCode = 1 - break - - if not exitCode: - print("All files are formatted correctly!") + if not exitCode: print("All files are formatted correctly with isort!") sys.exit(exitCode) EOF - name: Validate Black Formatting diff --git a/exporter/SynthesisFusionAddin/src/Parser/ParseOptions.py b/exporter/SynthesisFusionAddin/src/Parser/ParseOptions.py index 50b3fbcf41..d306be9e23 100644 --- a/exporter/SynthesisFusionAddin/src/Parser/ParseOptions.py +++ b/exporter/SynthesisFusionAddin/src/Parser/ParseOptions.py @@ -20,8 +20,8 @@ # Contains enums for parents of joints that have special cases class JointParentType: # validate for unique key and value - ROOT= 0 # grounded root object - END= 1 + ROOT = 0 # grounded root object + END = 1 class WheelType: diff --git a/scripts/format/isort_format_validation.py b/scripts/format/isort_format_validation.py index 0d065d9ddf..1ba06d8b1e 100644 --- a/scripts/format/isort_format_validation.py +++ b/scripts/format/isort_format_validation.py @@ -2,39 +2,18 @@ import subprocess import sys -FILES_DIRS = ["exporter/SynthesisFusionAddin"] -FILE_TARGETS = [".py", ".pyi"] - -def main(): - if sys.platform != "linux": - print("Warning: This script was designed to be run by github action linux machines") - - files = [] - for dir in FILES_DIRS: - for root, _, filenames in os.walk(dir): - for filename in filenames: - if os.path.splitext(filename)[1] in FILE_TARGETS: - files.append(os.path.abspath(os.path.join(root, filename))) - - file_states = [open(file, "r").readlines() for file in files] - for dir in FILES_DIRS: - subprocess.call(["isort", dir], bufsize=1, shell=False,) - - new_file_states = [open(file, "r").readlines() for file in files] - exit_code = 0 - for i, (previous_file_state, new_file_state) in enumerate(zip(file_states, new_file_states)): - for j, (previous_line, new_line) in enumerate(zip(previous_file_state, new_file_state)): - if previous_line != new_line: - print(f"File {files[i]} is not formatted correctly!") - print(f"Line: {j + 1}") - exit_code = 1 - break - - if exit_code == 0: - print("All files are formatted correctly!") - - sys.exit(exit_code) - - -if __name__ == '__main__': - main() +EXPORTER_DIR = "exporter/SynthesisFusionAddin" +files = (lambda d: [os.path.abspath(os.path.join(root, filename)) for root, _, filenames in os.walk(d) + for filename in filenames if filename.endswith(".py")])(EXPORTER_DIR) +oldFileStates = [open(file, "r").readlines() for file in files] +subprocess.call(["isort", EXPORTER_DIR], bufsize=1, shell=False) +newFileStates = [open(file, "r").readlines() for file in files] +exitCode = 0 +for i, (oldFileState, newFileState) in enumerate(zip(oldFileStates, newFileStates)): + for j, (previousLine, newLine) in enumerate(zip(oldFileState, newFileState)): + if previousLine != newLine: + print(f"File {files[i]} is not formatted correctly!\nLine: {j + 1}") + exitCode = 1 + +if not exitCode: print("All files are formatted correctly with isort!") +sys.exit(exitCode) From 3f711a741789a753ae1f5825da9fdc95d6b160f4 Mon Sep 17 00:00:00 2001 From: BrandonPacewic Date: Fri, 21 Jun 2024 11:41:01 -0700 Subject: [PATCH 12/20] Should fail the workflow --- .../src/Parser/ParseOptions.py | 2 +- scripts/format/isort_format_validation.py | 19 ------------------- 2 files changed, 1 insertion(+), 20 deletions(-) delete mode 100644 scripts/format/isort_format_validation.py diff --git a/exporter/SynthesisFusionAddin/src/Parser/ParseOptions.py b/exporter/SynthesisFusionAddin/src/Parser/ParseOptions.py index d306be9e23..45cbbee3cf 100644 --- a/exporter/SynthesisFusionAddin/src/Parser/ParseOptions.py +++ b/exporter/SynthesisFusionAddin/src/Parser/ParseOptions.py @@ -7,8 +7,8 @@ - this is essentially a flat configuration file with non serializable objects """ -from dataclasses import dataclass from typing import List, Union +from dataclasses import dataclass import adsk.core import adsk.fusion diff --git a/scripts/format/isort_format_validation.py b/scripts/format/isort_format_validation.py deleted file mode 100644 index 1ba06d8b1e..0000000000 --- a/scripts/format/isort_format_validation.py +++ /dev/null @@ -1,19 +0,0 @@ -import os -import subprocess -import sys - -EXPORTER_DIR = "exporter/SynthesisFusionAddin" -files = (lambda d: [os.path.abspath(os.path.join(root, filename)) for root, _, filenames in os.walk(d) - for filename in filenames if filename.endswith(".py")])(EXPORTER_DIR) -oldFileStates = [open(file, "r").readlines() for file in files] -subprocess.call(["isort", EXPORTER_DIR], bufsize=1, shell=False) -newFileStates = [open(file, "r").readlines() for file in files] -exitCode = 0 -for i, (oldFileState, newFileState) in enumerate(zip(oldFileStates, newFileStates)): - for j, (previousLine, newLine) in enumerate(zip(oldFileState, newFileState)): - if previousLine != newLine: - print(f"File {files[i]} is not formatted correctly!\nLine: {j + 1}") - exitCode = 1 - -if not exitCode: print("All files are formatted correctly with isort!") -sys.exit(exitCode) From ec148a24500c7a867ee7eaac3ff409161736881b Mon Sep 17 00:00:00 2001 From: BrandonPacewic Date: Fri, 21 Jun 2024 11:41:49 -0700 Subject: [PATCH 13/20] Should fail the workflow --- exporter/SynthesisFusionAddin/src/Parser/ParseOptions.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/exporter/SynthesisFusionAddin/src/Parser/ParseOptions.py b/exporter/SynthesisFusionAddin/src/Parser/ParseOptions.py index 45cbbee3cf..50b3fbcf41 100644 --- a/exporter/SynthesisFusionAddin/src/Parser/ParseOptions.py +++ b/exporter/SynthesisFusionAddin/src/Parser/ParseOptions.py @@ -7,8 +7,8 @@ - this is essentially a flat configuration file with non serializable objects """ -from typing import List, Union from dataclasses import dataclass +from typing import List, Union import adsk.core import adsk.fusion @@ -20,8 +20,8 @@ # Contains enums for parents of joints that have special cases class JointParentType: # validate for unique key and value - ROOT = 0 # grounded root object - END = 1 + ROOT= 0 # grounded root object + END= 1 class WheelType: From afc5b47c2997a238e55b1bcdccc534203236bf39 Mon Sep 17 00:00:00 2001 From: BrandonPacewic Date: Fri, 21 Jun 2024 11:44:27 -0700 Subject: [PATCH 14/20] Restored correct formatting --- .github/workflows/BlackFormat.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/BlackFormat.yml b/.github/workflows/BlackFormat.yml index bcda2db365..a9fdb48e4b 100644 --- a/.github/workflows/BlackFormat.yml +++ b/.github/workflows/BlackFormat.yml @@ -9,7 +9,7 @@ on: jobs: blackFormatChecker: - name: Validate Black and Isort Formatting for Python Exporter + name: Black Formatter for Python Exporter runs-on: ubuntu-latest steps: - name: Checkout Code From 9ed8d4b402f1e920e2776d18202a7706e5f76e9f Mon Sep 17 00:00:00 2001 From: BrandonPacewic Date: Fri, 21 Jun 2024 11:44:45 -0700 Subject: [PATCH 15/20] Restored correct formatting --- exporter/SynthesisFusionAddin/src/Parser/ParseOptions.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/exporter/SynthesisFusionAddin/src/Parser/ParseOptions.py b/exporter/SynthesisFusionAddin/src/Parser/ParseOptions.py index 50b3fbcf41..d306be9e23 100644 --- a/exporter/SynthesisFusionAddin/src/Parser/ParseOptions.py +++ b/exporter/SynthesisFusionAddin/src/Parser/ParseOptions.py @@ -20,8 +20,8 @@ # Contains enums for parents of joints that have special cases class JointParentType: # validate for unique key and value - ROOT= 0 # grounded root object - END= 1 + ROOT = 0 # grounded root object + END = 1 class WheelType: From 0ae99db648327d0432e1fa27b141e2cfee509c09 Mon Sep 17 00:00:00 2001 From: BrandonPacewic Date: Fri, 21 Jun 2024 11:49:02 -0700 Subject: [PATCH 16/20] Readme updates --- exporter/SynthesisFusionAddin/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/exporter/SynthesisFusionAddin/README.md b/exporter/SynthesisFusionAddin/README.md index e7de6ef58b..76a62d9df4 100644 --- a/exporter/SynthesisFusionAddin/README.md +++ b/exporter/SynthesisFusionAddin/README.md @@ -78,9 +78,9 @@ Contact us for information on how to use the packaging script to obfuscate all o ### How to Format -We format using a Python formatter called `black` [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) +We format using a Python formatter called `black` [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) in conjunction with [`isort`](https://pycqa.github.io/isort/). -- install by `pip3 install black` or `pip install black` -- use `black ./src`, Formats all files in src directory +- install by `pip3 install black && pip3 install isort` or `pip install black && pip install isort` +- use `isort .` followed by `black .` to format all relevant exporter python files. __Note: black will always ignore files in the proto/proto_out folder since google formats those__ From bcb8344d8a51ece9e4746f819e0f35f4cea03233 Mon Sep 17 00:00:00 2001 From: BrandonPacewic Date: Wed, 26 Jun 2024 14:21:07 -0700 Subject: [PATCH 17/20] Updated isort validation step --- .github/workflows/BlackFormat.yml | 29 ++++++----------- .../tools/verifyIsortFormatting.py | 32 +++++++++++++++++++ 2 files changed, 42 insertions(+), 19 deletions(-) create mode 100644 exporter/SynthesisFusionAddin/tools/verifyIsortFormatting.py diff --git a/.github/workflows/BlackFormat.yml b/.github/workflows/BlackFormat.yml index a9fdb48e4b..2916febbba 100644 --- a/.github/workflows/BlackFormat.yml +++ b/.github/workflows/BlackFormat.yml @@ -21,26 +21,17 @@ jobs: - name: Setup Isort run: python3 -m pip install isort - name: Validate Isort Formatting + run: python3 ./exporter/SynthesisFusionAddin/tools/verifyIsortFormatting.py + id: isort-format-validation + continue-on-error: true + - name: Check Isort Formatting Validation run: | - python - <<'EOF' - import os, subprocess, sys - - EXPORTER_DIR = "exporter/SynthesisFusionAddin" - files = (lambda d: [os.path.abspath(os.path.join(root, filename)) for root, _, filenames in os.walk(d) - for filename in filenames if filename.endswith(".py")])(EXPORTER_DIR) - oldFileStates = [open(file, "r").readlines() for file in files] - subprocess.call(["isort", EXPORTER_DIR], bufsize=1, shell=False) - newFileStates = [open(file, "r").readlines() for file in files] - exitCode = 0 - for i, (oldFileState, newFileState) in enumerate(zip(oldFileStates, newFileStates)): - for j, (previousLine, newLine) in enumerate(zip(oldFileState, newFileState)): - if previousLine != newLine: - print(f"File {files[i]} is not formatted correctly!\nLine: {j + 1}") - exitCode = 1 - - if not exitCode: print("All files are formatted correctly with isort!") - sys.exit(exitCode) - EOF + if [ ${{ steps.format-validation.outcome }} == "success" ]; then + echo "Isort Formatting Validation Passed" + else + echo "Isort Formatting Validation Failed" + exit 1 + fi - name: Validate Black Formatting uses: psf/black@stable with: diff --git a/exporter/SynthesisFusionAddin/tools/verifyIsortFormatting.py b/exporter/SynthesisFusionAddin/tools/verifyIsortFormatting.py new file mode 100644 index 0000000000..0f9d899d5a --- /dev/null +++ b/exporter/SynthesisFusionAddin/tools/verifyIsortFormatting.py @@ -0,0 +1,32 @@ +import os +import subprocess +import sys + +ROOT_EXPORTER_DIR = "exporter/SynthesisFusionAddin" + + +def main() -> None: + files = [ + os.path.abspath(os.path.join(root, filename)) + for root, _, filenames in os.walk(ROOT_EXPORTER_DIR) + for filename in filenames + if filename.endswith(".py") + ] + oldFileStates = [open(file, "r").readlines() for file in files] + subprocess.call(["isort", ROOT_EXPORTER_DIR], bufsize=1, shell=False) + newFileStates = [open(file, "r").readlines() for file in files] + exitCode = 0 + for i, (oldFileState, newFileState) in enumerate(zip(oldFileStates, newFileStates)): + for j, (previousLine, newLine) in enumerate(zip(oldFileState, newFileState)): + if previousLine != newLine: + print(f"File {files[i]} is not formatted correctly!\nLine: {j + 1}") + exitCode = 1 + + if not exitCode: + print("All files are formatted correctly with isort!") + + sys.exit(exitCode) + + +if __name__ == "__main__": + main() From 379051a251a1a1353042c6d92ee8ec60618f9aae Mon Sep 17 00:00:00 2001 From: BrandonPacewic Date: Wed, 26 Jun 2024 14:24:15 -0700 Subject: [PATCH 18/20] Update validation id --- .github/workflows/BlackFormat.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/BlackFormat.yml b/.github/workflows/BlackFormat.yml index 2916febbba..8763cf92c3 100644 --- a/.github/workflows/BlackFormat.yml +++ b/.github/workflows/BlackFormat.yml @@ -26,7 +26,7 @@ jobs: continue-on-error: true - name: Check Isort Formatting Validation run: | - if [ ${{ steps.format-validation.outcome }} == "success" ]; then + if [ ${{ steps.isort-format-validation.outcome }} == "success" ]; then echo "Isort Formatting Validation Passed" else echo "Isort Formatting Validation Failed" From 7edd7db39b806b42e48fc09d5d5aac766803bc18 Mon Sep 17 00:00:00 2001 From: BrandonPacewic Date: Wed, 26 Jun 2024 14:25:15 -0700 Subject: [PATCH 19/20] Update job name to be consistent with other format workflow --- .github/workflows/BlackFormat.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/BlackFormat.yml b/.github/workflows/BlackFormat.yml index 8763cf92c3..101e22ad5d 100644 --- a/.github/workflows/BlackFormat.yml +++ b/.github/workflows/BlackFormat.yml @@ -9,7 +9,7 @@ on: jobs: blackFormatChecker: - name: Black Formatter for Python Exporter + name: Black Format Validation runs-on: ubuntu-latest steps: - name: Checkout Code From 2be5a77577eb2c79f8c23b7dcc5d620c45a2f99e Mon Sep 17 00:00:00 2001 From: BrandonPacewic Date: Wed, 26 Jun 2024 14:56:44 -0700 Subject: [PATCH 20/20] Auto run formatters script --- exporter/SynthesisFusionAddin/README.md | 1 + exporter/SynthesisFusionAddin/tools/format.py | 25 +++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 exporter/SynthesisFusionAddin/tools/format.py diff --git a/exporter/SynthesisFusionAddin/README.md b/exporter/SynthesisFusionAddin/README.md index 76a62d9df4..d3272dc456 100644 --- a/exporter/SynthesisFusionAddin/README.md +++ b/exporter/SynthesisFusionAddin/README.md @@ -82,5 +82,6 @@ We format using a Python formatter called `black` [![Code style: black](https:// - install by `pip3 install black && pip3 install isort` or `pip install black && pip install isort` - use `isort .` followed by `black .` to format all relevant exporter python files. + - or, alternatively, run `python ./tools/format.py` to do this for you! __Note: black will always ignore files in the proto/proto_out folder since google formats those__ diff --git a/exporter/SynthesisFusionAddin/tools/format.py b/exporter/SynthesisFusionAddin/tools/format.py new file mode 100644 index 0000000000..7531b93de7 --- /dev/null +++ b/exporter/SynthesisFusionAddin/tools/format.py @@ -0,0 +1,25 @@ +import os +import subprocess +import sys + + +def main(args: list[str] = sys.argv[1:]) -> None: + dir = args[0] if len(args) else "." + if "pyproject.toml" not in os.listdir(dir): + print("WARNING: Configuration file for autoformatters was not found. Are you sure you specified the root DIR?") + + for command in ["isort", "black"]: + try: + print(f"Formatting with {command}...") + subprocess.call([command, dir], shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + except FileNotFoundError: + print(f'"{command}" could not be found. Please resolve dependencies.') + return + except BaseException as error: + print(f'An unknown error occurred while running "{command}"\n{error}') + + print("Done! All files successfully formatted.") + + +if __name__ == "__main__": + main()