Modernize to python-3.9+ with pyupgrade (--py39-plus)

This commit is contained in:
Fabien Castan 2025-04-30 19:18:06 +02:00
parent 22b2161ddd
commit 41738f7f40
26 changed files with 148 additions and 157 deletions

View file

@ -152,7 +152,7 @@ graph = meshroom.core.graph.Graph(name=args.pipeline)
with meshroom.core.graph.GraphModification(graph):
# initialize template pipeline
loweredPipelineTemplates = dict((k.lower(), v) for k, v in meshroom.core.pipelineTemplates.items())
loweredPipelineTemplates = {k.lower(): v for k, v in meshroom.core.pipelineTemplates.items()}
if args.pipeline.lower() in loweredPipelineTemplates:
graph.initFromTemplate(loweredPipelineTemplates[args.pipeline.lower()], publishOutputs=True if args.output else False)
else:
@ -232,7 +232,7 @@ with meshroom.core.graph.GraphModification(graph):
raise RuntimeError("meshroom_batch requires a pipeline graph with at least one Publish node, none found.")
if args.overrides:
with open(args.overrides, 'r', encoding='utf-8', errors='ignore') as f:
with open(args.overrides, encoding='utf-8', errors='ignore') as f:
data = json.load(f)
for nodeName, overrides in data.items():
for attrName, value in overrides.items():
@ -240,7 +240,7 @@ with meshroom.core.graph.GraphModification(graph):
if args.paramOverrides:
print("\n")
reExtract = re.compile('(\w+)([:.])(\w[\w.]*)=(.*)')
reExtract = re.compile(r'(\w+)([:.])(\w[\w.]*)=(.*)')
for p in args.paramOverrides:
result = reExtract.match(p)
if not result:
@ -249,12 +249,12 @@ with meshroom.core.graph.GraphModification(graph):
if t == ':':
nodesOfType = graph.nodesOfType(node)
if not nodesOfType:
raise ValueError('No node with the type "{}" in the scene.'.format(node))
raise ValueError(f'No node with the type "{node}" in the scene.')
for n in nodesOfType:
print('Overrides {node}.{param}={value}'.format(node=node, param=param, value=value))
print(f'Overrides {node}.{param}={value}')
n.attribute(param).value = value
elif t == '.':
print('Overrides {node}.{param}={value}'.format(node=node, param=param, value=value))
print(f'Overrides {node}.{param}={value}')
graph.findNode(node).attribute(param).value = value
else:
raise ValueError('Invalid param override: ' + str(p))
@ -265,10 +265,10 @@ with meshroom.core.graph.GraphModification(graph):
if args.save:
graph.save(args.save, setupProjectFile=not bool(args.cache))
print('File successfully saved: "{}"'.format(args.save))
print(f'File successfully saved: "{args.save}"')
if not args.output:
print('No output set, results will be available in the cache folder: "{}"'.format(graph.cacheDir))
print(f'No output set, results will be available in the cache folder: "{graph.cacheDir}"')
# find end nodes (None will compute all graph)
toNodes = graph.findNodes(args.toNode) if args.toNode else None

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python
from __future__ import print_function
import argparse
import os
@ -15,7 +14,7 @@ def trim(s):
"""
# regex to replace all space groups by a single space
# use split() to remove trailing space at beginning/end
return re.sub('\s+', ' ', s).strip()
return re.sub(r'\s+', ' ', s).strip()
def quotesForStrings(valueStr):
@ -30,9 +29,9 @@ def quotesForStrings(valueStr):
float(valueStr)
except ValueError:
if "'" in valueStr:
v = "'''{}'''".format(valueStr)
v = f"'''{valueStr}'''"
else:
v = "'{}'".format(valueStr)
v = f"'{valueStr}'"
return v
def convertToLabel(name):
@ -86,7 +85,7 @@ elif sys.stdin.isatty():
if not inputCmdLineDoc:
print('No input documentation.')
print('Usage: YOUR_COMMAND --help | {cmd}'.format(cmd=os.path.splitext(__file__)[0]))
print(f'Usage: YOUR_COMMAND --help | {os.path.splitext(__file__)[0]}')
sys.exit(-1)
@ -104,39 +103,39 @@ print(inputCmdLineDoc)
args_re = None
if args.parser == 'boost':
args_re = re.compile(
'^\s+' # space(s)
'(?:-(?P<argShortName>\w+)\|?)?' # potential argument short name
'\s*\[?' # potential '['
'\s*--(?P<argLongName>\w+)' # argument long name
'(?:\s*\])?' # potential ']'
'(?:\s+(?P<arg>\w+)?)?' # potential arg
'(?:\s+\(\=(?P<defaultValue>.+)\))?' # potential default value
'\s+(?P<descriptionFirst>.*?)\n' # end of the line
'(?P<descriptionNext>(?:\s+[^-\s].+?\n)*)' # next documentation lines
r'^\s+' # space(s)
r'(?:-(?P<argShortName>\w+)\|?)?' # potential argument short name
r'\s*\[?' # potential '['
r'\s*--(?P<argLongName>\w+)' # argument long name
r'(?:\s*\])?' # potential ']'
r'(?:\s+(?P<arg>\w+)?)?' # potential arg
r'(?:\s+\(\=(?P<defaultValue>.+)\))?' # potential default value
'\\s+(?P<descriptionFirst>.*?)\n' # end of the line
'(?P<descriptionNext>(?:\\s+[^-\\s].+?\n)*)' # next documentation lines
'',
re.MULTILINE)
elif args.parser == 'cmdLineLib':
args_re = re.compile(
'^'
'\[' # '['
'-(?P<argShortName>\w+)' # argument short name
'\|'
'--(?P<argLongName>\w+)' # argument long name
'(?:\s+(?P<arg>\w+)?)?' # potential arg
'\]' # ']'
r'\[' # '['
r'-(?P<argShortName>\w+)' # argument short name
r'\|'
r'--(?P<argLongName>\w+)' # argument long name
r'(?:\s+(?P<arg>\w+)?)?' # potential arg
r'\]' # ']'
'()' # no default value
'(?P<descriptionFirst>.*?)?\n' # end of the line
'(?P<descriptionNext>(?:[^\[\w].+?\n)*)' # next documentation lines
'(?P<descriptionNext>(?:[^\\[\\w].+?\n)*)' # next documentation lines
, re.MULTILINE)
elif args.parser == 'basic':
args_re = re.compile('()--(?P<argLongName>\w+)()()()()')
args_re = re.compile(r'()--(?P<argLongName>\w+)()()()()')
else:
print('Error: Unknown input parser "{}"'.format(args.parser))
print(f'Error: Unknown input parser "{args.parser}"')
sys.exit(-1)
choiceValues1_re = re.compile('\* (?P<value>\w+):')
choiceValues2_re = re.compile('\((?P<value>.+?)\)')
choiceValues3_re = re.compile('\{(?P<value>.+?)\}')
choiceValues1_re = re.compile(r'\* (?P<value>\w+):')
choiceValues2_re = re.compile(r'\((?P<value>.+?)\)')
choiceValues3_re = re.compile(r'\{(?P<value>.+?)\}')
cmdLineArgs = args_re.findall(inputCmdLineDoc.decode('utf-8'))
@ -286,10 +285,10 @@ fileStr += """
outputFilepath = os.path.join(args.output, args.node + '.py')
if not args.force and os.path.exists(outputFilepath):
print('Plugin "{}" already exists "{}".'.format(args.node, outputFilepath))
print(f'Plugin "{args.node}" already exists "{outputFilepath}".')
sys.exit(-1)
with open(outputFilepath, 'w') as pluginFile:
pluginFile.write(fileStr)
print('New node exported to: "{}"'.format(outputFilepath))
print(f'New node exported to: "{outputFilepath}"')

View file

@ -45,7 +45,7 @@ parser.add_argument("--verbose", help="Print full status information",
args = parser.parse_args()
if not os.path.exists(args.graphFile):
print('ERROR: No graph file "{}".'.format(args.graphFile))
print(f'ERROR: No graph file "{args.graphFile}".')
sys.exit(-1)
graph = pg.loadGraph(args.graphFile)
@ -64,7 +64,7 @@ else:
for node in nodes:
for chunk in node.chunks:
print('{}: {}\n'.format(chunk.name, chunk.statistics.toDict()))
print(f'{chunk.name}: {chunk.statistics.toDict()}\n')
if args.exportHtml:
with open(args.exportHtml, 'w') as fileObj:

View file

@ -22,7 +22,7 @@ parser.add_argument("--verbose", help="Print full status information",
args = parser.parse_args()
if not os.path.exists(args.graphFile):
print('ERROR: No graph file "{}".'.format(args.node, args.graphFile))
print(f'ERROR: No graph file "{args.node}".')
sys.exit(-1)
graph = meshroom.core.graph.loadGraph(args.graphFile)
@ -32,10 +32,10 @@ graph.update()
if args.node:
node = graph.node(args.node)
if node is None:
print('ERROR: node "{}" does not exist in file "{}".'.format(args.node, args.graphFile))
print(f'ERROR: node "{args.node}" does not exist in file "{args.graphFile}".')
sys.exit(-1)
for chunk in node.chunks:
print('{}: {}'.format(chunk.name, chunk.status.status.name))
print(f'{chunk.name}: {chunk.status.status.name}')
if args.verbose:
print('statusFile: ', node.statusFile)
pprint(node.status.toDict())
@ -46,6 +46,6 @@ else:
nodes, edges = graph.dfsOnFinish(startNodes=startNodes)
for node in nodes:
for chunk in node.chunks:
print('{}: {}'.format(chunk.name, chunk.status.status.name))
print(f'{chunk.name}: {chunk.status.status.name}')
if args.verbose:
pprint([n.status.toDict() for n in nodes])

View file

@ -16,13 +16,13 @@ from functools import partial
from weakref import WeakMethod
class Signal(object):
class Signal:
"""
The Signal is the core object that handles connection and emission .
"""
def __init__(self):
super(Signal, self).__init__()
super().__init__()
self._block = False
self._sender = None
self._slots = []
@ -151,7 +151,7 @@ class Signal(object):
return None
class ClassSignal(object):
class ClassSignal:
"""
The class signal allows a signal to be set on a class rather than an instance.
This emulates the behavior of a PyQt signal
@ -234,7 +234,7 @@ class SignalFactory(dict):
self[signal].block(isBlocked)
class ClassSignalFactory(object):
class ClassSignalFactory:
"""
The class signal allows a signal factory to be set on a class rather than an instance.
"""

View file

@ -126,13 +126,13 @@ def CoreSlot(*args, **kwargs):
class CoreProperty(property):
def __init__(self, ptype, fget=None, fset=None, **kwargs):
super(CoreProperty, self).__init__(fget, fset)
super().__init__(fget, fset)
class CoreObject(object):
class CoreObject:
def __init__(self, parent=None, *args, **kwargs):
super(CoreObject, self).__init__()
super().__init__()
self._parent = parent
# Note: we do not use ClassSignal, as it can not be used in __del__.
self.destroyed = PySignal.Signal()

View file

@ -14,7 +14,7 @@ class QObjectListModel(QtCore.QAbstractListModel):
def __init__(self, keyAttrName='', parent=None):
""" Constructs an object list model with the given parent. """
super(QObjectListModel, self).__init__(parent)
super().__init__(parent)
self._objects = list() # Internal list of objects
self._keyAttrName = keyAttrName
@ -322,7 +322,7 @@ class QTypedObjectListModel(QObjectListModel):
# TODO: handle notify signal to emit dataChanged signal
def __init__(self, keyAttrName="name", T=QtCore.QObject, parent=None):
super(QTypedObjectListModel, self).__init__(keyAttrName, parent)
super().__init__(keyAttrName, parent)
self._T = T
blacklist = ["id", "index", "class", "model", "modelData"]
@ -340,7 +340,7 @@ class QTypedObjectListModel(QObjectListModel):
print("Reserved role name: " + prop.name())
def data(self, index, role):
obj = super(QTypedObjectListModel, self).data(index, self.ObjectRole)
obj = super().data(index, self.ObjectRole)
if role == self.ObjectRole:
return obj
if obj:
@ -355,7 +355,7 @@ class QTypedObjectListModel(QObjectListModel):
if item.staticMetaObject != self._metaObject:
raise TypeError("Invalid object type: expected {}, got {}".format(
self._metaObject.className(), item.staticMetaObject.className()))
super(QTypedObjectListModel, self)._referenceItem(item)
super()._referenceItem(item)
class SortedModelByReference(QtCore.QSortFilterProxyModel):
@ -363,7 +363,7 @@ class SortedModelByReference(QtCore.QSortFilterProxyModel):
This proxy is useful if the model needs to be sorted a certain way for a specific use.
"""
def __init__(self, parent):
super(SortedModelByReference, self).__init__(parent)
super().__init__(parent)
self._reference = []
def setReference(self, iterable):
@ -385,7 +385,7 @@ class SortedModelByReference(QtCore.QSortFilterProxyModel):
def sort(self):
""" Sort the proxy and call invalidate() """
super(SortedModelByReference, self).sort(0, QtCore.Qt.AscendingOrder)
super().sort(0, QtCore.Qt.AscendingOrder)
self.invalidate()

View file

@ -161,7 +161,7 @@ def validateNodeDesc(nodeDesc):
return errors
class Version(object):
class Version:
"""
Version provides convenient properties and methods to manipulate and compare versions.
"""
@ -173,19 +173,19 @@ class Version(object):
"""
if len(args) == 0:
self.components = tuple()
self.status = str()
self.status = ''
elif len(args) == 1:
versionName = args[0]
if isinstance(versionName, str):
self.components, self.status = Version.toComponents(versionName)
elif isinstance(versionName, (list, tuple)):
self.components = tuple([int(v) for v in versionName])
self.status = str()
self.status = ''
else:
raise RuntimeError("Version: Unsupported input type.")
else:
self.components = tuple([int(v) for v in args])
self.status = str()
self.status = ''
def __repr__(self):
return self.name
@ -245,9 +245,9 @@ class Version(object):
tuple of int, string: split version numbers, status if any (or empty string)
"""
if not versionName:
return (), str()
return (), ''
status = str()
status = ''
# If there is a status, it is placed after a "-"
splitComponents = versionName.split("-", maxsplit=1)
if (len(splitComponents) > 1): # If there is no status, splitComponents is equal to [versionName]

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python
# coding:utf-8
import copy
import os
import re
@ -57,7 +56,7 @@ class Attribute(BaseObject):
root (Attribute): (optional) the root Attribute (List or Group) containing this one
parent (BaseObject): (optional) the parent BaseObject
"""
super(Attribute, self).__init__(parent)
super().__init__(parent)
self._name = attributeDesc.name
self._root = None if root is None else weakref.ref(root)
self._node = weakref.ref(node)
@ -473,7 +472,7 @@ def raiseIfLink(func):
class PushButtonParam(Attribute):
def __init__(self, node, attributeDesc, isOutput, root=None, parent=None):
super(PushButtonParam, self).__init__(node, attributeDesc, isOutput, root, parent)
super().__init__(node, attributeDesc, isOutput, root, parent)
@Slot()
def clicked(self):
@ -483,7 +482,7 @@ class PushButtonParam(Attribute):
class ChoiceParam(Attribute):
def __init__(self, node, attributeDesc: desc.ChoiceParam, isOutput, root=None, parent=None):
super(ChoiceParam, self).__init__(node, attributeDesc, isOutput, root, parent)
super().__init__(node, attributeDesc, isOutput, root, parent)
self._values = None
def __len__(self):
@ -544,7 +543,7 @@ class ChoiceParam(Attribute):
class ListAttribute(Attribute):
def __init__(self, node, attributeDesc, isOutput, root=None, parent=None):
super(ListAttribute, self).__init__(node, attributeDesc, isOutput, root, parent)
super().__init__(node, attributeDesc, isOutput, root, parent)
def __len__(self):
if self._value is None:
@ -650,13 +649,13 @@ class ListAttribute(Attribute):
if value.invalidate:
uids.append(value.uid())
return hashValue(uids)
return super(ListAttribute, self).uid()
return super().uid()
def _applyExpr(self):
if not self.node.graph:
return
if isinstance(self._value, ListAttribute) or Attribute.isLinkExpression(self._value):
super(ListAttribute, self)._applyExpr()
super()._applyExpr()
else:
for value in self._value:
value._applyExpr()
@ -689,7 +688,7 @@ class ListAttribute(Attribute):
return v
def updateInternals(self):
super(ListAttribute, self).updateInternals()
super().updateInternals()
for attr in self._value:
attr.updateInternals()
@ -711,11 +710,11 @@ class ListAttribute(Attribute):
class GroupAttribute(Attribute):
def __init__(self, node, attributeDesc, isOutput, root=None, parent=None):
super(GroupAttribute, self).__init__(node, attributeDesc, isOutput, root, parent)
super().__init__(node, attributeDesc, isOutput, root, parent)
def __getattr__(self, key):
try:
return super(GroupAttribute, self).__getattr__(key)
return super().__getattr__(key)
except AttributeError:
try:
return self._value.get(key)
@ -831,7 +830,7 @@ class GroupAttribute(Attribute):
return f'{strBegin}{s}{strEnd}'
def updateInternals(self):
super(GroupAttribute, self).updateInternals()
super().updateInternals()
for attr in self._value:
attr.updateInternals()

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python
# coding:utf-8
import os
@ -15,7 +14,7 @@ def getCgroupMemorySize():
cgroup = None
try:
with open(filename, "r") as f:
with open(filename) as f:
# cgroup file is a ':' separated table
# lookup a line where the second field is "memory"
@ -35,7 +34,7 @@ def getCgroupMemorySize():
size = -1
filename = f"/sys/fs/cgroup/memory/{cgroup}/memory.limit_in_bytes"
try:
with open(filename, "r") as f:
with open(filename) as f:
value = f.read().rstrip("\r\n")
if value.isnumeric():
size = int(value)
@ -72,7 +71,7 @@ def getCgroupCpuCount():
cgroup = None
try:
with open(filename, "r") as f:
with open(filename) as f:
# cgroup file is a ':' separated table
# lookup a line where the second field is "memory"
@ -92,7 +91,7 @@ def getCgroupCpuCount():
size = -1
filename = f"/sys/fs/cgroup/cpuset/{cgroup}/cpuset.cpus"
try:
with open(filename, "r") as f:
with open(filename) as f:
value = f.read().rstrip("\r\n")
nlist = parseNumericList(value)
size = len(nlist)

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python
# coding:utf-8
class MeshroomException(Exception):
@ -33,7 +32,7 @@ class UnknownNodeTypeError(GraphException):
"""
def __init__(self, nodeType, msg=None):
msg = "Unknown Node Type: " + nodeType
super(UnknownNodeTypeError, self).__init__(msg)
super().__init__(msg)
self.nodeType = nodeType
@ -42,7 +41,7 @@ class NodeUpgradeError(GraphException):
msg = f"Failed to upgrade node {nodeName}"
if details:
msg += f": {details}"
super(NodeUpgradeError, self).__init__(msg)
super().__init__(msg)
class GraphVisitMessage(GraphException):

View file

@ -1,10 +1,9 @@
from __future__ import print_function
import json
import logging
import os
import re
from typing import Any, Iterable, Optional
from typing import Any, Optional
from collections.abc import Iterable
import weakref
from collections import defaultdict, OrderedDict
from contextlib import contextmanager
@ -63,7 +62,7 @@ def GraphModification(graph):
class Edge(BaseObject):
def __init__(self, src, dst, parent=None):
super(Edge, self).__init__(parent)
super().__init__(parent)
self._src = weakref.ref(src)
self._dst = weakref.ref(dst)
self._repr = f"<Edge> {self._src()} -> {self._dst()}"
@ -85,13 +84,13 @@ GRAY = 1
BLACK = 2
class Visitor(object):
class Visitor:
"""
Base class for Graph Visitors that does nothing.
Sub-classes can override any method to implement specific algorithms.
"""
def __init__(self, reverse, dependenciesOnly):
super(Visitor, self).__init__()
super().__init__()
self.reverse = reverse
self.dependenciesOnly = dependenciesOnly
@ -197,7 +196,7 @@ class Graph(BaseObject):
"""
def __init__(self, name: str = "", parent: BaseObject = None):
super(Graph, self).__init__(parent)
super().__init__(parent)
self.name: str = name
self._loading: bool = False
self._saving: bool = False
@ -339,7 +338,7 @@ class Graph(BaseObject):
uidOccurrences = uidPattern.findall(updatedFileData)
for occ in uidOccurrences:
uid = occ.split("\"")[-2] # UID is second to last element
newUidStr = r'"uid": "{}"'.format(uid)
newUidStr = fr'"uid": "{uid}"'
updatedFileData = updatedFileData.replace(occ, newUidStr)
graphContent = json.loads(updatedFileData)
@ -856,11 +855,11 @@ class Graph(BaseObject):
return self._edges.get(dstAttributeName)
def getLeafNodes(self, dependenciesOnly):
nodesWithOutputLink = set([edge.src.node for edge in self.getEdges(dependenciesOnly)])
nodesWithOutputLink = {edge.src.node for edge in self.getEdges(dependenciesOnly)}
return set(self._nodes) - nodesWithOutputLink
def getRootNodes(self, dependenciesOnly):
nodesWithInputLink = set([edge.dst.node for edge in self.getEdges(dependenciesOnly)])
nodesWithInputLink = {edge.dst.node for edge in self.getEdges(dependenciesOnly)}
return set(self._nodes) - nodesWithInputLink
@changeTopology
@ -910,7 +909,7 @@ class Graph(BaseObject):
return minDepth if minimal else maxDepth
def getInputEdges(self, node, dependenciesOnly):
return set([edge for edge in self.getEdges(dependenciesOnly=dependenciesOnly) if edge.dst.node is node])
return {edge for edge in self.getEdges(dependenciesOnly=dependenciesOnly) if edge.dst.node is node}
def _getInputEdgesPerNode(self, dependenciesOnly):
nodeEdges = defaultdict(set)
@ -1167,7 +1166,7 @@ class Graph(BaseObject):
:return:
"""
nodesStack = []
edgesScore = defaultdict(lambda: 0)
edgesScore = defaultdict(int)
visitor = Visitor(reverse=False, dependenciesOnly=dependenciesOnly)
def finishEdge(edge, graph):
@ -1223,7 +1222,7 @@ class Graph(BaseObject):
def getInputNodes(self, node, recursive, dependenciesOnly):
""" Return either the first level input nodes of a node or the whole chain. """
if not recursive:
return set([edge.src.node for edge in self.getEdges(dependenciesOnly) if edge.dst.node is node])
return {edge.src.node for edge in self.getEdges(dependenciesOnly) if edge.dst.node is node}
inputNodes, edges = self.dfsOnDiscover(startNodes=[node], filterTypes=None, reverse=False)
return inputNodes[1:] # exclude current node
@ -1231,7 +1230,7 @@ class Graph(BaseObject):
def getOutputNodes(self, node, recursive, dependenciesOnly):
""" Return either the first level output nodes of a node or the whole chain. """
if not recursive:
return set([edge.dst.node for edge in self.getEdges(dependenciesOnly) if edge.src.node is node])
return {edge.dst.node for edge in self.getEdges(dependenciesOnly) if edge.src.node is node}
outputNodes, edges = self.dfsOnDiscover(startNodes=[node], filterTypes=None, reverse=True)
return outputNodes[1:] # exclude current node
@ -1253,7 +1252,7 @@ class Graph(BaseObject):
class SCVisitor(Visitor):
def __init__(self, reverse, dependenciesOnly):
super(SCVisitor, self).__init__(reverse, dependenciesOnly)
super().__init__(reverse, dependenciesOnly)
canCompute = True
canSubmit = True
@ -1611,7 +1610,7 @@ def executeGraph(graph, toNodes=None, forceCompute=False, forceStatus=False):
chunksInConflict = getAlreadySubmittedChunks(nodes)
if chunksInConflict:
chunksStatus = set([chunk.status.status.name for chunk in chunksInConflict])
chunksStatus = {chunk.status.status.name for chunk in chunksInConflict}
chunksName = [node.name for node in chunksInConflict]
msg = 'WARNING: Some nodes are already submitted with status: {}\nNodes: {}'.format(
', '.join(chunksStatus),

View file

@ -15,7 +15,7 @@ class GraphIO:
__version__ = "2.0"
class Keys(object):
class Keys:
"""File Keys."""
# Doesn't inherit enum to simplify usage (GraphIO.Keys.XX, without .value)
@ -98,7 +98,7 @@ class GraphSerializer:
def _getNodeTypesVersions(self) -> dict[str, str]:
"""Get registered versions of each node types in `nodes`, excluding CompatibilityNode instances."""
nodeTypes = set([node.nodeDesc.__class__ for node in self.nodes if isinstance(node, Node)])
nodeTypes = {node.nodeDesc.__class__ for node in self.nodes if isinstance(node, Node)}
nodeTypesVersions = {
nodeType.__name__: version
for nodeType in nodeTypes

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python
# coding:utf-8
import atexit
import copy
import datetime
@ -37,7 +36,7 @@ def renameWritingToFinalPath(writingFilepath: str, filepath: str) -> str:
os.remove(filepath)
# If remove is successful, we can stop the iterations
break
except WindowsError:
except OSError:
pass
os.rename(writingFilepath, filepath)
@ -70,7 +69,7 @@ class StatusData(BaseObject):
def __init__(self, nodeName='', nodeType='', packageName='', packageVersion='',
mrNodeType: MrNodeType = MrNodeType.NONE, parent: BaseObject = None):
super(StatusData, self).__init__(parent)
super().__init__(parent)
self.nodeName: str = nodeName
self.nodeType: str = nodeType
@ -267,7 +266,7 @@ class LogManager:
f.close()
with open(self.chunk.logFile, 'r') as f:
with open(self.chunk.logFile) as f:
content = f.read()
self.progressBarPosition = content.rfind('\n')
@ -320,7 +319,7 @@ def clearProcessesStatus():
class NodeChunk(BaseObject):
def __init__(self, node, range, parent=None):
super(NodeChunk, self).__init__(parent)
super().__init__(parent)
self.node = node
self.range = range
self.logManager: LogManager = LogManager(self)
@ -368,7 +367,7 @@ class NodeChunk(BaseObject):
self._status.setNodeType(self.node)
else:
try:
with open(statusFile, 'r') as jsonFile:
with open(statusFile) as jsonFile:
statusData = json.load(jsonFile)
# logging.debug(f"updateStatusFromCache({self.node.name}): From status {self.status.status} to {statusData['status']}")
self._status.fromDict(statusData)
@ -443,7 +442,7 @@ class NodeChunk(BaseObject):
statisticsFile = self.statisticsFile
if not os.path.exists(statisticsFile):
return
with open(statisticsFile, 'r') as jsonFile:
with open(statisticsFile) as jsonFile:
statisticsData = json.load(jsonFile)
self.statistics.fromDict(statisticsData)
if oldTimes != self.statistics.times:
@ -635,7 +634,7 @@ class BaseNode(BaseObject):
parent: this Node's parent
**kwargs: attributes values
"""
super(BaseNode, self).__init__(parent)
super().__init__(parent)
self._nodeType: str = nodeType
self.nodeDesc: desc.BaseNode = None
@ -1311,7 +1310,7 @@ class BaseNode(BaseObject):
return
# logging.warning("load output attr: {}, value: {}".format(self.name, valuesFile))
with open(valuesFile, 'r') as jsonFile:
with open(valuesFile) as jsonFile:
data = json.load(jsonFile)
# logging.warning(data)
@ -1513,8 +1512,8 @@ class BaseNode(BaseObject):
# If number of elements in both lists are identical,
# we must check if their content is the same
if len(newList) == len(self._duplicates):
newListName = set([node.name for node in newList])
oldListName = set([node.name for node in self._duplicates.values()])
newListName = {node.name for node in newList}
oldListName = {node.name for node in self._duplicates.values()}
# If strict equality between both sets,
# there is no need to set the new list
@ -1689,7 +1688,7 @@ class Node(BaseNode):
A standard Graph node based on a node type.
"""
def __init__(self, nodeType, position=None, parent=None, uid=None, **kwargs):
super(Node, self).__init__(nodeType, position, parent=parent, uid=uid, **kwargs)
super().__init__(nodeType, position, parent=parent, uid=uid, **kwargs)
if not self.nodeDesc:
raise UnknownNodeTypeError(nodeType)
@ -1834,7 +1833,7 @@ class CompatibilityNode(BaseNode):
with all its inputs and precomputed outputs.
"""
def __init__(self, nodeType, nodeDict, position=None, issue=CompatibilityIssue.UnknownIssue, parent=None):
super(CompatibilityNode, self).__init__(nodeType, position, parent)
super().__init__(nodeType, position, parent)
self.issue = issue
# Make a deepcopy of nodeDict to handle CompatibilityNode duplication

View file

@ -1,5 +1,6 @@
import logging
from typing import Any, Iterable, Optional, Union
from typing import Any, Optional, Union
from collections.abc import Iterable
import meshroom.core
from meshroom.core import Version, desc

View file

@ -1,12 +1,11 @@
#!/usr/bin/env python
# coding:utf-8
from meshroom.common import BaseObject, Property
class BaseSubmitter(BaseObject):
def __init__(self, name, parent=None):
super(BaseSubmitter, self).__init__(parent)
super().__init__(parent)
self._name = name
def submit(self, nodes, edges, filepath, submitLabel="{projectName}"):

View file

@ -98,7 +98,7 @@ class TaskManager(BaseObject):
Manage graph - local and external - computation tasks.
"""
def __init__(self, parent: BaseObject = None):
super(TaskManager, self).__init__(parent)
super().__init__(parent)
self._graph = None
self._nodes = DictModel(keyAttrName='_name', parent=self)
self._nodesToProcess = []
@ -208,7 +208,7 @@ class TaskManager(BaseObject):
chunksInConflict = self.getAlreadySubmittedChunks(nodes)
if chunksInConflict:
chunksStatus = set([chunk.status.status.name for chunk in chunksInConflict])
chunksStatus = {chunk.status.status.name for chunk in chunksInConflict}
chunksName = [node.name for node in chunksInConflict]
# Warning: Syntax and terms are parsed on QML side to recognize the error
# Syntax : [Context] ErrorType: ErrorMessage

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python
# coding:utf-8
from meshroom.core import unregisterNodeType, pipelineTemplates, Version
from meshroom.core.node import CompatibilityIssue, CompatibilityNode

View file

@ -1 +0,0 @@
# coding:utf-8

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python
# coding:utf-8
import os
import json
@ -24,7 +23,7 @@ class SimpleFarmSubmitter(BaseSubmitter):
DEFAULT_TAGS = {'prod': ''}
def __init__(self, parent=None):
super(SimpleFarmSubmitter, self).__init__(name='SimpleFarm', parent=parent)
super().__init__(name='SimpleFarm', parent=parent)
self.engine = os.environ.get('MESHROOM_SIMPLEFARM_ENGINE', 'tractor')
self.share = os.environ.get('MESHROOM_SIMPLEFARM_SHARE', 'vfx')
self.prod = os.environ.get('PROD', 'mvg')

View file

@ -31,7 +31,7 @@ from meshroom.ui.utils import QmlInstantEngine
from meshroom.ui import commands
class MessageHandler(object):
class MessageHandler:
"""
MessageHandler that translates Qt logs to Python logging system.
Also contains and filters a list of blacklisted QML warnings that end up in the
@ -211,7 +211,7 @@ class MeshroomApp(QApplication):
logging.getLogger().setLevel(meshroom.logStringToPython[args.verbose])
super(MeshroomApp, self).__init__(inputArgs[:1] + qtArgs)
super().__init__(inputArgs[:1] + qtArgs)
self.setOrganizationName('AliceVision')
self.setApplicationName('Meshroom')

View file

@ -14,7 +14,7 @@ from meshroom.core.mtyping import PathLike
class UndoCommand(QUndoCommand):
def __init__(self, parent=None):
super(UndoCommand, self).__init__(parent)
super().__init__(parent)
self._enabled = True
def setEnabled(self, enabled):
@ -47,7 +47,7 @@ class UndoCommand(QUndoCommand):
class UndoStack(QUndoStack):
def __init__(self, parent=None):
super(UndoStack, self).__init__(parent)
super().__init__(parent)
# connect QUndoStack signal to UndoStack's ones
self.cleanChanged.connect(self._cleanChanged)
self.canUndoChanged.connect(self._canUndoChanged)
@ -121,13 +121,13 @@ class UndoStack(QUndoStack):
class GraphCommand(UndoCommand):
def __init__(self, graph, parent=None):
super(GraphCommand, self).__init__(parent)
super().__init__(parent)
self.graph = graph
class AddNodeCommand(GraphCommand):
def __init__(self, graph, nodeType, position, parent=None, **kwargs):
super(AddNodeCommand, self).__init__(graph, parent)
super().__init__(graph, parent)
self.nodeType = nodeType
self.nodeName = None
self.position = position
@ -153,7 +153,7 @@ class AddNodeCommand(GraphCommand):
class RemoveNodeCommand(GraphCommand):
def __init__(self, graph, node, parent=None):
super(RemoveNodeCommand, self).__init__(graph, parent)
super().__init__(graph, parent)
self.nodeDict = node.toDict()
self.nodeName = node.getName()
self.setText(f"Remove Node {self.nodeName}")
@ -178,7 +178,7 @@ class DuplicateNodesCommand(GraphCommand):
Handle node duplication in a Graph.
"""
def __init__(self, graph, srcNodes, parent=None):
super(DuplicateNodesCommand, self).__init__(graph, parent)
super().__init__(graph, parent)
self.srcNodeNames = [ n.name for n in srcNodes ]
self.setText("Duplicate Nodes")
@ -200,7 +200,7 @@ class PasteNodesCommand(GraphCommand):
Handle node pasting in a Graph.
"""
def __init__(self, graph: "Graph", data: dict, position: Position, parent=None):
super(PasteNodesCommand, self).__init__(graph, parent)
super().__init__(graph, parent)
self.data = data
self.position = position
self.nodeNames: list[str] = []
@ -253,7 +253,7 @@ class ImportProjectCommand(GraphCommand):
"""
def __init__(self, graph: Graph, filepath: PathLike, position=None, yOffset=0, parent=None):
super(ImportProjectCommand, self).__init__(graph, parent)
super().__init__(graph, parent)
self.filepath = filepath
self.importedNames = []
self.position = position
@ -285,7 +285,7 @@ class ImportProjectCommand(GraphCommand):
class SetAttributeCommand(GraphCommand):
def __init__(self, graph, attribute, value, parent=None):
super(SetAttributeCommand, self).__init__(graph, parent)
super().__init__(graph, parent)
self.attrName = attribute.getFullNameToNode()
self.value = value
self.oldValue = attribute.getExportValue()
@ -309,7 +309,7 @@ class SetAttributeCommand(GraphCommand):
class AddEdgeCommand(GraphCommand):
def __init__(self, graph, src, dst, parent=None):
super(AddEdgeCommand, self).__init__(graph, parent)
super().__init__(graph, parent)
self.srcAttr = src.getFullNameToNode()
self.dstAttr = dst.getFullNameToNode()
self.setText(f"Connect '{self.srcAttr}'->'{self.dstAttr}'")
@ -327,7 +327,7 @@ class AddEdgeCommand(GraphCommand):
class RemoveEdgeCommand(GraphCommand):
def __init__(self, graph, edge, parent=None):
super(RemoveEdgeCommand, self).__init__(graph, parent)
super().__init__(graph, parent)
self.srcAttr = edge.src.getFullNameToNode()
self.dstAttr = edge.dst.getFullNameToNode()
self.setText(f"Disconnect '{self.srcAttr}'->'{self.dstAttr}'")
@ -343,7 +343,7 @@ class RemoveEdgeCommand(GraphCommand):
class ListAttributeAppendCommand(GraphCommand):
def __init__(self, graph, listAttribute, value, parent=None):
super(ListAttributeAppendCommand, self).__init__(graph, parent)
super().__init__(graph, parent)
assert isinstance(listAttribute, ListAttribute)
self.attrName = listAttribute.getFullNameToNode()
self.index = None
@ -368,7 +368,7 @@ class ListAttributeAppendCommand(GraphCommand):
class ListAttributeRemoveCommand(GraphCommand):
def __init__(self, graph, attribute, parent=None):
super(ListAttributeRemoveCommand, self).__init__(graph, parent)
super().__init__(graph, parent)
listAttribute = attribute.root
assert isinstance(listAttribute, ListAttribute)
self.listAttrName = listAttribute.getFullNameToNode()
@ -388,7 +388,7 @@ class ListAttributeRemoveCommand(GraphCommand):
class RemoveImagesCommand(GraphCommand):
def __init__(self, graph, cameraInitNodes, parent=None):
super(RemoveImagesCommand, self).__init__(graph, parent)
super().__init__(graph, parent)
self.cameraInits = cameraInitNodes
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 }
@ -417,7 +417,7 @@ class RemoveImagesCommand(GraphCommand):
class MoveNodeCommand(GraphCommand):
""" Move a node to a given position. """
def __init__(self, graph, node, position, parent=None):
super(MoveNodeCommand, self).__init__(graph, parent)
super().__init__(graph, parent)
self.nodeName = node.name
self.oldPosition = node.position
self.newPosition = position
@ -436,7 +436,7 @@ class UpgradeNodeCommand(GraphCommand):
Perform node upgrade on a CompatibilityNode.
"""
def __init__(self, graph, node, parent=None):
super(UpgradeNodeCommand, self).__init__(graph, parent)
super().__init__(graph, parent)
self.nodeDict = node.toDict()
self.nodeName = node.getName()
self.compatibilityIssue = None
@ -464,7 +464,7 @@ class EnableGraphUpdateCommand(GraphCommand):
Should not be used directly, use GroupedGraphModification context manager instead.
"""
def __init__(self, graph, enabled, parent=None):
super(EnableGraphUpdateCommand, self).__init__(graph, parent)
super().__init__(graph, parent)
self.enabled = enabled
self.previousState = self.graph.updateEnabled

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python
# coding:utf-8
from collections.abc import Iterable
import logging
import os
@ -7,7 +6,8 @@ import json
from enum import Enum
from threading import Thread, Event, Lock
from multiprocessing.pool import ThreadPool
from typing import Iterator, Optional, Union
from typing import Optional, Union
from collections.abc import Iterator
from PySide6.QtCore import (
Slot,
@ -49,7 +49,7 @@ class FilesModTimePollerThread(QObject):
timesAvailable = Signal(list)
def __init__(self, parent=None):
super(FilesModTimePollerThread, self).__init__(parent)
super().__init__(parent)
self._thread = None
self._mutex = Lock()
self._threadPool = ThreadPool(4)
@ -140,7 +140,7 @@ class ChunksMonitor(QObject):
Thus, for genericity, monitoring is based on regular polling and not file system watching.
"""
def __init__(self, chunks=(), parent=None):
super(ChunksMonitor, self).__init__(parent)
super().__init__(parent)
self.monitorableChunks = []
self.monitoredChunks = []
self._filesTimePoller = FilesModTimePollerThread(parent=self)
@ -254,7 +254,7 @@ class GraphLayout(QObject):
}
def __init__(self, graph):
super(GraphLayout, self).__init__(graph)
super().__init__(graph)
self.graph = graph
self._depthMode = GraphLayout.DepthMode.MaxDepth
self._nodeWidth = 160 # implicit node width
@ -365,7 +365,7 @@ class UIGraph(QObject):
It also provides a monitoring of all its computation units (NodeChunks).
"""
def __init__(self, undoStack: commands.UndoStack, taskManager: TaskManager, parent: QObject = None):
super(UIGraph, self).__init__(parent)
super().__init__(parent)
self._undoStack = undoStack
self._taskManager = taskManager
self._graph: Graph = Graph('', self)

View file

@ -8,7 +8,7 @@ class PaletteManager(QObject):
Manages QApplication's palette and provides a toggle between a dark and a light theme.
"""
def __init__(self, qmlEngine, parent=None):
super(PaletteManager, self).__init__(parent)
super().__init__(parent)
self.qmlEngine = qmlEngine
darkPalette = QPalette()
window = QColor(50, 52, 55)

View file

@ -29,7 +29,7 @@ class Message(QObject):
""" Simple structure wrapping a high-level message. """
def __init__(self, title, text, detailedText="", parent=None):
super(Message, self).__init__(parent)
super().__init__(parent)
self._title = title
self._text = text
self._detailedText = detailedText
@ -47,7 +47,7 @@ class LiveSfmManager(QObject):
File watching is based on regular polling and not filesystem events to work on network mounts.
"""
def __init__(self, reconstruction):
super(LiveSfmManager, self).__init__(reconstruction)
super().__init__(reconstruction)
self.reconstruction = reconstruction
self._folder = ''
self.timerId = -1
@ -188,7 +188,7 @@ class ViewpointWrapper(QObject):
viewpointAttribute (GroupAttribute): viewpoint attribute
reconstruction (Reconstruction): owner reconstruction of this Viewpoint
"""
super(ViewpointWrapper, self).__init__(parent=reconstruction)
super().__init__(parent=reconstruction)
self._viewpoint = viewpointAttribute
self._reconstruction = reconstruction
@ -428,7 +428,7 @@ class ActiveNode(QObject):
Hold one active node for a given NodeType.
"""
def __init__(self, nodeType, parent=None):
super(ActiveNode, self).__init__(parent)
super().__init__(parent)
self.nodeType = nodeType
self._node = None
@ -467,7 +467,7 @@ class Reconstruction(UIGraph):
]
def __init__(self, undoStack: commands.UndoStack, taskManager: TaskManager, defaultPipeline: str="", parent: QObject=None):
super(Reconstruction, self).__init__(undoStack, taskManager, parent)
super().__init__(undoStack, taskManager, parent)
# initialize member variables for key steps of the 3D reconstruction pipeline
self._active = False
@ -515,7 +515,7 @@ class Reconstruction(UIGraph):
@Slot()
def clear(self):
self.clearActiveNodes()
super(Reconstruction, self).clear()
super().clear()
self.setActive(False)
def setDefaultPipeline(self, defaultPipeline):
@ -554,7 +554,7 @@ class Reconstruction(UIGraph):
# Lower the input and the dictionary keys to make sure that all input types can be found:
# - correct pipeline name but the case does not match (e.g. panoramaHDR instead of panoramaHdr)
# - lowercase pipeline name given through the "New Pipeline" menu
loweredPipelineTemplates = dict((k.lower(), v) for k, v in meshroom.core.pipelineTemplates.items())
loweredPipelineTemplates = {k.lower(): v for k, v in meshroom.core.pipelineTemplates.items()}
filepath = loweredPipelineTemplates.get(p.lower(), p)
return self._loadWithErrorReport(self.initFromTemplate, filepath)
@ -698,7 +698,7 @@ class Reconstruction(UIGraph):
if not os.path.exists(sfmFile):
return QVector3D(0.0, 0.0, 0.0)
# skip decoding errors to avoid potential exceptions due to non utf-8 characters in images metadata
with open(sfmFile, 'r', encoding='utf-8', errors='ignore') as f:
with open(sfmFile, encoding='utf-8', errors='ignore') as f:
data = json.load(f)
intrinsics = data.get('intrinsics', [])
@ -881,7 +881,7 @@ class Reconstruction(UIGraph):
if not filesByType["images"] and not filesByType["videos"] and not filesByType["panoramaInfo"] and not filesByType["meshroomScenes"]:
if filesByType["other"]:
extensions = set([os.path.splitext(url)[1] for url in filesByType["other"]])
extensions = {os.path.splitext(url)[1] for url in filesByType["other"]}
self.error.emit(
Message(
"No Recognized Input File",

View file

@ -21,7 +21,7 @@ class QmlInstantEngine(QQmlApplicationEngine):
watching -- Defines whether the watcher is active (default: True)
verbose -- if True, output log infos (default: False)
"""
super(QmlInstantEngine, self).__init__(parent)
super().__init__(parent)
self._fileWatcher = QFileSystemWatcher() # Internal Qt File Watcher
self._sourceFile = ""
@ -51,7 +51,7 @@ class QmlInstantEngine(QQmlApplicationEngine):
def load(self, sourceFile):
self._sourceFile = sourceFile
super(QmlInstantEngine, self).load(sourceFile)
super().load(sourceFile)
def setWatching(self, watchValue):
"""