def setData(self, index, value, role):  # pylint: disable=too-many-return-statements,too-many-branches,unused-argument
        """
        Generic data modification (see QAbstractItemModel for details)

        :param index: a QModelIndex instance
        :param value: the new value
        :param role: the role to be changed
        :return:
        """
        if not index.isValid():
            return False
        item = index.internalPointer().content
        if isinstance(item, str):
            return False
        if isinstance(item, self.SubConfigContent):
            subConfig = item.subConfig
            if value == subConfig.getName():
                return False
            config = self.root.content
            if Configuration.configType(
                    subConfig) == Configuration.CONFIG_TYPE_APPLICATION:
                try:
                    if subConfig.getName() == self.activeApp:
                        self.activeApp = value
                    config.renameApp(subConfig.getName(), value)
                except NexTRuntimeError:
                    return False
                self.dataChanged.emit(index, index,
                                      [Qt.DisplayRole, Qt.EditRole])
                return True
            if Configuration.configType(
                    subConfig) == Configuration.CONFIG_TYPE_COMPOSITE:
                try:
                    config.renameComposite(subConfig.getName(), value)
                except NexTRuntimeError:
                    return False
                self.dataChanged.emit(index, index,
                                      [Qt.DisplayRole, Qt.EditRole])
                return True
        if isinstance(item, self.NodeContent):
            if item.name == value:
                return False
            subConfig = index.parent().internalPointer().content.subConfig
            graph = subConfig.getGraph()
            try:
                graph.renameNode(item.name, value)
            except NexTRuntimeError:
                return False
            self.dataChanged.emit(index, index, [Qt.DisplayRole, Qt.EditRole])
            return True
        if isinstance(item, self.PropertyContent):
            try:
                item.property.setProperty(item.name, value)
            except NexTRuntimeError:
                return False
            self.dataChanged.emit(index, index, [Qt.DisplayRole, Qt.EditRole])
            return True
        return False
def test_recursion():
    config = Configuration()
    cf_inner = CompositeFilter("cf_inner", config)
    cg_inner = cf_inner.getGraph()
    f1 = cg_inner.addNode("pyfile://" + os.path.dirname(__file__) + "/../interface/SimpleStaticFilter.py", "SimpleStaticFilter")

    cf = CompositeFilter("cf", config)
    cg = cf.getGraph()
    f1 = cg.addNode("pyfile://" + os.path.dirname(__file__) + "/../interface/SimpleStaticFilter.py", "SimpleStaticFilter")
    f2 = cg.addNode(cf_inner, "compositeNode")

    # add composite node to itself
    cg_oldNodes = set(cg.allNodes())
    cg_inner_oldNodes = set(cg_inner.allNodes())
    expect_exception(CompositeRecursion, cg.addNode, cf, "compositeNode")
    assert cg_oldNodes == set(cg.allNodes())

    # add composite node to an inner node
    expect_exception(CompositeRecursion, cg_inner.addNode, cf, "compositeNode")
    assert cg_inner_oldNodes == set(cg_inner.allNodes())

    # double dependency
    cf1 = CompositeFilter("cf1", config)
    cf2 = CompositeFilter("cf2", config)
    cf1.getGraph().addNode(cf2, "compositeNode")
    expect_exception(CompositeRecursion, cf2.getGraph().addNode, cf1, "compositeNode")
    def indexOfSubConfigParent(self, subConfig):
        """
        Returns the index of the given subConfig's parent

        :param subConfig: a SubConfiguration instance
        :return: a QModelIndex instance.
        """
        sctype = Configuration.configType(subConfig)
        if sctype is Configuration.CONFIG_TYPE_APPLICATION:
            parent = self.index(1, 0, QModelIndex())
        elif sctype is Configuration.CONFIG_TYPE_COMPOSITE:
            parent = self.index(0, 0, QModelIndex())
        else:
            raise NexTRuntimeError("Unexpected subconfig type")
        return parent
Exemple #4
0
def exception_setup(python, thread, where, activeTime_s):
    logging.getLogger(__name__).info("------------------------------------------------------")
    logging.getLogger(__name__).info("Starting exception_setup %d %s %s %f", python, thread, where, activeTime_s)
    from nexxT.services.ConsoleLogger import ConsoleLogger
    logger = ConsoleLogger()
    Services.addService("Logging", logger)
    class LogCollector(logging.StreamHandler):
        def __init__(self):
            super().__init__()
            self.logs = []
        def emit(self, record):
            self.logs.append(record)
    # avoid warning flood about service profiling not found
    Services.addService("Profiling", None)
    collector = LogCollector()
    logging.getLogger().addHandler(collector)
    try:
        t = QTimer()
        t.setSingleShot(True)
        # timeout if test case hangs
        t2 = QTimer()
        t2.start((activeTime_s + 3)*1000)
        try:
            test_json = Path(__file__).parent / "test_except_constr.json"
            with test_json.open("r", encoding='utf-8') as fp:
                cfg = json.load(fp)
            if nexxT.useCImpl and not python:
                cfg["composite_filters"][0]["nodes"][2]["library"] = "binary://../binary/${NEXXT_PLATFORM}/${NEXXT_VARIANT}/test_plugins"
            cfg["composite_filters"][0]["nodes"][2]["thread"] = thread
            cfg["composite_filters"][0]["nodes"][2]["properties"]["whereToThrow"] = where
            mod_json = Path(__file__).parent / "test_except_constr_tmp.json"
            with mod_json.open("w", encoding="utf-8") as fp:
                json.dump(cfg, fp)

            config = Configuration()
            ConfigFileLoader.load(config, mod_json)
            config.activate("testApp")
            app.processEvents()

            aa = Application.activeApplication

            init = True
            def timeout():
                nonlocal init
                if init:
                    init = False
                    aa.stop()
                    aa.close()
                    aa.deinit()
                else:
                    app.exit(0)

            def timeout2():
                print("Application timeout hit!")
                nonlocal init
                if init:
                    init = False
                    aa.stop()
                    aa.close()
                    aa.deinit()
                else:
                    print("application exit!")
                    app.exit(1)
            t2.timeout.connect(timeout2)
            t.timeout.connect(timeout)
            def state_changed(state):
                if state == FilterState.ACTIVE:
                    t.setSingleShot(True)
                    t.start(activeTime_s*1000)
                elif not init and state == FilterState.CONSTRUCTED:
                    t.start(1000)
            aa.stateChanged.connect(state_changed)

            aa.init()
            aa.open()
            aa.start()

            app.exec_()
        finally:
            del t
            del t2
    finally:
        logging.getLogger().removeHandler(collector)
        Services.removeAll()
    return collector.logs
    def data(self, index, role):  # pylint: disable=too-many-return-statements,too-many-branches
        """
        Generic data query

        :param index: a QModelIndex instance
        :param role: the data role (see QAbstractItemModel)
        :return:
        """
        if not index.isValid():
            return None
        item = index.internalPointer().content
        if role == Qt.DisplayRole:
            if isinstance(item, str):
                return item if index.column() == 0 else None
            if isinstance(item, self.SubConfigContent):
                return item.subConfig.getName() if index.column(
                ) == 0 else None
            if isinstance(item, self.NodeContent):
                return item.name if index.column() == 0 else None
            if isinstance(item, self.PropertyContent):
                if index.column() == 0:
                    return item.name
                p = item.property.getPropertyDetails(item.name)
                return p.handler.toViewValue(
                    item.property.getProperty(item.name))
            logger.warning("Unknown item %s", repr(item))
        if role == Qt.DecorationRole:
            if index.column() != 0:
                return None
            if isinstance(item, str):
                if not index.parent().isValid():
                    return QIcon.fromTheme(
                        "drive-harddisk",
                        QApplication.style().standardIcon(
                            QStyle.SP_DriveHDIcon))
            if isinstance(item, self.SubConfigContent):
                if Configuration.configType(
                        item.subConfig) == Configuration.CONFIG_TYPE_COMPOSITE:
                    return QIcon.fromTheme(
                        "repository",
                        QApplication.style().standardIcon(
                            QStyle.SP_DirLinkIcon))
                if Configuration.configType(
                        item.subConfig
                ) == Configuration.CONFIG_TYPE_APPLICATION:
                    return QIcon.fromTheme(
                        "folder",
                        QApplication.style().standardIcon(QStyle.SP_DirIcon))
            if isinstance(item, self.NodeContent):
                return QIcon.fromTheme(
                    "unknown",
                    QApplication.style().standardIcon(QStyle.SP_FileIcon))
            if isinstance(item, self.PropertyContent):
                return None
            logger.warning("Unknown item %s", repr(item))
        if role == Qt.FontRole:
            if index.column() != 0:
                return None
            if isinstance(item, self.SubConfigContent):
                if index.parent().row() == 1:
                    font = QFont()
                    if item.subConfig.getName() == self.activeApp:
                        font.setBold(True)
                        return font
        if role == Qt.ToolTipRole:
            if isinstance(item, self.PropertyContent):
                p = item.property.getPropertyDetails(item.name)
                return p.helpstr
        if role == ITEM_ROLE:
            return item
        return None
Exemple #6
0
def startNexT(cfgfile, active, execScripts, execCode, withGui):
    """
    Starts next with the given config file and activates the given application.
    :param cfgfile: path to config file
    :param active: active application (if None, the first application in the config will be used)
    :return: None
    """
    logger.debug("Starting nexxT...")
    config = Configuration()
    lcl = QLocale.system()
    lcl.setNumberOptions(QLocale.c().numberOptions())
    QLocale.setDefault(lcl)
    if withGui:
        app = QApplication() if QApplication.instance() is None else QApplication.instance()
        app.setWindowIcon(QIcon(":icons/nexxT.svg"))
        app.setOrganizationName("nexxT")
        app.setApplicationName("nexxT")
        setupGuiServices(config)
    else:
        app = QCoreApplication() if QCoreApplication.instance() is None else QCoreApplication.instance()
        app.setOrganizationName("nexxT")
        app.setApplicationName("nexxT")
        setupConsoleServices(config)

    if cfgfile is not None:
        ConfigFileLoader.load(config, cfgfile)
    if withGui:
        mainWindow = Services.getService("MainWindow")
        mainWindow.restoreState()
        mainWindow.show()
        # the reference will still be held by the service, but here we don't need it anymore
        del mainWindow
    if active is not None:
        config.activate(active)
        # pylint: disable=unused-variable
        # need to hold the reference of this until the method is called
        i2 = MethodInvoker(dict(object=Application, method="initialize", thread=app.thread()),
                           MethodInvoker.IDLE_TASK) # pylint: disable=unused-variable
        waitForSignal(config.appActivated)
        if Application.activeApplication.getState() != FilterState.ACTIVE:
            waitForSignal(Application.activeApplication.stateChanged, lambda s: s == FilterState.ACTIVE)
        logger.info("done")

    def cleanup():
        logger.debug("cleaning up loaded services")
        Services.removeAll()
        logger.debug("cleaning up loaded plugins")
        for v in ("last_traceback", "last_type", "last_value"):
            if hasattr(sys, v):
                del sys.__dict__[v]
        #PluginManager.singleton().unloadAll()
        logger.debug("cleaning up complete")

    code_globals = {}
    for c in execCode:
        logger.info("Executing code '%s'", c)
        # note that exec is used intentionally here to provide the user with scripting posibilities
        exec(compile(c, "<string>", 'exec'), code_globals) # pylint: disable=exec-used
        logger.debug("Executing code done")

    for s in execScripts:
        logger.info("Executing script '%s'", s)
        with open(s) as fscript:
            # note that exec is used intentionally here to provide the user with scripting possibilities
            exec(compile(fscript.read(), s, 'exec'), code_globals)  # pylint: disable=exec-used
        logger.debug("Executing script done")

    res = app.exec_()
    logger.debug("closing config")
    config.close()
    cleanup()

    logger.internal("app.exec_ returned")

    return res
def simple_setup(sourceFreq, activeTime_s):
    t = QTimer()
    t.setSingleShot(True)
    # timeout if test case hangs
    t2 = QTimer()
    t2.start((activeTime_s + 3)*1000)
    try:
        config = Configuration()
        cf_inner = CompositeFilter("cf_inner", config)
        cg_inner = cf_inner.getGraph()
        f1 = cg_inner.addNode("pyfile://" + os.path.dirname(__file__) + "/../interface/SimpleStaticFilter.py", "SimpleStaticFilter")
        cg_inner.addDynamicOutputPort("CompositeInput", "compositeIn")
        cg_inner.addDynamicInputPort("CompositeOutput", "compositeOut")
        app.processEvents()
        cg_inner.addConnection("CompositeInput", "compositeIn", f1, "inPort")
        cg_inner.addConnection(f1, "outPort", "CompositeOutput", "compositeOut")

        cf = CompositeFilter("cf", config)
        cg = cf.getGraph()
        f1 = cg.addNode("pyfile://" + os.path.dirname(__file__) + "/../interface/SimpleStaticFilter.py", "SimpleStaticFilter")
        f2 = cg.addNode(cf_inner, "compositeNode")
        app.processEvents()

        cg.addDynamicOutputPort("CompositeInput", "compositeIn")
        cg.addDynamicInputPort("CompositeOutput", "compositeOut")
        app.processEvents()

        cg.addConnection("CompositeInput", "compositeIn", f1, "inPort")
        cg.addConnection(f1, "outPort", f2, "compositeIn")
        cg.addConnection(f2, "compositeOut", "CompositeOutput", "compositeOut")

        expect_exception(CompositeRecursion, cg.addNode, cf, "compositeNode")
        expect_exception(CompositeRecursion, cg_inner.addNode, cf, "compositeNode")

        a = Application("app", config)
        ag = a.getGraph()
        cn = ag.addNode(cf, "compositeNode")

        app.processEvents()
        app.processEvents()

        cn_ip = [p.name() for p in ag.getMockup(cn).getAllInputPorts()]
        cn_op = [p.name() for p in ag.getMockup(cn).getAllOutputPorts()]
        assert cn_ip == ["compositeIn"]
        assert cn_op == ["compositeOut"]

        sn = ag.addNode("pyfile://" + os.path.dirname(__file__) + "/../interface/SimpleStaticFilter.py", "SimpleSource")
        p = ag.getMockup(sn).propertyCollection()
        p.setProperty("frequency", sourceFreq)
        ag.addConnection(sn, "outPort", cn, "compositeIn")
        fn = ag.addNode("pyfile://" + os.path.dirname(__file__) + "/../interface/SimpleStaticFilter.py", "SimpleStaticFilter")
        ag.addConnection(cn, "compositeOut", fn, "inPort")

        cg.renameDynamicInputPort("CompositeOutput", "compositeOut", "renamedOut")
        app.processEvents()
        cg.renameDynamicOutputPort("CompositeInput", "compositeIn", "renamedIn")
        app.processEvents()

        aa = ActiveApplication(ag)
        init = True

        def timeout():
            nonlocal init
            if init:
                init = False
                aa.stop()
                aa.close()
                aa.deinit()
            else:
                app.exit(0)

        def timeout2():
            print("Application timeout hit!")
            nonlocal init
            if init:
                init = False
                aa.stop()
                aa.close()
                aa.deinit()
            else:
                app.exit(1)
        t2.timeout.connect(timeout2)
        t.timeout.connect(timeout)

        events = []
        def logger(object, function, datasample):
            nonlocal events
            events.append(dict(object=object, function=function, datasample=datasample, time=time.time()))

        def state_changed(state):
            if state == FilterState.ACTIVE:
                t.setSingleShot(True)
                t.start(activeTime_s*1000)
            elif not init and state == FilterState.CONSTRUCTED:
                t.start(1000)
        aa.stateChanged.connect(state_changed)

        t1 = aa._filters2threads["/SimpleSource"]
        f1 = aa._threads[t1]._filters["/SimpleSource"].getPlugin()
        f1.beforeTransmit = lambda ds: logger(object="SimpleSource", function="beforeTransmit", datasample=ds)
        f1.afterTransmit = lambda: logger(object="SimpleSource", function="afterTransmit", datasample=None)

        t2 = aa._filters2threads["/SimpleStaticFilter"]
        f2 = aa._threads[t2]._filters["/SimpleStaticFilter"].getPlugin()
        f2.afterReceive = lambda ds: logger(object="SimpleStaticFilter", function="afterReceive", datasample=ds)
        f2.beforeTransmit = lambda ds: logger(object="SimpleStaticFilter", function="beforeTransmit", datasample=ds)
        f2.afterTransmit = lambda: logger(object="SimpleStaticFilter", function="afterTransmit", datasample=None)

        aa.init()
        aa.open()
        aa.start()

        app.exec_()

        return events
    finally:
        del t
        del t2
def simple_setup(activeTime_s):
    t = QTimer()
    t.setSingleShot(True)
    # timeout if test case hangs
    t2 = QTimer()
    t2.start((activeTime_s + 3) * 1000)
    try:
        if nexxT.useCImpl:
            test_json = Path(__file__).parent / "test2.json"
        else:
            test_json = Path(__file__).parent / "test1.json"
        config = Configuration()
        ConfigFileLoader.load(config, test_json)
        # we don't have a save as feature yet, so this function is throwing an exception atm
        expect_exception(ConfigFileLoader.save, config,
                         test_json.parent / "test1.saved.json")
        config.activate("testApp")
        app.processEvents()

        aa = Application.activeApplication

        init = True

        def timeout():
            nonlocal init
            if init:
                init = False
                aa.stop()
                aa.close()
                aa.deinit()
            else:
                app.exit(0)  #logging.INTERNAL = INTERNAL

        def timeout2():
            print("Application timeout hit!")
            nonlocal init
            if init:
                init = False
                aa.stop()
                aa.close()
                aa.deinit()
            else:
                app.exit(1)

        t2.timeout.connect(timeout2)
        t.timeout.connect(timeout)

        def state_changed(state):
            if state == FilterState.ACTIVE:
                t.setSingleShot(True)
                t.start(activeTime_s * 1000)
            elif not init and state == FilterState.CONSTRUCTED:
                t.start(1000)

        aa.stateChanged.connect(state_changed)

        aa.init()
        aa.open()
        aa.start()

        app.exec_()
    finally:
        del t
        del t2