Exemple #1
0
    def restoreState(self, state):
        """
        Restore the state of this flowchart from a previous call to `saveState()`.
        """
        self.blockSignals(True)
        try:
            if 'source_configuration' in state:
                src_cfg = state['source_configuration']
                self.widget().sourceConfigure.restoreState(src_cfg)
                if src_cfg['files']:
                    self.widget().sourceConfigure.applyClicked()

            if 'library' in state:
                lib_cfg = state['library']
                self.widget().libraryEditor.restoreState(lib_cfg)
                self.widget().libraryEditor.applyClicked()

            if 'viewbox' in state:
                self.viewBox.restoreState(state['viewbox'])

            nodes = state['nodes']
            nodes.sort(key=lambda a: a['state']['pos'][0])
            for n in nodes:
                if n['class'] == 'SourceNode':
                    try:
                        ttype = eval(n['state']['terminals']['Out']['ttype'])
                        n['state']['terminals']['Out']['ttype'] = ttype
                        node = SourceNode(name=n['name'],
                                          terminals=n['state']['terminals'])
                        self.addNode(node=node)
                    except Exception:
                        printExc(
                            "Error creating node %s: (continuing anyway)" %
                            n['name'])
                else:
                    try:
                        node = self.createNode(n['class'], name=n['name'])
                    except Exception:
                        printExc(
                            "Error creating node %s: (continuing anyway)" %
                            n['name'])

                node.restoreState(n['state'])
                if hasattr(node, "display"):
                    node.display(topics=None, terms=None, addr=None, win=None)
                    if hasattr(node.widget,
                               'restoreState') and 'widget' in n['state']:
                        node.widget.restoreState(n['state']['widget'])

            connections = {}
            with tempfile.NamedTemporaryFile(mode='w') as type_file:
                type_file.write("from mypy_extensions import TypedDict\n")
                type_file.write("from typing import *\n")
                type_file.write("import numbers\n")
                type_file.write("import amitypes\n")
                type_file.write("T = TypeVar('T')\n\n")

                nodes = self.nodes(data='node')

                for n1, t1, n2, t2 in state['connects']:
                    try:
                        node1 = nodes[n1]
                        term1 = node1[t1]
                        node2 = nodes[n2]
                        term2 = node2[t2]

                        self.connectTerminals(term1, term2, type_file)
                        if term1.isInput() or term1.isCondition:
                            in_name = node1.name() + '_' + term1.name()
                            in_name = in_name.replace('.', '_')
                            out_name = node2.name() + '_' + term2.name()
                            out_name = out_name.replace('.', '_')
                        else:
                            in_name = node2.name() + '_' + term2.name()
                            in_name = in_name.replace('.', '_')
                            out_name = node1.name() + '_' + term1.name()
                            out_name = out_name.replace('.', '_')

                        connections[(in_name, out_name)] = (term1, term2)
                    except Exception:
                        print(node1.terminals)
                        print(node2.terminals)
                        printExc("Error connecting terminals %s.%s - %s.%s:" %
                                 (n1, t1, n2, t2))

                type_file.flush()
                status = subprocess.run(
                    ["mypy", "--follow-imports", "silent", type_file.name],
                    capture_output=True,
                    text=True)
                if status.returncode != 0:
                    lines = status.stdout.split('\n')[:-1]
                    for line in lines:
                        m = re.search(r"\"+(\w+)\"+", line)
                        if m:
                            m = m.group().replace('"', '')
                            for i in connections:
                                if i[0] == m:
                                    term1, term2 = connections[i]
                                    term1.disconnectFrom(term2)
                                    break
                                elif i[1] == m:
                                    term1, term2 = connections[i]
                                    term1.disconnectFrom(term2)
                                    break

        finally:
            self.blockSignals(False)

        for name, node in self.nodes(data='node'):
            self.sigNodeChanged.emit(node)
Exemple #2
0
class NodeProcess(QtCore.QObject):
    def __init__(self,
                 msg,
                 broker_addr="",
                 graphmgr_addr="",
                 checkpoint_addr="",
                 loop=None,
                 library_paths=None,
                 hutch=''):
        super().__init__()

        if loop is None:
            self.app = QtGui.QApplication([])
            loop = QEventLoop(self.app)

        asyncio.set_event_loop(loop)

        self.win = NodeWindow(self)
        self.win.resize(800, 800)

        if msg.node_type == "SourceNode":
            self.node = SourceNode(name=msg.name)
        else:
            if library_paths:
                dirs = set(map(os.path.dirname, library_paths))
                sys.path.extend(dirs)

                for mod in library_paths:
                    mod = os.path.basename(mod)
                    mod = os.path.splitext(mod)[0]
                    mod = importlib.import_module(mod)

                    nodes = [
                        getattr(mod, name) for name in dir(mod)
                        if isNodeClass(getattr(mod, name))
                    ]

                    for node in nodes:
                        LIBRARY.addNodeType(node, [(mod.__name__, )])

            self.node = LIBRARY.getNodeType(msg.node_type)(msg.name)

        self.node.restoreState(msg.state)
        self.graphmgr_addr = graphmgr_addr
        self.ctx = zmq.asyncio.Context()

        self.broker = self.ctx.socket(zmq.SUB)
        self.broker.connect(broker_addr)
        self.broker.setsockopt_string(zmq.SUBSCRIBE,
                                      msg.name + ZMQ_TOPIC_DELIM)

        self.checkpoint = self.ctx.socket(zmq.PUB)
        self.checkpoint.connect(checkpoint_addr)

        self.ctrlWidget = self.node.ctrlWidget(self.win)
        self.widget = None

        title = msg.name
        if hutch:
            title += f' hutch: {hutch}'
        self.win.setWindowTitle(title)

        with loop:
            loop.run_until_complete(self.process())

    async def process(self):
        while True:
            await self.broker.recv_string()
            msg = await self.broker.recv_pyobj()

            if isinstance(msg, fcMsgs.DisplayNode):
                self.display(msg)
            elif isinstance(msg, fcMsgs.ReloadLibrary):
                self.reloadLibrary(msg)
            elif isinstance(msg, fcMsgs.CloseNode):
                return

    def display(self, msg):
        if self.node.viewed and msg.redisplay:
            self.node.close()
            self.widget = None

        if msg.geometry:
            self.win.restoreGeometry(msg.geometry)

        if self.widget is None:
            self.widget = self.node.display(msg.topics,
                                            msg.terms,
                                            self.graphmgr_addr,
                                            self.win,
                                            units=msg.units)

            if self.ctrlWidget and self.widget:
                splitter = QtWidgets.QSplitter(parent=self.win)
                splitter.addWidget(self.ctrlWidget)
                splitter.addWidget(self.widget)
                splitter.setStretchFactor(1, 10)
                self.win.setCentralWidget(splitter)
                self.ctrlWidget.setParent(splitter)
                self.widget.setParent(splitter)
            elif self.ctrlWidget:
                scrollarea = QtWidgets.QScrollArea(parent=self.win)
                scrollarea.setWidget(self.ctrlWidget)
                self.ctrlWidget.setParent(scrollarea)
                self.win.setCentralWidget(scrollarea)
            elif self.widget:
                scrollarea = QtWidgets.QScrollArea(parent=self.win)
                scrollarea.setWidgetResizable(True)
                scrollarea.setWidget(self.widget)
                self.widget.setParent(scrollarea)
                self.win.setCentralWidget(scrollarea)

            if msg.state and hasattr(self.widget, 'restoreState'):
                self.widget.restoreState(msg.state)

            self.node.sigStateChanged.connect(self.send_checkpoint)

        self.win.show()
        if self.node.viewed:
            self.win.activateWindow()
        self.node.viewed = True

    def reloadLibrary(self, msg):
        for mod in msg.mods:
            mod = sys.modules[mod]
            pg.reload.reload(mod)

    @asyncSlot(object)
    async def send_checkpoint(self, node):
        state = node.saveState()

        msg = fcMsgs.NodeCheckpoint(node.name(), state=state)
        await self.checkpoint.send_string(node.name() + ZMQ_TOPIC_DELIM,
                                          zmq.SNDMORE)
        await self.checkpoint.send_pyobj(msg)
Exemple #3
0
class NodeProcess(QtCore.QObject):

    def __init__(self, msg, broker_addr="", graphmgr_addr="", checkpoint_addr="", loop=None,
                 library_paths=None):
        super().__init__()

        if loop is None:
            self.app = QtGui.QApplication([])
            loop = QEventLoop(self.app)

        asyncio.set_event_loop(loop)

        self.win = NodeWindow(self)
        self.win.resize(800, 800)

        if msg.node_type == "SourceNode":
            self.node = SourceNode(name=msg.name)
        else:
            if library_paths:
                dirs = set(map(os.path.dirname, library_paths))
                sys.path.extend(dirs)

                for mod in library_paths:
                    mod = os.path.basename(mod)
                    mod = os.path.splitext(mod)[0]
                    mod = importlib.import_module(mod)

                    nodes = [getattr(mod, name) for name in dir(mod) if isNodeClass(getattr(mod, name))]

                    for node in nodes:
                        LIBRARY.addNodeType(node, [(mod.__name__, )])

            self.node = LIBRARY.getNodeType(msg.node_type)(msg.name)

        self.node.restoreState(msg.state)
        self.graphmgr_addr = graphmgr_addr
        self.ctx = zmq.asyncio.Context()

        self.broker = self.ctx.socket(zmq.SUB)
        self.broker.connect(broker_addr)
        self.broker.setsockopt_string(zmq.SUBSCRIBE, msg.name)

        self.checkpoint = self.ctx.socket(zmq.PUB)
        self.checkpoint.connect(checkpoint_addr)

        self.ctrlWidget = self.node.ctrlWidget(self.win)
        self.widget = None

        self.win.setWindowTitle(msg.name)

        with loop:
            loop.run_until_complete(asyncio.gather(self.process(), self.monitor_node_task()))

    async def monitor_node_task(self):
        if hasattr(self.node, 'task'):
            while self.node.task is None:
                await asyncio.sleep(0.1)
            # await the node task so we can see any exceptions it raised
            try:
                await self.node.task
            except asyncio.CancelledError:
                # ignore cancelled errors just means the window was closed
                pass

    async def process(self):
        while True:
            await self.broker.recv_string()
            msg = await self.broker.recv_pyobj()

            if isinstance(msg, fcMsgs.DisplayNode):
                self.display(msg)
            elif isinstance(msg, fcMsgs.ReloadLibrary):
                self.reloadLibrary(msg)
            elif isinstance(msg, fcMsgs.CloseNode):
                return

    def display(self, msg):
        if self.node.viewed and msg.redisplay:
            self.node.close()
            self.widget = None

        if msg.geometry:
            self.win.restoreGeometry(msg.geometry)

        if self.widget is None:
            self.widget = self.node.display(msg.topics, msg.terms, self.graphmgr_addr, self.win,
                                            units=msg.units)

            if self.ctrlWidget and self.widget:
                cw = QtGui.QWidget()
                self.win.setCentralWidget(cw)
                layout = QtGui.QGridLayout()
                cw.setLayout(layout)
                layout.addWidget(self.ctrlWidget, 0, 0, -1, 1)
                layout.addWidget(self.widget, 0, 1, -1, -1)
                layout.setColumnStretch(1, 10)
            elif self.ctrlWidget:
                scrollarea = QtWidgets.QScrollArea()
                scrollarea.setWidget(self.ctrlWidget)
                self.win.setCentralWidget(scrollarea)
            elif self.widget:
                scrollarea = QtWidgets.QScrollArea()
                scrollarea.setWidgetResizable(True)
                scrollarea.setWidget(self.widget)
                self.win.setCentralWidget(scrollarea)

            if msg.state and hasattr(self.widget, 'restoreState'):
                self.widget.restoreState(msg.state)

            self.node.sigStateChanged.connect(self.send_checkpoint)

        self.win.show()
        if self.node.viewed:
            self.win.activateWindow()
        self.node.viewed = True

    def reloadLibrary(self, msg):
        for mod in msg.mods:
            mod = sys.modules[mod]
            pg.reload.reload(mod)

    @asyncSlot(object)
    async def send_checkpoint(self, node):
        state = node.saveState()

        msg = fcMsgs.NodeCheckpoint(node.name(),
                                    state=state)
        await self.checkpoint.send_string(node.name(), zmq.SNDMORE)
        await self.checkpoint.send_pyobj(msg)