Apply flynt to use f-strings

This commit is contained in:
Fabien Castan 2025-04-14 11:08:33 +02:00
parent ee679fcf34
commit 51b04bc077
23 changed files with 141 additions and 142 deletions

View file

@ -86,7 +86,7 @@ class Signal(object):
Connects the signal to any callable object Connects the signal to any callable object
""" """
if not callable(slot): if not callable(slot):
raise ValueError("Connection to non-callable '%s' object failed" % slot.__class__.__name__) raise ValueError(f"Connection to non-callable '{slot.__class__.__name__}' object failed")
if isinstance(slot, (partial, Signal)) or '<' in slot.__name__: if isinstance(slot, (partial, Signal)) or '<' in slot.__name__:
# If it's a partial, a Signal or a lambda. The '<' check is the only py2 and py3 compatible way I could find # If it's a partial, a Signal or a lambda. The '<' check is the only py2 and py3 compatible way I could find
@ -199,7 +199,7 @@ class SignalFactory(dict):
Emits a signal by name if it exists. Any additional args or kwargs are passed to the signal Emits a signal by name if it exists. Any additional args or kwargs are passed to the signal
:param signalName: the signal name to emit :param signalName: the signal name to emit
""" """
assert signalName in self, "%s is not a registered signal" % signalName assert signalName in self, f"{signalName} is not a registered signal"
self[signalName].emit(*args, **kwargs) self[signalName].emit(*args, **kwargs)
def connect(self, signalName, slot): def connect(self, signalName, slot):
@ -208,7 +208,7 @@ class SignalFactory(dict):
:param signalName: the signal name to connect to :param signalName: the signal name to connect to
:param slot: the callable slot to register :param slot: the callable slot to register
""" """
assert signalName in self, "%s is not a registered signal" % signalName assert signalName in self, f"{signalName} is not a registered signal"
self[signalName].connect(slot) self[signalName].connect(slot)
def block(self, signals=None, isBlocked=True): def block(self, signals=None, isBlocked=True):
@ -230,7 +230,7 @@ class SignalFactory(dict):
for signal in signals: for signal in signals:
if signal not in self: if signal not in self:
raise RuntimeError("Could not find signal matching %s" % signal) raise RuntimeError(f"Could not find signal matching {signal}")
self[signal].block(isBlocked) self[signal].block(isBlocked)

View file

@ -279,7 +279,7 @@ class QObjectListModel(QtCore.QAbstractListModel):
if key is None: if key is None:
return return
if key in self._objectByKey: if key in self._objectByKey:
raise ValueError("Object key {}:{} is not unique".format(self._keyAttrName, key)) raise ValueError(f"Object key {self._keyAttrName}:{key} is not unique")
self._objectByKey[key] = item self._objectByKey[key] = item

View file

@ -72,10 +72,10 @@ def loadPlugins(folder, packageName, classType):
try: try:
pluginMod = importlib.import_module(pluginModuleName, package=package.__name__) pluginMod = importlib.import_module(pluginModuleName, package=package.__name__)
plugins = [plugin for name, plugin in inspect.getmembers(pluginMod, inspect.isclass) plugins = [plugin for name, plugin in inspect.getmembers(pluginMod, inspect.isclass)
if plugin.__module__ == '{}.{}'.format(package.__name__, pluginName) if plugin.__module__ == f'{package.__name__}.{pluginName}'
and issubclass(plugin, classType)] and issubclass(plugin, classType)]
if not plugins: if not plugins:
logging.warning("No class defined in plugin: {}".format(pluginModuleName)) logging.warning(f"No class defined in plugin: {pluginModuleName}")
importPlugin = True importPlugin = True
for p in plugins: for p in plugins:
@ -91,7 +91,7 @@ def loadPlugins(folder, packageName, classType):
if importPlugin: if importPlugin:
pluginTypes.extend(plugins) pluginTypes.extend(plugins)
except Exception as e: except Exception as e:
errors.append(' * {}: {}'.format(pluginName, str(e))) errors.append(f' * {pluginName}: {str(e)}')
if errors: if errors:
logging.warning('== The following "{package}" plugins could not be loaded ==\n' logging.warning('== The following "{package}" plugins could not be loaded ==\n'
@ -285,7 +285,7 @@ def registerNodeType(nodeType):
""" """
global nodesDesc global nodesDesc
if nodeType.__name__ in nodesDesc: if nodeType.__name__ in nodesDesc:
logging.error("Node Desc {} is already registered.".format(nodeType.__name__)) logging.error(f"Node Desc {nodeType.__name__} is already registered.")
nodesDesc[nodeType.__name__] = nodeType nodesDesc[nodeType.__name__] = nodeType
@ -307,13 +307,13 @@ def loadAllNodes(folder):
nodeTypes = loadNodes(folder, package) nodeTypes = loadNodes(folder, package)
for nodeType in nodeTypes: for nodeType in nodeTypes:
registerNodeType(nodeType) registerNodeType(nodeType)
logging.debug('Nodes loaded [{}]: {}'.format(package, ', '.join([nodeType.__name__ for nodeType in nodeTypes]))) logging.debug(f"Nodes loaded [{package}]: {', '.join([nodeType.__name__ for nodeType in nodeTypes])}")
def registerSubmitter(s): def registerSubmitter(s):
global submitters global submitters
if s.name in submitters: if s.name in submitters:
logging.error("Submitter {} is already registered.".format(s.name)) logging.error(f"Submitter {s.name} is already registered.")
submitters[s.name] = s submitters[s.name] = s
@ -354,4 +354,4 @@ def initPipelines():
if os.path.isdir(f): if os.path.isdir(f):
loadPipelineTemplates(f) loadPipelineTemplates(f)
else: else:
logging.warning("Pipeline templates folder '{}' does not exist.".format(f)) logging.warning(f"Pipeline templates folder '{f}' does not exist.")

View file

@ -91,19 +91,19 @@ class Attribute(BaseObject):
def getFullName(self): def getFullName(self):
""" Name inside the Graph: groupName.name """ """ Name inside the Graph: groupName.name """
if isinstance(self.root, ListAttribute): if isinstance(self.root, ListAttribute):
return '{}[{}]'.format(self.root.getFullName(), self.root.index(self)) return f'{self.root.getFullName()}[{self.root.index(self)}]'
elif isinstance(self.root, GroupAttribute): elif isinstance(self.root, GroupAttribute):
return '{}.{}'.format(self.root.getFullName(), self.getName()) return f'{self.root.getFullName()}.{self.getName()}'
return self.getName() return self.getName()
def getFullNameToNode(self): def getFullNameToNode(self):
""" Name inside the Graph: nodeName.groupName.name """ """ Name inside the Graph: nodeName.groupName.name """
return '{}.{}'.format(self.node.name, self.getFullName()) return f'{self.node.name}.{self.getFullName()}'
def getFullNameToGraph(self): def getFullNameToGraph(self):
""" Name inside the Graph: graphName.nodeName.groupName.name """ """ Name inside the Graph: graphName.nodeName.groupName.name """
graphName = self.node.graph.name if self.node.graph else "UNDEFINED" graphName = self.node.graph.name if self.node.graph else "UNDEFINED"
return '{}.{}'.format(graphName, self.getFullNameToNode()) return f'{graphName}.{self.getFullNameToNode()}'
def asLinkExpr(self): def asLinkExpr(self):
""" Return link expression for this Attribute """ """ Return link expression for this Attribute """
@ -130,17 +130,17 @@ class Attribute(BaseObject):
if isinstance(self.root, ListAttribute): if isinstance(self.root, ListAttribute):
return self.root.getFullLabel() return self.root.getFullLabel()
elif isinstance(self.root, GroupAttribute): elif isinstance(self.root, GroupAttribute):
return '{} {}'.format(self.root.getFullLabel(), self.getLabel()) return f'{self.root.getFullLabel()} {self.getLabel()}'
return self.getLabel() return self.getLabel()
def getFullLabelToNode(self): def getFullLabelToNode(self):
""" Label inside the Graph: nodeLabel groupLabel Label """ """ Label inside the Graph: nodeLabel groupLabel Label """
return '{} {}'.format(self.node.label, self.getFullLabel()) return f'{self.node.label} {self.getFullLabel()}'
def getFullLabelToGraph(self): def getFullLabelToGraph(self):
""" Label inside the Graph: graphName nodeLabel groupLabel Label """ """ Label inside the Graph: graphName nodeLabel groupLabel Label """
graphName = self.node.graph.name if self.node.graph else "UNDEFINED" graphName = self.node.graph.name if self.node.graph else "UNDEFINED"
return '{} {}'.format(graphName, self.getFullLabelToNode()) return f'{graphName} {self.getFullLabelToNode()}'
def getEnabled(self): def getEnabled(self):
if isinstance(self.desc.enabled, types.FunctionType): if isinstance(self.desc.enabled, types.FunctionType):
@ -350,7 +350,7 @@ class Attribute(BaseObject):
g.addEdge(node.attribute(linkAttrName), self) g.addEdge(node.attribute(linkAttrName), self)
except KeyError as err: except KeyError as err:
logging.warning('Connect Attribute from Expression failed.') logging.warning('Connect Attribute from Expression failed.')
logging.warning('Expression: "{exp}"\nError: "{err}".'.format(exp=v, err=err)) logging.warning(f'Expression: "{v}"\nError: "{err}".')
self.resetToDefaultValue() self.resetToDefaultValue()
def getExportValue(self): def getExportValue(self):
@ -389,11 +389,11 @@ class Attribute(BaseObject):
assert (isinstance(self.value, Sequence) and not isinstance(self.value, str)) assert (isinstance(self.value, Sequence) and not isinstance(self.value, str))
v = self.attributeDesc.joinChar.join(self.getEvalValue()) v = self.attributeDesc.joinChar.join(self.getEvalValue())
if withQuotes and v: if withQuotes and v:
return '"{}"'.format(v) return f'"{v}"'
return v return v
# String, File, single value Choice are based on strings and should includes quotes to deal with spaces # String, File, single value Choice are based on strings and should includes quotes to deal with spaces
if withQuotes and isinstance(self.attributeDesc, (desc.StringParam, desc.File, desc.ChoiceParam)): if withQuotes and isinstance(self.attributeDesc, (desc.StringParam, desc.File, desc.ChoiceParam)):
return '"{}"'.format(self.getEvalValue()) return f'"{self.getEvalValue()}"'
return str(self.getEvalValue()) return str(self.getEvalValue())
def defaultValue(self): def defaultValue(self):
@ -685,7 +685,7 @@ class ListAttribute(Attribute):
else: else:
v = self.attributeDesc.joinChar.join([v.getValueStr(withQuotes=False) for v in self.value]) v = self.attributeDesc.joinChar.join([v.getValueStr(withQuotes=False) for v in self.value])
if withQuotes and v: if withQuotes and v:
return '"{}"'.format(v) return f'"{v}"'
return v return v
def updateInternals(self): def updateInternals(self):
@ -730,11 +730,11 @@ class GroupAttribute(Attribute):
self._value.get(key).value = v self._value.get(key).value = v
elif isinstance(value, (list, tuple)): elif isinstance(value, (list, tuple)):
if len(self.desc._groupDesc) != len(value): if len(self.desc._groupDesc) != len(value):
raise AttributeError("Incorrect number of values on GroupAttribute: {}".format(str(value))) raise AttributeError(f"Incorrect number of values on GroupAttribute: {str(value)}")
for attrDesc, v in zip(self.desc._groupDesc, value): for attrDesc, v in zip(self.desc._groupDesc, value):
self._value.get(attrDesc.name).value = v self._value.get(attrDesc.name).value = v
else: else:
raise AttributeError("Failed to set on GroupAttribute: {}".format(str(value))) raise AttributeError(f"Failed to set on GroupAttribute: {str(value)}")
def upgradeValue(self, exportedValue): def upgradeValue(self, exportedValue):
value = self.validateValue(exportedValue) value = self.validateValue(exportedValue)
@ -745,11 +745,11 @@ class GroupAttribute(Attribute):
self._value.get(key).upgradeValue(v) self._value.get(key).upgradeValue(v)
elif isinstance(value, (list, tuple)): elif isinstance(value, (list, tuple)):
if len(self.desc._groupDesc) != len(value): if len(self.desc._groupDesc) != len(value):
raise AttributeError("Incorrect number of values on GroupAttribute: {}".format(str(value))) raise AttributeError(f"Incorrect number of values on GroupAttribute: {str(value)}")
for attrDesc, v in zip(self.desc._groupDesc, value): for attrDesc, v in zip(self.desc._groupDesc, value):
self._value.get(attrDesc.name).upgradeValue(v) self._value.get(attrDesc.name).upgradeValue(v)
else: else:
raise AttributeError("Failed to set on GroupAttribute: {}".format(str(value))) raise AttributeError(f"Failed to set on GroupAttribute: {str(value)}")
def initValue(self): def initValue(self):
self._value = DictModel(keyAttrName='name', parent=self) self._value = DictModel(keyAttrName='name', parent=self)
@ -816,7 +816,7 @@ class GroupAttribute(Attribute):
strBegin = self.attributeDesc.brackets[0] strBegin = self.attributeDesc.brackets[0]
strEnd = self.attributeDesc.brackets[1] strEnd = self.attributeDesc.brackets[1]
else: else:
raise AttributeError("Incorrect brackets on GroupAttribute: {}".format(self.attributeDesc.brackets)) raise AttributeError(f"Incorrect brackets on GroupAttribute: {self.attributeDesc.brackets}")
# particular case when using space separator # particular case when using space separator
spaceSep = self.attributeDesc.joinChar == ' ' spaceSep = self.attributeDesc.joinChar == ' '
@ -827,8 +827,8 @@ class GroupAttribute(Attribute):
s = self.attributeDesc.joinChar.join(sortedSubValues) s = self.attributeDesc.joinChar.join(sortedSubValues)
if withQuotes and not spaceSep: if withQuotes and not spaceSep:
return '"{}{}{}"'.format(strBegin, s, strEnd) return f'"{strBegin}{s}{strEnd}"'
return '{}{}{}'.format(strBegin, s, strEnd) return f'{strBegin}{s}{strEnd}'
def updateInternals(self): def updateInternals(self):
super(GroupAttribute, self).updateInternals() super(GroupAttribute, self).updateInternals()

View file

@ -113,10 +113,10 @@ class Node(object):
pass pass
def stopProcess(self, chunk): def stopProcess(self, chunk):
raise NotImplementedError('No stopProcess implementation on node: {}'.format(chunk.node.name)) raise NotImplementedError(f'No stopProcess implementation on node: {chunk.node.name}')
def processChunk(self, chunk): def processChunk(self, chunk):
raise NotImplementedError('No processChunk implementation on node: "{}"'.format(chunk.node.name)) raise NotImplementedError(f'No processChunk implementation on node: "{chunk.node.name}"')
class InputNode(Node): class InputNode(Node):
@ -146,7 +146,7 @@ class CommandLineNode(Node):
# If rez available in env, we use it # If rez available in env, we use it
if "REZ_ENV" in os.environ and chunk.node.packageVersion: if "REZ_ENV" in os.environ and chunk.node.packageVersion:
# If the node package is already in the environment, we don't need a new dedicated rez environment # If the node package is already in the environment, we don't need a new dedicated rez environment
alreadyInEnv = os.environ.get("REZ_{}_VERSION".format(chunk.node.packageName.upper()), alreadyInEnv = os.environ.get(f"REZ_{chunk.node.packageName.upper()}_VERSION",
"").startswith(chunk.node.packageVersion) "").startswith(chunk.node.packageVersion)
if not alreadyInEnv: if not alreadyInEnv:
cmdPrefix = '{rez} {packageFullName} -- '.format(rez=os.environ.get("REZ_ENV"), cmdPrefix = '{rez} {packageFullName} -- '.format(rez=os.environ.get("REZ_ENV"),
@ -178,8 +178,8 @@ class CommandLineNode(Node):
cmd = self.buildCommandLine(chunk) cmd = self.buildCommandLine(chunk)
chunk.status.commandLine = cmd chunk.status.commandLine = cmd
chunk.saveStatusFile() chunk.saveStatusFile()
print(' - commandLine: {}'.format(cmd)) print(f' - commandLine: {cmd}')
print(' - logFile: {}'.format(chunk.logFile)) print(f' - logFile: {chunk.logFile}')
chunk.subprocess = psutil.Popen(shlex.split(cmd), stdout=logF, stderr=logF, cwd=chunk.node.internalFolder) chunk.subprocess = psutil.Popen(shlex.split(cmd), stdout=logF, stderr=logF, cwd=chunk.node.internalFolder)
# Store process static info into the status file # Store process static info into the status file
@ -195,7 +195,7 @@ class CommandLineNode(Node):
if chunk.subprocess.returncode != 0: if chunk.subprocess.returncode != 0:
with open(chunk.logFile, 'r') as logF: with open(chunk.logFile, 'r') as logF:
logContent = ''.join(logF.readlines()) logContent = ''.join(logF.readlines())
raise RuntimeError('Error on node "{}":\nLog:\n{}'.format(chunk.name, logContent)) raise RuntimeError(f'Error on node "{chunk.name}":\nLog:\n{logContent}')
except Exception: except Exception:
raise raise
finally: finally:
@ -217,12 +217,12 @@ class AVCommandLineNode(CommandLineNode):
AVCommandLineNode.cmdMem = '' AVCommandLineNode.cmdMem = ''
memSize = cgroup.getCgroupMemorySize() memSize = cgroup.getCgroupMemorySize()
if memSize > 0: if memSize > 0:
AVCommandLineNode.cmdMem = ' --maxMemory={memSize}'.format(memSize=memSize) AVCommandLineNode.cmdMem = f' --maxMemory={memSize}'
AVCommandLineNode.cmdCore = '' AVCommandLineNode.cmdCore = ''
coresCount = cgroup.getCgroupCpuCount() coresCount = cgroup.getCgroupCpuCount()
if coresCount > 0: if coresCount > 0:
AVCommandLineNode.cmdCore = ' --maxCores={coresCount}'.format(coresCount=coresCount) AVCommandLineNode.cmdCore = f' --maxCores={coresCount}'
AVCommandLineNode.cgroupParsed = True AVCommandLineNode.cgroupParsed = True

View file

@ -39,9 +39,9 @@ class UnknownNodeTypeError(GraphException):
class NodeUpgradeError(GraphException): class NodeUpgradeError(GraphException):
def __init__(self, nodeName, details=None): def __init__(self, nodeName, details=None):
msg = "Failed to upgrade node {}".format(nodeName) msg = f"Failed to upgrade node {nodeName}"
if details: if details:
msg += ": {}".format(details) msg += f": {details}"
super(NodeUpgradeError, self).__init__(msg) super(NodeUpgradeError, self).__init__(msg)

View file

@ -66,7 +66,7 @@ class Edge(BaseObject):
super(Edge, self).__init__(parent) super(Edge, self).__init__(parent)
self._src = weakref.ref(src) self._src = weakref.ref(src)
self._dst = weakref.ref(dst) self._dst = weakref.ref(dst)
self._repr = "<Edge> {} -> {}".format(self._src(), self._dst()) self._repr = f"<Edge> {self._src()} -> {self._dst()}"
@property @property
def src(self): def src(self):
@ -825,12 +825,12 @@ class Graph(BaseObject):
def findNode(self, nodeExpr): def findNode(self, nodeExpr):
candidates = self.findNodeCandidates('^' + nodeExpr) candidates = self.findNodeCandidates('^' + nodeExpr)
if not candidates: if not candidates:
raise KeyError('No node candidate for "{}"'.format(nodeExpr)) raise KeyError(f'No node candidate for "{nodeExpr}"')
if len(candidates) > 1: if len(candidates) > 1:
for c in candidates: for c in candidates:
if c.name == nodeExpr: if c.name == nodeExpr:
return c return c
raise KeyError('Multiple node candidates for "{}": {}'.format(nodeExpr, str([c.name for c in candidates]))) raise KeyError(f'Multiple node candidates for "{nodeExpr}": {str([c.name for c in candidates])}')
return candidates[0] return candidates[0]
def findNodes(self, nodesExpr): def findNodes(self, nodesExpr):
@ -856,7 +856,7 @@ class Graph(BaseObject):
if srcAttr.node.graph != self or dstAttr.node.graph != self: if srcAttr.node.graph != self or dstAttr.node.graph != self:
raise RuntimeError('The attributes of the edge should be part of a common graph.') raise RuntimeError('The attributes of the edge should be part of a common graph.')
if dstAttr in self.edges.keys(): if dstAttr in self.edges.keys():
raise RuntimeError('Destination attribute "{}" is already connected.'.format(dstAttr.getFullNameToNode())) raise RuntimeError(f'Destination attribute "{dstAttr.getFullNameToNode()}" is already connected.')
edge = Edge(srcAttr, dstAttr) edge = Edge(srcAttr, dstAttr)
self.edges.add(edge) self.edges.add(edge)
self.markNodesDirty(dstAttr.node) self.markNodesDirty(dstAttr.node)
@ -873,7 +873,7 @@ class Graph(BaseObject):
@changeTopology @changeTopology
def removeEdge(self, dstAttr): def removeEdge(self, dstAttr):
if dstAttr not in self.edges.keys(): if dstAttr not in self.edges.keys():
raise RuntimeError('Attribute "{}" is not connected'.format(dstAttr.getFullNameToNode())) raise RuntimeError(f'Attribute "{dstAttr.getFullNameToNode()}" is not connected')
edge = self.edges.pop(dstAttr) edge = self.edges.pop(dstAttr)
self.markNodesDirty(dstAttr.node) self.markNodesDirty(dstAttr.node)
dstAttr.valueChanged.emit() dstAttr.valueChanged.emit()
@ -1608,12 +1608,11 @@ def executeGraph(graph, toNodes=None, forceCompute=False, forceStatus=False):
node=n+1, nbNodes=len(nodes), node=n+1, nbNodes=len(nodes),
chunk=c+1, nbChunks=len(node.chunks), nodeName=node.nodeType)) chunk=c+1, nbChunks=len(node.chunks), nodeName=node.nodeType))
else: else:
print('\n[{node}/{nbNodes}] {nodeName}'.format( print(f'\n[{n + 1}/{len(nodes)}] {node.nodeType}')
node=n + 1, nbNodes=len(nodes), nodeName=node.nodeType))
chunk.process(forceCompute) chunk.process(forceCompute)
node.postprocess() node.postprocess()
except Exception as e: except Exception as e:
logging.error("Error on node computation: {}".format(e)) logging.error(f"Error on node computation: {e}")
graph.clearSubmittedNodes() graph.clearSubmittedNodes()
raise raise
@ -1630,8 +1629,8 @@ def submitGraph(graph, submitter, toNodes=None, submitLabel="{projectName}"):
logging.warning('Nothing to compute') logging.warning('Nothing to compute')
return return
logging.info("Nodes to process: {}".format(edgesToProcess)) logging.info(f"Nodes to process: {edgesToProcess}")
logging.info("Edges to process: {}".format(edgesToProcess)) logging.info(f"Edges to process: {edgesToProcess}")
sub = None sub = None
if submitter: if submitter:
@ -1649,7 +1648,7 @@ def submitGraph(graph, submitter, toNodes=None, submitLabel="{projectName}"):
for node in nodesToProcess: for node in nodesToProcess:
node.submit() # update node status node.submit() # update node status
except Exception as e: except Exception as e:
logging.error("Error on submit : {}".format(e)) logging.error(f"Error on submit : {e}")
def submit(graphFile, submitter, toNode=None, submitLabel="{projectName}"): def submit(graphFile, submitter, toNode=None, submitLabel="{projectName}"):

View file

@ -268,7 +268,7 @@ class NodeChunk(BaseObject):
@property @property
def name(self): def name(self):
if self.range.blockSize: if self.range.blockSize:
return "{}({})".format(self.node.name, self.index) return f"{self.node.name}({self.index})"
else: else:
return self.node.name return self.node.name
@ -403,7 +403,7 @@ class NodeChunk(BaseObject):
def process(self, forceCompute=False): def process(self, forceCompute=False):
if not forceCompute and self._status.status == Status.SUCCESS: if not forceCompute and self._status.status == Status.SUCCESS:
logging.info("Node chunk already computed: {}".format(self.name)) logging.info(f"Node chunk already computed: {self.name}")
return return
global runningProcesses global runningProcesses
runningProcesses[self.name] = self runningProcesses[self.name] = self
@ -427,7 +427,7 @@ class NodeChunk(BaseObject):
self._status.elapsedTime = time.time() - startTime self._status.elapsedTime = time.time() - startTime
if exceptionStatus is not None: if exceptionStatus is not None:
self.upgradeStatusTo(exceptionStatus) self.upgradeStatusTo(exceptionStatus)
logging.info(" - elapsed time: {}".format(self._status.elapsedTimeStr)) logging.info(f" - elapsed time: {self._status.elapsedTimeStr}")
# Ask and wait for the stats thread to stop # Ask and wait for the stats thread to stop
self.statThread.stopRequest() self.statThread.stopRequest()
self.statThread.join() self.statThread.join()
@ -582,7 +582,7 @@ class BaseNode(BaseObject):
str: the high-level label from the technical node name str: the high-level label from the technical node name
""" """
t, idx = name.split("_") t, idx = name.split("_")
return "{}{}".format(t, idx if int(idx) > 1 else "") return f"{t}{idx if int(idx) > 1 else ''}"
def getDocumentation(self): def getDocumentation(self):
if not self.nodeDesc: if not self.nodeDesc:
@ -739,7 +739,7 @@ class BaseNode(BaseObject):
if group is not None: if group is not None:
# If there is a valid command line "group" # If there is a valid command line "group"
v = attr.getValueStr(withQuotes=True) v = attr.getValueStr(withQuotes=True)
cmdVars[name] = "--{name} {value}".format(name=name, value=v) cmdVars[name] = f"--{name} {v}"
# xxValue is exposed without quotes to allow to compose expressions # xxValue is exposed without quotes to allow to compose expressions
cmdVars[name + "Value"] = attr.getValueStr(withQuotes=False) cmdVars[name + "Value"] = attr.getValueStr(withQuotes=False)
@ -810,7 +810,7 @@ class BaseNode(BaseObject):
v = attr.getValueStr(withQuotes=True) v = attr.getValueStr(withQuotes=True)
self._cmdVars[name] = '--{name} {value}'.format(name=name, value=v) self._cmdVars[name] = f'--{name} {v}'
# xxValue is exposed without quotes to allow to compose expressions # xxValue is exposed without quotes to allow to compose expressions
self._cmdVars[name + 'Value'] = attr.getValueStr(withQuotes=False) self._cmdVars[name + 'Value'] = attr.getValueStr(withQuotes=False)
@ -1117,7 +1117,7 @@ class BaseNode(BaseObject):
return return
valuesFile = self.valuesFile valuesFile = self.valuesFile
if not os.path.exists(valuesFile): if not os.path.exists(valuesFile):
logging.warning("No output attr file: {}".format(valuesFile)) logging.warning(f"No output attr file: {valuesFile}")
return return
# logging.warning("load output attr: {}, value: {}".format(self.name, valuesFile)) # logging.warning("load output attr: {}, value: {}".format(self.name, valuesFile))
@ -1564,7 +1564,7 @@ class Node(BaseNode):
chunk.range = range chunk.range = range
except RuntimeError: except RuntimeError:
# TODO: set node internal status to error # TODO: set node internal status to error
logging.warning("Invalid Parallelization on node {}".format(self._name)) logging.warning(f"Invalid Parallelization on node {self._name}")
self._chunks.clear() self._chunks.clear()
else: else:
if len(self._chunks) != 1: if len(self._chunks) != 1:
@ -1758,7 +1758,7 @@ class CompatibilityNode(BaseNode):
@property @property
def issueDetails(self): def issueDetails(self):
if self.issue == CompatibilityIssue.UnknownNodeType: if self.issue == CompatibilityIssue.UnknownNodeType:
return "Unknown node type: '{}'.".format(self.nodeType) return f"Unknown node type: '{self.nodeType}'."
elif self.issue == CompatibilityIssue.VersionConflict: elif self.issue == CompatibilityIssue.VersionConflict:
return "Node version '{}' conflicts with current version '{}'.".format( return "Node version '{}' conflicts with current version '{}'.".format(
self.nodeDict["version"], nodeVersion(self.nodeDesc) self.nodeDict["version"], nodeVersion(self.nodeDesc)
@ -1834,7 +1834,7 @@ class CompatibilityNode(BaseNode):
try: try:
upgradedAttrValues = node.nodeDesc.upgradeAttributeValues(attrValues, self.version) upgradedAttrValues = node.nodeDesc.upgradeAttributeValues(attrValues, self.version)
except Exception as e: except Exception as e:
logging.error("Error in the upgrade implementation of the node: {}.\n{}".format(self.name, repr(e))) logging.error(f"Error in the upgrade implementation of the node: {self.name}.\n{repr(e)}")
upgradedAttrValues = attrValues upgradedAttrValues = attrValues
if not isinstance(upgradedAttrValues, dict): if not isinstance(upgradedAttrValues, dict):

View file

@ -24,8 +24,8 @@ def bytes2human(n):
for s in reversed(symbols): for s in reversed(symbols):
if n >= prefix[s]: if n >= prefix[s]:
value = float(n) / prefix[s] value = float(n) / prefix[s]
return '%.2f %s' % (value, s) return f'{value:.2f} {s}'
return '%.2f B' % (n) return f'{n:.2f} B'
class ComputerStatistics: class ComputerStatistics:
@ -57,7 +57,7 @@ class ComputerStatistics:
if self.nvidia_smi is None: if self.nvidia_smi is None:
# Could not be found from the environment path, # Could not be found from the environment path,
# try to find it from system drive with default installation path # try to find it from system drive with default installation path
default_nvidia_smi = "%s\\Program Files\\NVIDIA Corporation\\NVSMI\\nvidia-smi.exe" % os.environ['systemdrive'] default_nvidia_smi = f"{os.environ['systemdrive']}\\Program Files\\NVIDIA Corporation\\NVSMI\\nvidia-smi.exe"
if os.path.isfile(default_nvidia_smi): if os.path.isfile(default_nvidia_smi):
self.nvidia_smi = default_nvidia_smi self.nvidia_smi = default_nvidia_smi
else: else:
@ -84,7 +84,7 @@ class ComputerStatistics:
self._addKV('ioCounters', psutil.disk_io_counters()) self._addKV('ioCounters', psutil.disk_io_counters())
self.updateGpu() self.updateGpu()
except Exception as e: except Exception as e:
logging.debug('Failed to get statistics: "{}".'.format(str(e))) logging.debug(f'Failed to get statistics: "{str(e)}".')
def updateGpu(self): def updateGpu(self):
if not self.nvidia_smi: if not self.nvidia_smi:
@ -99,38 +99,38 @@ class ComputerStatistics:
try: try:
self.gpuName = gpuTree.find('product_name').text self.gpuName = gpuTree.find('product_name').text
except Exception as e: except Exception as e:
logging.debug('Failed to get gpuName: "{}".'.format(str(e))) logging.debug(f'Failed to get gpuName: "{str(e)}".')
pass pass
try: try:
gpuMemoryUsed = gpuTree.find('fb_memory_usage').find('used').text.split(" ")[0] gpuMemoryUsed = gpuTree.find('fb_memory_usage').find('used').text.split(" ")[0]
self._addKV('gpuMemoryUsed', gpuMemoryUsed) self._addKV('gpuMemoryUsed', gpuMemoryUsed)
except Exception as e: except Exception as e:
logging.debug('Failed to get gpuMemoryUsed: "{}".'.format(str(e))) logging.debug(f'Failed to get gpuMemoryUsed: "{str(e)}".')
pass pass
try: try:
self.gpuMemoryTotal = gpuTree.find('fb_memory_usage').find('total').text.split(" ")[0] self.gpuMemoryTotal = gpuTree.find('fb_memory_usage').find('total').text.split(" ")[0]
except Exception as e: except Exception as e:
logging.debug('Failed to get gpuMemoryTotal: "{}".'.format(str(e))) logging.debug(f'Failed to get gpuMemoryTotal: "{str(e)}".')
pass pass
try: try:
gpuUsed = gpuTree.find('utilization').find('gpu_util').text.split(" ")[0] gpuUsed = gpuTree.find('utilization').find('gpu_util').text.split(" ")[0]
self._addKV('gpuUsed', gpuUsed) self._addKV('gpuUsed', gpuUsed)
except Exception as e: except Exception as e:
logging.debug('Failed to get gpuUsed: "{}".'.format(str(e))) logging.debug(f'Failed to get gpuUsed: "{str(e)}".')
pass pass
try: try:
gpuTemperature = gpuTree.find('temperature').find('gpu_temp').text.split(" ")[0] gpuTemperature = gpuTree.find('temperature').find('gpu_temp').text.split(" ")[0]
self._addKV('gpuTemperature', gpuTemperature) self._addKV('gpuTemperature', gpuTemperature)
except Exception as e: except Exception as e:
logging.debug('Failed to get gpuTemperature: "{}".'.format(str(e))) logging.debug(f'Failed to get gpuTemperature: "{str(e)}".')
pass pass
except subprocess.TimeoutExpired as e: except subprocess.TimeoutExpired as e:
logging.debug('Timeout when retrieving information from nvidia_smi: "{}".'.format(str(e))) logging.debug(f'Timeout when retrieving information from nvidia_smi: "{str(e)}".')
p.kill() p.kill()
outs, errs = p.communicate() outs, errs = p.communicate()
return return
except Exception as e: except Exception as e:
logging.debug('Failed to get information from nvidia_smi: "{}".'.format(str(e))) logging.debug(f'Failed to get information from nvidia_smi: "{str(e)}".')
return return
def toDict(self): def toDict(self):
@ -263,22 +263,22 @@ class Statistics:
def fromDict(self, d): def fromDict(self, d):
version = d.get('fileVersion', 0.0) version = d.get('fileVersion', 0.0)
if version != self.fileVersion: if version != self.fileVersion:
logging.debug('Statistics: file version was {} and the current version is {}.'.format(version, self.fileVersion)) logging.debug(f'Statistics: file version was {version} and the current version is {self.fileVersion}.')
self.computer = ComputerStatistics() self.computer = ComputerStatistics()
self.process = ProcStatistics() self.process = ProcStatistics()
self.times = [] self.times = []
try: try:
self.computer.fromDict(d.get('computer', {})) self.computer.fromDict(d.get('computer', {}))
except Exception as e: except Exception as e:
logging.debug('Failed while loading statistics: computer: "{}".'.format(str(e))) logging.debug(f'Failed while loading statistics: computer: "{str(e)}".')
try: try:
self.process.fromDict(d.get('process', {})) self.process.fromDict(d.get('process', {}))
except Exception as e: except Exception as e:
logging.debug('Failed while loading statistics: process: "{}".'.format(str(e))) logging.debug(f'Failed while loading statistics: process: "{str(e)}".')
try: try:
self.times = d.get('times', []) self.times = d.get('times', [])
except Exception as e: except Exception as e:
logging.debug('Failed while loading statistics: times: "{}".'.format(str(e))) logging.debug(f'Failed while loading statistics: times: "{str(e)}".')
bytesPerGiga = 1024. * 1024. * 1024. bytesPerGiga = 1024. * 1024. * 1024.

View file

@ -69,7 +69,7 @@ class TaskThread(Thread):
stopAndRestart = True stopAndRestart = True
break break
else: else:
logging.error("Error on node computation: {}".format(e)) logging.error(f"Error on node computation: {e}")
nodesToRemove, _ = self._manager._graph.dfsOnDiscover(startNodes=[node], reverse=True) nodesToRemove, _ = self._manager._graph.dfsOnDiscover(startNodes=[node], reverse=True)
# remove following nodes from the task queue # remove following nodes from the task queue
for n in nodesToRemove[1:]: # exclude current node for n in nodesToRemove[1:]: # exclude current node
@ -425,8 +425,8 @@ class TaskManager(BaseObject):
flowEdges = graph.flowEdges(startNodes=toNodes) flowEdges = graph.flowEdges(startNodes=toNodes)
edgesToProcess = set(edgesToProcess).intersection(flowEdges) edgesToProcess = set(edgesToProcess).intersection(flowEdges)
logging.info("Nodes to process: {}".format(nodesToProcess)) logging.info(f"Nodes to process: {nodesToProcess}")
logging.info("Edges to process: {}".format(edgesToProcess)) logging.info(f"Edges to process: {edgesToProcess}")
try: try:
res = sub.submit(nodesToProcess, edgesToProcess, graph.filepath, submitLabel=submitLabel) res = sub.submit(nodesToProcess, edgesToProcess, graph.filepath, submitLabel=submitLabel)
@ -441,7 +441,7 @@ class TaskManager(BaseObject):
if not allReady: if not allReady:
self.raiseDependenciesMessage("SUBMITTING") self.raiseDependenciesMessage("SUBMITTING")
except Exception as e: except Exception as e:
logging.error("Error on submit : {}".format(e)) logging.error(f"Error on submit : {e}")
def submitFromFile(self, graphFile, submitter, toNode=None, submitLabel="{projectName}"): def submitFromFile(self, graphFile, submitter, toNode=None, submitLabel="{projectName}"):
""" """

View file

@ -54,7 +54,7 @@ def checkTemplateVersions(path: str, nodesAlreadyLoaded: bool = False) -> bool:
break break
if compatibilityIssue is not None: if compatibilityIssue is not None:
print("{} in {} for node {}".format(compatibilityIssue, path, nodeType)) print(f"{compatibilityIssue} in {path} for node {nodeType}")
return False return False
return True return True

View file

@ -161,7 +161,7 @@ def mvsPipeline(graph, sfm=None):
list of Node: the created nodes list of Node: the created nodes
""" """
if sfm and not sfm.nodeType == "StructureFromMotion": if sfm and not sfm.nodeType == "StructureFromMotion":
raise ValueError("Invalid node type. Expected StructureFromMotion, got {}.".format(sfm.nodeType)) raise ValueError(f"Invalid node type. Expected StructureFromMotion, got {sfm.nodeType}.")
prepareDenseScene = graph.addNewNode('PrepareDenseScene', prepareDenseScene = graph.addNewNode('PrepareDenseScene',
input=sfm.output if sfm else "") input=sfm.output if sfm else "")

View file

@ -71,7 +71,7 @@ This node allows to copy files into a specific folder.
if not outFiles: if not outFiles:
error = 'Publish: input files listed, but nothing to publish' error = 'Publish: input files listed, but nothing to publish'
chunk.logger.error(error) chunk.logger.error(error)
chunk.logger.info('Listed input files: {}'.format([i.value for i in chunk.node.inputFiles.value])) chunk.logger.info(f'Listed input files: {[i.value for i in chunk.node.inputFiles.value]}')
raise RuntimeError(error) raise RuntimeError(error)
if not os.path.exists(chunk.node.output.value): if not os.path.exists(chunk.node.output.value):
@ -79,10 +79,10 @@ This node allows to copy files into a specific folder.
for iFile, oFile in outFiles.items(): for iFile, oFile in outFiles.items():
if os.path.isdir(iFile): # If the input is a directory, copy the directory's content if os.path.isdir(iFile): # If the input is a directory, copy the directory's content
chunk.logger.info('Publish directory {} into {}'.format(iFile, oFile)) chunk.logger.info(f'Publish directory {iFile} into {oFile}')
du.copy_tree(iFile, oFile) du.copy_tree(iFile, oFile)
else: else:
chunk.logger.info('Publish file {} into {}'.format(iFile, oFile)) chunk.logger.info(f'Publish file {iFile} into {oFile}')
shutil.copyfile(iFile, oFile) shutil.copyfile(iFile, oFile)
chunk.logger.info('Publish end') chunk.logger.info('Publish end')
finally: finally:

View file

@ -45,7 +45,7 @@ class RippleSubmitter(BaseSubmitter):
} }
#Specify some constraints #Specify some constraints
requirements = "!\"rs*\",@.mem>25{gpu}".format(gpu=gpudict[node.nodeDesc.gpu.name]) requirements = f"!\"rs*\",@.mem>25{gpudict[node.nodeDesc.gpu.name]}"
#decide if we need multiple slots #decide if we need multiple slots
minProcessors = 1 minProcessors = 1
@ -67,7 +67,7 @@ class RippleSubmitter(BaseSubmitter):
waitsFor.append(parent.name) waitsFor.append(parent.name)
#Basic command line for this node #Basic command line for this node
command='meshroom_compute --node {nodeName} "{meshroomFile}" --extern'.format(nodeName=node.name, meshroomFile=meshroomFile) command=f'meshroom_compute --node {node.name} "{meshroomFile}" --extern'
if node.isParallelized: if node.isParallelized:
_, _, nbBlocks = node.nodeDesc.parallelization.getSizes(node) _, _, nbBlocks = node.nodeDesc.parallelization.getSizes(node)
@ -77,13 +77,13 @@ class RippleSubmitter(BaseSubmitter):
for iteration in range(0, nbBlocks): for iteration in range(0, nbBlocks):
#Add iteration number #Add iteration number
commandext = '{cmd} --iteration {iter}'.format(cmd=command, iter=iteration) commandext = f'{command} --iteration {iteration}'
#Create process task with parameters #Create process task with parameters
rippleproc = RippleProcessWithSlots(name='{name} iteration {iter}'.format(name=node.name, iter=iteration), discipline='ripple', appendKeys=True, keys=requirements, label=node.name, cmdList=[commandext], waitsFor=waitsFor, minProcessors=minProcessors, maxProcessors=maxProcessors) rippleproc = RippleProcessWithSlots(name=f'{node.name} iteration {iteration}', discipline='ripple', appendKeys=True, keys=requirements, label=node.name, cmdList=[commandext], waitsFor=waitsFor, minProcessors=minProcessors, maxProcessors=maxProcessors)
rippleprocs.append(rippleproc) rippleprocs.append(rippleproc)
rippleObj = RippleGroup(label="{name} Group".format(name=node.name), tasks=rippleprocs, name=node.name, waitsFor=waitsFor) rippleObj = RippleGroup(label=f"{node.name} Group", tasks=rippleprocs, name=node.name, waitsFor=waitsFor)
else: else:
rippleObj = RippleProcessWithSlots(name=node.name, discipline='ripple', appendKeys=True, keys=requirements, label=node.name, cmdList=[command], waitsFor=waitsFor, minProcessors=minProcessors, maxProcessors=maxProcessors) rippleObj = RippleProcessWithSlots(name=node.name, discipline='ripple', appendKeys=True, keys=requirements, label=node.name, cmdList=[command], waitsFor=waitsFor, minProcessors=minProcessors, maxProcessors=maxProcessors)

View file

@ -46,9 +46,9 @@ class SimpleFarmSubmitter(BaseSubmitter):
continue continue
v = p.split('-') v = p.split('-')
self.reqPackages.append('-'.join([v[0], resolvedVersions[v[0]]])) self.reqPackages.append('-'.join([v[0], resolvedVersions[v[0]]]))
logging.debug('REZ Packages: {}'.format(str(self.reqPackages))) logging.debug(f'REZ Packages: {str(self.reqPackages)}')
elif 'REZ_MESHROOM_VERSION' in os.environ: elif 'REZ_MESHROOM_VERSION' in os.environ:
self.reqPackages = ["meshroom-{}".format(os.environ.get('REZ_MESHROOM_VERSION', ''))] self.reqPackages = [f"meshroom-{os.environ.get('REZ_MESHROOM_VERSION', '')}"]
else: else:
self.reqPackages = None self.reqPackages = None

View file

@ -379,13 +379,13 @@ class MeshroomApp(QApplication):
return viewpoints[0].get("path", "") return viewpoints[0].get("path", "")
except FileNotFoundError: except FileNotFoundError:
logging.info("File {} not found on disk.".format(filepath)) logging.info(f"File {filepath} not found on disk.")
except (json.JSONDecodeError, UnicodeDecodeError): except (json.JSONDecodeError, UnicodeDecodeError):
logging.info("Error while loading file {}.".format(filepath)) logging.info(f"Error while loading file {filepath}.")
except KeyError as err: except KeyError as err:
logging.info("The following key does not exist: {}".format(str(err))) logging.info(f"The following key does not exist: {str(err)}")
except Exception as err: except Exception as err:
logging.info("Exception: {}".format(str(err))) logging.info(f"Exception: {str(err)}")
return "" return ""
@ -443,7 +443,7 @@ class MeshroomApp(QApplication):
projectFile (str or QUrl): path to the project file to add to the list projectFile (str or QUrl): path to the project file to add to the list
""" """
if not isinstance(projectFile, (QUrl, str)): if not isinstance(projectFile, (QUrl, str)):
raise TypeError("Unexpected data type: {}".format(projectFile.__class__)) raise TypeError(f"Unexpected data type: {projectFile.__class__}")
if isinstance(projectFile, QUrl): if isinstance(projectFile, QUrl):
projectFileNorm = projectFile.toLocalFile() projectFileNorm = projectFile.toLocalFile()
if not projectFileNorm: if not projectFileNorm:
@ -495,7 +495,7 @@ class MeshroomApp(QApplication):
Otherwise, it is effectively removed and the QSettings are updated accordingly. Otherwise, it is effectively removed and the QSettings are updated accordingly.
""" """
if not isinstance(projectFile, (QUrl, str)): if not isinstance(projectFile, (QUrl, str)):
raise TypeError("Unexpected data type: {}".format(projectFile.__class__)) raise TypeError(f"Unexpected data type: {projectFile.__class__}")
if isinstance(projectFile, QUrl): if isinstance(projectFile, QUrl):
projectFileNorm = projectFile.toLocalFile() projectFileNorm = projectFile.toLocalFile()
if not projectFileNorm: if not projectFileNorm:
@ -551,7 +551,7 @@ class MeshroomApp(QApplication):
if not folderPath: if not folderPath:
folderPath = imagesFolder.toString() folderPath = imagesFolder.toString()
else: else:
raise TypeError("Unexpected data type: {}".format(imagesFolder.__class__)) raise TypeError(f"Unexpected data type: {imagesFolder.__class__}")
folders = self._recentImportedImagesFolders() folders = self._recentImportedImagesFolders()
@ -586,7 +586,7 @@ class MeshroomApp(QApplication):
if not folderPath: if not folderPath:
folderPath = imagesFolder.toString() folderPath = imagesFolder.toString()
else: else:
raise TypeError("Unexpected data type: {}".format(imagesFolder.__class__)) raise TypeError(f"Unexpected data type: {imagesFolder.__class__}")
folders = self._recentImportedImagesFolders() folders = self._recentImportedImagesFolders()
@ -633,9 +633,9 @@ class MeshroomApp(QApplication):
import platform import platform
import sys import sys
return { return {
'platform': '{} {}'.format(platform.system(), platform.release()), 'platform': f'{platform.system()} {platform.release()}',
'python': 'Python {}'.format(sys.version.split(" ")[0]), 'python': f"Python {sys.version.split(' ')[0]}",
'pyside': 'PySide6 {}'.format(PySideVersion) 'pyside': f'PySide6 {PySideVersion}'
} }
systemInfo = Property(QJsonValue, _systemInfo, constant=True) systemInfo = Property(QJsonValue, _systemInfo, constant=True)

View file

@ -26,7 +26,7 @@ class UndoCommand(QUndoCommand):
try: try:
self.redoImpl() self.redoImpl()
except Exception: except Exception:
logging.error("Error while redoing command '{}': \n{}".format(self.text(), traceback.format_exc())) logging.error(f"Error while redoing command '{self.text()}': \n{traceback.format_exc()}")
def undo(self): def undo(self):
if not self._enabled: if not self._enabled:
@ -34,7 +34,7 @@ class UndoCommand(QUndoCommand):
try: try:
self.undoImpl() self.undoImpl()
except Exception: except Exception:
logging.error("Error while undoing command '{}': \n{}".format(self.text(), traceback.format_exc())) logging.error(f"Error while undoing command '{self.text()}': \n{traceback.format_exc()}")
def redoImpl(self): def redoImpl(self):
# type: () -> bool # type: () -> bool
@ -64,7 +64,7 @@ class UndoStack(QUndoStack):
try: try:
res = command.redoImpl() res = command.redoImpl()
except Exception as e: except Exception as e:
logging.error("Error while trying command '{}': \n{}".format(command.text(), traceback.format_exc())) logging.error(f"Error while trying command '{command.text()}': \n{traceback.format_exc()}")
res = False res = False
if res is not False: if res is not False:
command.setEnabled(False) command.setEnabled(False)
@ -144,7 +144,7 @@ class AddNodeCommand(GraphCommand):
def redoImpl(self): def redoImpl(self):
node = self.graph.addNewNode(self.nodeType, position=self.position, **self.kwargs) node = self.graph.addNewNode(self.nodeType, position=self.position, **self.kwargs)
self.nodeName = node.name self.nodeName = node.name
self.setText("Add Node {}".format(self.nodeName)) self.setText(f"Add Node {self.nodeName}")
return node return node
def undoImpl(self): def undoImpl(self):
@ -156,7 +156,7 @@ class RemoveNodeCommand(GraphCommand):
super(RemoveNodeCommand, self).__init__(graph, parent) super(RemoveNodeCommand, self).__init__(graph, parent)
self.nodeDict = node.toDict() self.nodeDict = node.toDict()
self.nodeName = node.getName() self.nodeName = node.getName()
self.setText("Remove Node {}".format(self.nodeName)) self.setText(f"Remove Node {self.nodeName}")
self.outEdges = {} self.outEdges = {}
self.outListAttributes = {} # maps attribute's key with a tuple containing the name of the list it is connected to and its value self.outListAttributes = {} # maps attribute's key with a tuple containing the name of the list it is connected to and its value
@ -221,7 +221,7 @@ class PasteNodesCommand(GraphCommand):
nodes = self.graph.importGraphContent(graph) nodes = self.graph.importGraphContent(graph)
self.nodeNames = [node.name for node in nodes] self.nodeNames = [node.name for node in nodes]
self.setText("Paste Node{} ({})".format("s" if len(self.nodeNames) > 1 else "", ", ".join(self.nodeNames))) self.setText(f"Paste Node{'s' if len(self.nodeNames) > 1 else ''} ({', '.join(self.nodeNames)})")
return nodes return nodes
def undoImpl(self): def undoImpl(self):
@ -289,7 +289,7 @@ class SetAttributeCommand(GraphCommand):
self.attrName = attribute.getFullNameToNode() self.attrName = attribute.getFullNameToNode()
self.value = value self.value = value
self.oldValue = attribute.getExportValue() self.oldValue = attribute.getExportValue()
self.setText("Set Attribute '{}'".format(attribute.getFullNameToNode())) self.setText(f"Set Attribute '{attribute.getFullNameToNode()}'")
def redoImpl(self): def redoImpl(self):
if self.value == self.oldValue: if self.value == self.oldValue:
@ -312,10 +312,10 @@ class AddEdgeCommand(GraphCommand):
super(AddEdgeCommand, self).__init__(graph, parent) super(AddEdgeCommand, self).__init__(graph, parent)
self.srcAttr = src.getFullNameToNode() self.srcAttr = src.getFullNameToNode()
self.dstAttr = dst.getFullNameToNode() self.dstAttr = dst.getFullNameToNode()
self.setText("Connect '{}'->'{}'".format(self.srcAttr, self.dstAttr)) self.setText(f"Connect '{self.srcAttr}'->'{self.dstAttr}'")
if src.baseType != dst.baseType: if src.baseType != dst.baseType:
raise ValueError("Attribute types are not compatible and cannot be connected: '{}'({})->'{}'({})".format(self.srcAttr, src.baseType, self.dstAttr, dst.baseType)) raise ValueError(f"Attribute types are not compatible and cannot be connected: '{self.srcAttr}'({src.baseType})->'{self.dstAttr}'({dst.baseType})")
def redoImpl(self): def redoImpl(self):
self.graph.addEdge(self.graph.attribute(self.srcAttr), self.graph.attribute(self.dstAttr)) self.graph.addEdge(self.graph.attribute(self.srcAttr), self.graph.attribute(self.dstAttr))
@ -330,7 +330,7 @@ class RemoveEdgeCommand(GraphCommand):
super(RemoveEdgeCommand, self).__init__(graph, parent) super(RemoveEdgeCommand, self).__init__(graph, parent)
self.srcAttr = edge.src.getFullNameToNode() self.srcAttr = edge.src.getFullNameToNode()
self.dstAttr = edge.dst.getFullNameToNode() self.dstAttr = edge.dst.getFullNameToNode()
self.setText("Disconnect '{}'->'{}'".format(self.srcAttr, self.dstAttr)) self.setText(f"Disconnect '{self.srcAttr}'->'{self.dstAttr}'")
def redoImpl(self): def redoImpl(self):
self.graph.removeEdge(self.graph.attribute(self.dstAttr)) self.graph.removeEdge(self.graph.attribute(self.dstAttr))
@ -349,7 +349,7 @@ class ListAttributeAppendCommand(GraphCommand):
self.index = None self.index = None
self.count = 1 self.count = 1
self.value = value if value else None self.value = value if value else None
self.setText("Append to {}".format(self.attrName)) self.setText(f"Append to {self.attrName}")
def redoImpl(self): def redoImpl(self):
listAttribute = self.graph.attribute(self.attrName) listAttribute = self.graph.attribute(self.attrName)
@ -374,7 +374,7 @@ class ListAttributeRemoveCommand(GraphCommand):
self.listAttrName = listAttribute.getFullNameToNode() self.listAttrName = listAttribute.getFullNameToNode()
self.index = listAttribute.index(attribute) self.index = listAttribute.index(attribute)
self.value = attribute.getExportValue() self.value = attribute.getExportValue()
self.setText("Remove {}".format(attribute.getFullNameToNode())) self.setText(f"Remove {attribute.getFullNameToNode()}")
def redoImpl(self): def redoImpl(self):
listAttribute = self.graph.attribute(self.listAttrName) listAttribute = self.graph.attribute(self.listAttrName)
@ -392,7 +392,7 @@ class RemoveImagesCommand(GraphCommand):
self.cameraInits = cameraInitNodes self.cameraInits = cameraInitNodes
self.viewpoints = { cameraInit.name: cameraInit.attribute("viewpoints").getExportValue() for cameraInit in self.cameraInits } self.viewpoints = { cameraInit.name: cameraInit.attribute("viewpoints").getExportValue() for cameraInit in self.cameraInits }
self.intrinsics = { cameraInit.name: cameraInit.attribute("intrinsics").getExportValue() for cameraInit in self.cameraInits } self.intrinsics = { cameraInit.name: cameraInit.attribute("intrinsics").getExportValue() for cameraInit in self.cameraInits }
self.title = "Remove{}Images".format(" " if len(self.cameraInits) == 1 else " All ") self.title = f"Remove{' ' if len(self.cameraInits) == 1 else ' All '}Images"
self.setText(self.title) self.setText(self.title)
def redoImpl(self): def redoImpl(self):
@ -421,7 +421,7 @@ class MoveNodeCommand(GraphCommand):
self.nodeName = node.name self.nodeName = node.name
self.oldPosition = node.position self.oldPosition = node.position
self.newPosition = position self.newPosition = position
self.setText("Move {}".format(self.nodeName)) self.setText(f"Move {self.nodeName}")
def redoImpl(self): def redoImpl(self):
self.graph.node(self.nodeName).position = self.newPosition self.graph.node(self.nodeName).position = self.newPosition
@ -440,7 +440,7 @@ class UpgradeNodeCommand(GraphCommand):
self.nodeDict = node.toDict() self.nodeDict = node.toDict()
self.nodeName = node.getName() self.nodeName = node.getName()
self.compatibilityIssue = None self.compatibilityIssue = None
self.setText("Upgrade Node {}".format(self.nodeName)) self.setText(f"Upgrade Node {self.nodeName}")
def redoImpl(self): def redoImpl(self):
if not (node := self.graph.node(self.nodeName)).canUpgrade: if not (node := self.graph.node(self.nodeName)).canUpgrade:

View file

@ -77,7 +77,7 @@ class CsvData(QObject):
for idx, value in enumerate(elt): for idx, value in enumerate(elt):
dataList[idx].appendValue(value) dataList[idx].appendValue(value)
except Exception as e: except Exception as e:
logging.error("CsvData: Failed to load file: {}\n{}".format(self._filepath, str(e))) logging.error(f"CsvData: Failed to load file: {self._filepath}\n{str(e)}")
return dataList return dataList

View file

@ -28,7 +28,7 @@ class FilepathHelper(QObject):
str: String representation of 'path' str: String representation of 'path'
""" """
if not isinstance(path, (QUrl, str)): if not isinstance(path, (QUrl, str)):
raise TypeError("Unexpected data type: {}".format(path.__class__)) raise TypeError(f"Unexpected data type: {path.__class__}")
if isinstance(path, QUrl): if isinstance(path, QUrl):
path = path.toLocalFile() path = path.toLocalFile()
return path return path

View file

@ -836,14 +836,14 @@ class UIGraph(QObject):
if isinstance(src, ListAttribute) and not isinstance(dst, ListAttribute): if isinstance(src, ListAttribute) and not isinstance(dst, ListAttribute):
self._addEdge(src.at(0), dst) self._addEdge(src.at(0), dst)
elif isinstance(dst, ListAttribute) and not isinstance(src, ListAttribute): elif isinstance(dst, ListAttribute) and not isinstance(src, ListAttribute):
with self.groupedGraphModification("Insert and Add Edge on {}".format(dst.getFullNameToNode())): with self.groupedGraphModification(f"Insert and Add Edge on {dst.getFullNameToNode()}"):
self.appendAttribute(dst) self.appendAttribute(dst)
self._addEdge(src, dst.at(-1)) self._addEdge(src, dst.at(-1))
else: else:
self._addEdge(src, dst) self._addEdge(src, dst)
def _addEdge(self, src, dst): def _addEdge(self, src, dst):
with self.groupedGraphModification("Connect '{}'->'{}'".format(src.getFullNameToNode(), dst.getFullNameToNode())): with self.groupedGraphModification(f"Connect '{src.getFullNameToNode()}'->'{dst.getFullNameToNode()}'"):
if dst in self._graph.edges.keys(): if dst in self._graph.edges.keys():
self.removeEdge(self._graph.edge(dst)) self.removeEdge(self._graph.edge(dst))
self.push(commands.AddEdgeCommand(self._graph, src, dst)) self.push(commands.AddEdgeCommand(self._graph, src, dst))
@ -851,7 +851,7 @@ class UIGraph(QObject):
@Slot(Edge) @Slot(Edge)
def removeEdge(self, edge): def removeEdge(self, edge):
if isinstance(edge.dst.root, ListAttribute): if isinstance(edge.dst.root, ListAttribute):
with self.groupedGraphModification("Remove Edge and Delete {}".format(edge.dst.getFullNameToNode())): with self.groupedGraphModification(f"Remove Edge and Delete {edge.dst.getFullNameToNode()}"):
self.push(commands.RemoveEdgeCommand(self._graph, edge)) self.push(commands.RemoveEdgeCommand(self._graph, edge))
self.removeAttribute(edge.dst) self.removeAttribute(edge.dst)
else: else:
@ -859,7 +859,7 @@ class UIGraph(QObject):
@Slot(Edge, Attribute, Attribute, result=Edge) @Slot(Edge, Attribute, Attribute, result=Edge)
def replaceEdge(self, edge, newSrc, newDst): def replaceEdge(self, edge, newSrc, newDst):
with self.groupedGraphModification("Replace Edge '{}'->'{}' with '{}'->'{}'".format(edge.src.getFullNameToNode(), edge.dst.getFullNameToNode(), newSrc.getFullNameToNode(), newDst.getFullNameToNode())): with self.groupedGraphModification(f"Replace Edge '{edge.src.getFullNameToNode()}'->'{edge.dst.getFullNameToNode()}' with '{newSrc.getFullNameToNode()}'->'{newDst.getFullNameToNode()}'"):
self.removeEdge(edge) self.removeEdge(edge)
self.addEdge(newSrc, newDst) self.addEdge(newSrc, newDst)
return self._graph.edge(newDst) return self._graph.edge(newDst)
@ -875,7 +875,7 @@ class UIGraph(QObject):
@Slot(Attribute) @Slot(Attribute)
def resetAttribute(self, attribute): def resetAttribute(self, attribute):
""" Reset 'attribute' to its default value """ """ Reset 'attribute' to its default value """
with self.groupedGraphModification("Reset Attribute '{}'".format(attribute.name)): with self.groupedGraphModification(f"Reset Attribute '{attribute.name}'"):
# if the attribute is a ListAttribute, remove all edges # if the attribute is a ListAttribute, remove all edges
if isinstance(attribute, ListAttribute): if isinstance(attribute, ListAttribute):
for edge in self._graph.edges: for edge in self._graph.edges:

View file

@ -54,5 +54,5 @@ with open(os.path.join(args.output, 'MaterialIcons.qml'), 'w') as qml_file:
name = name + str(index) name = name + str(index)
names.append(name) names.append(name)
qml_file.write(' readonly property string {}: "\\u{}"\n'.format(name, code)) qml_file.write(f' readonly property string {name}: "\\u{code}\"\n')
qml_file.write('}\n') qml_file.write('}\n')

View file

@ -80,7 +80,7 @@ class LiveSfmManager(QObject):
""" """
# print('[LiveSfmManager] Watching {} for images'.format(folder)) # print('[LiveSfmManager] Watching {} for images'.format(folder))
if not os.path.isdir(folder): if not os.path.isdir(folder):
raise RuntimeError("Invalid folder provided: {}".format(folder)) raise RuntimeError(f"Invalid folder provided: {folder}")
self._folder = folder self._folder = folder
self.folderChanged.emit() self.folderChanged.emit()
self.cameraInit = self.sfm = None self.cameraInit = self.sfm = None
@ -225,7 +225,7 @@ class ViewpointWrapper(QObject):
# When the viewpoint attribute has already been deleted, metadata.value becomes a PySide property (whereas a string is expected) # When the viewpoint attribute has already been deleted, metadata.value becomes a PySide property (whereas a string is expected)
self._metadata = json.loads(self._viewpoint.metadata.value) if isinstance(self._viewpoint.metadata.value, str) and self._viewpoint.metadata.value else None self._metadata = json.loads(self._viewpoint.metadata.value) if isinstance(self._viewpoint.metadata.value, str) and self._viewpoint.metadata.value else None
except Exception as e: except Exception as e:
logging.warning("Failed to parse Viewpoint metadata: '{}', '{}'".format(str(e), str(self._viewpoint.metadata.value))) logging.warning(f"Failed to parse Viewpoint metadata: '{str(e)}', '{str(self._viewpoint.metadata.value)}'")
self._metadata = {} self._metadata = {}
if not self._metadata: if not self._metadata:
self._metadata = {} self._metadata = {}
@ -567,22 +567,22 @@ class Reconstruction(UIGraph):
self.error.emit( self.error.emit(
Message( Message(
"No Such File", "No Such File",
"Error While Loading '{}': No Such File.".format(os.path.basename(filepath)), f"Error While Loading '{os.path.basename(filepath)}': No Such File.",
"" ""
) )
) )
logging.error("Error while loading '{}': No Such File.".format(filepath)) logging.error(f"Error while loading '{filepath}': No Such File.")
except Exception: except Exception:
import traceback import traceback
trace = traceback.format_exc() trace = traceback.format_exc()
self.error.emit( self.error.emit(
Message( Message(
"Error While Loading Project File", "Error While Loading Project File",
"An unexpected error has occurred while loading file: '{}'".format(os.path.basename(filepath)), f"An unexpected error has occurred while loading file: '{os.path.basename(filepath)}'",
trace trace
) )
) )
logging.error("Error while loading '{}'.".format(filepath)) logging.error(f"Error while loading '{filepath}'.")
logging.error(trace) logging.error(trace)
return False return False
@ -805,9 +805,9 @@ class Reconstruction(UIGraph):
keyframeNode = self.addNewNode("KeyframeSelection", position=p) keyframeNode = self.addNewNode("KeyframeSelection", position=p)
keyframeNode.inputPaths.value = filesByType["videos"] keyframeNode.inputPaths.value = filesByType["videos"]
if len(filesByType["videos"]) == 1: if len(filesByType["videos"]) == 1:
newVideoNodeMessage = "New node '{}' added for the input video.".format(keyframeNode.getLabel()) newVideoNodeMessage = f"New node '{keyframeNode.getLabel()}' added for the input video."
else: else:
newVideoNodeMessage = "New node '{}' added for a rig of {} synchronized cameras.".format(keyframeNode.getLabel(), len(filesByType["videos"])) newVideoNodeMessage = f"New node '{keyframeNode.getLabel()}' added for a rig of {len(filesByType['videos'])} synchronized cameras."
self.info.emit( self.info.emit(
Message( Message(
"Video Input", "Video Input",
@ -836,13 +836,13 @@ class Reconstruction(UIGraph):
Message( Message(
"Panorama XML", "Panorama XML",
"XML file declared on PanoramaInit node", "XML file declared on PanoramaInit node",
"XML file '{}' set on node '{}'".format(','.join(filesByType["panoramaInfo"]), ','.join([n.getLabel() for n in panoramaInitNodes])), f"XML file '{','.join(filesByType['panoramaInfo'])}' set on node '{','.join([n.getLabel() for n in panoramaInitNodes])}'",
)) ))
else: else:
self.error.emit( self.error.emit(
Message( Message(
"No PanoramaInit Node", "No PanoramaInit Node",
"No PanoramaInit Node to set the Panorama file:\n'{}'.".format(','.join(filesByType["panoramaInfo"])), f"No PanoramaInit Node to set the Panorama file:\n'{','.join(filesByType['panoramaInfo'])}'.",
"", "",
)) ))
@ -865,7 +865,7 @@ class Reconstruction(UIGraph):
self.error.emit( self.error.emit(
Message( Message(
"No Recognized Input File", "No Recognized Input File",
"No recognized input file in the {} dropped files".format(len(filesByType["other"])), f"No recognized input file in the {len(filesByType['other'])} dropped files",
"Unknown file extensions: " + ', '.join(extensions) "Unknown file extensions: " + ', '.join(extensions)
) )
) )
@ -974,7 +974,7 @@ class Reconstruction(UIGraph):
# Retrieve the list of updated viewpoints and intrinsics # Retrieve the list of updated viewpoints and intrinsics
views, intrinsics = cameraInitCopy.nodeDesc.buildIntrinsics(cameraInitCopy, additionalViews) views, intrinsics = cameraInitCopy.nodeDesc.buildIntrinsics(cameraInitCopy, additionalViews)
except Exception as e: except Exception as e:
logging.error("Error while building intrinsics: {}".format(str(e))) logging.error(f"Error while building intrinsics: {str(e)}")
raise raise
finally: finally:
# Delete the duplicate # Delete the duplicate
@ -1008,7 +1008,7 @@ class Reconstruction(UIGraph):
commandTitle = "Augment Reconstruction ({} Images)" commandTitle = "Augment Reconstruction ({} Images)"
if rebuild: if rebuild:
commandTitle = "Rebuild '{}' Intrinsics".format(cameraInit.label) commandTitle = f"Rebuild '{cameraInit.label}' Intrinsics"
# No additional views: early return # No additional views: early return
if not views: if not views:

View file

@ -102,7 +102,7 @@ class QmlInstantEngine(QQmlApplicationEngine):
# Make sure the file exists # Make sure the file exists
if not os.path.isfile(filename): if not os.path.isfile(filename):
raise ValueError("addFile: file %s doesn't exist." % filename) raise ValueError(f"addFile: file {filename} doesn't exist.")
# Return if the file is already in our internal list # Return if the file is already in our internal list
if filename in self._watchedFiles: if filename in self._watchedFiles:
@ -135,7 +135,7 @@ class QmlInstantEngine(QQmlApplicationEngine):
recursive -- if True, will search inside each subdirectories recursively. recursive -- if True, will search inside each subdirectories recursively.
""" """
if not os.path.isdir(dirname): if not os.path.isdir(dirname):
raise RuntimeError("addFilesFromDirectory : %s is not a valid directory." % dirname) raise RuntimeError(f"addFilesFromDirectory : {dirname} is not a valid directory.")
if recursive: if recursive:
for dirpath, dirnames, filenames in os.walk(dirname): for dirpath, dirnames, filenames in os.walk(dirname):
@ -193,7 +193,7 @@ class QmlInstantEngine(QQmlApplicationEngine):
QTimer.singleShot(200, lambda: self.addFile(filepath)) QTimer.singleShot(200, lambda: self.addFile(filepath))
def reload(self): def reload(self):
print("Reloading {}".format(self._sourceFile)) print(f"Reloading {self._sourceFile}")
self.load(self._sourceFile) self.load(self._sourceFile)